Keyboard input

Programming, for all ages and all languages.
rdos
Member
Member
Posts: 3279
Joined: Wed Oct 01, 2008 1:55 pm

Re: Keyboard input

Post by rdos »

Jezze wrote:Well, what is compelling about it should be pretty obvious and I'm unsure if I really need to explain why? A program writing data to stdout does not need to know anything about the target device. It could be a printer, a framebuffer or a serial console but it does not matter from the program's perspective, it will just work.
I can understand what is compelling, but OTOH, few people today use command-line like they did when this was invented. For typical end users, this feature has no relevance at all. For an advanced user, it seems just as easy to write a proper application that uses the serial port API rather than opening it as a file. For one thing, the file API doesn't handle timeouts and doesn't support baud rate settings. The problems for sockets are similar, but then the issue is destination IP & port, and also broken sockets and timeouts, which are unsupported in the file API.
Jezze wrote:I understand that thinking of everything as streams might not feel clean from your perspective but consider the problem you will have when you add a new device type to your os. You will have to modify all programs who wants to utilize that device. Each program will eventually grow incredibly large and difficult to maintain. It would be a nightmare.
When I add a new device type, I first add a "virtual interface" (similar to virtual methods in C++), which is the basis of what all real devices must support. Then I give the device type a unique handle ID so references to handles are unique.

So the main issue isn't really how clean the design is, but rather that no device that isn't a file in a file system has the same methods as files, and thus cannot implement the file API methods properly, and typically also has a few extra required methods that cannot be added to the file API since they typically have no meaning for a file.

The traditional solution to the above is that things like file positioning are ignored for non-file objects, while the additional methods required by non-file objects are implemented with IOCTL or similar bastard-solutions. Some systems also invent strange file names for devices, and open these as if they were files.

In RDOS, none of this is supported, and if required, need to be implemented in the C library as the kernel will not support it. Ever.

Besides, it is pretty trivial to implement the typical *nix view of handles in the C library. You can keep the OS handle & type per C handle, and then call the correct read/write method in a switch statement. The reverse (to provide a clean OO interface) is not trivial though, as it needs to know the specifics of special file names and IOCTL control methods in order to implement device-specific methods. It is also faster to have a simple interface to the OS kernel, and let time-sensitive applications use it directly, rather than on top of a file-API abstraction. I practically never use the C file handle interface myself, but rather use the TFile object which goes directly to the relevant OS API.
User avatar
xenos
Member
Member
Posts: 1118
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: Keyboard input

Post by xenos »

I think there is not necessarily a contradiction between the standard stream / file approach and the object oriented file approach. For example, I would expect several RDOS classes to have a "putchar" function that writes a single character to a console, a serial port, a network socket or appends it to a file. Similarly, I would expect those classes to have a "getchar" function as well, that reads a single character from a console, serial port, network socket or file. In other words, all these classes implement a putchar / getchar interface. Assume some program simply wants to read characters from somewhere and write characters to somewhere else. One could pass two handles to this program, one for input and one for output, which point to classes that implement the putchar / getchar interface. The program itself does not need to know which classes are involved, as long as they implement the correct interface. Calling the classes' implementations of putchar / getchar would be up to the C library, so the program does not need to be modified if there is a new class.
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
rdos
Member
Member
Posts: 3279
Joined: Wed Oct 01, 2008 1:55 pm

Re: Keyboard input

Post by rdos »

XenOS wrote:I think there is not necessarily a contradiction between the standard stream / file approach and the object oriented file approach. For example, I would expect several RDOS classes to have a "putchar" function that writes a single character to a console, a serial port, a network socket or appends it to a file. Similarly, I would expect those classes to have a "getchar" function as well, that reads a single character from a console, serial port, network socket or file. In other words, all these classes implement a putchar / getchar interface.
Yes, many devices have a Read and Write method (usually using a buffer & count, not for single characters), so that is correct.

Standard keyboard input does have a simplified getchar-like method, but it is really an emulation since the keyboard driver doesn't operate that way. The keyboard driver report key pressed / released events, which contain scan codes and virtual key codes, that for international keyboards cannot be abstracted to a single char.

There are similar problems for standard output. There is an emulation method which know about current position and how to scroll the screen, but the basic text-mode operations use a position, color attribute and buffer in order to output text. The graphics mode equivalent operates against a bitmap-context (which in no way can be abstracted as a file) uses x and y coordinates, assumes the text is in UTF-8, and uses current settings (in the bitmap) for font type/size, color and how to write it to the device.

Then we have the topic of waits for objects which are required for many devices that have Read/Write methods that can be abstracted onto the file-API. For instance, the keyboard driver uses a event queue, and unless you want getchar() to busy-poll the GetKeyEvent() method for a new event, you need to use the device with a generic wait object in order to avoid busy-polling. The same goes for serial ports and sockets.
XenOS wrote: Assume some program simply wants to read characters from somewhere and write characters to somewhere else. One could pass two handles to this program, one for input and one for output, which point to classes that implement the putchar / getchar interface. The program itself does not need to know which classes are involved, as long as they implement the correct interface. Calling the classes' implementations of putchar / getchar would be up to the C library, so the program does not need to be modified if there is a new class.
Yes. At least for applications that wants to take advantage of the traditional stream interface.

At least in my design, I implement redirection (and console input / output) by having a structure (allocated with malloc) with OS handles, device type and share count. This interface can be extended to serial ports or TCP/IP connections without much problems. When I duplicate a handle in C, I just allocate a new C-handle, link to the existing table entry, and increase share count. Thus, the pecularities in C are implemented in the C library, not in the OS kernel.
Post Reply