Documente Academic
Documente Profesional
Documente Cultură
Device Drivers, Part 12: USB Drivers in Linux Continued - LINUX For You
Subscribe to Print Edition Search
HOME
REVIEWS
HOW-TOS
CODING
INTERVIEWS
FEATURES
OVERVIEW
BLOGS
SERIES
IT ADMIN
Search for:
Search
The 12th part of the series on Linux device drivers takes you further along the path to writing your first USB driver in Linux a continuation from the previous article.
Pugs continued, Lets build upon the USB device driver coded in our previous session, using the same handy JetFlash pen drive from Transcend, with the vendor ID 0x058f and product ID 06387. For that, lets dig further into the USB protocol, and then convert our learning into code.
Follow
+2,490
www.linuxforu.com/2011/11/usb-drivers-in-linux-2/
1/7
8/13/13
Device Drivers, Part 12: USB Drivers in Linux Continued - LINUX For You
Find us on Facebook
Popular
Comments
Tag cloud
To be specific, the E :lines in the figure show examples of an interrupt endpoint of a UHCI Host Controller, and two bulk endpoints of the pen drive under consideration. Also, the endpoint numbers (in hex) are, respectively, 0 x 8 1 ,0 x 0 1and 0 x 8 2 the MSB of the first and third being 1 , indicating in endpoints, represented by ( I )in the figure; the second is an ( O )or out endpoint. M x P Sspecifies the maximum packet size, i.e., the data size that can be transferred in a single go. Again, as expected, for the interrupt endpoint, it is 2 ( < = 8 ) , and 6 4for the bulk endpoints. I v lspecifies the interval in milliseconds to be given between two consecutive data packet transfers for proper transfer, and is more significant for the interrupt endpoints.
class/category of this interface, the driver associated with this interface, and the number of endpoints under this interface. The interface class may or may not be the same as that of the device class. And depending on the number of endpoints, there would be as many Elines, details of which have already been discussed earlier. The * after the Cand Irepresents the currently active configuration and interface, respectively. The Pline provides the vendor ID, product ID, and the product revision. Slines are string descriptors showing up some vendor-specific descriptive information about the device. Peeping into cat / p r o c / b u s / u s b / d e v i c e sis good in order to figure out whether a device has been detected or not, and possibly to get the first-cut overview of the device. But most probably this information would be required to write the driver for the device as well. So, is there a way to access it using Ccode? Shweta asked.
www.linuxforu.com/2011/11/usb-drivers-in-linux-2/
2/7
8/13/13
Device Drivers, Part 12: USB Drivers in Linux Continued - LINUX For You
Yes, definitely; thats what I am going to tell you about, next. Do you remember that as soon as a USB device is plugged into the system, the USB host controller driver populates its information into the generic USB core layer? To be precise, it puts that into a set of structures embedded into one another, exactly as per the USB specifications, Pugs replied. The following are the exact data structures defined in < l i n u x / u s b . h > , ordered here in reverse, for flow clarity:
1 2 3 4 5 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8 2 9 3 0 s t r u c tu s b _ d e v i c e { s t r u c tu s b _ d e v i c e _ d e s c r i p t o rd e s c r i p t o r ; s t r u c tu s b _ h o s t _ c o n f i g* c o n f i g ,* a c t c o n f i g ; } ; s t r u c tu s b _ h o s t _ c o n f i g { s t r u c tu s b _ c o n f i g _ d e s c r i p t o rd e s c ; s t r u c tu s b _ i n t e r f a c e* i n t e r f a c e [ U S B _ M A X I N T E R F A C E S ] ; } ; s t r u c tu s b _ i n t e r f a c e { s t r u c tu s b _ h o s t _ i n t e r f a c e* a l t s e t t i n g/ *a r r a y* / ,* c u r _ a l t s e t t i n g ; } ; s t r u c tu s b _ h o s t _ i n t e r f a c e { s t r u c tu s b _ i n t e r f a c e _ d e s c r i p t o rd e s c ; s t r u c tu s b _ h o s t _ e n d p o i n t* e n d p o i n t/ *a r r a y* / ; } ; s t r u c tu s b _ h o s t _ e n d p o i n t { s t r u c tu s b _ e n d p o i n t _ d e s c r i p t o rd e s c ; } ;
So, with access to the s t r u c tu s b _ d e v i c ehandle for a specific device, all the USB-specific information about the device can be decoded, as shown through the / p r o cwindow. But how does one get the device handle? In fact, the device handle is not available directly in a driver; rather, the per-interface handles (pointers to s t r u c tu s b _ i n t e r f a c e ) are available, as USB drivers are written for device interfaces rather than the device as a whole. Recall that the probe and disconnect callbacks, which are invoked by the USB core for every interface of the registered device, have the corresponding interface handle as their first parameter. Refer to the prototypes below:
i n t( * p r o b e ) ( s t r u c tu s b _ i n t e r f a c e* i n t e r f a c e ,c o n s ts t r u c tu s b _ d e v i c e _ i d* i d ) ; v o i d( * d i s c o n n e c t ) ( s t r u c tu s b _ i n t e r f a c e* i n t e r f a c e ) ;
So, with the interface pointer, all information about the corresponding interface can be accessed and to get the container device handle, the following macro comes to the rescue:
s t r u c tu s b _ d e v i c ed e v i c e=i n t e r f a c e _ t o _ u s b d e v ( i n t e r f a c e ) ;
Adding this new learning into last months registration-only driver gets the following code listing (p e n _ i n f o . c ):
1 2 3 4 5 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8 2 9 3 0 3 1 3 2 3 3 # i n c l u d e< l i n u x / m o d u l e . h > # i n c l u d e< l i n u x / k e r n e l . h > # i n c l u d e< l i n u x / u s b . h > s t a t i cs t r u c tu s b _ d e v i c e* d e v i c e ; s t a t i ci n tp e n _ p r o b e ( s t r u c tu s b _ i n t e r f a c e* i n t e r f a c e ,c o n s ts t r u c tu s b _ d e v i c e _ i d* i d ) { s t r u c tu s b _ h o s t _ i n t e r f a c e* i f a c e _ d e s c ; s t r u c tu s b _ e n d p o i n t _ d e s c r i p t o r* e n d p o i n t ; i n ti ; i f a c e _ d e s c=i n t e r f a c e > c u r _ a l t s e t t i n g ; p r i n t k ( K E R N _ I N F O" P e ni / f% dn o wp r o b e d :( % 0 4 X : % 0 4 X ) \ n " , i f a c e _ d e s c > d e s c . b I n t e r f a c e N u m b e r ,i d > i d V e n d o r ,i d > i d P r o d u c t ) ; p r i n t k ( K E R N _ I N F O" I D > b N u m E n d p o i n t s :% 0 2 X \ n " , i f a c e _ d e s c > d e s c . b N u m E n d p o i n t s ) ; p r i n t k ( K E R N _ I N F O" I D > b I n t e r f a c e C l a s s :% 0 2 X \ n " , i f a c e _ d e s c > d e s c . b I n t e r f a c e C l a s s ) ; f o r( i=0 ;i<i f a c e _ d e s c > d e s c . b N u m E n d p o i n t s ;i + + ) { e n d p o i n t=& i f a c e _ d e s c > e n d p o i n t [ i ] . d e s c ; p r i n t k ( K E R N _ I N F O" E D [ % d ] > b E n d p o i n t A d d r e s s :0 x % 0 2 X \ n " , i ,e n d p o i n t > b E n d p o i n t A d d r e s s ) ; p r i n t k ( K E R N _ I N F O" E D [ % d ] > b m A t t r i b u t e s :0 x % 0 2 X \ n " , i ,e n d p o i n t > b m A t t r i b u t e s ) ; p r i n t k ( K E R N _ I N F O" E D [ % d ] > w M a x P a c k e t S i z e :0 x % 0 4 X( % d ) \ n " , i ,e n d p o i n t > w M a x P a c k e t S i z e ,e n d p o i n t > w M a x P a c k e t S i z e ) ;
d e v i c e=i n t e r f a c e _ t o _ u s b d e v ( i n t e r f a c e ) ;
www.linuxforu.com/2011/11/usb-drivers-in-linux-2/
3/7
8/13/13
3 4 3 5 3 6 3 7 3 8 3 9 4 0 4 1 4 2 4 3 4 4 4 5 4 6 4 7 4 8 4 9 5 0 5 1 5 2 5 3 5 4 5 5 5 6 5 7 5 8 5 9 6 0 6 1 6 2 6 3 6 4 6 5 6 6 6 7 6 8 6 9 7 0 7 1 7 2 7 3 } r e t u r n0 ;
Device Drivers, Part 12: USB Drivers in Linux Continued - LINUX For You
s t a t i cv o i dp e n _ d i s c o n n e c t ( s t r u c tu s b _ i n t e r f a c e* i n t e r f a c e ) { p r i n t k ( K E R N _ I N F O" P e ni / f% dn o wd i s c o n n e c t e d \ n " , i n t e r f a c e > c u r _ a l t s e t t i n g > d e s c . b I n t e r f a c e N u m b e r ) ; } s t a t i cs t r u c tu s b _ d e v i c e _ i dp e n _ t a b l e [ ]= { {U S B _ D E V I C E ( 0 x 0 5 8 F ,0 x 6 3 8 7 )} , { }/ *T e r m i n a t i n ge n t r y* / } ; M O D U L E _ D E V I C E _ T A B L E( u s b ,p e n _ t a b l e ) ; s t a t i cs t r u c tu s b _ d r i v e rp e n _ d r i v e r= { . n a m e=" p e n _ d r i v e r " , . p r o b e=p e n _ p r o b e , . d i s c o n n e c t=p e n _ d i s c o n n e c t , . i d _ t a b l e=p e n _ t a b l e , } ; s t a t i ci n t_ _ i n i tp e n _ i n i t ( v o i d ) { r e t u r nu s b _ r e g i s t e r ( & p e n _ d r i v e r ) ; } s t a t i cv o i d_ _ e x i tp e n _ e x i t ( v o i d ) { u s b _ d e r e g i s t e r ( & p e n _ d r i v e r ) ; } m o d u l e _ i n i t ( p e n _ i n i t ) ; m o d u l e _ e x i t ( p e n _ e x i t ) ; M O D U L E _ L I C E N S E ( " G P L " ) ; M O D U L E _ A U T H O R ( " A n i lK u m a rP u g a l i a< e m a i l @ s a r i k a p u g s . c o m > " ) ; M O D U L E _ D E S C R I P T I O N ( " U S BP e nI n f oD r i v e r " ) ;
Then, the usual steps for any Linux device driver may be repeated, along with the pen drive steps: Build the driver (p e n _ i n f o . k ofile) by running make. Load the driver using i n s m o dp e n _ i n f o . k o . Plug in the pen drive (after making sure that the usb-storage driver is not already loaded). Unplug the pen drive. Check the output of d m e s gfor the logs. Unload the driver using r m m o dp e n _ i n f o . Figure 2 shows a snippet of the above steps on Pugs system. Remember to ensure (in the output of c a t/ p r o c / b u s / u s b / d e v i c e s ) that the usual u s b s t o r a g edriver is not the one associated with the pen drive interface, but rather the p e n _ i n f odriver.
Summing up
Before taking another break, Pugs shared two of the many mechanisms for a driver to specify its
www.linuxforu.com/2011/11/usb-drivers-in-linux-2/
4/7
8/13/13
Device Drivers, Part 12: USB Drivers in Linux Continued - LINUX For You
device to the USB core, using the s t r u c tu s b _ d e v i c e _ i dtable. The first one is by specifying the < v e n d o ri d ,p r o d u c ti d >pair using the U S B _ D E V I C E ( )macro (as done above). The second one is by specifying the device class/category using the U S B _ D E V I C E _ I N F O ( )macro. In fact, many more macros are available in < l i n u x / u s b . h >for various combinations. Moreover, multiple of these macros could be specified in the u s b _ d e v i c e _ i dtable (terminated by a null entry), for matching with any one of the criteria, enabling to write a single driver for possibly many devices. Earlier, you mentioned writing multiple drivers for a single device, as well. Basically, how do we selectively register or not register a particular interface of a USB device?, queried Shweta. Sure. Thats next in line of our discussion, along with the ultimate task in any device driver the data-transfer mechanisms, replied Pugs.
Related Posts:
Device Drivers, Part 11: USB Drivers in Linux Device Drivers, Part 13: Data Transfer to and from USB Devices Device Drivers, Part 6: Decoding Character Device File Operations Device Drivers, Part 5: Character Device Files Creation & Operations Device Drivers, Part 4: Linux Character Drivers
Tags: LFY November 2011, linux device drivers, Linux Device Drivers Series, mass storage devices, serial ports, usb device driver, usb devices, USB host controller driver, usb protocol
Previous Post
Next Post
Share
18 days ago
how to know the functions pen_probe,pen_disconnect (where these functions available and how to find the headder files)
Reply
Share
aadhirai
2 months ago
I have tried the code in Part 11 which was working for me. Here I am not getting the /dev/pen0 listed on my system (Linux Ubuntu 12.04), even when I copy paste the code from here.... compiled & followed all your steps accordingly.. Will you please help me in completing this ?
1
Reply
Share
David
3 months ago
Its Fantastic !! Thank you for your valuable Linux device driver articles.
www.linuxforu.com/2011/11/usb-drivers-in-linux-2/
5/7
8/13/13
anil_pugalia
Device Drivers, Part 12: USB Drivers in Linux Continued - LINUX For You
> David
2 months ago
I doubt, if it would be possible, as currently doing the same for mathematics in open source.
Reply
Share
ME LW IN JOS E
7 months ago
I got an error when i tried to remove the "usb_storage" melwin-Satellite-L640 USB_2 # rmmod usb_storage ERROR: Module usb_storage is in use by ums_realtek Here is the output for "lsusb" Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 001 Device 002: ID 8087:0020 Intel Corp. Integrated Rate Matching Hub Bus 002 Device 002: ID 8087:0020 Intel Corp. Integrated Rate Matching Hub Bus 002 Device 005: ID 0930:0214 Toshiba Corp. Bus 002 Device 006: ID 04f2:b1d6 Chicony Electronics Co., Ltd
Reply Share
ME LW IN JOS E
7 months ago
MenDuong
8 months ago
Dear, When I pug and unplug my USB driver. I can't see message in dmesg as above. My dmesg as follow: SELinux: initialized (dev sdd1, type vfat), uses genfs_contexts usb 2-1: USB disconnect, address 5 SELinux: initialized (dev sdb4, type fuseblk), uses genfs_contexts lo: Disabled Privacy Extensions SELinux: initialized (dev proc, type proc), uses genfs_contexts lo: Disabled Privacy Extensions SELinux: initialized (dev proc, type proc), uses genfs_contexts lo: Disabled Privacy Extensions SELinux: initialized (dev proc, type proc), uses genfs_contexts
see more
Reply
Share
anil_pugalia
> MenDuong
Share
8 months ago
Because the usb-storage driver is loaded. You need to make sure that is unloaded, as mentioned in the article.
Reply
MenDuong
> anil_pugalia
Share
8 months ago
> MenDuong
Reply
7 months ago
anil_pugalia
> MenDuong
8 months ago
If it is listed in lsmod, just do a "rmmod usb-storage". Otherwise, you'd have to recompile your kernel, by making usb-storage as a module.
2
Reply
Share
www.linuxforu.com/2011/11/usb-drivers-in-linux-2/
6/7
8/13/13
Device Drivers, Part 12: USB Drivers in Linux Continued - LINUX For You
C o m m e n t fe e d
Su b s cri b e vi a e m a i l
Reviews
How-Tos
Coding
Interviews
Features
Overview
Blogs
Search
Popular tags
Linux , ubuntu, Java, MySQL, Google, python, Fedora, Android, PHP, C, html, w eb applications , India, Microsoft, unix , Window s , Red Hat, Oracle, Security , Apache, xml, LFY April 2012, FOSS, GNOME, http, JavaScript, LFY June 2011, open source, RAM, operating systems
All published articles are released under Creative Commons Attribution-NonCommercial 3.0 Unported License, unless otherw ise noted. LINUX For You is pow ered by WordPress, w hich gladly sits on top of a CentOS-based LEMP stack.
www.linuxforu.com/2011/11/usb-drivers-in-linux-2/
7/7