Fix for USB under linux

mick-eng wrote on Wednesday, June 25, 2008:


I’m playing with the usb serial port code from FreeRTOS V5.0.2 / lwIP_Demo_Rowley_ARM7 and I think there’s a couple of things in the descriptors.h which might be improved.

The serial port can be made to work with linux if you change the value of the interface protocol (the comment is bInterfaceProtocol) in the config descriptor (pxConfigDescriptor) to something valid.  It has a value of 0, which I don’t think the spec allows.  By making it 1, linux will work.  In ubuntu, my device is now available as a serial port named /dev/ttyACM0 .  Windows is unaffected, except that you might have to reinstall the driver if you’ve used the old value.

That is, change the value in descriptors.h line 117 from: 0x00  to 0x01 .

Also, I think the values for the vendor id and product id are confusing.  The atmel USB vendor id is 0x03EB.  In descriptors.h and the FreeRTOSCDC.inf for windows this value has the wrong byte order.  This will work fine for the demo, but its confusing as an example (if you did mean to use the atmel vendor id).


Mick D

— C:/FreeRTOSV5.0.2-orig/Demo/lwIP_Demo_Rowley_ARM7/USB/descriptors.h    Fri May 30 16:27:00 2008
+++ C:/FreeRTOSV5.0.2/Demo/lwIP_Demo_Rowley_ARM7/USB/descriptors.h    Wed Jun 25 11:47:19 2008
@@ -114,8 +114,8 @@
     0x00,                                /* bDeviceSubclass:        */
     0x00,                                /* bDeviceProtocol:        */
     0x08,                                /* bMaxPacketSize0        */
-    0x03, 0xEB,                            /* idVendorL            */
-    0x20, 0x09,                            /* idProductL            */
+    0xEB, 0x03,                            /* idVendorL            */
+    0x09, 0x20,                            /* idProductL            */
     0x10, 0x01,                            /* bcdDeviceL            */
     usbMANUFACTURER_STRING,              /* iManufacturer        */
     usbPRODUCT_STRING,                    /* iProduct                */
@@ -148,7 +148,7 @@
     0x01,                /* bNumEndpoints                        */
     0x02,                /* bInterfaceClass: Comm Interface Class */
     0x02,                /* bInterfaceSubclass: Abstract Control Model*/
-    0x00,                /* bInterfaceProtocol                    */
+    0x01,                /* bInterfaceProtocol                    */
     usbINTERFACE_STRING,/* iInterface                            */

     /* Header Functional Descriptor                                */

rtel wrote on Wednesday, June 25, 2008:

Excellent information - thanks.  I’m updating the SVN repository now.


chaalar wrote on Wednesday, June 25, 2008:

FYI, by making this change device will not be seen as a usb-serial device so
it is not possible to use serial console programs like minicom. Instead
one can change bmCapabilities field in call management functional descriptor
to 0x01(originally it is 0x00). So it will be possible to use serial
emulation programs with the device, at least this is what I’m doing.


rtel wrote on Wednesday, June 25, 2008:

So you are saying its best to leave bInterfaceProtocol as 0, and change bInterfaceProtocol to 1 instead.  Can somebody verify that this will work under Linux too?


chaalar wrote on Wednesday, June 25, 2008:

Both yes and no. If you were meant to say bmCapabilities in the place second of bInterfaceProtocol in your second, then yes. I’ve tested this on SUSE and it’s working with usbserial module. To test driver someone can try these as root after plugging device.

$modprobe usbserial vendor=0xeb03 product=0x0920
$minicom -s

then write /dev/ttyUSB0 under Serial Port Setup->Serial Device and click ESC twice. It should work.


mick-eng wrote on Thursday, June 26, 2008:

I’ve tried this and can’t get it to work, for ubuntu hardy at least.  If I understand you correctly, then compared to the freertos source, there’s only 1 change. bmCapabilities = 0x01 for the call management interface in descriptors.h .  My patch is below.  /dev/ttyUSB0 shows up after I use the modprobe command, but minicom seems to hang when sending to it, even running as root.

I tried minicom with my previous patch, and it worked with /dev/ACM0 ok.


— FreeRTOSV5.0.2-orig/Demo/lwIP_Demo_Rowley_ARM7/USB/descriptors.h    2008-05-30 16:27:00 +0800
+++ FreeRTOSV5.0.2/Demo/lwIP_Demo_Rowley_ARM7/USB/descriptors.h    2008-06-26 14:11:31 +0800
@@ -175,7 +175,7 @@
     0x05,                /* bFunctionLength                        */
     0x24,                /* bDescriptor type: CS_INTERFACE        */
     0x01,                /* bDescriptor subtype: Call Management Func*/
-    0x00,                /* bmCapabilities: D1 + D0                */
+    0x01,                /* bmCapabilities: D1 + D0                */
     0x01,                /* bDataInterface: Data Class Interface 1*/

     /* CDC Control - Endpoint 3 descriptor

chaalar wrote on Thursday, June 26, 2008:

You are right, your solution is working with minicom also. Both methods are working for me.


ben_fnr wrote on Thursday, June 26, 2008:

I have used LPCUSB on a NXP lpc2368 and it sets both bInterfaceProtocol and bmCapabilities to a 1. It works fine for me in Ubuntu using minicom.

// device descriptor
    LE_WORD(0x0101),            // bcdUSB
    0x02,                        // bDeviceClass
    0x00,                        // bDeviceSubClass
    0x00,                        // bDeviceProtocol
    MAX_PACKET_SIZE0,            // bMaxPacketSize
    LE_WORD(0xFFFF),            // idVendor
    LE_WORD(0x0005),            // idProduct
    LE_WORD(0x0100),            // bcdDevice
    0x01,                        // iManufacturer
    0x02,                        // iProduct
    0x03,                        // iSerialNumber
    0x01,                        // bNumConfigurations

// configuration descriptor
    LE_WORD(67),                // wTotalLength
    0x02,                        // bNumInterfaces
    0x01,                        // bConfigurationValue
    0x00,                        // iConfiguration
    0xC0,                        // bmAttributes
    0x32,                        // bMaxPower
// control class interface
    0x00,                        // bInterfaceNumber
    0x00,                        // bAlternateSetting
    0x01,                        // bNumEndPoints
    0x02,                        // bInterfaceClass
    0x02,                        // bInterfaceSubClass
    0x01,                        // bInterfaceProtocol, linux requires value of 1 for the cdc_acm module
    0x00,                        // iInterface
// header functional descriptor
// call management functional descriptor
    0x01,                        // bmCapabilities = device handles call management
    0x01,                        // bDataInterface
// ACM functional descriptor
    0x02,                        // bmCapabilities
// union functional descriptor
    0x00,                        // bMasterInterface
    0x01,                        // bSlaveInterface0
// notification EP
    INT_IN_EP,                    // bEndpointAddress
    0x03,                        // bmAttributes = intr
    LE_WORD(8),                    // wMaxPacketSize
    0x0A,                        // bInterval
// data class interface descriptor
    0x01,                        // bInterfaceNumber
    0x00,                        // bAlternateSetting
    0x02,                        // bNumEndPoints
    0x0A,                        // bInterfaceClass = data
    0x00,                        // bInterfaceSubClass
    0x00,                        // bInterfaceProtocol
    0x00,                        // iInterface
// data EP OUT
    BULK_OUT_EP,                // bEndpointAddress
    0x02,                        // bmAttributes = bulk
    LE_WORD(MAX_PACKET_SIZE),    // wMaxPacketSize
    0x00,                        // bInterval
// data EP in
    BULK_IN_EP,                    // bEndpointAddress
    0x02,                        // bmAttributes = bulk
    LE_WORD(MAX_PACKET_SIZE),    // wMaxPacketSize
    0x00,                        // bInterval

clawoo wrote on Thursday, December 11, 2008:

Sorry to re-open an old discussion but I see that the bInterfaceProtocol is back to 0x00 since revision 426 as evidenced here:

Is there a reason for that? I am asking because without that I haven’t been able to get USB working from Linux (I am using Ubuntu Hardy) without setting bInterfacceProtocol to 1.


rtel wrote on Thursday, December 11, 2008:

Unfortunately I don’t have a Linux machine to test on, and I get conflicting reports from users on how the descriptors should be configured.  Its nothing more than that.