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:
bLength18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize064
idVendor 0x2a18
idProduct 0x5000
bcdDevice3.14
iManufacturer 1
iProduct2
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
bInterfaceNumber0
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass11 Chip/SmartCard
bInterfaceSubClass 0
bInterfaceProtocol 0
iInterface 5
ChipCard Interface Descriptor:
bLength54
bDescriptorType33
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