RE: Configfs composite gadget with CCID and mass storage

2015-10-08 Thread Frans-Pieter van Wyk
I managed to get the implementation working for us using the following dirty 
patch for kernel 3.14,
-
diff -u -r a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c
--- a/drivers/usb/gadget/f_fs.c 2014-06-11 21:02:49.0 +0200
+++ b/drivers/usb/gadget/f_fs.c 2015-10-08 11:34:29.177420065 +0200
@@ -1449,8 +1449,9 @@
break;
 
case HID_DT_HID:
-   pr_vdebug("hid descriptor\n");
-   if (length != sizeof(struct hid_descriptor))
+   pr_vdebug("hid or sc device class descriptor\n");
+   if (length != sizeof(struct hid_descriptor) &&
+   length != 0x36)
goto inv_length;
break;
 
-

It turns out that our main problem was passing the smart card device class 
descriptor to FunctionFS as the code in f_fs.c incorrectly identified our 
descriptor as a HID descriptor since HID_DT_HID == 0x21 which corresponds to 
the bDescriptorType value for a smart card device class descriptor. It looks 
like FunctionFS does not make provision for class descriptors specific to 
certain interfaces.

I also had to remove "USB wakeup signalling" from dwFeatures in our smart card 
class descriptor to get the implementation working on Windows.

This might help someone someday :-)

Cheers,
Pieter



--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


RE: Configfs composite gadget with CCID and mass storage

2015-10-06 Thread Frans-Pieter van Wyk
> ConfigFS is used to compose a gadget of existing functions.
> As far as I can tell there is no smart card CCID usb function in kernel, so 
> either you need to have your own out-of-tree implementation or implement it 
> in userspace with FunctionFS.

I also could not find a CCID usb function in the kernel so my intention is to 
implement it in user space with FunctionFS.

> FunctionFS is a specific USB function which forwards most of USB traffic to 
> userspace. FunctionFS can be composed into a gadget with ConfigFS, but, by 
> design, its function directory in ConfigFS is _empty_. In other words, if you
> 
> mkdir functions/ffs.ccid
> 
> you have empty functions/ffs.ccid. You need to mount corresponding FunctionFS 
> instance (ccid) and provide all the descriptors the way FunctionFS expects it.

I mounted the FunctionFS instance (ccid) by doing

mount -t functionfs ccid /dev/gadget

Note that "/dev/gadget" is not there because of GadgetFS. It is an empty 
directory. The mount is successful and "ep0" appears in "/dev/gadget". After 
the mount I start the user space application which writes the descriptors, as 
the structure "descriptors" listed below, to "/dev/gadget/ep0". The application 
only writes the interface descriptor, CCID class descriptor and endpoint 
descriptors.

struct {
  struct usb_functionfs_descs_head header;
  struct {
struct usb_interface_descriptor intf;
struct ccid_class_descriptor ccid;
struct usb_endpoint_descriptor_no_audio source; 
struct usb_endpoint_descriptor_no_audio sink;
  } __attribute__((packed)) fs_descs, hs_descs;
} __attribute__((packed)) descriptors;

Then I get the kernel error "invalid length: 54 (descriptor 33)". How should I 
pass the CCID class descriptor?

Thanks for the help,
Pieter

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Configfs composite gadget with CCID and mass storage

2015-10-06 Thread Frans-Pieter van Wyk
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