I'm following the advice:
It is possible to achieve your own composite USB Device, by combining the desired classes' drivers into one class, under your own folder within: Middlewares\ST\STM32_USB Device Library\Class
from https://community.st.com/s/question/0D50X00009XkgYtSAJ/stm32f4-hal-composite-usb-device-example
I now have a unified configuration descriptor.
/* USB CDC device Configuration Descriptor */
__ALIGN_BEGIN uint8_t USBD_CDC_CfgFSDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END =
{
/*Configuration Descriptor*/
0x09, /* bLength: Configuration Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
USB_CDC_CONFIG_DESC_SIZ, /* wTotalLength:no of returned bytes */
0x00,
0x03, /* bNumInterfaces: 2 interface */
0x01, /* bConfigurationValue: Configuration value */
0x00, /* iConfiguration: Index of string descriptor describing the configuration */
0xC0, /* bmAttributes: self powered */
0x32, /* MaxPower 0 mA */
/*---------------------------------------------------------------------------*/
//////////////////////////////////////////////////////////////////////////////////////
//Add 1 IAD class here // this one is for COM port
0x08, // bLength: Interface Descriptor size
0x0B, // bDescriptorType: IAD
0x00, // bFirstInterface //starting of interface
0x02, // bInterfaceCount //interfaces under this IAD class
0x02, // bFunctionClass: CDC
0x02, // bFunctionSubClass
0x01, // bFunctionProtocol
0x02, // iFunction
//////////////////////////////////////////////////////////////////////////////////////
/*Interface Descriptor */
0x09, /* bLength: Interface Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */
/* Interface descriptor type */
0x00, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x01, /* bNumEndpoints: One endpoints used */
0x02, /* bInterfaceClass: Communication Interface Class */
0x02, /* bInterfaceSubClass: Abstract Control Model */
0x01, /* bInterfaceProtocol: Common AT commands */
0x00, /* iInterface: */
/*Header Functional Descriptor*/
0x05, /* bLength: Endpoint Descriptor size */
0x24, /* bDescriptorType: CS_INTERFACE */
0x00, /* bDescriptorSubtype: Header Func Desc */
0x10, /* bcdCDC: spec release number */
0x01,
/*Call Management Functional Descriptor*/
0x05, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x01, /* bDescriptorSubtype: Call Management Func Desc */
0x00, /* bmCapabilities: D0+D1 */
0x01, /* bDataInterface: 1 */
/*ACM Functional Descriptor*/
0x04, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x02, /* bDescriptorSubtype: Abstract Control Management desc */
0x02, /* bmCapabilities */
/*Union Functional Descriptor*/
0x05, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x06, /* bDescriptorSubtype: Union func desc */
0x00, /* bMasterInterface: Communication class interface */
0x01, /* bSlaveInterface0: Data Class Interface */
/*Endpoint 2 Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_CMD_EP, /* bEndpointAddress */
0x03, /* bmAttributes: Interrupt */
LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */
HIBYTE(CDC_CMD_PACKET_SIZE),
CDC_FS_BINTERVAL, /* bInterval: */
/*---------------------------------------------------------------------------*/
/*Data class interface descriptor*/
0x09, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */
0x01, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints: Two endpoints used */
0x0A, /* bInterfaceClass: CDC */
0x00, /* bInterfaceSubClass: */
0x00, /* bInterfaceProtocol: */
0x00, /* iInterface: */
/*Endpoint OUT Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_OUT_EP, /* bEndpointAddress */
0x02, /* bmAttributes: Bulk */
LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */
HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
0x00, /* bInterval: ignore for Bulk transfer */
/*Endpoint IN Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_IN_EP, /* bEndpointAddress */
0x02, /* bmAttributes: Bulk */
LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */
HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
0x00, /* bInterval: ignore for Bulk transfer */
///////////////////////////////////////////////////////////////////////////////////////////////
// IAD Mouse
0x08, // bLength: Interface Descriptor size
0x0B, // bDescriptorType: IAD
0x02, // bFirstInterface //starts from zero .. hence 0-1- and now 2
0x01, // bInterfaceCount //no of interfaces used in function. for above cdc it was 2
0x03, //*bInterfaceClass: HID*/
0x01, //*bInterfaceSubClass : 1=BOOT, 0=no boot*/
0x02, //*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
0x02, //*iInterface: Index of string descriptor*/
////////////////////////////////////////////////////////////////////////////////////////////////
/************** Descriptor of Joystick Mouse interface ****************/
/* 09 */
0x09, /*bLength: Interface Descriptor size*/
USB_DESC_TYPE_INTERFACE,/*bDescriptorType: Interface descriptor type*/
0x02, /*bInterfaceNumber: Number of Interface*/
0x00, /*bAlternateSetting: Alternate setting*/
0x01, /*bNumEndpoints*/
0x03, /*bInterfaceClass: HID*/
0x01, /*bInterfaceSubClass : 1=BOOT, 0=no boot*/
0x02, /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
0x02, /*iInterface: Index of string descriptor*/
/******************** Descriptor of Joystick Mouse HID ********************/
/* 18 */
0x09, /*bLength: HID Descriptor size*/
HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
0x11, /*bcdHID: HID Class Spec release number*/
0x01,
0x00, /*bCountryCode: Hardware target country*/
0x01, /*bNumDescriptors: Number of HID class descriptors to follow*/
0x22, /*bDescriptorType*/
HID_MOUSE_REPORT_DESC_SIZE,/*wItemLength: Total length of Report descriptor*/
0x00,
/******************** Descriptor of Mouse endpoint ********************/
/* 27 */
0x07, /*bLength: Endpoint Descriptor size*/
USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/
HID_EPIN_ADDR, /*bEndpointAddress: Endpoint Address (IN)*/
0x03, /*bmAttributes: Interrupt endpoint*/
HID_EPIN_SIZE, /*wMaxPacketSize: 4 Byte max */
0x00,
HID_FS_BINTERVAL, /*bInterval: Polling Interval */
/* 34 */
} ;
and a unified init:
static uint8_t USBD_CDC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
uint8_t ret = 0U;
USBD_CDC_HandleTypeDef *hcdc;
if (pdev->dev_speed == USBD_SPEED_HIGH)
{
/* Open EP IN */
USBD_LL_OpenEP(pdev, CDC_IN_EP, USBD_EP_TYPE_BULK,
CDC_DATA_HS_IN_PACKET_SIZE);
pdev->ep_in[CDC_IN_EP & 0xFU].is_used = 1U;
/* Open EP OUT */
USBD_LL_OpenEP(pdev, CDC_OUT_EP, USBD_EP_TYPE_BULK,
CDC_DATA_HS_OUT_PACKET_SIZE);
pdev->ep_out[CDC_OUT_EP & 0xFU].is_used = 1U;
}
else
{
/* Open EP IN */
USBD_LL_OpenEP(pdev, CDC_IN_EP, USBD_EP_TYPE_BULK,
CDC_DATA_FS_IN_PACKET_SIZE);
pdev->ep_in[CDC_IN_EP & 0xFU].is_used = 1U;
/* Open EP OUT */
USBD_LL_OpenEP(pdev, CDC_OUT_EP, USBD_EP_TYPE_BULK,
CDC_DATA_FS_OUT_PACKET_SIZE);
pdev->ep_out[CDC_OUT_EP & 0xFU].is_used = 1U;
}
/* Open Command IN EP */
USBD_LL_OpenEP(pdev, CDC_CMD_EP, USBD_EP_TYPE_INTR, CDC_CMD_PACKET_SIZE);
pdev->ep_in[CDC_CMD_EP & 0xFU].is_used = 1U;
pdev->pClassData = USBD_malloc(sizeof(USBD_CDC_HandleTypeDef));
if (pdev->pClassData == NULL)
{
ret = 1U;
}
else
{
hcdc = (USBD_CDC_HandleTypeDef *) pdev->pClassData;
/* Init physical Interface components */
((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Init();
/* Init Xfer states */
hcdc->TxState = 0U;
hcdc->RxState = 0U;
if (pdev->dev_speed == USBD_SPEED_HIGH)
{
/* Prepare Out endpoint to receive next packet */
USBD_LL_PrepareReceive(pdev, CDC_OUT_EP, hcdc->RxBuffer,
CDC_DATA_HS_OUT_PACKET_SIZE);
}
else
{
/* Prepare Out endpoint to receive next packet */
USBD_LL_PrepareReceive(pdev, CDC_OUT_EP, hcdc->RxBuffer,
CDC_DATA_FS_OUT_PACKET_SIZE);
}
}
// HID
/* Open EP IN */
USBD_LL_OpenEP(pdev, HID_EPIN_ADDR, USBD_EP_TYPE_INTR, HID_EPIN_SIZE);
pdev->ep_in[HID_EPIN_ADDR & 0xFU].is_used = 1U;
pdev->pClassData = USBD_malloc(sizeof(USBD_HID_HandleTypeDef));
if (pdev->pClassData == NULL)
{
return USBD_FAIL;
}
((USBD_HID_HandleTypeDef *)pdev->pClassData)->state = HID_IDLE;
return ret;
}
I am concerned that the value of CDC_IN_EP (0x81) clashes with HID_EPIN_ADDR (also 0x81).
Is this a valid concern?
Is there an example of making a composite CDC/HID using CubeMX?
I needed to use 0x83 as the HID endpoint. I confirmed that this worked in the simple HID example, too.
There are still many other obstacles in the way of getting a working CDC/HID composite device on STM32.
Related
I am trying to develop a USB audio device compliant to USB Audio Class version 2.0 specification. I have written the descriptors by referring to the specification as such. But, I find that the device is not enumerating correctly. The status in device manager just shows "This device cannot start (Code 10)."
Please find the configuration descriptors that I am using below:
/* Configuration descriptor */
0x09, /* Descriptor size */
0x02, /* Configuration descriptor type */
0x8A,0x00, /* Length of this descriptor and all sub descriptors */
0x02, /* Number of interfaces */
0x01, /* Configuration number */
0x00, /* Configuration string index */
0x80, /* Config characteristics - Bus powered */
0x32, /* Max power consumption of device (in 8mA unit) : 400mA */
//IAD
0x08, /* bLength */
0x0B, /* bDescriptorType */
0x00, /* bFirstInterface */
0x02, /* bInterfaceCount */
0x01, /* bFunctionClass */
0x00, /* bFunctionSubClass */
0x20, /* bFunctionProtocol */
0x00, /* iFunction */
/* Standard AC Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x00, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x00, /* bNumEndoints */
0x01, /* bInterfaceClass */
0x01, /* bInterfaceSubClass */
0x20, /* bInterfaceProtocol */
0x00, /* iInterface */
/* Class-Specific AC Interface Header Descriptor */
0x09, /* bLength */
0x24, /* bDescriptorType */
0x01, /* bDescriptorSubtype */
0x00, 0x02, /* bcdADC */
0x03, /* bCatagory MICROPHONE*/
0x2E, 0x00, /* wTotalLength (46 Bytes) */
0x00, /* bmControls */
/* Class-Specific AC Clock Source Descriptor (INTERNAL) */
0x08, /* bLength */
0x24, /* bDescriptorType */
0x0A, /* bDescriptorSubtype */
0x10, /* bClockID */
0x01, /* bmAttributes:
D[1:0]:
00: External Clock
01: Internal Fixed Clock
10: Internal Variable Clock
11: Internal Progamable Clock
D[2]:
Clock Synced to SOF
D[7:3]:
Reserved (0) */
0x00, /* bmControls:
D[1:0]:
Clock Freq Control
D[3:2]:
Clock Validity Control
D[7:4]:
Reserved (0) */
0x00, /* bAssocTerminal */
0x00, /* iClockSource */
/* Class-Specific AC Input Terminal Descriptor */
0x11, /* bLength */
0x24, /* bDescriptorType */
0x02, /* bDescriptorSubtype */
0x01, /* bTerminalID */
0x01, 0x02, /* wTerminalType */
0x00, /* bAssocTerminal */
0x10, /* bCSourceID */
0x02, /* bNrChannels,indicate has number of channel in cluster*/
0x03, 0x00, 0x00, 0x00, /* bmChannelConfig,spatial positions*/
0x00, /* iChannelNames,index remaining channel spatial positions descripte*/
0x00, 0x00, /* bmControls */
0x00, /* iTerminal */
/* Class-Specific AC Output Terminal Descriptor*/
0x0C, /* bLength */
0x24, /* bDescriptorType */
0x03, /* bDescriptorSubtype */
0x02, /* bTerminalID */
0x01, 0x01, /* wTerminalType */
0x00, /* bAssocTerminal */
0x01, /* bSourceID */
0x10, /* bCSourceID */
0x00, 0x00, /* bmControls */
0x00, /* iTerminal */
/* Audio In Standard AS Interface Descriptor (Alt 0 - Zero Bandwidth) */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x01, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x00, /* bNumEndpoints */
0x01, /* bInterfaceClass */
0x02, /* bInterfaceSubClass */
0x20, /* bInterfaceProtocol */
0x00, /* iInterface */
/* Audio In Standard AS Interface Descriptor (Alt 1) */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x01, /* bInterfaceNumber */
0x01, /* bAlternateSetting */
0x01, /* bNumEndpoints */
0x01, /* bInterfaceClass */
0x02, /* bInterfaceSubClass */
0x20, /* bInterfaceProtocol */
0x00, /* iInterface */
/* Audio In Class-Specific AS Interface descriptor */
0x10, /* bLength */
0x24, /* bDescriptorType */
0x01, /* bDescriptorSubtype */
0x02, /* bTerminalLink,Terminal ID of Output Terminal */
0x00, /* bmControls */
0x01, /* bFormatType */
0x01, 0x00, 0x00, 0x00, /* bmFormats PCM*/
0x02, /* bNrChannels 2 channel*/
0x03, 0x00, 0x00, 0x00, /* bmChannelConfig */
0x00, /* iChannelNames */
/* Audio In Class-Specific AS Type I Format Descriptor */
0x0B, /* Descriptor size */
0x24, /* Class-specific Interface Descriptor Type */
0x02, /* Format Type Descriptor subtype */
0x01, /* PCM FORMAT_TYPE_I */
0x02, /* Number of channels - 2 */
0x02, /* Subframe size - 2 bytes per audio subframe */
0x10, /* Bit resolution - 16 bits */
0x01, /* Number of samping frequencies - 1 */
0x80, 0xBB, 0x00, /* Sampling frequency - 48000 Hz */
/* Audio In Standard AS Isochronous Data EP Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x81, /* bEndpointAddress */
0x05, /* bmAttributes */
0xC8, 0x00, /* wMaxPacketSize 200byte*/
0x01, /* bInterval */
/* Superspeed Endpoint Companion Descriptor */
0x06, /* bLength */
0x30, /* bDescriptorType */
0x00, /* bMaxBurst */
0x00, /* bmAttributes */
0x60, 0x00, /* wBytesPerInterval */
/* Audio In Class-Specific AS Isochronous Data EP Descriptor */
0x08, /* bLength */
0x25, /* bDescriptorType */
0x01, /* bDescriptorSubtype */
0x00, /* bmAttributes */
0x00, /* bmControls */
0x02, /* bLockDelayUnits */
0x08, 0x00, /* wLockDelay */
I have emulated two VCPs with only one USB Device. I can send data in one VCP that has the following Endpoint Address.
#define CDC_IN_EP 0x81 /* EP1 for data IN */
#define CDC_OUT_EP 0x01 /* EP1 for data OUT */
#define CDC_CMD_EP 0x82 /* EP2 for CDC commands */
I would like to know if it's possible to send data in the other VCP with other Endpoint Address like:
#define CDC_IN_EP3 0x83 /* EP3 for data IN */
#define CDC_OUT_EP3 0x03 /* EP3 for data OUT */
#define CDC_CMD_EP4 0x84 /* EP4 for CDC commands */
My problem is that addresses others than 0x81 don't allow me to send data over the second VCP. I'm using two CDC interfaces Full-Speed. Normally we can use seven endpoints with CDC_FS and that's what I'm trying to do... I have six Endpoints: three for each VCP and the seventh is Endpoint 0 for configuration.
Have I missed something in the Endpoints Configuration or in the Composite Device Descriptors?
/* USB CDC device Configuration Descriptor */
__ALIGN_BEGIN uint8_t USBD_CDC_CfgFSDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END =
{
/* Configuration Descriptor */
0x09, /* bLength: Configuration Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
USB_CDC_CONFIG_DESC_SIZ, /* wTotalLength:no of returned bytes */
0x00,
0x04, /* bNumInterfaces: 4 interface */
0x01, /* bConfigurationValue: Configuration value */
0x00, /* iConfiguration: Index of string descriptor describing the configuration */
0xC0, /* bmAttributes: Self powered */
0x32, /* MaxPower 100 mA */
/*---------------------------------------------------------------------------*/
// IAD0
0x08, // bLength: Interface Descriptor size
0x0B, // bDescriptorType: IAD
0x00, // bFirstInterface
0x02, // bInterfaceCount
0x02, // bFunctionClass: CDC
0x02, // bFunctionSubClass
0x01, // bFunctionProtocol
0x02, // iFunction
/* Interface0 Descriptor */
0x09, /* bLength: Interface Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */
/* Interface descriptor type */
0x00, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x01, /* bNumEndpoints: One endpoints used */
0x02, /* bInterfaceClass: Communication Interface Class */
0x02, /* bInterfaceSubClass: Abstract Control Model */
0x01, /* bInterfaceProtocol: Common AT commands */
0x00, /* iInterface: */
/* Header Functional Descriptor */
0x05, /* bLength: Endpoint Descriptor size */
0x24, /* bDescriptorType: CS_INTERFACE */
0x00, /* bDescriptorSubtype: Header Func Desc */
0x10, /* bcdCDC: spec release number */
0x01,
/* Call Management Functional Descriptor */
0x05, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x01, /* bDescriptorSubtype: Call Management Func Desc */
0x03, /* bmCapabilities: D0+D1 */
0x01, /* bDataInterface: 1 */
/* ACM Functional Descriptor */
0x04, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x02, /* bDescriptorSubtype: Abstract Control Management desc */
0x02, /* bmCapabilities */
/* Union Functional Descriptor */
0x05, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x06, /* bDescriptorSubtype: Union func desc */
0x00, /* bMasterInterface: Communication class interface */
0x01, /* bSlaveInterface0: Data Class Interface */
/* Endpoint 2 Descriptor */
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_CMD_EP, /* bEndpointAddress */
0x03, /* bmAttributes: Interrupt */
LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */
HIBYTE(CDC_CMD_PACKET_SIZE),
0xFF, /* bInterval: */
/*---------------------------------------------------------------------------*/
/*Data class interface descriptor*/
0x09, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */
0x01, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints: Two endpoints used */
0x0A, /* bInterfaceClass: CDC */
0x00, /* bInterfaceSubClass: */
0x00, /* bInterfaceProtocol: */
0x00, /* iInterface: */
/*Endpoint OUT Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_OUT_EP, /* bEndpointAddress */
0x02, /* bmAttributes: Bulk */
LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */
HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
0x00, /* bInterval: ignore for Bulk transfer */
/*Endpoint IN Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_IN_EP, /* bEndpointAddress */
0x02, /* bmAttributes: Bulk */
LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */
HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
0x00, /* bInterval: ignore for Bulk transfer */
/*---------------------------------------------------------------------------*/
// IAD1
0x08, // bLength: Interface Descriptor size
0x0B, // bDescriptorType: IAD
0x02, // bFirstInterface
0x02, // bInterfaceCount
0x02, // bFunctionClass: CDC
0x02, // bFunctionSubClass
0x01, // bFunctionProtocol
0x02, // iFunction
/* Interface1 Descriptor */
0x09, /* bLength: Interface Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */
/* Interface descriptor type */
0x02, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x01, /* bNumEndpoints: One endpoints used */
0x02, /* bInterfaceClass: Communication Interface Class */
0x02, /* bInterfaceSubClass: Abstract Control Model */
0x01, /* bInterfaceProtocol: Common AT commands */
0x00, /* iInterface: */
/*Header Functional Descriptor*/
0x05, /* bLength: Endpoint Descriptor size */
0x24, /* bDescriptorType: CS_INTERFACE */
0x00, /* bDescriptorSubtype: Header Func Desc */
0x10, /* bcdCDC: spec release number */
0x01,
/*Call Management Functional Descriptor*/
0x05, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x01, /* bDescriptorSubtype: Call Management Func Desc */
0x03, /* bmCapabilities: D0+D1 */
0x03, /* bDataInterface: 1 */
/*ACM Functional Descriptor*/
0x04, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x02, /* bDescriptorSubtype: Abstract Control Management desc */
0x02, /* bmCapabilities */
/*Union Functional Descriptor*/
0x05, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x06, /* bDescriptorSubtype: Union func desc */
0x02, /* bMasterInterface: Communication class interface */
0x03, /* bSlaveInterface0: Data Class Interface */
/*Endpoint 2 Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_CMD_EP4, /* bEndpointAddress */
0x03, /* bmAttributes: Interrupt */
LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */
HIBYTE(CDC_CMD_PACKET_SIZE),
0xFF, /* bInterval: */
/*---------------------------------------------------------------------------*/
/*Data class interface descriptor*/
0x09, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */
0x03, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints: Two endpoints used */
0x0A, /* bInterfaceClass: CDC */
0x00, /* bInterfaceSubClass: */
0x00, /* bInterfaceProtocol: */
0x00, /* iInterface: */
/*Endpoint OUT Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_OUT_EP3, /* bEndpointAddress */
0x02, /* bmAttributes: Bulk */
LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */
HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
0x00, /* bInterval: ignore for Bulk transfer */
/*Endpoint IN Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_IN_EP3, /* bEndpointAddress */
0x02, /* bmAttributes: Bulk */
LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */
HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
0x00 /* bInterval: ignore for Bulk transfer */
};
I had a similar problem with the STM32 USB device library. When you modify or add a new endpoint address in the configuration descriptor, you also have to set the endpoint address in the PMA (packet memory area). You can do that in the USBD_LL_INIT block with the HAL_PCDEx_PMAConfig function:
USBD_StatusTypeDef USBD_LL_Init (USBD_HandleTypeDef *pdev)
{
/* Init USB_IP */
/* enable USB power on Pwrctrl CR2 register */
HAL_PWREx_EnableVddUSB();
/* Link The driver to the stack */
hpcd_USB_FS.pData = pdev;
pdev->pData = &hpcd_USB_FS;
hpcd_USB_FS.Instance = USB;
hpcd_USB_FS.Init.dev_endpoints = 8;
hpcd_USB_FS.Init.speed = PCD_SPEED_FULL;
hpcd_USB_FS.Init.ep0_mps = DEP0CTL_MPS_8;
hpcd_USB_FS.Init.phy_itface = PCD_PHY_EMBEDDED;
hpcd_USB_FS.Init.Sof_enable = DISABLE;
hpcd_USB_FS.Init.low_power_enable = DISABLE;
hpcd_USB_FS.Init.lpm_enable = DISABLE;
hpcd_USB_FS.Init.battery_charging_enable = DISABLE;
if (HAL_PCD_Init(&hpcd_USB_FS) != HAL_OK)
{
Error_Handler();
}
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x00 , PCD_SNG_BUF, 0x18);
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x80 , PCD_SNG_BUF, 0x58);
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x81 , PCD_SNG_BUF, 0xC0);
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x01 , PCD_SNG_BUF, 0x110);
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x82 , PCD_SNG_BUF, 0x100);
return USBD_OK;
}
After that I could use the new endpoints for data transfer.
I've been developing an application for the NXP LPC1788 microcontroller that involves communicating with a host PC using USB.
In general the application works fine. However, something I've noticed with multiple different computers is that if the microcontroller is powered-on and connected to a powered-off computer, and the computer is then turned on, the computer will not boot. Unplugging the microcontroller and trying to boot the computer again will resolve the problem.
Why is the microcontroller preventing the computer from booting? I've Googled the problem and it seems that this issue occurs when Windows tries to treat a USB device as bootable when it shouldn't be.
Is there a way I can prevent this happening with my application? What information should I provide to help others diagnose the problem?
In case it's useful, below is the micro's device descriptor:
/* USB Standard Device Descriptor */
const uint8_t USB_DeviceDescriptor[] = {
USB_DEVICE_DESC_SIZE, /* bLength */
USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType */
WBVAL(0x0200), /* 2.00 */ /* bcdUSB */
0xFF, /* bDeviceClass */
0x00, /* bDeviceSubClass */
0x00, /* bDeviceProtocol */
USB_MAX_PACKET_SIZE, /* bMaxPacketSize0 */
WBVAL(<...>), /* idVendor */
WBVAL(<...>), /* idProduct */
WBVAL(0x0100), /* 1.00 */ /* bcdDevice */
0x04, /* iManufacturer */
0x30, /* iProduct */
0x42, /* iSerialNumber */
0x01 /* bNumConfigurations */
};
Here is the configuration descriptor:
const uint8_t USB_ConfigDescriptor[] = {
/* Configuration 1 */
USB_CONFIGURATION_DESC_SIZE, /* bDescriptorType */
USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType */
WBVAL( /* wTotalLength */
1*USB_CONFIGURATION_DESC_SIZE +
1*USB_INTERFACE_DESC_SIZE +
2*USB_ENDPOINT_DESC_SIZE
),
0x01, /* bNumInterfaces */
0x01, /* bConfigurationValue */
0x00, /* iConfiguration */
USB_CONFIG_SELF_POWERED /*|*/ /* bmAttributes */
/*USB_CONFIG_REMOTE_WAKEUP*/,
USB_CONFIG_POWER_MA(100), /* bMaxPower */
/* Interface 0, Alternate Setting 0, MSC Class */
USB_INTERFACE_DESC_SIZE, /* bLength */
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
0x00, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x02, /* bNumEndpoints */
0xFF, /* bInterfaceClass */
0x0, /* bInterfaceSubClass */
0x0, /* bInterfaceProtocol */
0x5C, /* iInterface */
/* Bulk In Endpoint (data) */
USB_ENDPOINT_DESC_SIZE, /* bLength */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
USB_ENDPOINT_IN(2), /* bEndpointAddress */
USB_ENDPOINT_TYPE_BULK, /* bmAttributes */
WBVAL(0x0040), /* wMaxPacketSize */
0x0, /* bInterval */
/* Bulk Out Endpoint (data) */
USB_ENDPOINT_DESC_SIZE, /* bLength */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
USB_ENDPOINT_OUT(2), /* bEndpointAddress */
USB_ENDPOINT_TYPE_BULK, /* bmAttributes */
WBVAL(0x0040), /* wMaxPacketSize */
0x0, /* bInterval */
/* Terminator */
0 /* bLength */
};
EDIT
String descriptor (replaced letters with underscores):
const uint8_t USB_StringDescriptor[] = {
/* Index 0x00: LANGID Codes */
0x04, /* bLength */
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
WBVAL(0x0409), /* US English */ /* wLANGID */
/* Index 0x04: Manufacturer */
0x2C, /* bLength */
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
'_',0,
'_',0,
'_',0,
' ',0,
'_',0,
'_',0,
'_',0,
'_',0,
'_',0,
'_',0,
'_',0,
'_',0,
'_',0,
'_',0,
' ',0,
'_',0,
'_',0,
'_',0,
'_',0,
'_',0,
' ',0,
/* Index 0x30: Product */
0x14, /* bLength */
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
'_',0,
'_',0,
'_',0,
'_',0,
'_',0,
'_',0,
'_',0,
'_',0,
' ',0,
/* Index 0x42: Serial Number */
0x1A, /* bLength */
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
'0',0,
'0',0,
'0',0,
'0',0,
'0',0,
'0',0,
'0',0,
'0',0,
'0',0,
'0',0,
'0',0,
'0',0,
/* Index 0x5C: Interface 0, Alternate Setting 0 */
0x0E, /* bLength */
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
'0',0,
'0',0,
'0',0,
'0',0,
'0',0,
'0',0,
};
EDIT 2
Changing iManufacturer, iProduct and iSerialNumber to 0x1, 0x2 and 0x3 respectively makes it so that USBLyzer doesn't fetch the string descriptors, which isn't a promising sign. If I use the original index values, it does. I haven't checked how this affects the computer's ability to boot.
EDIT 3
I noticed that my iSerialNumber and iInterface parameters were 2 off. 0x30+0x14 = 0x44.
I'll see if that's fixed anything.
EDIT 4
After correcting the two parameters above, my issue seems to be fixed. TurboJ brought my attention to the fact that index values are meant to be small e.g. 0x1, 0x2, 0x3...
NXP seem to have a different idea of how to do it and I copied their way, but I think I can modify the code at some later time to make it work like it does for other USB devices.
0x04, /* iManufacturer */
0x30, /* iProduct */
0x42, /* iSerialNumber */
Your iProduct and iSerialNumber bytes seem to be off - these are index numbers, ususally small ones. Your descriptor would require 66 strings in the string descriptor. These unusual high numbers could cause an overflow in a BIOS USB implementation.
I corrected my problem and improved over NXP's method.
NXP's example USB projects kept all the string descriptors in a single array. They then implemented the "USB Get Descriptor" functionality in the following way:
case USB_STRING_DESCRIPTOR_TYPE:
EP0Data.pData = (uint8_t *)USB_StringDescriptor + SetupPacket.wValue.WB.L;
len = ((USB_STRING_DESCRIPTOR *)EP0Data.pData)->bLength;
break;
This meant that they had to specify iManufacturer, iProduct, etc. using ridiculous index values such as (in their case) 0x04, 0x20 and 0x48.
In my own code, I modified their approach. I maintain the string descriptors as an array of arrays:
const uint8_t USB_StringDescriptor[][100] = {
{
/* Index 0x00: LANGID Codes */
0x04, /* bLength */
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
WBVAL(0x0409), /* US English */ /* wLANGID */
},
{
/* Index 0x01: Manufacturer */
0x2A, /* bLength */
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
// ...
},
{
/* Index 0x02: Product */
0x12, /* bLength */
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
// ...
},
{
/* Index 0x03: Serial Number */
0x1A, /* bLength */
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
// ...
},
{
/* Index 0x04: Interface 0, Alternate Setting 0 */
0x0E, /* bLength */
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
// ...
}
};
I then change the way that string descriptor requests are processed:
case USB_STRING_DESCRIPTOR_TYPE:
EP0Data.pData = (uint8_t *)USB_StringDescriptor[SetupPacket.wValue.WB.L];
len = ((USB_STRING_DESCRIPTOR *)EP0Data.pData)->bLength;
break;
This way, within my device descriptor I can specify iManufacturer, iProduct, etc. as simply 0x01, 0x02...
I've tested this with two computers and both are able to boot successfully when my application is connected and running.
Has anyone been able to authenticate with this card using this encryption method? I have no clue what to do after selecting the app and starting the authentication. Below is my code. Only copied the relevant parts and used example KEY and SELECT_APP
//AUTHENTICATION COMMANDS
private static final byte[] NATIVE_AUTHENTICATION_KEY = new byte[] {
(byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x04, (byte) 0x05,
(byte) 0x06, (byte) 0x07, (byte) 0x08, (byte) 0x09, (byte) 0x0A,
(byte) 0x0B, (byte) 0x0C, (byte) 0x0D, (byte) 0x0E, (byte) 0x0F,
(byte) 0x00 };
private static final byte[] START_AUTHENTICATION_COMMAND = new byte[] {
(byte) 0xAA, (byte) 0x01 };
private static byte[] SELECT_APPLICATION = { (byte) 0x5A, (byte) 0x01,
(byte) 0x02, (byte) 0x03 };
//AUTHENTICATION FUNCTION
private void StartAuthentication(Tag tag) {
try {
IsoDep.get(tag).connect();
byte[] response = IsoDep.get(tag)
.transceive(SELECT_APPLICATION);
Log.e("SELECT_APP", ByteArrayToHexString(response));
byte[] response2 = IsoDep.get(tag).transceive(START_AUTHENTICATION_COMMAND);
Log.e("START_AUTH", ByteArrayToHexString(response2));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
SELECT_APP returns 0x00 (OK) and START_AUTH returns 0xAF+(16bit). What to do after getting that?
If your answer returns 0xAF means extra info is pending.
Send 0xAF till you get 0x00 in retun, 0xAF means more data in return is pending.
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.
For those of you out there that come across this thread, because you are having similar problems with RNDIS and windows code 10 errors, using the built in configfs libcomposite device, after tons of googling, and going over code on the internet, code in the libcomposite module..... I found that instead of patching the driver I could work around this if I force loaded the usb_f_rndis module directly after libcomposite module, this forces usb_f_rndis to first and second iad slot. The rest of the modules for libcomposite devices will load, as you add the devices in configfs, and Windows will be happy with it.
Also, to force windows to load the right driver, make sure you set up the os_desc stuff. There is a nice guide that goes over that here: http://irq5.io/2016/12/22/raspberry-pi-zero-as-multiple-usb-gadgets/
As I said in my comment on the answer mentioning the preload workaround, I couldn't get preloading the usb_f_rndis module to make any difference when using configfs to set up a composite gadget.
I have found that the order in which the function directories are linked into the configuration directory makes a difference, however.
ln -s gadget/functions/acm.usb0 gadget/configs/c.1
ln -s gadget/functions/rndis.usb0 gadget/configs/c.1
Leaves me with a functional USB serial port, but broken RNDIS adapter showing error code 10.
ln -s gadget/functions/rndis.usb0 gadget/configs/c.1
ln -s gadget/functions/acm.usb0 gadget/configs/c.1
Gives me both a functional serial port and RNDIS adapter.
The question is of course how stable this will be over time. I suspect it could be sort of a fluke, similar to what the usb_f_rndis preload trick appears to be.
This was on Debian 10.9 with Linux raspberrypi 5.15.74-v7l+, by the way.