Configfs composite gadget with CCID and mass storage

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux