463 lines
15 KiB
C
463 lines
15 KiB
C
/**
|
|
******************************************************************************
|
|
* @file usbd_ccid_core.c
|
|
* @author MCD Application Team
|
|
* @version V1.0.1
|
|
* @date 31-January-2014
|
|
* @brief This file provides all the CCID core functions.
|
|
*
|
|
* @verbatim
|
|
*
|
|
* ===================================================================
|
|
* CCID Class Description
|
|
* ===================================================================
|
|
* This module manages the Specification for Integrated Circuit(s)
|
|
* Cards Interface Revision 1.1
|
|
* This driver implements the following aspects of the specification:
|
|
* - Bulk Transfers
|
|
*
|
|
* @endverbatim
|
|
*
|
|
******************************************************************************
|
|
* @attention
|
|
*
|
|
* <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
|
|
*
|
|
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
|
* You may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at:
|
|
*
|
|
* http://www.st.com/software_license_agreement_liberty_v2
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
|
|
/* Includes ------------------------------------------------------------------*/
|
|
#include "usbd_ccid_core.h"
|
|
|
|
#ifdef HAVE_USB_CLASS_CCID
|
|
|
|
#define USBD_LANGID_STRING 0x409
|
|
|
|
#define USBD_VID 0x2C97
|
|
#if TARGET_ID == 0x31000002 // blue
|
|
#define USBD_PID 0x0000
|
|
static const uint8_t const USBD_PRODUCT_FS_STRING[] = {
|
|
4*2+2,
|
|
USB_DESC_TYPE_STRING,
|
|
'B', 0,
|
|
'l', 0,
|
|
'u', 0,
|
|
'e', 0,
|
|
};
|
|
|
|
#elif TARGET_ID == 0x31100002 // nano s
|
|
#define USBD_PID 0x0001
|
|
static const uint8_t const USBD_PRODUCT_FS_STRING[] = {
|
|
6*2+2,
|
|
USB_DESC_TYPE_STRING,
|
|
'N', 0,
|
|
'a', 0,
|
|
'n', 0,
|
|
'o', 0,
|
|
' ', 0,
|
|
'S', 0,
|
|
};
|
|
#elif TARGET_ID == 0x31200002 // aramis
|
|
#define USBD_PID 0x0002
|
|
static const uint8_t const USBD_PRODUCT_FS_STRING[] = {
|
|
6*2+2,
|
|
USB_DESC_TYPE_STRING,
|
|
'A', 0,
|
|
'r', 0,
|
|
'a', 0,
|
|
'm', 0,
|
|
'i', 0,
|
|
's', 0,
|
|
};
|
|
#else
|
|
#error unknown TARGET_ID
|
|
#endif
|
|
|
|
|
|
/* USB Standard Device Descriptor */
|
|
static __ALIGN_BEGIN const uint8_t const USBD_DeviceQualifierDesc[] __ALIGN_END =
|
|
{
|
|
USB_LEN_DEV_QUALIFIER_DESC,
|
|
USB_DESC_TYPE_DEVICE_QUALIFIER,
|
|
0x00,
|
|
0x02,
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x40,
|
|
0x01,
|
|
0x00,
|
|
};
|
|
|
|
/* USB Standard Device Descriptor */
|
|
static const uint8_t const USBD_LangIDDesc[]=
|
|
{
|
|
USB_LEN_LANGID_STR_DESC,
|
|
USB_DESC_TYPE_STRING,
|
|
LOBYTE(USBD_LANGID_STRING),
|
|
HIBYTE(USBD_LANGID_STRING),
|
|
};
|
|
|
|
static const uint8_t const USB_SERIAL_STRING[] =
|
|
{
|
|
4*2+2,
|
|
USB_DESC_TYPE_STRING,
|
|
'0', 0,
|
|
'0', 0,
|
|
'0', 0,
|
|
'1', 0,
|
|
};
|
|
|
|
static const uint8_t const USBD_MANUFACTURER_STRING[] = {
|
|
6*2+2,
|
|
USB_DESC_TYPE_STRING,
|
|
'L', 0,
|
|
'e', 0,
|
|
'd', 0,
|
|
'g', 0,
|
|
'e', 0,
|
|
'r', 0,
|
|
};
|
|
|
|
#define USBD_INTERFACE_FS_STRING USBD_PRODUCT_FS_STRING
|
|
#define USBD_CONFIGURATION_FS_STRING USBD_PRODUCT_FS_STRING
|
|
|
|
|
|
/* USB Standard Device Descriptor */
|
|
static const uint8_t const USBD_DeviceDesc[]= {
|
|
0x12, /* bLength */
|
|
USB_DESC_TYPE_DEVICE, /* bDescriptorType */
|
|
0x00, /* bcdUSB */
|
|
0x02,
|
|
0x00, /* bDeviceClass */
|
|
0x00, /* bDeviceSubClass */
|
|
0x00, /* bDeviceProtocol */
|
|
USB_MAX_EP0_SIZE, /* bMaxPacketSize */
|
|
LOBYTE(USBD_VID), /* idVendor */
|
|
HIBYTE(USBD_VID), /* idVendor */
|
|
LOBYTE(USBD_PID), /* idVendor */
|
|
HIBYTE(USBD_PID), /* idVendor */
|
|
0x00, /* bcdDevice rel. 2.00 */
|
|
0x02,
|
|
USBD_IDX_MFC_STR, /* Index of manufacturer string */
|
|
USBD_IDX_PRODUCT_STR, /* Index of product string */
|
|
USBD_IDX_SERIAL_STR, /* Index of serial number string */
|
|
USBD_MAX_NUM_CONFIGURATION /* bNumConfigurations */
|
|
}; /* USB_DeviceDescriptor */
|
|
|
|
|
|
/* USB Mass storage device Configuration Descriptor */
|
|
/* All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */
|
|
#define USBD_OFFSET_CfgDesc_bPINSupport 70
|
|
const uint8_t N_USBD_CfgDesc[] =
|
|
{
|
|
|
|
0x09, /* bLength: Configuration Descriptor size */
|
|
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
|
|
0x9+0x9+0x36+0x7+0x7+0x7,
|
|
|
|
0x00,
|
|
0x01, /* bNumInterfaces: 1 interface */
|
|
0x01, /* bConfigurationValue: */
|
|
0x04, /* iConfiguration: */
|
|
0x80, /*bmAttributes: bus powered */
|
|
0x32, /* MaxPower 100 mA */
|
|
|
|
/******************** CCID **** interface ********************/
|
|
0x09, /* bLength: Interface Descriptor size */
|
|
0x04, /* bDescriptorType: */
|
|
0x00, /* 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*/
|
|
|
|
0x01,0x00,0x00,0x00, /* dwProtocols: 0001h = Protocol T=0 */
|
|
0x10,0x0E,0x00,0x00, /* dwDefaultClock: 3.6Mhz = 3600kHz = 0x0E10,
|
|
for 4 Mhz the value is (0x00000FA0) :
|
|
This is used in ETU and waiting time calculations*/
|
|
0x10,0x0E,0x00,0x00, /* dwMaximumClock: Maximum supported ICC clock frequency
|
|
in KHz. So, 3.6Mhz = 3600kHz = 0x0E10,
|
|
4 Mhz (0x00000FA0) : */
|
|
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 */
|
|
|
|
0xCD,0x25,0x00,0x00, /* dwDataRate: Default ICC I/O data rate in bps
|
|
9677 bps = 0x25CD
|
|
for example 10752 bps (0x00002A00) */
|
|
|
|
0xCD,0x25,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
|
|
*/
|
|
//46
|
|
0x00,0x00,0x00,0x00, /* dwMaxIFSD: 0 (T=0 only) */
|
|
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*/
|
|
#if 1
|
|
0x0F,0x01,0x00,0x00, /* dwMaxCCIDMessageLength: Maximum block size + header*/
|
|
/* 261 + 10 */
|
|
#else
|
|
0xF8,0x00,0x00,0x00, /* dwMaxCCIDMessageLength: Maximum block size + header*/
|
|
/* EEh + 10 */
|
|
#endif
|
|
0x00, /* bClassGetResponse*/
|
|
0x00, /* bClassEnvelope */
|
|
0x00,0x00, /* wLcdLayout : 0000h no LCD. */
|
|
0x03, /* bPINSupport : no PIN verif and modif */ //<= offset: 70
|
|
0x01, /* bMaxCCIDBusySlots */
|
|
|
|
//72
|
|
/******************** CCID Endpoints ********************/
|
|
0x07, /*Endpoint descriptor length = 7*/
|
|
0x05, /*Endpoint descriptor type */
|
|
CCID_BULK_IN_EP, /*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 */
|
|
0x05, /*Endpoint descriptor type */
|
|
CCID_BULK_OUT_EP, /*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*/
|
|
0x05, /*bDescriptorType:*/
|
|
CCID_INTR_IN_EP, /*bEndpointAddress: Endpoint Address (IN)*/
|
|
0x03, /* bmAttributes: Interrupt endpoint */
|
|
LOBYTE(CCID_INTR_EPIN_SIZE),
|
|
HIBYTE(CCID_INTR_EPIN_SIZE),
|
|
0x18 /*Polling interval in milliseconds */
|
|
};
|
|
|
|
|
|
|
|
static uint8_t *USBD_GetCfgDesc_impl (uint16_t *length)
|
|
{
|
|
*length = sizeof (N_USBD_CfgDesc);
|
|
return (uint8_t*)(N_USBD_CfgDesc);
|
|
}
|
|
|
|
/**
|
|
* @brief Returns the device descriptor.
|
|
* @param speed: Current device speed
|
|
* @param length: Pointer to data length variable
|
|
* @retval Pointer to descriptor buffer
|
|
*/
|
|
static uint8_t *USBD_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
|
{
|
|
UNUSED(speed);
|
|
*length = sizeof(USBD_DeviceDesc);
|
|
return (uint8_t*)USBD_DeviceDesc;
|
|
}
|
|
|
|
/**
|
|
* @brief Returns the LangID string descriptor.
|
|
* @param speed: Current device speed
|
|
* @param length: Pointer to data length variable
|
|
* @retval Pointer to descriptor buffer
|
|
*/
|
|
static uint8_t *USBD_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
|
{
|
|
UNUSED(speed);
|
|
*length = sizeof(USBD_LangIDDesc);
|
|
return (uint8_t*)USBD_LangIDDesc;
|
|
}
|
|
|
|
/**
|
|
* @brief Returns the product string descriptor.
|
|
* @param speed: Current device speed
|
|
* @param length: Pointer to data length variable
|
|
* @retval Pointer to descriptor buffer
|
|
*/
|
|
static uint8_t *USBD_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
|
{
|
|
UNUSED(speed);
|
|
*length = sizeof(USBD_PRODUCT_FS_STRING);
|
|
return (uint8_t*)USBD_PRODUCT_FS_STRING;
|
|
}
|
|
|
|
/**
|
|
* @brief Returns the manufacturer string descriptor.
|
|
* @param speed: Current device speed
|
|
* @param length: Pointer to data length variable
|
|
* @retval Pointer to descriptor buffer
|
|
*/
|
|
static uint8_t *USBD_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
|
{
|
|
UNUSED(speed);
|
|
*length = sizeof(USBD_MANUFACTURER_STRING);
|
|
return (uint8_t*)USBD_MANUFACTURER_STRING;
|
|
}
|
|
|
|
/**
|
|
* @brief Returns the serial number string descriptor.
|
|
* @param speed: Current device speed
|
|
* @param length: Pointer to data length variable
|
|
* @retval Pointer to descriptor buffer
|
|
*/
|
|
static uint8_t *USBD_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
|
{
|
|
UNUSED(speed);
|
|
*length = sizeof(USB_SERIAL_STRING);
|
|
return (uint8_t*)USB_SERIAL_STRING;
|
|
}
|
|
|
|
/**
|
|
* @brief Returns the configuration string descriptor.
|
|
* @param speed: Current device speed
|
|
* @param length: Pointer to data length variable
|
|
* @retval Pointer to descriptor buffer
|
|
*/
|
|
static uint8_t *USBD_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
|
{
|
|
UNUSED(speed);
|
|
*length = sizeof(USBD_CONFIGURATION_FS_STRING);
|
|
return (uint8_t*)USBD_CONFIGURATION_FS_STRING;
|
|
}
|
|
|
|
/**
|
|
* @brief Returns the interface string descriptor.
|
|
* @param speed: Current device speed
|
|
* @param length: Pointer to data length variable
|
|
* @retval Pointer to descriptor buffer
|
|
*/
|
|
static uint8_t *USBD_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
|
{
|
|
UNUSED(speed);
|
|
*length = sizeof(USBD_INTERFACE_FS_STRING);
|
|
return (uint8_t*)USBD_INTERFACE_FS_STRING;
|
|
}
|
|
|
|
/**
|
|
* @brief DeviceQualifierDescriptor
|
|
* return Device Qualifier descriptor
|
|
* @param length : pointer data length
|
|
* @retval pointer to descriptor buffer
|
|
*/
|
|
static uint8_t *USBD_GetDeviceQualifierDesc_impl (uint16_t *length)
|
|
{
|
|
*length = sizeof (USBD_DeviceQualifierDesc);
|
|
return (uint8_t*)USBD_DeviceQualifierDesc;
|
|
}
|
|
|
|
|
|
uint8_t SC_AnswerToReset (uint8_t voltage, uint8_t* atr_buffer) {
|
|
// return the atr length
|
|
atr_buffer[0] = 0x3B;
|
|
atr_buffer[1] = 0;
|
|
return 2;
|
|
}
|
|
|
|
|
|
// note: how core lib usb calls the hid class
|
|
static const USBD_DescriptorsTypeDef const CCID_Desc = {
|
|
USBD_DeviceDescriptor,
|
|
USBD_LangIDStrDescriptor,
|
|
USBD_ManufacturerStrDescriptor,
|
|
USBD_ProductStrDescriptor,
|
|
USBD_SerialStrDescriptor,
|
|
USBD_ConfigStrDescriptor,
|
|
USBD_InterfaceStrDescriptor,
|
|
NULL,
|
|
};
|
|
|
|
static const USBD_ClassTypeDef USBD_CCID =
|
|
{
|
|
USBD_CCID_Init,
|
|
USBD_CCID_DeInit,
|
|
USBD_CCID_Setup,
|
|
NULL, /*EP0_TxSent*/
|
|
NULL, /*EP0_RxReady*/
|
|
USBD_CCID_DataIn,
|
|
USBD_CCID_DataOut,
|
|
NULL, /*SOF */
|
|
NULL, /*ISOIn*/
|
|
NULL, /*ISOOut*/
|
|
USBD_GetCfgDesc_impl,
|
|
USBD_GetCfgDesc_impl,
|
|
USBD_GetCfgDesc_impl,
|
|
USBD_GetDeviceQualifierDesc_impl,
|
|
};
|
|
|
|
|
|
void USBD_CCID_activate_pinpad(int enabled) {
|
|
unsigned char e;
|
|
e = enabled?3:0;
|
|
nvm_write(((char*)PIC(N_USBD_CfgDesc))+USBD_OFFSET_CfgDesc_bPINSupport, &e,1);
|
|
}
|
|
|
|
void USB_CCID_power(unsigned char enabled) {
|
|
os_memset(&USBD_Device, 0, sizeof(USBD_Device));
|
|
|
|
if (enabled) {
|
|
os_memset(&USBD_Device, 0, sizeof(USBD_Device));
|
|
/* Init Device Library */
|
|
USBD_Init(&USBD_Device, (USBD_DescriptorsTypeDef*)&CCID_Desc, 0);
|
|
|
|
/* Register the HID class */
|
|
USBD_RegisterClass(&USBD_Device, (USBD_ClassTypeDef*)&USBD_CCID);
|
|
|
|
/* Start Device Process */
|
|
USBD_Start(&USBD_Device);
|
|
}
|
|
else {
|
|
USBD_DeInit(&USBD_Device);
|
|
}
|
|
}
|
|
|
|
#endif // HAVE_USB_CLASS_CCID
|