Hi, I am trying to implement a composite USB device, which consists of a Smart card Chip Card Interface Device (CCID) and a mass storage device, on an embedded platform (ARM processor) using Configfs composite gadget. I was able to successfully setup the mass storage device but I am having some issues with the CCID part. My question is, is it possible to setup a USB composite device consisting of a smart card CCID and a mass storage device using Configfs? Or more generally speaking, how can I pass a class descriptor, specific to a particular interface, to Configfs? I am using kernel 3.14 with Configfs compiled into the kernel only with mass storage and FunctionFS support. Here is some background and what I have tried thus far... Using a previous implementation, I was able to successfully expose the embedded device as a CCID using gadgetfs and implementing the necessary user space application. I am hoping to improve on this by adding a mass storage device, and to me Configfs looks like the way to go. My idea is to use the mass_storage function of Configfs to expose the mass storage device and FunctionFS the expose the CCID. My current implementation is setup by using the following bash script (this is only for the CCID): #-------------------------------------------------------------------- CONFIG_HOME=/sys/kernel/config/usb_gadget mount -t configfs configfs /sys/kernel/config mkdir $CONFIG_HOME/g1 cd $CONFIG_HOME/g1 echo 0x0200 > bcdUSB echo 0x2A18 > idVendor echo 0x5000 > idProduct mkdir strings/0x409 echo "my-manufacturer" > strings/0x409/manufacturer echo "my-product" > strings/0x409/product echo "my-serialnumber" > strings/0x409/serialnumber mkdir functions/ffs.ccid mkdir configs/c.1 mkdir configs/c.1/strings/0x409 echo "Config 1" > configs/c.1/strings/0x409/configuration echo 250 > configs/c.1/MaxPower ln -s functions/ffs.ccid configs/c.1 mount -t functionfs ccid /dev/gadget #--------------------------------------------------------------------- After this, I tweaked the previous CCID user space implementation to only pass the interface, class, and endpoint descriptors to the control endpoint "ep0". But I get the following error from the kernel after I run the user space application: "ffs_do_desc() hid descriptor invalid length: 54 (descriptor 33)". This means that one of my descriptors, length 54, is not equal to the size of a hid_descriptor structure. It appears as if the problem lies with the class descriptor (USB specification http://www.usb.org/developers/docs/devclass_docs/DWG_Smart-Card_CCID_Rev110.pdf page 17). Digging around in the kernel code I found the problem (f_fs.c). The CCID descriptor is identified by a bDescriptorType value of 0x21 which happens to correspond to the HID_DT_HID (USB_TYPE_CLASS | 0x01) makro used to identify the type of descriptor in function ffs_do_desc(). The kernel therefore thinks I am passing a HID descriptor when in fact I am passing a Smart card CCID class descriptor. I suspect the question now boils down to, "How do I pass a class descriptor to Configfs"? The USB descriptors of my device should look like this: Device descriptor Configuration descriptor Interface descriptor (USB_CLASS_CSCID) Class descriptor Endpoint descriptor Endpoint descriptor Here is the output from lsusb when I used the gadgetfs implementation (I presume the new implementation should generate the same descriptors): Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 2.00 bDeviceClass 0 (Defined at Interface level) bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 64 idVendor 0x2a18 idProduct 0x5000 bcdDevice 3.14 iManufacturer 1 iProduct 2 iSerial 3 bNumConfigurations 1 Configuration Descriptor: bLength 9 bDescriptorType 2 wTotalLength 86 bNumInterfaces 1 bConfigurationValue 1 iConfiguration 4 bmAttributes 0x80 (Bus Powered) MaxPower 250mA Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 0 bAlternateSetting 0 bNumEndpoints 2 bInterfaceClass 11 Chip/SmartCard bInterfaceSubClass 0 bInterfaceProtocol 0 iInterface 5 ChipCard Interface Descriptor: bLength 54 bDescriptorType 33 bcdCCID 1.10 (Warning: Only accurate for version 1.0) nMaxSlotIndex 0 bVoltageSupport 7 5.0V 3.0V 1.8V dwProtocols 3 T=0 T=1 dwDefaultClock 5000 dwMaxiumumClock 5000 bNumClockSupported 1 dwDataRate 115200 bps dwMaxDataRate 115200 bps bNumDataRatesSupp. 1 dwMaxIFSD 254 dwSyncProtocols 00000000 dwMechanical 00000000 dwFeatures 0014047E Auto configuration based on ATR Auto activation on insert Auto voltage selection Auto clock change Auto baud rate change Auto parameter negotation made by CCID Auto IFSD exchange Short and extended APDU level exchange dwMaxCCIDMsgLen 65504 bClassGetResponse echo bClassEnvelope echo wlcdLayout none bPINSupport 0 bMaxCCIDBusySlots 1 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x01 EP 1 OUT bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0200 1x 512 bytes bInterval 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x82 EP 2 IN bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0200 1x 512 bytes bInterval 0 I was curious what would happen if I briefly convinced the kernel that my descriptor data was correct and removed the error checking from the ffs_do_desc() function for HID_DT_HID descriptors (this is the part of the code that is raising the error). The result was that the implementation works on Linux (I tested on Ubuntu 14.04 and was able to communicate with my device) but not on Windows. lsusb generates the same USB descriptor as shown above for the "hacked" implementation. This is obviously not a valid solution but the result of mere curiosity. Any help and suggestions will be much appreciated! Cheers, Pieter -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html