I am developing a RNDIS composite device which includes a RNDIS device, a usbnet device ,a modem device and a self-defined CDC device.
The PC is running Win7 32bit, and I am using the default RNDIS driver. When I answers the Windows enumeration with only RNDIS device, everything works fine. But when I compose all 4 device into the descriptor as composite device, Windows still enumerates correctly and the other 3 devices works fine, but RNDIS device encounters with "cannot start error code 10" issue.
I traced the USB data flow with a USB analyzer, found that Windows RNDIS driver did not send RNDIS initialize messages after “Set Configuration”.
The composite device descriptor is as posted:
devDesc[0] = 0x12; // bLength - Descriptor length
devDesc[1] = 0x01; // bDescriptorType - Descriptor Type
devDesc[2] = bcdUSB_LSB; // bcdUSB (LSB) - Device Compliant to USB specification ..
devDesc[3] = bcdUSB_MSB; // bcdUSB (MSB)
devDesc[4] = 0x00; // bDeviceClass - class of the device
devDesc[5] = 0x00; // bDeviceSubClass - subclass of the device
devDesc[6] = 0x00; // bDeviceProtocol - protocol of the device
devDesc[7] = bEp0MaxPacketSize; // bMaxPacketSize0 - Max Packet Size for EP zero
devDesc[8] = 0x86; // idVendor (LSB) - Vendor ID
devDesc[9] = 0x12; // idVendor (MSB)
devDesc[10] = 0x0E; // idProduct (LSB) - Product ID
devDesc[11] = 0x81; // idProduct (MSB)
devDesc[12] = 0x02; // bcdDevice (LSB) - The device release number
devDesc[13] = 0x00; // bcdDevice (MSB)
devDesc[14] = 0x01; // iManufacturer - Index of string descriptor describing Manufacturer
devDesc[15] = 0x03; // iProduct - Index of string descriptor describing Product
devDesc[16] = 0x04; // iSerialNumber - Index of string descriptor describing Serial number
devDesc[17] = 0x01; // bNumConfigurations - Number of configurations
//Configuration Descriptor
configDesc[0] = 0x09; // bLength - Descriptor length
configDesc[1] = 0x02; // bDescriptorType - Descriptor Type
configDesc[2] = 177; // wTotalLength (LSB) - Total Data length for the configuration,
configDesc[3] = 0x00; // wTotalLength (MSB) - includes all descriptors for this configuration
configDesc[4] = 0x05; // bNumInterfaces - Number of interfaces this configuration supports
configDesc[5] = 0x01; // bConfigurationValue - The Value that should be used to select this configuration
configDesc[6] = 0x00; // iConfiguration - Index of string descriptor describing this configuration
configDesc[7] = 0xC0; // bmAttributes - bit6: Self-Powered, bit5: RemoteWakeup
configDesc[8] = 0xfa; // MaxPower - Maximum power consumption for this configuration (mA)
//Interface Descriptor 0 usbnet
configDesc[9] = 0x09; // bLength - Descriptor length
configDesc[10] = 0x04; // bDescriptorType - Descriptor Type
configDesc[11] = 0x00; // bInterfaceNumber - Index (Number) of this interfaces
configDesc[12] = 0x00; // bAlternateSetting - The value to select alternate setting of this interface
configDesc[13] = 0x03; // bNumEndpoints - Number endpoints used by this interface
configDesc[14] = 0xff; // bInterfaceClass - Class of this Interface
configDesc[15] = 0xff; // bInterfaceSubClass - Sub class of this Interface
configDesc[16] = 0x00; // bInterfaceProtocol - Protocol of this Interface
configDesc[17] = 0x05; // iInterface - Index of string descriptor describing this Interface
// usbnet Endpoint Descriptor
configDesc[18] = 0x07; // bLength - Descriptor length
configDesc[19] = 0x05; // bDescriptorType - Descriptor Type
configDesc[20] = 0x85; // bEndpointAddress - Endpoint Address & Direction
configDesc[21] = 0x03; // bmAttributes - BULK,ISO,Interrupt
configDesc[22] = 0x0F; // wMaxPacketSize (LSB) - Max packet size
configDesc[23] = 0x00; // wMaxPacketSize (MSB)
configDesc[24] = bInterval; // bInterval - Polling Interval (ms)
configDesc[25] = 0x07; // bLength - Descriptor length
configDesc[26] = 0x05; // bDescriptorType - Descriptor Type
configDesc[27] = 0x81; // bEndpointAddress - Endpoint Address & Direction
configDesc[28] = 0x02; // bmAttributes - BULK,ISO,Interrupt
configDesc[29] = bBulkMaxPacketSize_LSB; // wMaxPacketSize (LSB) - Max packet size
configDesc[30] = bBulkMaxPacketSize_MSB; // wMaxPacketSize (MSB)
configDesc[31] = 0x00; // bInterval - Polling Interval (ms)
configDesc[32] = 0x07; // bLength - Descriptor length
configDesc[33] = 0x05; // bDescriptorType - Descriptor Type
configDesc[34] = 0x02; // bEndpointAddress - Endpoint Address & Direction
configDesc[35] = 0x02; // bmAttributes - BULK,ISO,Interrupt
configDesc[36] = bBulkMaxPacketSize_LSB; // wMaxPacketSize (LSB) - Max packet size
configDesc[37] = bBulkMaxPacketSize_MSB; // wMaxPacketSize (MSB)
configDesc[38] = 0x00; // bInterval - Polling Interval (ms)
//Interface descriptor 1 ICAT
configDesc[39] = 0x09; // bLength - Descriptor length
configDesc[40] = 0x04; // bDescriptorType - Descriptor Type
configDesc[41] = 0x01; // bInterfaceNumber - Index (Number) of this interfaces
configDesc[42] = 0x00; // bAlternateSetting - The value to select alternate setting of this interface
configDesc[43] = 0x02; // bNumEndpoints - Number endpoints used by this interface
configDesc[44] = 0xFF; // bInterfaceClass - Class of this Interface
configDesc[45] = 0x00; // bInterfaceSubClass - Sub class of this Interface
configDesc[46] = 0x00; // bInterfaceProtocol - Protocol of this Interface
configDesc[47] = 0x00; // iInterface - Index of string descriptor describing this Interface
//ICAT endpoints
configDesc[48] = 0x07; // bLength - Descriptor length
configDesc[49] = 0x05; // bDescriptorType - Descriptor Type
configDesc[50] = 0x87; // bEndpointAddress - Endpoint Address & Direction
configDesc[51] = 0x02; // bmAttributes - BULK,ISO,Interrupt
configDesc[52] = bBulkMaxPacketSize_LSB; // wMaxPacketSize (LSB) - Max packet size
configDesc[53] = bBulkMaxPacketSize_MSB; // wMaxPacketSize (MSB)
configDesc[54] = 0x00; // bInterval - Polling Interval (ms)
configDesc[55] = 0x07; // bLength - Descriptor length
configDesc[56] = 0x05; // bDescriptorType - Descriptor Type
configDesc[57] = 0x08; // bEndpointAddress - Endpoint Address & Direction
configDesc[58] = 0x02; // bmAttributes - BULK,ISO,Interrupt
configDesc[59] = bBulkMaxPacketSize_LSB; // wMaxPacketSize (LSB) - Max packet size
configDesc[60] = bBulkMaxPacketSize_MSB; // wMaxPacketSize (MSB)
configDesc[61] = 0x00; // bInterval - Polling Interval (ms)
//Modem class specific descriptors
configDesc[62] = 0x09; // bLength - Descriptor length
configDesc[63] = 0x04; // bDescriptorType - Descriptor Type
configDesc[64] = 0x02; // bInterfaceNumber - Index (Number) of this interfaces
configDesc[65] = 0x00; // bAlternateSetting - The value to select alternate setting of this interface
configDesc[66] = 0x03; // bNumEndpoints - Number endpoints used by this interface
configDesc[67] = 0x02; // bInterfaceClass - Class of this Interface
configDesc[68] = 0x02; // bInterfaceSubClass - Sub class of this Interface
configDesc[69] = 0x01; // bInterfaceProtocol - Protocol of this Interface
configDesc[70] = 0x00; // iInterface - Index of string descriptor describing this Interface
configDesc[71] = 0x05; // descriptor length Comms Class CS_INTERFACE 'Functional Descriptors' Triplet
configDesc[72] = 0x24; // descriptor type
configDesc[73] = 0x00; // subtype = header
configDesc[74] = 0x10; // BCD
configDesc[75] = 0x01; //
configDesc[76] = 0x05; // 2. descriptor length - Call Manangement Func Desc
configDesc[77] = 0x24; // descriptor type
configDesc[78] = 0x01; // subtype = Call management
configDesc[79] = 0x00; //bmcapabilities; MS driver usbser.sys seems to ignore this bit and sends AT over the data,interface anyway
configDesc[80] = 0x01; // Interface number of data class interface
configDesc[81] = 0x04; // 3.descriptor length Abstract Control Func Desc
configDesc[82] = 0x24; // descriptor type
configDesc[83] = 0x02; // subtype = Abstract CM
configDesc[84] = 0x00; // bmcapabilities
configDesc[85] = 0x05; // Size of descriptor. Number of interfaces plus 3 bytes of header
configDesc[86] = 0x24; // 0x24 - CS_INTERFACE
configDesc[87] = 0x06; // 0x06 - See table 25 of document "USB Class definitions for Comms Devices"
configDesc[88] = 0x00;
configDesc[89] = 0x01;
//Endpoint Descriptors MODEM
configDesc[90] = 0x07; // bLength - Descriptor length
configDesc[91] = 0x05; // bDescriptorType - Descriptor Type
configDesc[92] = 0x86; // bEndpointAddress - Endpoint Address & Direction
configDesc[93] = 0x03; // bmAttributes - BULK,ISO,Interrupt
configDesc[94] = 0x0F; // wMaxPacketSize (LSB) - Max packet size
configDesc[95] = 0x00; // wMaxPacketSize (MSB)
configDesc[96] = bInterval; // bInterval - Polling Interval (ms)
configDesc[97] = 0x07; // bLength - Descriptor length
configDesc[98] = 0x05; // bDescriptorType - Descriptor Type
configDesc[99] = 0x83; // bEndpointAddress - Endpoint Address & Direction
configDesc[100] = 0x02; // bmAttributes - BULK,ISO,Interrupt
configDesc[101] = bBulkMaxPacketSize_LSB; // wMaxPacketSize (LSB) - Max packet size
configDesc[102] = bBulkMaxPacketSize_MSB; // wMaxPacketSize (MSB)
configDesc[103] = 0x00; // bInterval - Polling Interval (ms)
configDesc[104] = 0x07; // bLength - Descriptor length
configDesc[105] = 0x05; // bDescriptorType - Descriptor Type
configDesc[106] = 0x04; // bEndpointAddress - Endpoint Address & Direction
configDesc[107] = 0x02; // bmAttributes - BULK,ISO,Interrupt
configDesc[108] = bBulkMaxPacketSize_LSB; // wMaxPacketSize (LSB) - Max packet size
configDesc[109] = bBulkMaxPacketSize_MSB; // wMaxPacketSize (MSB)
configDesc[110] = 0x00; // bInterval - Polling Interval (ms)
//rndis IAD
configDesc[111] = 0x08; // bLength
configDesc[112] = 0x0b; // INTERFACE ASSOCIATION DESCRIPTOR bDescriptorType
configDesc[113] = 0x03; // bFirstInterface
configDesc[114] = 0x02; // bInterfaceCount
configDesc[115] = 0x02; // bFunctionClass
configDesc[116] = 0x02; // bFunctionSubClass
configDesc[117] = 0xFF; // bFunctionProtocol
configDesc[118] = 0x03; // Index of string descriptor describing this function
//rndis comm interface
configDesc[119] = 0x09; // bLength - Descriptor length
configDesc[120] = 0x04; // bDescriptorType - Descriptor Type
configDesc[121] = 0x03; //bInterfaceNumber - for RNDIS
configDesc[122] = 0x00; // bAlt
configDesc[123] = 0x01; // bNumEnd
configDesc[124] = 0x02; //bInterfaceClass
configDesc[125] = 0x02; // bInterfaceSubclass
configDesc[126] = 0xFF; // bInterfaceprotocol
configDesc[127] = 0x00; // iInterface +++++++++++++++++++++++++++++++++++++need modified
// Class specified descriptor
configDesc[128] = 0x05; //
configDesc[129] = 0x24; // bDescriptorType
configDesc[130] = 0x00; //bDescriptorSubtype
configDesc[131] = 0x10; // BCD
configDesc[132] = 0x01; //
configDesc[133] = 0x05; //
configDesc[134] = 0x24; // bDescriptorType
configDesc[135] = 0x01; // bDescriptorSubtype
configDesc[136] = 0x00; // bmCapabilities
configDesc[137] = 0x04; //bDataInterface
configDesc[138] = 0x04; //
configDesc[139] = 0x24; // bDescriptorType
configDesc[140] = 0x02; // bDescriptorSubtype
configDesc[141] = 0x00; // bmCapabilities
configDesc[142] = 0x05; //
configDesc[143] = 0x24; // bDescriptorType
configDesc[144] = 0x06; // bDescriptorSubtype
configDesc[145] = 0x03; // bControlInterface
configDesc[146] = 0x04; // bsubordinateInterface
//Interrupt In endpoint
configDesc[147] = 0x07; //
configDesc[148] = 0x05; //
configDesc[149] = 0x8C; //bendpointAddress
configDesc[150] = 0x03; //bmAttributes
configDesc[151] = 0x08; // wMaxPacketSize
configDesc[152] = 0x00; //
configDesc[153] = 0x01; // bInterval
//rndis data interface
configDesc[154] = 0x09; // bLength - Descriptor length
configDesc[155] = 0x04; // bDescriptorType - Descriptor Type
configDesc[156] = 0x04; //bInterfaceNumber --- for RNDIS
configDesc[157] = 0x00; // bAlt
configDesc[158] = 0x02; // NumEndpoints
configDesc[159] = 0x0a; //bInterfaceClass
configDesc[160] = 0x00; // bInterfaceSubclass
configDesc[161] = 0x00; // bInterfaceprotocol
configDesc[162] = 0x00; // iInterface +++++++++++++++++++++++++++++++++++++need modified
//Bulk In endpoint
configDesc[163] = 0x07; //
configDesc[164] = 0x05; //
configDesc[165] = 0x8E; //bendpointAddress
configDesc[166] = 0x02; //bmAttributes
configDesc[167] = 0x00; // wMaxPacketSize
configDesc[168] = 0x02; //
configDesc[169] = 0x00; // bInterval
//Bulk Out endpoint
configDesc[170] = 0x07; //
configDesc[171] = 0x05; //
configDesc[172] = 0x0D; //bendpointAddress
configDesc[173] = 0x02; //bmAttributes
configDesc[174] = 0x00; // wMaxPacketSize
configDesc[175] = 0x02; //
configDesc[176] = 0x00; // bInterva
Let me answer my own question, I have figured out this issue:
The RNDIS IAD interface must be the first and second of the composite device. Although the problem is solved, it still puzzles me.
Hope this note will help others encountering similar issues.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With