new usb device class

The official pyboard running MicroPython.
This is the reference design and main target board for MicroPython.
You can buy one at the store.
Target audience: Users with a pyboard.
Post Reply
pagano.paganino
Posts: 89
Joined: Fri Sep 11, 2015 10:47 pm
Location: Italy

new usb device class

Post by pagano.paganino » Thu Nov 12, 2015 3:43 pm

Hello,
How can I add a new class USB device ("CCID") in combo with CDC and MSC?
Tips on where to start to implement something like that?

Special arrangements for the implementation of pyboard?

thanks,
Francesco

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: new usb device class

Post by dhylands » Thu Nov 12, 2015 4:31 pm

I've never messed around with the descriptors and stuff to add a new class, but the gist of what you need to do is this (if its even possible):

1 - modify the USB descriptors to advertise that the device supports CCID. These can be found in the stmhal/usbd_desc.h/.c files.

2 - Add a new class driver that supports the combination of descriptors you want to support. We're currently using usbdev/class/src/usbd_cdc_msc_hid.c You'd need to create a new file that implements the portions that you want.

3 - When initializing the USB device in the pyb_usb_dev_init function, call into your new code to register callbacks etc to handle the new interface.

While developing the USB stuff, you'll want to use a HW UART for the REPL, since the USB-serial will almost certainly be broken. One simple way to add a UART REPL is to change the stmhal/boards/PYBV10/mpconfigboard.h (assumes you're using the pyboard) and add these 2 lines:

Code: Select all

#define MICROPY_HW_UART_REPL        PYB_UART_6
#define MICROPY_HW_UART_REPL_BAUD   115200
which will setup a UART REPL on UART6.

pagano.paganino
Posts: 89
Joined: Fri Sep 11, 2015 10:47 pm
Location: Italy

Re: new usb device class

Post by pagano.paganino » Thu Nov 12, 2015 10:10 pm

Hi Dave,
for ccid class i need 3 ep, 1 in, 1 out and 1 for int.
hid and msc implementation on pyboard only use 1 for in e 1 for out, where can i find the third ep for int?
Any hint?

Thanks,
Francesco

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: new usb device class

Post by dhylands » Thu Nov 12, 2015 10:38 pm

I think you'll have to disable one of CDC or MSC then.

Looking at the 405 datasheet, there are only a total 3 IN endpoints, and 3 OUT endpoints (and these can be configured to be bulk or INT).

Personally, I'd recommend disabling MSC and use CDC + CCID. You can use something like rshell to copy files into and out of the pyboard using CDC.

pagano.paganino
Posts: 89
Joined: Fri Sep 11, 2015 10:47 pm
Location: Italy

Re: new usb device class

Post by pagano.paganino » Tue Nov 17, 2015 10:54 pm

Hi Dave,
this is my configuration:

Code: Select all


#define CCID_BULK_EP_MAX_PACKET               64
#define CCID_INTR_EP_MAX_PACKET               8

#define CCID_BULK_EPIN_SIZE          CCID_BULK_EP_MAX_PACKET
#define CCID_BULK_EPOUT_SIZE         CCID_BULK_EP_MAX_PACKET
#define CCID_INTR_EPIN_SIZE          CCID_INTR_EP_MAX_PACKET

#define CCID_BULK_OUT_EP_WITH_CDC             0x01
#define CCID_BULK_IN_EP_WITH_CDC              0x81
#define CCID_INTR_IN_EP_WITH_CDC              0x02

#define CDC_CCID_TEMPLATE_CONFIG_DESC_SIZE (159)

#define CCID_IFACE_NUM_WITH_CDC (0)
#define CDC_IFACE_NUM_WITH_CCID (1)

// USB CDC CCID device Configuration Descriptor
static const uint8_t cdc_ccid_template_config_desc[CDC_CCID_TEMPLATE_CONFIG_DESC_SIZE] = {
    //--------------------------------------------------------------------------
    // Configuration Descriptor
    0x09,   // bLength: Configuration Descriptor size
    USB_DESC_TYPE_CONFIGURATION, // bDescriptorType: Configuration
    LOBYTE(CDC_CCID_TEMPLATE_CONFIG_DESC_SIZE), // wTotalLength: no of returned bytes
    HIBYTE(CDC_CCID_TEMPLATE_CONFIG_DESC_SIZE),
    0x03,   // bNumInterfaces: 3 interfaces
    0x01,   // bConfigurationValue: Configuration value
    0x04,   // iConfiguration: Index of string descriptor describing the configuration
    0x80,   // bmAttributes: bus powered; 0xc0 for self powered
    0xfa,   // bMaxPower: in units of 2mA

    // CCID only has 1 interface so doesn't need an IAD
    /********************  CCID **** interface ********************/
    0x09,   /* bLength: Interface Descriptor size */
    USB_DESC_TYPE_INTERFACE,   /* bDescriptorType: */
    CCID_IFACE_NUM_WITH_CDC,   /* bInterfaceNumber: Number of Interface */
    0x00,   /* bAlternateSetting: Alternate setting */
    0x03,   /* bNumEndpoints: 3 endpoints used */
    0x0B,   /* bInterfaceClass: user's interface for CCID */
    0x00,   /* bInterfaceSubClass : */
    0x00,   /* nInterfaceProtocol : None */
    0x05,   /* iInterface: */

    /*******************  CCID class descriptor ********************/
    0x36,   /* bLength: CCID Descriptor size */
    0x21,   /* bDescriptorType: Functional Descriptor type. */
    0x10,   /* bcdCCID(LSB): CCID Class Spec release number (1.00) */
    0x01,   /* bcdCCID(MSB) */

    0x00,   /* bMaxSlotIndex :highest available slot on this device */
    0x03,   /* bVoltageSupport: bit Wise OR for 01h-5.0V 02h-3.0V
            04h 1.8V*/

    0x02,0x00,0x00,0x00, /* dwProtocols: 0001h = Protocol T=0, 0002h = Protocol T=1 */
    0x68,0x10,0x00,0x00, /* dwDefaultClock: 3.6Mhz = 3600kHz = 0x0E10,
                         for 4 Mhz the value is (0x00000FA0), 4.2 Mhz (0x00001068) :
                         This is used in ETU and waiting time calculations*/
    0x68,0x10,0x00,0x00, /* dwMaximumClock: Maximum supported ICC clock frequency
                         in KHz. So, 3.6Mhz = 3600kHz = 0x0E10,
                         4 Mhz (0x00000FA0), 4.2 Mhz (0x00001068):*/
    0x00,   /* bNumClockSupported : no setting from PC
            If the value is 00h, the
            supported clock frequencies are assumed to be the
            default clock frequency defined by dwDefaultClock
            and the maximum clock frequency defined by
            dwMaximumClock */

    0x1A,0x2C,0x00,0x00, /* dwDataRate: Default ICC I/O data rate in bps
                         9677 bps = 0x25CD
                         for example 10752 bps (0x00002A00), 11290 bps = (0x00002C1A) */

    0x1A,0x2C,0x00,0x00, /* dwMaxDataRate: Maximum supported ICC I/O data
                         rate in bps */
    0x00,                 /* bNumDataRatesSupported :
                          The number of data rates that are supported by the CCID
                          If the value is 00h, all data rates between the default
                          data rate dwDataRate and the maximum data rate
                          dwMaxDataRate are supported.
                          Dont support GET_CLOCK_FREQUENCIES
                          */

    0xFE,0x00,0x00,0x00,   /* dwMaxIFSD: 0 (T=0 only) 0x000000FE (T=1)  */
    0x00,0x00,0x00,0x00,   /* dwSynchProtocols  */
    0x00,0x00,0x00,0x00,   /* dwMechanical: no special characteristics */

    0x38,0x00,EXCHANGE_LEVEL_FEATURE,0x00,
    /* dwFeatures: clk, baud rate, voltage : automatic */
    /* 00000008h Automatic ICC voltage selection
    00000010h Automatic ICC clock frequency change
    00000020h Automatic baud rate change according to
    active parameters provided by the Host or self
    determined 00000100h CCID can set
    ICC in clock stop mode

    Only one of the following values may be present to
    select a level of exchange:
    00010000h TPDU level exchanges with CCID
    00020000h Short APDU level exchange with CCID
    00040000h Short and Extended APDU level exchange
    If none of those values : character level of exchange*/
    0x0F,0x01,0x00,0x00,  /* dwMaxCCIDMessageLength: Maximum block size + header*/
                          /* 261 + 10   */

    0x00,   /* bClassGetResponse*/
    0x00,   /* bClassEnvelope */
    0x00,0x00,  /* wLcdLayout : 0000h no LCD. */
    0x00,   /* bPINSupport : no PIN verif and modif  */
    0x01,   /* bMaxCCIDBusySlots */

            /********************  CCID   Endpoints ********************/
    0x07,   /*Endpoint descriptor length = 7*/
    USB_DESC_TYPE_ENDPOINT,   /*Endpoint descriptor type */
    CCID_BULK_IN_EP_WITH_CDC,   /*Endpoint address (IN, address 1) */
    0x02,   /*Bulk endpoint type */
    LOBYTE(CCID_BULK_EPIN_SIZE),
    HIBYTE(CCID_BULK_EPIN_SIZE),
    0x00,   /*Polling interval in milliseconds */

    0x07,   /*Endpoint descriptor length = 7 */
    USB_DESC_TYPE_ENDPOINT,   /*Endpoint descriptor type */
    CCID_BULK_OUT_EP_WITH_CDC,   /*Endpoint address (OUT, address 1) */
    0x02,   /*Bulk endpoint type */
    LOBYTE(CCID_BULK_EPOUT_SIZE),
    HIBYTE(CCID_BULK_EPOUT_SIZE),
    0x00,   /*Polling interval in milliseconds*/


    0x07,   /*bLength: Endpoint Descriptor size*/
    USB_DESC_TYPE_ENDPOINT,   /*bDescriptorType:*/
    CCID_INTR_IN_EP_WITH_CDC,    /*bEndpointAddress: Endpoint Address (IN)*/
    0x03,   /* bmAttributes: Interrupt endpoint */
    LOBYTE(CCID_INTR_EPIN_SIZE),
    HIBYTE(CCID_INTR_EPIN_SIZE),
    0x18,    /*Polling interval in milliseconds */

    //==========================================================================
    // Interface Association for CDC VCP
    0x08,   // bLength: 8 bytes
    USB_DESC_TYPE_ASSOCIATION, // bDescriptorType: IAD
    CDC_IFACE_NUM_WITH_CCID, // bFirstInterface: first interface for this association
    0x02,   // bInterfaceCount: nummber of interfaces for this association
    0x02,   // bFunctionClass: Communication Interface Class
    0x02,   // bFunctionSubClass: Abstract Control Model
    0x01,   // bFunctionProtocol: Common AT commands
    0x00,   // iFunction: index of string for this function

            //--------------------------------------------------------------------------
            // Interface Descriptor
    0x09,   // bLength: Interface Descriptor size
    USB_DESC_TYPE_INTERFACE, // bDescriptorType: Interface
    CDC_IFACE_NUM_WITH_CCID, // bInterfaceNumber: Number of Interface
    0x00,   // bAlternateSetting: Alternate setting
    0x01,   // bNumEndpoints: One endpoints used
    0x02,   // bInterfaceClass: Communication Interface Class
    0x02,   // bInterfaceSubClass: Abstract Control Model
    0x01,   // bInterfaceProtocol: Common AT commands
    0x00,   // iInterface:

            // Header Functional Descriptor
    0x05,   // bLength: Endpoint Descriptor size
    0x24,   // bDescriptorType: CS_INTERFACE
    0x00,   // bDescriptorSubtype: Header Func Desc
    0x10,   // bcdCDC: spec release number
    0x01,   // ?

            // Call Management Functional Descriptor
    0x05,   // bFunctionLength
    0x24,   // bDescriptorType: CS_INTERFACE
    0x01,   // bDescriptorSubtype: Call Management Func Desc
    0x00,   // bmCapabilities: D0+D1
    CDC_IFACE_NUM_WITH_CCID + 1,   // bDataInterface: 1

                                  // ACM Functional Descriptor
    0x04,   // bFunctionLength
    0x24,   // bDescriptorType: CS_INTERFACE
    0x02,   // bDescriptorSubtype: Abstract Control Management desc
    0x02,   // bmCapabilities

            // Union Functional Descriptor
    0x05,   // bFunctionLength
    0x24,   // bDescriptorType: CS_INTERFACE
    0x06,   // bDescriptorSubtype: Union func desc
    CDC_IFACE_NUM_WITH_CCID + 0,   // bMasterInterface: Communication class interface
    CDC_IFACE_NUM_WITH_CCID + 1,   // bSlaveInterface0: Data Class Interface

                                  // Endpoint 2 Descriptor
    0x07,                           // bLength: Endpoint Descriptor size
    USB_DESC_TYPE_ENDPOINT,         // bDescriptorType: Endpoint
    CDC_CMD_EP,                     // bEndpointAddress
    0x03,                           // bmAttributes: Interrupt
    LOBYTE(CDC_CMD_PACKET_SIZE),    // wMaxPacketSize:
    HIBYTE(CDC_CMD_PACKET_SIZE),
    0x20,                           // bInterval: polling interval in frames of 1ms

                                    //--------------------------------------------------------------------------
                                    // Data class interface descriptor
    0x09,   // bLength: Endpoint Descriptor size
    USB_DESC_TYPE_INTERFACE, // bDescriptorType: interface
    CDC_IFACE_NUM_WITH_CCID + 1,   // bInterfaceNumber: Number of Interface
    0x00,   // bAlternateSetting: Alternate setting
    0x02,   // bNumEndpoints: Two endpoints used
    0x0A,   // bInterfaceClass: CDC
    0x00,   // bInterfaceSubClass: ?
    0x00,   // bInterfaceProtocol: ?
    0x00,   // iInterface:

            // Endpoint OUT Descriptor
    0x07,                               // bLength: Endpoint Descriptor size
    USB_DESC_TYPE_ENDPOINT,             // bDescriptorType: Endpoint
    CDC_OUT_EP,                         // bEndpointAddress
    0x02,                               // bmAttributes: Bulk
    LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),// wMaxPacketSize:
    HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
    0x00,                               // bInterval: ignore for Bulk transfer

                                        // Endpoint IN Descriptor
    0x07,                               // bLength: Endpoint Descriptor size
    USB_DESC_TYPE_ENDPOINT,             // bDescriptorType: Endpoint
    CDC_IN_EP,                          // bEndpointAddress
    0x02,                               // bmAttributes: Bulk
    LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),// wMaxPacketSize:
    HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
    0x00,                               // bInterval: ignore for Bulk transfer
};

but from:
USBD_CDC_MSC_HID_CCID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)  { 
... 
uncomment:
printf("SU: %x %x %x %x\n", req->bmRequest, req->bRequest, req->wValue, req->wIndex);
...
}

i see:
MicroPython v1.5 on 2015-11-17; PYBv1.0 with STM32F405RG
Type "help()" for more information.
>>> SU: a1 21 0 1
SU: 21 22 0 1
SU: 21 20 0 1
SU: a1 21 0 1
SU: a1 21 0 1
SU: a1 21 0 1
SU: a1 21 0 1
SU: a1 21 0 1
SU: 21 20 0 1
SU: a1 21 0 1
SU: 21 22 3 1
SU: 21 20 0 1
SU: a1 21 0 1

req->wIndex "0" is missing, any suggest?

Attached the screen capture of device manager, i can see the cdc and ccid device correctly configured and ready to use, but isn't corrent ...

Thanks,
Francesco

Attachments
devices.PNG
devices.PNG (8.38 KiB) Viewed 10524 times

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: new usb device class

Post by dhylands » Wed Nov 18, 2015 1:39 am

Sorry, but I'm not sure what the issue is.

My recommendation would be to hook this up to a linux machine and use lsusb -v to see what the descriptors look like. (and perhaps looks through http://www.beyondlogic.org/usbnutshell/usb5.shtml)

There is probably an equivalent tool under Windows, but its been a long time since I've done any active Windows development.

pagano.paganino
Posts: 89
Joined: Fri Sep 11, 2015 10:47 pm
Location: Italy

Re: new usb device class

Post by pagano.paganino » Fri Nov 20, 2015 10:32 pm

Someone else can help me?

pagano.paganino
Posts: 89
Joined: Fri Sep 11, 2015 10:47 pm
Location: Italy

Re: new usb device class

Post by pagano.paganino » Wed Nov 25, 2015 12:17 pm

Hi Dave,
dhylands wrote:I think you'll have to disable one of CDC or MSC then.

Looking at the 405 datasheet, there are only a total 3 IN endpoints, and 3 OUT endpoints (and these can be configured to be bulk or INT).

Personally, I'd recommend disabling MSC and use CDC + CCID. You can use something like rshell to copy files into and out of the pyboard using CDC.
As you counsel'm trying configuration ccid + CDC.
But I have some doubts, with 6 endpoints 3 input and 3 output specifically:

Code: Select all

#define CDC_IN_EP (0x83) 
#define CDC_OUT_EP (0x03) 
#define CDC_CMD_EP (0x82) 

#define CCID_BULK_IN_EP_WITH_CDC (0x81) 
#define CCID_BULK_OUT_EP_WITH CDC (0x01) 
#define CCID_INTR_IN_EP_WITH CDC (0x02)
I can not use 0x02 as the endpoint interrupts because it is an output, how can I do? suggestions?

Thanks,

pagano.paganino
Posts: 89
Joined: Fri Sep 11, 2015 10:47 pm
Location: Italy

Re: new usb device class

Post by pagano.paganino » Fri Dec 11, 2015 12:00 pm

Can someone help me?

Post Reply