Hello, I am trying to add a second MSC interface to my USB device, but despite that the second interface is identified by Windows, I get a problem notification (the respective endpoint is never addressed). I just don't see what's wrong. Do you? Thanks.
/* USB Standard Device Descriptor */ const U8 USB_DeviceDescriptor[] = { USB_DEVICE_DESC_SIZE, /* bLength */ USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType */ WBVAL(0x0200), /* 2.00 */ /* bcdUSB */ 0x00, /* bDeviceClass */ 0x00, /* bDeviceSubClass */ 0x00, /* bDeviceProtocol */ USB_MAX_PACKET0, /* bMaxPacketSize0 */ WBVAL(0xC251), /* idVendor */ WBVAL(0x1D03), /* idProduct */ WBVAL(0x0100), /* 1.00 */ /* bcdDevice */ 0x01, /* iManufacturer */ 0x02, /* iProduct */ 0x03, /* iSerialNumber */ 0x01 /* bNumConfigurations: one possible configuration*/ }; /* USB Configuration Descriptor */ /* All Descriptors (Configuration, Interface, Endpoint, Class, Vendor) */ const U8 USB_ConfigDescriptor[] = { /* Configuration 1 */ USB_CONFIGUARTION_DESC_SIZE, /* bLength */ USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType */ WBVAL( /* wTotalLength */ 1*USB_CONFIGUARTION_DESC_SIZE + 2*USB_INTERFACE_DESC_SIZE + 4*USB_ENDPOINT_DESC_SIZE ), 0x02, /* bNumInterfaces */ 0x01, /* bConfigurationValue: 0x01 is used to select this configuration */ 0x00, /* iConfiguration: no string to describe this configuration */ USB_CONFIG_SELF_POWERED /*|*/ /* bmAttributes */ /*USB_CONFIG_REMOTE_WAKEUP*/, USB_CONFIG_POWER_MA(100), /* bMaxPower, device power consumption is 100 mA */ /* Interface 0, Alternate Setting 0, MSC Class */ USB_INTERFACE_DESC_SIZE, /* bLength */ USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ 0x01, /* bInterfaceNumber */ 0x00, /* bAlternateSetting */ 0x02, /* bNumEndpoints */ USB_DEVICE_CLASS_STORAGE, /* bInterfaceClass */ MSC_SUBCLASS_SCSI, /* bInterfaceSubClass */ MSC_PROTOCOL_BULK_ONLY, /* bInterfaceProtocol */ 0x04, /* iInterface */ /* Endpoint, EP2 Bulk IN */ USB_ENDPOINT_DESC_SIZE, /* bLength */ USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ USB_ENDPOINT_IN(2), /* bEndpointAddress */ USB_ENDPOINT_TYPE_BULK, /* bmAttributes */ WBVAL(0x0040), /* wMaxPacketSize */ 0x00, /* bInterval: ignore for Bulk transfer */ /* Endpoint, EP2 Bulk OUT */ USB_ENDPOINT_DESC_SIZE, /* bLength */ USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ USB_ENDPOINT_OUT(2), /* bEndpointAddress */ USB_ENDPOINT_TYPE_BULK, /* bmAttributes */ WBVAL(0x0040), /* wMaxPacketSize */ 0x00, /* bInterval: ignore for Bulk transfer */ /* Interface 1, Alternate Setting 0, MSC Class */ USB_INTERFACE_DESC_SIZE, /* bLength */ USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ 0x02, /* bInterfaceNumber */ 0x00, /* bAlternateSetting */ 0x02, /* bNumEndpoints */ USB_DEVICE_CLASS_STORAGE, /* bInterfaceClass */ MSC_SUBCLASS_SCSI, /* bInterfaceSubClass */ MSC_PROTOCOL_BULK_ONLY, /* bInterfaceProtocol */ 0x05, /* iInterface */ /* Endpoint, EP3 Bulk IN */ USB_ENDPOINT_DESC_SIZE, /* bLength */ USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ USB_ENDPOINT_IN(3), /* bEndpointAddress */ USB_ENDPOINT_TYPE_BULK, /* bmAttributes */ WBVAL(0x0040), /* wMaxPacketSize */ 0x00, /* bInterval: ignore for Bulk transfer */ /* Endpoint, EP3 Bulk OUT */ USB_ENDPOINT_DESC_SIZE, /* bLength */ USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ USB_ENDPOINT_OUT(3), /* bEndpointAddress */ USB_ENDPOINT_TYPE_BULK, /* bmAttributes */ WBVAL(0x0040), /* wMaxPacketSize */ 0x00, /* bInterval: ignore for Bulk transfer */ /* Terminator */ 0 /* bLength */ }; /* USB String Descriptor (optional) */ const U8 USB_StringDescriptor[] = { /* Index 0x00: LANGID Codes */ 0x04, /* bLength */ USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */ WBVAL(0x0409), /* US English */ /* wLANGID */ /* Index 0x01: Manufacturer */ (13*2 + 2), /* bLength (13 Char + Type + lenght) */ USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */ 'K',0, 'e',0, 'i',0, 'l',0, ' ',0, 'S',0, 'o',0, 'f',0, 't',0, 'w',0, 'a',0, 'r',0, 'e',0, /* Index 0x02: Product */ (19*2 + 2), /* bLength ( 19 Char + Type + lenght) */ USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */ 'U',0,// 'K',0, //Device manager => Universal Serial Bus controllers 'S',0,// 'e',0, 'B',0,// 'i',0, ' ',0,// 'l',0, ' ',0, 'L',0,// 'M',0, 'P',0,// 'C',0, 'C',0,// 'B',0, '2',0,// '2',0, '4',0,// '4',0, '7',0,// '0',0, '8',0,// '0',0, ' ',0, 'M',0, 'e',0, 'm',0, 'o',0, 'r',0, 'y',0, /* Index 0x03: Serial Number */ (12*2 + 2), /* bLength (12 Char + Type + lenght) */ USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */ '0',0, /* allowed characters are */ '0',0, /* 0x0030 - 0x0039 ('0'..'9') */ '0',0, /* 0x0041 - 0x0046 ('A'..'F') */ '1',0, /* length >= 26 */ 'A',0, '0',0, '0',0, '0',0, '0',0, '0',0, '0',0, '0',0, /* Index 0x04: Interface 0, Alternate Setting 0 */ ( 9*2 + 2), /* bLength (6 Char + Type + lenght) */ USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */ 'I',0, '/',0, 'O',0, ' ',0, 'D',0, 'r',0, 'i',0, 'v',0, 'e',0, /* Index 0x05: Interface 1, Alternate Setting 0 */ ( 12*2 + 2), /* bLength (6 Char + Type + lenght) */ USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */ 'O',0, 'u',0, 't',0, 'p',0, 'u',0, 't',0, ' ',0, 'D',0, 'r',0, 'i',0, 'v',0, 'e',0, };
Hello Tamir Michael,
I assume that you are using a LPC24xx.
Please note that logical endpoint 3 (physical endpoint 6,7) is a isochronous Endpoint and not a bulk endpoint.
Please check Chapter 13: LPC24XX USB device controller, 4. Fixed endpoint configuration in the LPC24xx user manual for endpoint configuration.
Best Regards, Martin Guenther
Ho, thanks Martin. I will certainly avail myself to do that right away! or: TRTFM !
In addition to Martin,
"the respective endpoint is never addressed"
On the usbcfg.h, - Did you set the number of interfaces, USB_IF_NUM, to 2? - Did you enable the Endpoint Event, USB_EP_EVENT, for the endpoint?
Keil provides easy user interface to set up these parameters - Configuration Wizard. Open usbcfg.h on uVision, and click on the bottom tab to switch to Configuration Wizard.
Tsuneo
Hello Tsuneo,
Yes I did all that - I am now working with logical endpoints 2 and 5, which are bulk only for the LPC2478. both are now addressed, but the second interface hangs the system and eventually reports an error. So I understand that in theory, I can map a device to 2 drives? But, what if I want to unmount the device using SCSI commands? Am I current in assuming the I need to fail the "test unit ready" command, and to report an unmount in the ensuing "request sense"? Sorry for the basic question, I never had to work with SCSI before.
The two MSC interfaces work independently. That is, you have to implement two pairs of these handlers, so as the pairs work independently. - Bulk endpoint handler - BOT handler (CBW-CSW) - SCSI command handler
Maybe some of the handlers for the second interface are still mixed up with the first one.
When you implement it with multiple LUN (Logical Unit Number) on a single MSC interface, it's much simpler. Just dispatch the drive by LUN at SCSI handler. You don't need to touch to any other part of the implementation.
Tsuneo, Thanks for your reply. I managed to get it to work using SCSI commands that unmount the drive while the device updates the file system but I am not satisfied. I could have done the same with the soft-connect pin of the LPC2478. I am interested in the LUN solution: I had a look at the Keil USB software and to the best of my judgment, it is not supported. apart from that, what do you mean by "Just dispatch the drive by LUN at SCSI handler" ?
thanks for your advise
View all questions in Keil forum