Speed speed speed! Hacking USB Gadget serial driver


The latest task for me using ARM9 devboard was to try to start USB slave device in the board. Since I was using Linux kernel 2.6.29.1, I have searched for the solution for starting devboard as a slave device using USB and the solution was found using USB Gadget device as it offers USB device as ethernet device, serial device or mass storage device, so I have chosen using communication via serial port, because it is easy to read and write data and also there are Windows drivers for it.

The kernel recompilation was easy, go to Device Drivers->USB support->USB Gadget Support and add required options:
Kernel config USB Gadget
Driver created me /dev/ttyGS0 device, that allowed to read and write like a simple serial device, but the problem was slow speed of the device as it was working only at 9600bps baud rate, so I had to modify the kernel source of the device, which is in linux-2.6.xx/drivers/usb/gadget/u_serial.c and make it to run at the maximum speed. So I went to termios specifications and found that it is possible to run serial device at 4mbps, but the maximum speed of Windows Hyper Terminal allowed 921600bps baud rate and that was enough for me. The little patch file code is provided here:

1091,1093c1091,1093
< B9600 | CS8 | CREAD | HUPCL | CLOCAL;
< gs_tty_driver->init_termios.c_ispeed = 9600;
< gs_tty_driver->init_termios.c_ospeed = 9600;
---
> B921600 | CS8 | CREAD | HUPCL | CLOCAL;
> gs_tty_driver->init_termios.c_ispeed = 921600;
> gs_tty_driver->init_termios.c_ospeed = 921600;
1095c1095
< coding.dwDTERate = __constant_cpu_to_le32(9600);
---
> coding.dwDTERate = __constant_cpu_to_le32(921600);

The next problem was Windows driver extraction and installation. Firstly, the sys file for the driver can be found in C:\WINDOWS\Driver Cache\i386\driver.cab archive and you have to extract it using this command: expand C:\WINDOWS\Driver~1\i386\driver.cab -F:usbser.sys .
The dot in the end shows the current directory, so it is needed for extraction. If you have installed Service Pack, then the driver can be found in C:\WINDOWS\Driver Cache\i386\sp2.cab or sp3.cab. Later, put the gserial.inf file in the same directory as usbser.sys with this content inside the file:

[Version]
Signature="$Windows NT$"
Class=Ports
ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318}
Provider=%LINUX%
DriverVer=08/17/2004,0.0.2.0
[Manufacturer]
%LINUX%=GSerialDeviceList
[GSerialDeviceList]
%GSERIAL%=GSerialInstall, USB\VID_0525&PID_A4A7
[DestinationDirs]
DefaultDestDir=10,System32\Drivers
[GSerialInstall]
CopyFiles=GSerialCopyFiles
AddReg=GSerialAddReg
[GSerialCopyFiles]
usbser.sys
[GSerialAddReg]
HKR,,DevLoader,,*ntkern
HKR,,NTMPDriver,,usbser.sys
HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"
[GSerialInstall.Services]
AddService = usbser,0x0002,GSerialService
[GSerialService]
DisplayName = %GSERIAL_DISPLAY_NAME%
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
ServiceBinary = %10%\System32\Drivers\usbser.sys
LoadOrderGroup = Base
[Strings]
LINUX = "Linux"
GSERIAL = "Gadget Serial"
GSERIAL_DISPLAY_NAME = "USB Gadget Serial Driver"

The device should be found as soon as you plug in the device and start working after driver installation. You should see new serial port device in the device manager (I found COM3).

References:
http://docs.blackfin.uclinux.org/kernel/generated/gadget.pdf
http://www.mjmwired.net/kernel/Documentation/usb/gadget_serial.txt
http://www.linux-usb.org/

  1. No comments yet.
(will not be published)