The USB Serial Driver Layer
In my last column [see LJ December 2002], we covered the serial layer in the 2.5 (hopefully soon to be 2.6) kernel tree. We mentioned in passing that a USB-to-serial driver layer in the kernel helps out in working with those types of device drivers. This time we discuss that layer in more depth.
A long time ago (in kernel development time, at least), a single USB-to-serial device driver was written and accepted into the kernel tree. It barely worked for one type of device and didn't work at all on SMP machines. As no standard USB-to-serial protocol existed, all devices used a custom protocol created by the individual vendors. The reason why there is no standard protocol is a long and sordid story; check the archives of the linux-usb-devel mailing list for the details. Soon a second type of USB-to-serial device was implemented within the first driver, sharing the reserved major and minor numbers. Over time, more and more devices were added to the driver until it was becoming an unwieldy mess. With the help of Peter Berger and Al Borchers, the original author of the driver rewrote the infrastructure and created what is now known as the USB-to-serial layer. This bit of code allows different USB-to-serial drivers to be written with a minimal amount of code, all sharing the same major and minor number range. It insulates the individual drivers from some of the complexity in the tty layer and the USB layer. It also allows the drivers to be compiled as individual modules and loaded only when they are needed.
In the 2.5 development cycle, the serial layer was created in order to provide an easier way to write serial port drivers, so as not to have to deal with the tty layer directly. Hopefully, someday the USB and serial layers will be merged. Both maintainers want to see this happen, but they do not have the time to do it. (They would gladly accept patches to accomplish this, if someone is looking for a project.)
In this article we cover the basics of the USB-to-serial layer, detailing how to register and unregister a driver and how to set up the main structures needed for a driver.
All of the code and examples in this article are for the 2.5/2.6 kernel tree. The 2.4 and 2.2 kernel trees also support USB-to-serial drivers, but their interfaces are a bit different in places. For ease of use, we focus on only one kernel tree. If you have any problems porting a USB-to-serial driver to these older trees (once it is running on 2.5), please let me know.
To register a USB-to-serial driver with the kernel, the driver has to do two things: register with the USB-to-serial core and register with the USB core. Registering with the USB-to-serial core tells it to call your driver when new devices are found by the USB subsystem, and registering with the USB core is needed to tell it what kind of devices your driver can accept.
To register with the USB core, all you need is a list of USB devices that your driver will work for, in traditional USB device ID format:
static struct usb_device_id id_table [] = {
{USB_DEVICE(MY_PRODUCT_ID, MY_DEVICE_ID)},
{} /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, id_table);
This table is needed so the USB core knows what devices the driver can accept and the user-space hot-plug code knows what kind of devices are used. See my article “How the PCI Hot Plug Driver Filesystem Works”, LJ May 2002, for more information about this table and how the hot-plug code uses it.
Then, a simple USB device-driver structure is created with this ID information:
static struct usb_driver tiny_driver = {
.name = "tiny",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
};
The .probe and .disconnect fields must be set to point to the USB serial core's functions because that type of logic is handled by it and not by your driver.
Then, a simple call registers this driver with the USB core:
usb_register (&tiny_driver);
After this, the USB serial driver must be notified of the driver with a call to:
usb_serial_register (&tiny_device);This function takes a pointer to a struct usb_serial_driver_type, which will be explained in the following section.
To unregister a driver, the same steps have to happen, but in reverse order. First, we unregister with the USB serial core:
usb_serial_unregister (&tiny_device);
Then, we unregister with the USB core:
usb_unregister (&tiny_driver);
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Sponsored by AMD
Built-in forensics, incident response, and security with Red Hat Enterprise Linux 6
Every security policy provides guidance and requirements for ensuring adequate protection of information and data, as well as high-level technical and administrative security requirements for a system in a given environment. Traditionally, providing security for a system focuses on the confidentiality of the information on it. However, protecting the data integrity and system and data availability is just as important. For example, when processing United States intelligence information, there are three attributes that require protection: confidentiality, integrity, and availability.
Learn more about catching the bad guy in this free white paper.
Sponsored by DLT Solutions
| Dynamic DNS—an Object Lesson in Problem Solving | May 21, 2013 |
| Using Salt Stack and Vagrant for Drupal Development | May 20, 2013 |
| Making Linux and Android Get Along (It's Not as Hard as It Sounds) | May 16, 2013 |
| Drupal Is a Framework: Why Everyone Needs to Understand This | May 15, 2013 |
| Home, My Backup Data Center | May 13, 2013 |
| Non-Linux FOSS: Seashore | May 10, 2013 |
- Dynamic DNS—an Object Lesson in Problem Solving
- Making Linux and Android Get Along (It's Not as Hard as It Sounds)
- Using Salt Stack and Vagrant for Drupal Development
- New Products
- A Topic for Discussion - Open Source Feature-Richness?
- RSS Feeds
- Drupal Is a Framework: Why Everyone Needs to Understand This
- Validate an E-Mail Address with PHP, the Right Way
- Readers' Choice Awards
- Tech Tip: Really Simple HTTP Server with Python
- Reply to comment | Linux Journal
24 min 8 sec ago - All the articles you talked
2 hours 47 min ago - All the articles you talked
2 hours 50 min ago - All the articles you talked
2 hours 52 min ago - myip
7 hours 16 min ago - Keeping track of IP address
9 hours 7 min ago - Roll your own dynamic dns
14 hours 21 min ago - Please correct the URL for Salt Stack's web site
17 hours 32 min ago - Android is Linux -- why no better inter-operation
19 hours 48 min ago - Connecting Android device to desktop Linux via USB
20 hours 16 min ago




Comments
Interesting article, when
Interesting article, when searching for Linux compatible USB serial adapters
this is a good source.