Linux Port Devices Driver



Mastering Linux Device Driver Development provides complete coverage of kernel topics, including video and audio frameworks, that usually go unaddressed. You’ll work with some of the most complex and impactful Linux kernel frameworks, such as PCI, ALSA for SoC, and Video4Linux2, and discover expert tips and best practices along the way. The identifier consists of two parts: major and minor. The first part identifies the device type (IDE disk, SCSI disk, serial port, etc.) and the second one identifies the device (first disk, second serial port, etc.). Most times, the major identifies the driver, while the minor identifies each physical device served by the driver.

This article brought to you by LWN subscribers

Subscribers to LWN.net made this article — and everything that surrounds it — possible. If you appreciate our content, please buy a subscription and make the next set of articles possible.

Linux Port Devices Driver Windows 10

October 19, 2016

This article was contributed by Neil Brown

Writing device drivers in user space, rather than as kernel modules,is a topic that comes up from time to time for a variety of reasons.The kernel's approach to user-space drivers varies considerably dependingon the type of device involved.The recent posting of a patch set aimed at allowing LED drivers to bewritten as user-space programs seems like a suitable opportunity tohave a look at the range of options currently available.

For it to be possible to write a device driver in user space it isnecessary for the kernel to export the required interfaces. There aretwo different sorts of interfaces, that meet different needs, that thekernel can export; I will call them 'upstream' and 'downstream'interfaces.

When one reflects on the tree-like nature of the drivermodel, as described in an earlier article, it is clear thatthere is a chain, or path, of drivers from the root out to the leaves,each making use of services provided by the driver closer to the root(or 'upstream') and providing services to the driver closer to theleaf (or 'downstream'). An upstream interface allows a user-spaceprogram to directly access services provided by the kernel thatnormally are only accessed by other kernel drivers. A downstreaminterface allows a user-space program to instantiate a new device forsome specific kernel driver, and then provide services to it thatwould normally be provided by some other kernel driver.

Upstream interfaces

An upstream interface is one that provides access to some hardware,possibly more directly than with the standard interfaces. In severalcases this is provided not with a new interface but with a slightmodification to an existing interface. Opening a block device withthe O_DIRECT flag allows directly reading from and writing to thatdevice without involving the page cache or the readahead andwrite-behind that it supports. Similarly, direct access to a serialport is obtained by opening a TTY device and disabling certaintermios settings such as ECHO and ICANON. The documentation forcfmakeraw() identifies 16 such flags that are cleared.

Direct access to a network device can be achieved by creating anetwork socket using the AF_PACKET address family and specifyingthe SOCK_RAW communication type. This socket can then be bound to aparticular interface or a particular Ethernet protocol type. A slightlyless direct interface can be had by using SOCK_RAW with AF_INET.This still provides the routing and other functionality common to allIP protocols, but gives complete control over the payload of each IPpacket.

Moving on to more purpose-built interfaces, the sg and bsgdrivers (SCSI generic and block SCSI generic) both provide directaccess to SCSI devices, or other devices such as SATA that use acompatible protocol. They allow SCSI command descriptor blocks(CDBs) to be sent todevices and to have results returned. The bsginterface is integrated with the block layer and supports a newerversion of the sg interface that includes support for bidirectionalcommands. libsgutils is the recommended mechanism for making use ofthese interfaces, rather than working directly with /dev/sgN.Similarly, libusb provides adirect interface to USB devices, allowing arbitrary USB commands to be sent to any connected USBdevice.

I2C and SPI — 2-wire and 4-wire buses for communicating betweenintegrated circuits on the same board — can be directly accessed viaspecial-purpose character devices. For I2C, the i2c-tools packageprovides a scriptable interface. For SPI there do not appear to beany packaged solutions, though the armbedded.eu web site providessome code that would be worth trying for anyone who is interested.

All the interfaces listed so far are always available, to sufficientlyprivileged processes, if the kernel knows about the target device atall. Other interfaces require the kernel to be explicitly instructedto export a low-level interface. In the case of GPIOs (general-purpose I/O pins) and power regulators, this is as simple as addingsome directives to the device-tree description of the hardware. Thedevices then appear in sysfs complete with attribute files allowingrelevant settings to be changed and values to be read.

Finally, and requiring even more in-kernel support, is the UIOframework, which is intended for devices that are accessed through memory-mapped deviceregisters, as is the norm for devices attached to PCI and similarbuses. A simple in-kernel device driver can be written using the UIOframework that allows a user-space program to map that register bankinto its own memory, and also to respond to interrupts from thedevice. This does not provide generic access to any PCI device, butdoes make it easy to get user-space access to a particular device ofinterest, so that the bulk of the driver can be developed, debugged,and maintained outside of the kernel.

This variety of different interface styles could be seen as ahodge-podge that is just crying out to be unified. On the other hand,different sorts of devices really are different and need differentsorts of interfaces. Part of the role of an operating system likeLinux is to hide as much of that difference as possible behinduniform abstractions. It should not be surprising that, if we want tobypass those abstractions and access the devices directly, we will beconfronted by the variety that Linux generally tries to hide.

Linux Port Devices Driver Updater

Downstream interfaces

Where upstream interfaces provide direct access to hardware,downstream interfaces allow a program to emulate some hardware and soprovide access to other programs that expect to use a particularsort of interface. Rather than just providing a different sort ofaccess to an already existing device, a downstream interface mustmake it possible to create a new device, configure it, and thenprovide whatever functionality is expected of that device type.

Probably the first driving force for these downstream interfaces wasthe introduction of networking and the consequent desire to allow aprogram on one computer to work with a device on another computer.With this came pseudo TTYs (PTYs), which are likely the oldestdownstream interface in Unix. They allow a TTY to be created on whicha user can log in and run programs that don't need to be aware thatthey are not attached to a physical terminal. The text entered caneasily come from anywhere on the network, and the output generated cango back to the same place (or elsewhere).

The desire for network access to storage brought about such things asnbd, the network block device, and NFS, the network file system.Their design differs from that of PTYs in that they don't just provide an interfaceto user space that a network service could use but, instead, create thenetwork connection themselves and define a protocol to carry the dataand control over that connection. The most likely reason for this isthat managing a storage service in a user-space program is prone todeadlocks. If the program ever needs to allocate memory, the kernelmight choose to free up memory by writing out to a storage device, andif that device is managed by the program allocating memory it couldeasily deadlock. It is much safer to bypass user space and senddirectly to the network.

These network protocols can still serve as downstream interfaces inthat they make it possible to instantiate a block device (with nbd)or a filesystem (with NFS) and provide services to it. This hasbeen used to good effect with automounting programs such as amd(subsequently renamed to am-utils) that present as an NFSfilesystem that contains only directories and symlinks (thus avoidingany deadlock issues) and transparently mounts filesystems when theyare first accessed.

Linux Port Devices Driver Windows 7

Though using NFS for this purpose is quite effective, it is not perfect;due to the limited possible interactions with the Linux virtual filesystemlayer, filesystems must be mounted somewhere else and the NFS filesystemonly contains a symbolic link to the real mount point. To address thisshortcoming, Linux provides a dedicated downstream interface for creatingfilesystems, autofs, whichsupports the extra interactions required to automount filesystems directly onto directories.

Similarly there is adownstream interface for writing filesystems that is careful about how itinterfaces with the page cache, and manages to avoid the writebackdeadlocks described above: FUSE.

Linux port devices driver windows 10

As part of FUSE there is CUSE, which allows characterdevices to be implemented in user space. There does not appear to bea corresponding 'BUSE' for implementing block devices in user space,though some years ago there was a proposalfor 'ABUSE' which aimed to do just that.Block devices can be implemented in user space on a remote machineusing nbd and presumably that is sufficient to meet most needs.

Networking plays a role in the next pair of examples too; the TUN andTAP drivers allow network devices to be emulated. TAP sends andreceives Ethernet frames, so any networking protocol can be used with aTAP device. TUN works at the IP level, which is simpler and oftensufficient providing there is no need to handle non-IP protocols suchas ARP. These can most obviously be used for tunneling and creatingvirtual private networks (VPNs) but could also be used for user-spacemonitoring and filtering of network traffic.

Network devices, block devices and character devices (which includeTTYs) cover all the device types that Unix supported before Linux camealong. Linux has added a variety of new device types, some of whichcan be implemented in user space.

The input subsystem provides a standard interface for input devicesuch as keyboards, mice, joysticks, touch pads, and similar devices.These are exposed to user space as character devices, so it might bepossible to emulate them using CUSE, but it is more convenient ifthey are integrated with the rest of the input subsystem, and that iswhat uinput allows. If a program opens /dev/uinput and issues someioctl() commands, a new input device is created. Events will bereported on that device when they are written to the file descriptoropened on /dev/uinput.

User-space LEDs — how and why

The latest addition to the collection of downstream interfaces isconceptually similar to uinput but it allows the emulation of LEDdevices rather than input devices. To support this functionality, itintroduces a new device called /dev/uleds.Opening this device and writing the name of a new device (zero-paddedto 64 bytes) will create an LED device with the given name.

Linux Port Devices Driver

There is no option to configure any other aspects of the LED, butthere is not much that could be configured anyway. A LED cangenerally indicate the number of brightness levels that it cansupport; LEDs created with uleds always support 256 brightnesslevels. Whenever the brightness is changed, a byte can be read whichreports the new level. An LED can also indicate that it knows how toblink so that, when needed, it can be given a single 'blink' requestrather than periodic 'on' and 'off' requests. A uleds device cannotbe used to experiment with this functionality, but it couldundoubtedly be added later using an ioctl() if a need was found.

The particular need that is driving the development of this interfaceby David Lechner is the desire to make two embedded systems compatiblewith one another. 'I would like to make a userspace programthat works the same on both devices.' If that program accessesan LED device directly, the device must appear to be present on bothsystems; where it isn't physically present it can now be emulated,possibly using a widget on a graphic display.

Linux Serial Port Device Driver Source Code

At much the same time Marcel Holtmann had been working on a similarinterface to allow the testing of LED triggers from the Bluetoothsubsystem. Various subsystems can be connected to a LED, using atrigger, to signal the current state of that subsystem. Without anLED device, it is hard to test those triggers. With the ability toemulate a LED device, that impediment to development need no longer exist.

The 4threvision of the user-space LEDs patch set was posted in mid-September andappears to have addressed all the issues that reviewers found. We canexpect the code to land in mainline for Linux 4.10. It seemsunlikely that this will be the last device type that someone will wantto emulate. Some devices, such as power regulators, seem sointimately related to hardware that it is hard to imagine an emulatorever being wanted. Others, like maybe a GPIO, might usefully beprovided with a downstream interface for emulation. Whether thereturns out to be a genuine need for that is something we will have towait to see.


Index entries for this article
KernelDevice drivers/In user space
GuestArticlesBrown, Neil

(Log in to post comments)



Comments are closed.