I2C (Inter-Integrated Circuit) driver
This example is a driver for an I2C bus controller. The I2C bus is simply a 2-wire bus, and the hardware is extremely cheap to implement. The bus supports up to 127 devices on the bus, and each device can handle 256 commands. When devices want to read or write information to or from another device, they must first be set up as a controller to own the bus. Then the device sends out the device address and command register number. The worker then acts upon the command received.
You think a resource manager wouldn't apply in this case. All read() and write() operations require a device address and command register. You could use devctl(), but a resource manager again provides a cleaner interface.
/dev/i2c1/
An important thing to note is that each filename (127 devices * 256 registers = 32512 filenames) doesn't really need to exist. Each device would be created live, as it's required. Therefore, each open() is actually an O_CREAT.
To prevent any problems caused by a high number of possibly existing files, you could make an ls command of the /dev/i2c1 directory return nothing. Alternatively, you could make ls list the filenames that have been opened at least once. At this point, it's important to clarify that the existence of the filenames is totally handled by the resource manager; the OS itself isn't used in that process. So it isn't a problem if filenames respond to open() requests, but not to ls.
One element is left to solve: the I2C bus has a concept of a baud rate. There are already C functions to set up baud rates, and you can make it work via the stty command from the shell.
People using the driver don't have to worry about libraries or
include
files because there are none.
The resource manager, at no cost, allows each command register to be
accessed via the shell, or for that matter, though SAMBA from a Linux or Windows machine.
Access via the shell makes debugging so easy—there's no need to
write custom test tools, and it's unbelievably flexible, not to mention
the support for separate permissions for each and every command register of every device.
fd = open ( "/dev/i2c1/34/45" );
read( fd, &variable, sizeof( variable ) );
close(fd);
fd = open ( "/dev/i2c1/flash/page_number" );
read( fd, &page_number, sizeof( page_number ) );
close (fd );
#define
directives to show meaningful
information, but an even better solution is to create a configuration file
that the driver could read to create an alias.
The configuration file looks like this:
[4=temperature_sensor]
10=max
11=min
12=temperature
13=alarm
[5=flash]
211=page_number
The field inside the square brackets defines the device address and name. The data that follows specifies each register of that device. The main advantages to this approach are:
- The configuration file's format helps document the program.
- If the hardware is changed, and devices are assigned new addresses, you simply change the configuration file; there's no need to recompile the program to recompile.
These predefined devices would always show via the ls command.