HOW TO WRITE USB DEVICE DRIVERS BY OLANREWAJU AYO 111204

Reviews
Shared by: hermanos
Stats
views:
34
rating:
not rated
reviews:
0
posted:
11/15/2008
language:
pages:
0
HOW TO WRITE USB DEVICE DRIVERS BY OLANREWAJU AYO 11/12/04 Executive Summary • Purpose and Scope: The purpose and scope of this document is to explain the importance and highlight the procedures involved in communicating with highspeed/low-speed Universal Serial Bus (USB) devices connected to a host computer using USB drivers. • Methods: The two main software approaches are undertaken throughout the course of this document. The two main methods used in communicating with USB devices are the Kernel-level approach and the User-level approach. Codes are implemented in C programming language. • Results: A working interface between a USB device and the host computer. The device should be able to communicate effectively with the host. • Conclusion: Intermediate procedures are involved in writing a USB driver for a device. Depending on the availability of the device protocol or documentation from the manufacturer. This is a very crucial part that determines how much time to be spent in writing the driver for the device. • Recommendations: User space device drivers are generally easier to write and debug than kernel space device drivers. People with very little experience in device programming should go the User-space approach which uses functions in a standard library and runs in user space, instead of kernel space. User space driver development can also be implemented using any programming language. Kernel space is much difficult to debug and can cause crashing of the system kernel. An Introduction to Device Drivers The device driver is a very crucial part in providing an interface for a device and the system or host. It is also important to know about device drivers as a system will not function without them. The device I would be providing a step by step overview on how to write a driver for is a Stellar-Net spectrometer. This device originally works only on windows platform and our goal is to provide an interface for it to function properly on the Linux platform. Two main approaches were considered in the course of my research. The first approach is writing the driver using the user-space for the system. This approach is a much simpler method because it completely isolates the system Kernel; it prevents any problems with debugging of the code and requires less coding. The second approach is writing the entire driver right from the kernel-level. When kernel codes are written, one must be conscious of ensuring that access is given to hardware capabilities without adding any constraints. Kernel level drivers are much more difficult to write and should be used only if it is very necessary. A user-level approach was used in writing the driver for the spectrometer device. A step by step approach used to the current status of my goal will be shown in the subsequent sections. Writing USB-device drivers One of the problems encountered during the course of my research was the availability of the documentation of the device. I needed to know how and what kind of communication occurring between the device and host at run-time. Since this was not provided by the manufactures, I decided to use other methods to obtain the protocol for the device. I had to do some reverse engineer the windows USB device for the purpose of creating a compatible device driver. • Reverse Engineering of the spectrometer: this was achieved by using one of the many windows-sniff software out there. They can be downloaded for free on several websites. I used the Snoopy Pro software. In deciding the type of sniffing software to use, one must choose the ones with noise filtering capabilities to allow easier decoding of the log. This software logs all the activities between a device and the host computer when the device is attached to the USB port. The following figure shows a portion of the log obtained using snoopy pro. [0 ms] UsbSnoop compiled on Jan 18 2003 22:41:32 loading [0 ms] UsbSnoop - DriverEntry(f8898c40) : Windows NT WDM version 1.32 [21 ms] UsbSnoop - AddDevice(f8898f50) : DriverObject 81d61248, pdo 81d88030 [21 ms] UsbSnoop - DispatchAny(f8896610) : IRP_MJ_PNP (0x00000018) [21 ms] UsbSnoop - MyDispatchPNP(f8898ee0) : IRP_MJ_PNP (0x00000018) [41 ms] UsbSnoop - DispatchAny(f8896610) : IRP_MJ_PNP (IRP_MN_QUERY_RESOURCE_REQUIREMENTS) [41 ms] UsbSnoop - MyDispatchPNP(f8898ee0) : IRP_MJ_PNP (IRP_MN_QUERY_RESOURCE_REQUIREMENTS) [41 ms] UsbSnoop - DispatchAny(f8896610) : IRP_MJ_PNP (IRP_MN_FILTER_RESOURCE_REQUIREMENTS) [41 ms] UsbSnoop - MyDispatchPNP(f8898ee0) : IRP_MJ_PNP (IRP_MN_FILTER_RESOURCE_REQUIREMENTS) [99 ms] UsbSnoop - DispatchAny(f8896610) : IRP_MJ_PNP (IRP_MN_START_DEVICE) [99 ms] UsbSnoop - MyDispatchPNP(f8898ee0) : IRP_MJ_PNP (IRP_MN_START_DEVICE) [99 ms] UsbSnoop - DispatchAny(f8896610) : IRP_MJ_INTERNAL_DEVICE_CONTROL [99 ms] UsbSnoop - MyDispatchInternalIOCTL(f8897e80) : fdo=81d88030, Irp=81e91cc0, IRQL=0 [99 ms] >>> URB 1 going down >>> -- URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE: TransferBufferLength = 00000012 TransferBuffer = 81ed2930 TransferBufferMDL = 00000000 Index = 00000000 DescriptorType = 00000001 (USB_DEVICE_DESCRIPTOR_TYPE) LanguageId = 00000000 [99 ms] UsbSnoop - DispatchAny(f8896610) : IRP_MJ_SYSTEM_CONTROL [103 ms] UsbSnoop - MyInternalIOCTLCompletion(f8897db0) : fido=00000000, Irp=81e91cc0, Context=81eaa260, IRQL=2 [103 ms] <<< URB 1 coming back <<< -- URB_FUNCTION_CONTROL_TRANSFER: PipeHandle = 81e88118 TransferFlags = 0000000b (USBD_TRANSFER_DIRECTION_IN, USBD_SHORT_TRANSFER_OK) TransferBufferLength = 00000012 TransferBuffer = 81ed2930 TransferBufferMDL = 81e8d148 00000000: 12 01 00 02 00 00 00 40 d7 0b 12 a0 00 00 01 02 00000010: 00 01 UrbLink = 00000000 SetupPacket = 00000000: 80 06 00 01 00 00 12 00 [103 ms] UsbSnoop - DispatchAny(f8896610) : IRP_MJ_INTERNAL_DEVICE_CONTROL [103 ms] UsbSnoop - MyDispatchInternalIOCTL(f8897e80) : fdo=81d88030, Irp=81e91cc0, IRQL=0 [103 ms] >>> URB 2 going down >>> -- URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE: TransferBufferLength = 00000009 TransferBuffer = f89858a8 TransferBufferMDL = 00000000 Index = 00000000 DescriptorType = 00000002 (USB_CONFIGURATION_DESCRIPTOR_TYPE) LanguageId = 00000000 Figure 1. Result from using Snoopy Pro. The next phase of this step involves decoding this log in order to implement it in userlevel codes. This can be attempted by reading the documentation for the software used in sniffing the commands, so as to tell you what the terms translates to in codes. This is just a log and only gives you the process of communication between the device and the host. Much of the work now lies in decoding it. • Coding the device driver: Now during coding, one must use the information specific to the device which was obtained from the step above. It should be used to identify the device, before any processing can be done. Since I was implementing my device driver in user-space, I had to include a standard library called libusb (standard Linux USB library) which contains all the function calls used in the body of my code. This library is supported by later kernel versions (version 2.0 and greater), so I had to download it on the operating system I was using. Figure below shows a skeleton of the code for the device driver. Some functions used will be explained later. //Before you can communicate with any devices, you need to find the device you want to //talk to. This is accomplished by finding all of the busses and then finding all of the //devices on all of the busses: //in the main function do the ffg; struct usb_bus *busses; //pointer to library function usb_bus usb_init(); //initialize the usb device library usb_find_busses(); //find all the busses on system usb_find_devices(); //find the devices attached busses = usb_get_busses(); // return number of busses found // After this, you manually loop through all of the busess and all of the devices and //matching the device by whatever criteria needed: struct usb_bus *bus; for (bus = busses; bus; bus = bus->next) { struct usb_device *dev; for (dev = bus->devices; dev; dev = dev->next) { if (dev->descriptor.idVendor ==0xbd7 && dev- >descriptor.idProduct==0xa012) { /* Open the device and do your processing */ } } } descriptor.idVendor and descriptor.idProduct are the product and vendor id’s of the device which can be obtained in the log from the windows Snoop Pro. Figure 2. Skeleton of device driver code. The complete documentation on using libusb functions can be found by going to Linux websites and searching for keyword libusb. Alternatively one, can acces it by going to the man page for kernel version 2.6.0 (http://www.stillhq.com/linux/mandocs/2.6.0test3/index.html). One should try to read and understand how USB devices work before attempting to do any coding.The following websites was very useful during the course of my research on how to write USB drivers: http://www.beyondlogic.org/usbnutshell/usb1.htm, http://libusb.sourceforge.net/doc/.

Related docs
USB in a Nutshwell
Views: 247  |  Downloads: 44
How to Write a Device Driver
Views: 16  |  Downloads: 6
USB EasyCap DC60 Video Capture
Views: 294  |  Downloads: 1
Benefits of USB Device Connectivity
Views: 72  |  Downloads: 4
USB Host Drivers Installation Manual
Views: 0  |  Downloads: 0
USB_mass_storage_device_class
Views: 5  |  Downloads: 2
Thorough Static Analysis of Device Drivers
Views: 26  |  Downloads: 5
How to write a Device Driver in FreeBSD
Views: 9  |  Downloads: 3
Get rid of old device drivers hidden in Vista
Views: 26  |  Downloads: 0
Disable USB Drives
Views: 29  |  Downloads: 4
LINUX DEVICE DRIVERS
Views: 15  |  Downloads: 2
How to disable Usb port
Views: 99  |  Downloads: 1
premium docs
Other docs by hermanos