simtrace2/firmware/libcommon/source/usb.c

732 lines
26 KiB
C

/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
* Copyright (c) 2018-2019, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "board.h"
#include "simtrace.h"
#include "simtrace_usb.h"
#include "utils.h"
#include "USBD_HAL.h"
#include <cciddriverdescriptors.h>
#include <usb/common/dfu/usb_dfu.h>
#include <usb/device/dfu/dfu.h>
/*------------------------------------------------------------------------------
* USB String descriptors
*------------------------------------------------------------------------------*/
#include "usb_strings_generated.h"
// the index of the strings (must match the order in usb_strings.txt)
enum strDescNum {
// static strings from usb_strings
MANUF_STR = 1,
PRODUCT_STRING,
SNIFFER_CONF_STR,
CCID_CONF_STR,
PHONE_CONF_STR,
MITM_CONF_STR,
CARDEM_USIM1_INTF_STR,
CARDEM_USIM2_INTF_STR,
CARDEM_USIM3_INTF_STR,
CARDEM_USIM4_INTF_STR,
// runtime strings
SERIAL_STR,
VERSION_CONF_STR,
VERSION_STR,
// count
STRING_DESC_CNT
};
/** array of static (from usb_strings) and runtime (serial, version) USB strings
*/
static const unsigned char *usb_strings_extended[ARRAY_SIZE(usb_strings) + 3];
/* USB string for the serial (using 128-bit device ID) */
static unsigned char usb_string_serial[] = {
USBStringDescriptor_LENGTH(32),
USBGenericDescriptor_STRING,
USBStringDescriptor_UNICODE('0'),
USBStringDescriptor_UNICODE('0'),
USBStringDescriptor_UNICODE('1'),
USBStringDescriptor_UNICODE('1'),
USBStringDescriptor_UNICODE('2'),
USBStringDescriptor_UNICODE('2'),
USBStringDescriptor_UNICODE('3'),
USBStringDescriptor_UNICODE('3'),
USBStringDescriptor_UNICODE('4'),
USBStringDescriptor_UNICODE('4'),
USBStringDescriptor_UNICODE('5'),
USBStringDescriptor_UNICODE('5'),
USBStringDescriptor_UNICODE('6'),
USBStringDescriptor_UNICODE('6'),
USBStringDescriptor_UNICODE('7'),
USBStringDescriptor_UNICODE('7'),
USBStringDescriptor_UNICODE('8'),
USBStringDescriptor_UNICODE('8'),
USBStringDescriptor_UNICODE('9'),
USBStringDescriptor_UNICODE('9'),
USBStringDescriptor_UNICODE('a'),
USBStringDescriptor_UNICODE('a'),
USBStringDescriptor_UNICODE('b'),
USBStringDescriptor_UNICODE('b'),
USBStringDescriptor_UNICODE('c'),
USBStringDescriptor_UNICODE('c'),
USBStringDescriptor_UNICODE('d'),
USBStringDescriptor_UNICODE('d'),
USBStringDescriptor_UNICODE('e'),
USBStringDescriptor_UNICODE('e'),
USBStringDescriptor_UNICODE('f'),
USBStringDescriptor_UNICODE('f'),
};
/* USB string for the version */
static const unsigned char usb_string_version_conf[] = {
USBStringDescriptor_LENGTH(16),
USBGenericDescriptor_STRING,
USBStringDescriptor_UNICODE('f'),
USBStringDescriptor_UNICODE('i'),
USBStringDescriptor_UNICODE('r'),
USBStringDescriptor_UNICODE('m'),
USBStringDescriptor_UNICODE('w'),
USBStringDescriptor_UNICODE('a'),
USBStringDescriptor_UNICODE('r'),
USBStringDescriptor_UNICODE('e'),
USBStringDescriptor_UNICODE(' '),
USBStringDescriptor_UNICODE('v'),
USBStringDescriptor_UNICODE('e'),
USBStringDescriptor_UNICODE('r'),
USBStringDescriptor_UNICODE('s'),
USBStringDescriptor_UNICODE('i'),
USBStringDescriptor_UNICODE('o'),
USBStringDescriptor_UNICODE('n'),
};
static const char git_version[] = GIT_VERSION;
static unsigned char usb_string_version[2 + ARRAY_SIZE(git_version) * 2 - 2];
/*------------------------------------------------------------------------------
* USB Device descriptors
*------------------------------------------------------------------------------*/
#ifdef HAVE_SNIFFER
typedef struct _SIMTraceDriverConfigurationDescriptorSniffer {
/** Standard configuration descriptor. */
USBConfigurationDescriptor configuration;
USBInterfaceDescriptor sniffer;
USBEndpointDescriptor sniffer_dataOut;
USBEndpointDescriptor sniffer_dataIn;
USBEndpointDescriptor sniffer_interruptIn;
DFURT_IF_DESCRIPTOR_STRUCT;
} __attribute__ ((packed)) SIMTraceDriverConfigurationDescriptorSniffer;
static const SIMTraceDriverConfigurationDescriptorSniffer
configurationDescriptorSniffer = {
/* Standard configuration descriptor */
.configuration = {
.bLength = sizeof(USBConfigurationDescriptor),
.bDescriptorType = USBGenericDescriptor_CONFIGURATION,
.wTotalLength = sizeof(SIMTraceDriverConfigurationDescriptorSniffer),
.bNumInterfaces = 1+DFURT_NUM_IF,
.bConfigurationValue = CFG_NUM_SNIFF,
.iConfiguration = SNIFFER_CONF_STR,
.bmAttributes = USBD_BMATTRIBUTES,
.bMaxPower = USBConfigurationDescriptor_POWER(100),
},
/* Communication class interface standard descriptor */
.sniffer = {
.bLength = sizeof(USBInterfaceDescriptor),
.bDescriptorType = USBGenericDescriptor_INTERFACE,
.bInterfaceNumber = 0,
.bAlternateSetting = 0,
.bNumEndpoints = 3,
.bInterfaceClass = USB_CLASS_PROPRIETARY,
.bInterfaceSubClass = SIMTRACE_SNIFFER_USB_SUBCLASS,
.bInterfaceProtocol = 0,
.iInterface = SNIFFER_CONF_STR,
},
/* Bulk-OUT endpoint standard descriptor */
.sniffer_dataOut = {
.bLength = sizeof(USBEndpointDescriptor),
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
.bEndpointAddress = USBEndpointDescriptor_ADDRESS(
USBEndpointDescriptor_OUT,
SIMTRACE_USB_EP_CARD_DATAOUT),
.bmAttributes = USBEndpointDescriptor_BULK,
.wMaxPacketSize = USBEndpointDescriptor_MAXBULKSIZE_FS,
.bInterval = 0,
},
/* Bulk-IN endpoint descriptor */
.sniffer_dataIn = {
.bLength = sizeof(USBEndpointDescriptor),
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
.bEndpointAddress = USBEndpointDescriptor_ADDRESS(
USBEndpointDescriptor_IN,
SIMTRACE_USB_EP_CARD_DATAIN),
.bmAttributes = USBEndpointDescriptor_BULK,
.wMaxPacketSize = USBEndpointDescriptor_MAXBULKSIZE_FS,
.bInterval = 0,
},
// Notification endpoint descriptor
.sniffer_interruptIn = {
.bLength = sizeof(USBEndpointDescriptor),
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
.bEndpointAddress = USBEndpointDescriptor_ADDRESS(
USBEndpointDescriptor_IN,
SIMTRACE_USB_EP_CARD_INT),
.bmAttributes = USBEndpointDescriptor_INTERRUPT,
.wMaxPacketSize = USBEndpointDescriptor_MAXINTERRUPTSIZE_FS,
.bInterval = 0x10,
},
DFURT_IF_DESCRIPTOR(1, 0),
};
#endif /* HAVE_SNIFFER */
#ifdef HAVE_CCID
static const CCIDDriverConfigurationDescriptors configurationDescriptorCCID = {
// Standard USB configuration descriptor
{
.bLength = sizeof(USBConfigurationDescriptor),
.bDescriptorType = USBGenericDescriptor_CONFIGURATION,
.wTotalLength = sizeof(CCIDDriverConfigurationDescriptors),
.bNumInterfaces = 1+DFURT_NUM_IF,
.bConfigurationValue = CFG_NUM_CCID,
.iConfiguration = CCID_CONF_STR,
.bmAttributes = BOARD_USB_BMATTRIBUTES,
.bMaxPower = USBConfigurationDescriptor_POWER(100),
},
// CCID interface descriptor
// Table 4.3-1 Interface Descriptor
// Interface descriptor
{
.bLength = sizeof(USBInterfaceDescriptor),
.bDescriptorType = USBGenericDescriptor_INTERFACE,
.bInterfaceNumber = 0,
.bAlternateSetting = 0,
.bNumEndpoints = 3,
.bInterfaceClass = SMART_CARD_DEVICE_CLASS,
.bInterfaceSubClass = 0,
.bInterfaceProtocol = 0,
.iInterface = CCID_CONF_STR,
},
{
.bLength = sizeof(CCIDDescriptor),
.bDescriptorType = CCID_DECRIPTOR_TYPE,
.bcdCCID = CCID1_10, // CCID version
.bMaxSlotIndex = 0, // 1 slot
.bVoltageSupport = VOLTS_3_0,
.dwProtocols = (1 << PROTOCOL_TO),
.dwDefaultClock = 3580,
.dwMaximumClock = 3580,
.bNumClockSupported = 0,
.dwDataRate = 9600,
.dwMaxDataRate = 9600,
.bNumDataRatesSupported = 0,
.dwMaxIFSD = 0xfe,
.dwSynchProtocols = 0,
.dwMechanical = 0,
.dwFeatures = CCID_FEATURES_AUTO_CLOCK | CCID_FEATURES_AUTO_BAUD |
CCID_FEATURES_AUTO_PCONF | CCID_FEATURES_AUTO_PNEGO |
CCID_FEATURES_EXC_TPDU,
.dwMaxCCIDMessageLength = 271, /* For extended APDU
level the value shall
be between 261 + 10 */
.bClassGetResponse = 0xFF, // Echoes the class of the APDU
.bClassEnvelope = 0xFF, // Echoes the class of the APDU
.wLcdLayout = 0, // wLcdLayout: no LCD
.bPINSupport = 0, // bPINSupport: No PIN
.bMaxCCIDBusySlots = 1,
},
// Bulk-OUT endpoint descriptor
{
.bLength = sizeof(USBEndpointDescriptor),
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
.bEndpointAddress =
USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_OUT,
CCID_EPT_DATA_OUT),
.bmAttributes = USBEndpointDescriptor_BULK,
.wMaxPacketSize = USBEndpointDescriptor_MAXBULKSIZE_FS,
.bInterval = 0x00,
},
// Bulk-IN endpoint descriptor
{
.bLength = sizeof(USBEndpointDescriptor),
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
.bEndpointAddress =
USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
CCID_EPT_DATA_IN),
.bmAttributes = USBEndpointDescriptor_BULK,
.wMaxPacketSize = USBEndpointDescriptor_MAXBULKSIZE_FS),
.bInterval = 0x00,
},
// Notification endpoint descriptor
{
.bLength = sizeof(USBEndpointDescriptor),
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
.bEndpointAddress =
USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
CCID_EPT_NOTIFICATION),
.bmAttributes = USBEndpointDescriptor_INTERRUPT,
.wMaxPacketSize = USBEndpointDescriptor_MAXINTERRUPTSIZE_FS,
.bInterval = 0x10,
},
DFURT_IF_DESCRIPTOR(1, 0),
};
#endif /* HAVE_CCID */
#ifdef HAVE_CARDEM
/* SIM card emulator */
typedef struct _SIMTraceDriverConfigurationDescriptorPhone {
/* Standard configuration descriptor. */
USBConfigurationDescriptor configuration;
USBInterfaceDescriptor phone;
USBEndpointDescriptor phone_dataOut;
USBEndpointDescriptor phone_dataIn;
USBEndpointDescriptor phone_interruptIn;
#ifdef CARDEMU_SECOND_UART
USBInterfaceDescriptor usim2;
USBEndpointDescriptor usim2_dataOut;
USBEndpointDescriptor usim2_dataIn;
USBEndpointDescriptor usim2_interruptIn;
#endif
DFURT_IF_DESCRIPTOR_STRUCT;
} __attribute__ ((packed)) SIMTraceDriverConfigurationDescriptorPhone;
static const SIMTraceDriverConfigurationDescriptorPhone
configurationDescriptorPhone = {
/* Standard configuration descriptor */
.configuration = {
.bLength = sizeof(USBConfigurationDescriptor),
.bDescriptorType = USBGenericDescriptor_CONFIGURATION,
.wTotalLength = sizeof(SIMTraceDriverConfigurationDescriptorPhone),
#ifdef CARDEMU_SECOND_UART
.bNumInterfaces = 2+DFURT_NUM_IF,
#else
.bNumInterfaces = 1+DFURT_NUM_IF,
#endif
.bConfigurationValue = CFG_NUM_PHONE,
.iConfiguration = PHONE_CONF_STR,
.bmAttributes = USBD_BMATTRIBUTES,
.bMaxPower = USBConfigurationDescriptor_POWER(100)
},
/* Communication class interface standard descriptor */
.phone = {
.bLength = sizeof(USBInterfaceDescriptor),
.bDescriptorType = USBGenericDescriptor_INTERFACE,
.bInterfaceNumber = 0,
.bAlternateSetting = 0,
.bNumEndpoints = 3,
.bInterfaceClass = USB_CLASS_PROPRIETARY,
.bInterfaceSubClass = SIMTRACE_CARDEM_USB_SUBCLASS,
.bInterfaceProtocol = 0,
.iInterface = CARDEM_USIM1_INTF_STR,
},
/* Bulk-OUT endpoint standard descriptor */
.phone_dataOut = {
.bLength = sizeof(USBEndpointDescriptor),
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
.bEndpointAddress = USBEndpointDescriptor_ADDRESS(
USBEndpointDescriptor_OUT,
SIMTRACE_CARDEM_USB_EP_USIM1_DATAOUT),
.bmAttributes = USBEndpointDescriptor_BULK,
.wMaxPacketSize = USBEndpointDescriptor_MAXBULKSIZE_FS,
.bInterval = 0 /* Must be 0 for full-speed bulk endpoints */
},
/* Bulk-IN endpoint descriptor */
.phone_dataIn = {
.bLength = sizeof(USBEndpointDescriptor),
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
.bEndpointAddress = USBEndpointDescriptor_ADDRESS(
USBEndpointDescriptor_IN,
SIMTRACE_CARDEM_USB_EP_USIM1_DATAIN),
.bmAttributes = USBEndpointDescriptor_BULK,
.wMaxPacketSize = USBEndpointDescriptor_MAXBULKSIZE_FS,
.bInterval = 0 /* Must be 0 for full-speed bulk endpoints */
},
/* Notification endpoint descriptor */
.phone_interruptIn = {
.bLength = sizeof(USBEndpointDescriptor),
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
.bEndpointAddress = USBEndpointDescriptor_ADDRESS(
USBEndpointDescriptor_IN,
SIMTRACE_CARDEM_USB_EP_USIM1_INT),
.bmAttributes = USBEndpointDescriptor_INTERRUPT,
.wMaxPacketSize = USBEndpointDescriptor_MAXINTERRUPTSIZE_FS,
.bInterval = 0x10
},
#ifdef CARDEMU_SECOND_UART
/* Communication class interface standard descriptor */
.usim2 = {
.bLength = sizeof(USBInterfaceDescriptor),
.bDescriptorType = USBGenericDescriptor_INTERFACE,
.bInterfaceNumber = 1,
.bAlternateSetting = 0,
.bNumEndpoints = 3,
.bInterfaceClass = USB_CLASS_PROPRIETARY,
.bInterfaceSubClass = SIMTRACE_CARDEM_USB_SUBCLASS,
.bInterfaceProtocol = 0,
.iInterface = CARDEM_USIM2_INTF_STR,
},
/* Bulk-OUT endpoint standard descriptor */
.usim2_dataOut = {
.bLength = sizeof(USBEndpointDescriptor),
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
.bEndpointAddress = USBEndpointDescriptor_ADDRESS(
USBEndpointDescriptor_OUT,
SIMTRACE_CARDEM_USB_EP_USIM2_DATAOUT),
.bmAttributes = USBEndpointDescriptor_BULK,
.wMaxPacketSize = USBEndpointDescriptor_MAXBULKSIZE_FS,
.bInterval = 0 /* Must be 0 for full-speed bulk endpoints */
}
,
/* Bulk-IN endpoint descriptor */
.usim2_dataIn = {
.bLength = sizeof(USBEndpointDescriptor),
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
.bEndpointAddress = USBEndpointDescriptor_ADDRESS(
USBEndpointDescriptor_IN,
SIMTRACE_CARDEM_USB_EP_USIM2_DATAIN),
.bmAttributes = USBEndpointDescriptor_BULK,
.wMaxPacketSize = USBEndpointDescriptor_MAXBULKSIZE_FS,
.bInterval = 0 /* Must be 0 for full-speed bulk endpoints */
},
/* Notification endpoint descriptor */
.usim2_interruptIn = {
.bLength = sizeof(USBEndpointDescriptor),
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
.bEndpointAddress = USBEndpointDescriptor_ADDRESS(
USBEndpointDescriptor_IN,
SIMTRACE_CARDEM_USB_EP_USIM2_INT),
.bmAttributes = USBEndpointDescriptor_INTERRUPT,
.wMaxPacketSize = USBEndpointDescriptor_MAXINTERRUPTSIZE_FS,
.bInterval = 0x10,
},
DFURT_IF_DESCRIPTOR(2, 0),
#else
DFURT_IF_DESCRIPTOR(1, 0),
#endif
};
#endif /* HAVE_CARDEM */
#ifdef HAVE_MITM
typedef struct _SIMTraceDriverConfigurationDescriptorMITM {
/* Standard configuration descriptor. */
USBConfigurationDescriptor configuration;
USBInterfaceDescriptor simcard;
/// CCID descriptor
CCIDDescriptor ccid;
/// Bulk OUT endpoint descriptor
USBEndpointDescriptor simcard_dataOut;
/// Bulk IN endpoint descriptor
USBEndpointDescriptor simcard_dataIn;
/// Interrupt OUT endpoint descriptor
USBEndpointDescriptor simcard_interruptIn;
USBInterfaceDescriptor phone;
USBEndpointDescriptor phone_dataOut;
USBEndpointDescriptor phone_dataIn;
USBEndpointDescriptor phone_interruptIn;
DFURT_IF_DESCRIPTOR_STRUCT;
} __attribute__ ((packed)) SIMTraceDriverConfigurationDescriptorMITM;
static const SIMTraceDriverConfigurationDescriptorMITM
configurationDescriptorMITM = {
/* Standard configuration descriptor */
.configuration = {
.bLength = sizeof(USBConfigurationDescriptor),
.bDescriptorType = USBGenericDescriptor_CONFIGURATION,
.wTotalLength = sizeof(SIMTraceDriverConfigurationDescriptorMITM),
.bNumInterfaces = 2+DFURT_NUM_IF,
.bConfigurationValue = CFG_NUM_MITM,
.iConfiguration = MITM_CONF_STR,
.bmAttributes = USBD_BMATTRIBUTES,
.bMaxPower = USBConfigurationDescriptor_POWER(100),
},
// CCID interface descriptor
// Table 4.3-1 Interface Descriptor
// Interface descriptor
.simcard = {
.bLength = sizeof(USBInterfaceDescriptor),
.bDescriptorType = USBGenericDescriptor_INTERFACE,
.bInterfaceNumber = 0,
.bAlternateSetting = 0,
.bNumEndpoints = 3,
.bInterfaceClass = SMART_CARD_DEVICE_CLASS,
.bInterfaceSubClass = 0,
.bInterfaceProtocol = 0,
.iInterface = CCID_CONF_STR,
},
.ccid = {
.bLength = sizeof(CCIDDescriptor),
.bDescriptorType = CCID_DECRIPTOR_TYPE,
.bcdCCID = CCID1_10, // CCID version
.bMaxSlotIndex = 0, // 1 slot
.bVoltageSupport = VOLTS_3_0,
.dwProtocols = (1 << PROTOCOL_TO),
.dwDefaultClock = 3580,
.dwMaximumClock = 3580,
.bNumClockSupported = 0,
.dwDataRate = 9600,
.dwMaxDataRate = 9600,
.bNumDataRatesSupported = 0,
.dwMaxIFSD = 0xfe,
.dwSynchProtocols = 0,
.dwMechanical = 0,
.dwFeatures = CCID_FEATURES_AUTO_CLOCK | CCID_FEATURES_AUTO_BAUD |
CCID_FEATURES_AUTO_PCONF | CCID_FEATURES_AUTO_PNEGO |
CCID_FEATURES_EXC_TPDU,
.dwMaxCCIDMessageLength = 271, /* For extended APDU
level the value shall
be between 261 + 10 */
.bClassGetResponse = 0xFF, // Echoes the class of the APDU
.bClassEnvelope = 0xFF, // Echoes the class of the APDU
.wLcdLayout = 0, // wLcdLayout: no LCD
.bPINSupport = 0, // bPINSupport: No PIN
.bMaxCCIDBusySlots = 1,
},
// Bulk-OUT endpoint descriptor
.simcard_dataOut = {
.bLength = sizeof(USBEndpointDescriptor),
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
.bEndpointAddress =
USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_OUT,
CCID_EPT_DATA_OUT),
.bmAttributes = USBEndpointDescriptor_BULK,
.wMaxPacketSize = USBEndpointDescriptor_MAXBULKSIZE_FS,
.bInterval = 0x00,
},
// Bulk-IN endpoint descriptor
.simcard_dataIn = {
.bLength = sizeof(USBEndpointDescriptor),
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
.bEndpointAddress =
USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
CCID_EPT_DATA_IN),
.bmAttributes = USBEndpointDescriptor_BULK,
.wMaxPacketSize = USBEndpointDescriptor_MAXBULKSIZE_FS,
.bInterval = 0x00,
},
// Notification endpoint descriptor
.simcard_interruptIn = {
.bLength = sizeof(USBEndpointDescriptor),
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
.bEndpointAddress =
USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
CCID_EPT_NOTIFICATION),
.bmAttributes = USBEndpointDescriptor_INTERRUPT,
.wMaxPacketSize = USBEndpointDescriptor_MAXINTERRUPTSIZE_FS,
.bInterval = 0x10,
},
/* Communication class interface standard descriptor */
.phone = {
.bLength = sizeof(USBInterfaceDescriptor),
.bDescriptorType = USBGenericDescriptor_INTERFACE,
.bInterfaceNumber = 1,
.bAlternateSetting = 0,
.bNumEndpoints = 3,
.bInterfaceClass = 0xff,
.bInterfaceSubClass = SIMTRACE_SUBCLASS_CARDEM,
.bInterfaceProtocol = 0,
.iInterface = PHONE_CONF_STR,
},
/* Bulk-OUT endpoint standard descriptor */
.phone_dataOut = {
.bLength = sizeof(USBEndpointDescriptor),
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
.bEndpointAddress = USBEndpointDescriptor_ADDRESS(
USBEndpointDescriptor_OUT,
SIMTRACE_USB_EP_PHONE_DATAOUT),
.bmAttributes = USBEndpointDescriptor_BULK,
.wMaxPacketSize = USBEndpointDescriptor_MAXBULKSIZE_FS,
.bInterval = 0, /* Must be 0 for full-speed bulk endpoints */
},
/* Bulk-IN endpoint descriptor */
.phone_dataIn = {
.bLength = sizeof(USBEndpointDescriptor),
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
.bEndpointAddress = USBEndpointDescriptor_ADDRESS(
USBEndpointDescriptor_IN,
SIMTRACE_USB_EP_PHONE_DATAIN),
.bmAttributes = USBEndpointDescriptor_BULK,
.wMaxPacketSize = USBEndpointDescriptor_MAXBULKSIZE_FS,
.bInterval = 0, /* Must be 0 for full-speed bulk endpoints */
},
/* Notification endpoint descriptor */
{
.bLength = sizeof(USBEndpointDescriptor),
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
.bEndpointAddress = USBEndpointDescriptor_ADDRESS(
USBEndpointDescriptor_IN,
SIMTRACE_USB_EP_PHONE_INT),
.bmAttributes = USBEndpointDescriptor_INTERRUPT,
.wMaxPacketSize = USBEndpointDescriptor_MAXINTERRUPTSIZE_FS,
.bInterval = 0x10
},
DFURT_IF_DESCRIPTOR(2, 0),
};
#endif /* HAVE_CARDEM */
/* USB descriptor just to show the version */
typedef struct _SIMTraceDriverConfigurationDescriptorVersion {
/** Standard configuration descriptor. */
USBConfigurationDescriptor configuration;
USBInterfaceDescriptor version;
} __attribute__ ((packed)) SIMTraceDriverConfigurationDescriptorVersion;
static const SIMTraceDriverConfigurationDescriptorVersion
configurationDescriptorVersion = {
/* Standard configuration descriptor for the interface descriptor*/
.configuration = {
.bLength = sizeof(USBConfigurationDescriptor),
.bDescriptorType = USBGenericDescriptor_CONFIGURATION,
.wTotalLength = sizeof(SIMTraceDriverConfigurationDescriptorVersion),
.bNumInterfaces = 1,
.bConfigurationValue = CFG_NUM_VERSION,
.iConfiguration = VERSION_CONF_STR,
.bmAttributes = USBD_BMATTRIBUTES,
.bMaxPower = USBConfigurationDescriptor_POWER(100),
},
/* Interface standard descriptor just holding the version information */
.version = {
.bLength = sizeof(USBInterfaceDescriptor),
.bDescriptorType = USBGenericDescriptor_INTERFACE,
.bInterfaceNumber = 0,
.bAlternateSetting = 0,
.bNumEndpoints = 0,
.bInterfaceClass = USB_CLASS_PROPRIETARY,
.bInterfaceSubClass = 0xff,
.bInterfaceProtocol = 0,
.iInterface = VERSION_STR,
},
};
const USBConfigurationDescriptor *configurationDescriptorsArr[] = {
#ifdef HAVE_SNIFFER
&configurationDescriptorSniffer.configuration,
#endif
#ifdef HAVE_CCID
&configurationDescriptorCCID.configuration,
#endif
#ifdef HAVE_CARDEM
&configurationDescriptorPhone.configuration,
#endif
#ifdef HAVE_MITM
&configurationDescriptorMITM.configuration,
#endif
&configurationDescriptorVersion.configuration,
};
/** Standard USB device descriptor for the CDC serial driver */
const USBDeviceDescriptor deviceDescriptor = {
.bLength = sizeof(USBDeviceDescriptor),
.bDescriptorType = USBGenericDescriptor_DEVICE,
.bcdUSB = USBDeviceDescriptor_USB2_00,
.bDeviceClass = 0,
.bDeviceSubClass = 0,
.bDeviceProtocol = 0,
.bMaxPacketSize0 = 64,
.idVendor = BOARD_USB_VENDOR_ID,
.idProduct = BOARD_USB_PRODUCT_ID,
.bcdDevice = 2, /* Release number */
.iManufacturer = MANUF_STR,
.iProduct = PRODUCT_STRING,
.iSerialNumber = SERIAL_STR,
.bNumConfigurations = ARRAY_SIZE(configurationDescriptorsArr),
};
/* AT91SAM3S only supports full speed, but not high speed USB */
static const USBDDriverDescriptors driverDescriptors = {
&deviceDescriptor,
(const USBConfigurationDescriptor **)&(configurationDescriptorsArr), /* first full-speed configuration descriptor */
0, /* No full-speed device qualifier descriptor */
0, /* No full-speed other speed configuration */
0, /* No high-speed device descriptor */
0, /* No high-speed configuration descriptor */
0, /* No high-speed device qualifier descriptor */
0, /* No high-speed other speed configuration descriptor */
usb_strings_extended,
ARRAY_SIZE(usb_strings_extended),/* cnt string descriptors in list */
};
/*----------------------------------------------------------------------------
* Functions
*----------------------------------------------------------------------------*/
void SIMtrace_USB_Initialize(void)
{
unsigned int i;
/* Signal USB reset by disabling the pull-up on USB D+ for at least 10 ms */
USBD_HAL_Suspend();
mdelay(20);
USBD_HAL_Activate();
// Get std USB driver
USBDDriver *pUsbd = USBD_GetDriver();
// put device ID into USB serial number description
unsigned int device_id[4];
EEFC_ReadUniqueID(device_id);
char device_id_string[32 + 1];
snprintf(device_id_string, ARRAY_SIZE(device_id_string), "%08x%08x%08x%08x",
device_id[0], device_id[1], device_id[2], device_id[3]);
for (i = 0; i < ARRAY_SIZE(device_id_string) - 1; i++) {
usb_string_serial[2 + 2 * i] = device_id_string[i];
}
// put version into USB string
usb_string_version[0] = USBStringDescriptor_LENGTH(ARRAY_SIZE(git_version) - 1);
usb_string_version[1] = USBGenericDescriptor_STRING;
for (i = 0; i < ARRAY_SIZE(git_version) - 1; i++) {
usb_string_version[2 + i * 2 + 0] = git_version[i];
usb_string_version[2 + i * 2 + 1] = 0;
}
// fill extended USB strings
for (i = 0; i < ARRAY_SIZE(usb_strings) && i < ARRAY_SIZE(usb_strings_extended); i++) {
usb_strings_extended[i] = usb_strings[i];
}
usb_strings_extended[SERIAL_STR] = usb_string_serial;
usb_strings_extended[VERSION_CONF_STR] = usb_string_version_conf;
usb_strings_extended[VERSION_STR] = usb_string_version;
// Initialize standard USB driver
USBDDriver_Initialize(pUsbd, &driverDescriptors, 0); // Multiple interface settings not supported
USBD_Init();
USBD_Connect();
NVIC_EnableIRQ(UDP_IRQn);
}