/**
******************************************************************************
* @file usbd_hid.c
* @author MCD Application Team
* @version V2.2.0
* @date 13-June-2014
* @brief This file provides the HID core functions.
*
* @verbatim
*
* ===================================================================
* HID Class Description
* ===================================================================
* This module manages the HID class V1.11 following the "Device Class Definition
* for Human Interface Devices (HID) Version 1.11 Jun 27, 2001".
* This driver implements the following aspects of the specification:
* - The Boot Interface Subclass
* - Usage Page : Generic Desktop
* - Usage : Vendor
* - Collection : Application
*
* @note In HS mode and when the DMA is used, all variables and data structures
* dealing with the DMA during the transaction process should be 32-bit aligned.
*
*
* @endverbatim
*
******************************************************************************
* @attention
*
*
© COPYRIGHT 2014 STMicroelectronics
*
* 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.
*
******************************************************************************
*/
#include
#include "os_io.h"
#include "os_helpers.h"
#include "os_io_usb.h"
/* Includes ------------------------------------------------------------------*/
#include "usbd_hid.h"
#include "usbd_hid_impl.h"
#include "usbd_ctlreq.h"
#include "usbd_core.h"
#include "usbd_conf.h"
#include "usbd_def.h"
#include "os_io_seproxyhal.h"
#ifdef HAVE_IO_U2F
#include "u2f_transport.h"
#include "u2f_impl.h"
#endif // HAVE_IO_U2F
#ifdef HAVE_USB_CLASS_CCID
#include "usbd_ccid_core.h"
#endif // HAVE_USB_CLASS_CCID
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_HID
* @brief usbd core module
* @{
*/
/** @defgroup USBD_HID_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBD_HID_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBD_HID_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_HID_Private_FunctionPrototypes
* @{
*/
/**
* @}
*/
/** @defgroup USBD_HID_Private_Variables
* @{
*/
#define USBD_LANGID_STRING 0x409
#ifdef HAVE_VID_PID_PROBER
#define USBD_VID 0x2581
#define USBD_PID 0xf1d1
static uint8_t const USBD_PRODUCT_FS_STRING[] = {
10*2+2,
USB_DESC_TYPE_STRING,
'N', 0,
'a', 0,
'n', 0,
'o', 0,
'-', 0,
'U', 0,
'2', 0,
'F', 0,
'-', 0,
'P', 0,
};
#else
#define USBD_VID 0x2C97
#if defined(TARGET_BLUE)
#define USBD_PID 0x0000
static uint8_t const USBD_PRODUCT_FS_STRING[] = {
4*2+2,
USB_DESC_TYPE_STRING,
'B', 0,
'l', 0,
'u', 0,
'e', 0,
};
#elif defined(TARGET_NANOS)
#ifndef HAVE_LEGACY_PID
#define USBD_PID 0x1000
#else // HAVE_LEGACY_PID
#define USBD_PID 0x0001
#endif // HAVE_LEGACY_PID
static 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 defined(TARGET_HW2)
#ifndef HAVE_LEGACY_PID
#define USBD_PID 0x3000
#else // HAVE_LEGACY_PID
#define USBD_PID 0x0003
#endif // HAVE_LEGACY_PID
static uint8_t const USBD_PRODUCT_FS_STRING[] = {
3*2+2,
USB_DESC_TYPE_STRING,
'H', 0,
'W', 0,
'2', 0,
};
#elif defined(TARGET_NANOX)
#ifndef HAVE_LEGACY_PID
#define USBD_PID 0x4000
#else // HAVE_LEGACY_PID
#define USBD_PID 0x0004
#endif // HAVE_LEGACY_PID
static uint8_t const USBD_PRODUCT_FS_STRING[] = {
6*2+2,
USB_DESC_TYPE_STRING,
'N', 0,
'a', 0,
'n', 0,
'o', 0,
' ', 0,
'X', 0,
};
#elif defined(TARGET_NANOS2)
#ifndef HAVE_LEGACY_PID
#define USBD_PID 0x5000
#else // HAVE_LEGACY_PID
#define USBD_PID 0x0005
#endif // HAVE_LEGACY_PID
static uint8_t const USBD_PRODUCT_FS_STRING[] = {
11*2+2,
USB_DESC_TYPE_STRING,
'N', 0,
'a', 0,
'n', 0,
'o', 0,
' ', 0,
'S', 0,
' ', 0,
'P', 0,
'l', 0,
'u', 0,
's', 0,
};
#else
#error unknown TARGET_ID
#endif
#endif
/* USB Standard Device Descriptor */
static uint8_t const USBD_LangIDDesc[]=
{
USB_LEN_LANGID_STR_DESC,
USB_DESC_TYPE_STRING,
LOBYTE(USBD_LANGID_STRING),
HIBYTE(USBD_LANGID_STRING),
};
static uint8_t const USB_SERIAL_STRING[] =
{
4*2+2,
USB_DESC_TYPE_STRING,
'0', 0,
'0', 0,
'0', 0,
'1', 0,
};
static 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
#ifndef HAVE_USB_HIDKBD
static uint8_t const HID_ReportDesc[] = {
0x06, 0xA0, 0xFF, // Usage page (vendor defined)
0x09, 0x01, // Usage ID (vendor defined)
0xA1, 0x01, // Collection (application)
// The Input report
0x09, 0x03, // Usage ID - vendor defined
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x75, 0x08, // Report Size (8 bits)
0x95, HID_EPIN_SIZE, // Report Count (64 fields)
0x81, 0x08, // Input (Data, Variable, Absolute)
// The Output report
0x09, 0x04, // Usage ID - vendor defined
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x75, 0x08, // Report Size (8 bits)
0x95, HID_EPOUT_SIZE, // Report Count (64 fields)
0x91, 0x08, // Output (Data, Variable, Absolute)
0xC0
};
#else
static uint8_t const HID_ReportDesc_kbd[] = {
0x05, 0x01,
0x09, 0x06,
0xA1, 0x01,
0x05, 0x07,
0x19, 0xE0,
0x29, 0xE7,
0x15, 0x00,
0x25, 0x01,
0x75, 0x01,
0x95, 0x08,
0x81, 0x02,
0x95, 0x01,
0x75, 0x08,
0x81, 0x01,
0x95, 0x05,
0x75, 0x01,
0x05, 0x08,
0x19, 0x01,
0x29, 0x05,
0x91, 0x02,
0x95, 0x01,
0x75, 0x03,
0x91, 0x01,
0x95, 0x06,
0x75, 0x08,
0x15, 0x00,
0x25, 0x65,
0x05, 0x07,
0x19, 0x00,
0x29, 0x65,
0x81, 0x00,
0xC0
};
#endif // HAVE_USB_HIDKBD
#ifdef HAVE_IO_U2F
static uint8_t const HID_ReportDesc_fido[] = {
0x06, 0xD0, 0xF1, // Usage page (vendor defined)
0x09, 0x01, // Usage ID (vendor defined)
0xA1, 0x01, // Collection (application)
// The Input report
0x09, 0x03, // Usage ID - vendor defined
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x75, 0x08, // Report Size (8 bits)
0x95, U2F_EPIN_SIZE, // Report Count (64 fields)
0x81, 0x08, // Input (Data, Variable, Absolute)
// The Output report
0x09, 0x04, // Usage ID - vendor defined
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x75, 0x08, // Report Size (8 bits)
0x95, U2F_EPOUT_SIZE, // Report Count (64 fields)
0x91, 0x08, // Output (Data, Variable, Absolute)
0xC0
};
#endif // HAVE_IO_U2F
#define ARRAY_U2LE(l) (l)&0xFF, (l)>>8
/* USB HID device Configuration Descriptor */
static __ALIGN_BEGIN uint8_t const USBD_CfgDesc[] __ALIGN_END =
{
0x09, /* bLength: Configuration Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
ARRAY_U2LE(0x9 /* wTotalLength: Bytes returned */
+0x9+0x9+0x7+0x7
#ifdef HAVE_IO_U2F
+0x9+0x9+0x7+0x7
#endif // HAVE_IO_U2F
#ifdef HAVE_USB_CLASS_CCID
+0x9+0x36+0x7+0x7
#endif // HAVE_USB_CLASS_CCID
#ifdef HAVE_WEBUSB
+0x9+0x7+0x7
#endif // HAVE_WEBUSB
),
1
#ifdef HAVE_IO_U2F
+1
#endif // HAVE_IO_U2F
#ifdef HAVE_USB_CLASS_CCID
+1
#endif // HAVE_USB_CLASS_CCID
#ifdef HAVE_WEBUSB
+1
#endif // HAVE_WEBUSB
, /*bNumInterfaces */
0x01, /*bConfigurationValue: Configuration value*/
USBD_IDX_PRODUCT_STR, /*iConfiguration: Index of string descriptor describing the configuration*/
0xC0, /*bmAttributes: bus powered */
0x32, /*MaxPower 100 mA: this current is used for detecting Vbus*/
#ifndef HAVE_USB_HIDKBD
/* HIDGEN ################################################################################################ */
/************** Descriptor of KBD HID interface ****************/
0x09, /*bLength: Interface Descriptor size*/
USB_DESC_TYPE_INTERFACE,/*bDescriptorType: Interface descriptor type*/
HID_INTF, /*bInterfaceNumber: Number of Interface*/
0x00, /*bAlternateSetting: Alternate setting*/
0x02, /*bNumEndpoints*/
0x03, /*bInterfaceClass: HID*/
0x00, /*bInterfaceSubClass : 1=BOOT, 0=no boot*/
0x00, /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
USBD_IDX_PRODUCT_STR, /*iInterface: Index of string descriptor*/
/******************** Descriptor of HID *************************/
0x09, /*bLength: HID Descriptor size*/
HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
0x11, /*bHIDUSTOM_HID: HID Class Spec release number*/
0x01,
0x00, /*bCountryCode: Hardware target country*/
0x01, /*bNumDescriptors: Number of HID class descriptors to follow*/
0x22, /*bDescriptorType*/
sizeof(HID_ReportDesc),/*wItemLength: Total length of Report descriptor*/
0x00,
/******************** Descriptor of Custom HID endpoints ********************/
0x07, /*bLength: Endpoint Descriptor size*/
USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/
HID_EPIN_ADDR, /*bEndpointAddress: Endpoint Address (IN)*/
0x03, /*bmAttributes: Interrupt endpoint*/
HID_EPIN_SIZE, /*wMaxPacketSize: 2 Byte max */
0x00,
0x01, /*bInterval: Polling Interval (20 ms)*/
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: */
HID_EPOUT_ADDR, /*bEndpointAddress: Endpoint Address (OUT)*/
0x03, /* bmAttributes: Interrupt endpoint */
HID_EPOUT_SIZE, /* wMaxPacketSize: 2 Bytes max */
0x00,
0x01, /* bInterval: Polling Interval (20 ms) */
#else
/* HIDKBD ################################################################################################ */
/************** Descriptor of KBD HID interface ****************/
0x09, /*bLength: Interface Descriptor size*/
USB_DESC_TYPE_INTERFACE,/*bDescriptorType: Interface descriptor type*/
0x00, /*bInterfaceNumber: Number of Interface*/
0x00, /*bAlternateSetting: Alternate setting*/
0x02, /*bNumEndpoints*/
0x03, /*bInterfaceClass: HID*/
0x01, /*bInterfaceSubClass : 1=BOOT, 0=no boot*/
0x01, /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
USBD_IDX_PRODUCT_STR, /*iInterface: Index of string descriptor*/
/******************** Descriptor of HID *************************/
0x09, /*bLength: HID Descriptor size*/
HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
0x11, /*bHIDUSTOM_HID: HID Class Spec release number*/
0x01,
0x21, /*bCountryCode: Hardware target country*/ // 0x21: US, 0x08: FR, 0x0D: ISO Intl
0x01, /*bNumDescriptors: Number of HID class descriptors to follow*/
0x22, /*bDescriptorType*/
sizeof(HID_ReportDesc_kbd),/*wItemLength: Total length of Report descriptor*/
0x00,
/******************** Descriptor of Custom HID endpoints ********************/
0x07, /*bLength: Endpoint Descriptor size*/
USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/
HID_EPIN_ADDR, /*bEndpointAddress: Endpoint Address (IN)*/
0x03, /*bmAttributes: Interrupt endpoint*/
8, /*wMaxPacketSize: */
0x00,
0x01, /*bInterval: Polling Interval */
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: */
HID_EPOUT_ADDR, /*bEndpointAddress: Endpoint Address (OUT)*/
0x03, /* bmAttributes: Interrupt endpoint */
8, /* wMaxPacketSize: */
0x00,
0x01, /* bInterval: Polling Interval */
#endif // HAVE_USB_HIDKBD
#ifdef HAVE_IO_U2F
/* HID FIDO ################################################################################################ */
/************** Descriptor of HID FIDO interface ****************/
0x09, /*bLength: Interface Descriptor size*/
USB_DESC_TYPE_INTERFACE,/*bDescriptorType: Interface descriptor type*/
U2F_INTF, /*bInterfaceNumber: Number of Interface*/
0x00, /*bAlternateSetting: Alternate setting*/
0x02, /*bNumEndpoints*/
0x03, /*bInterfaceClass: HID*/
0x01, /*bInterfaceSubClass : 1=BOOT, 0=no boot*/
0x01, /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
USBD_IDX_PRODUCT_STR, /*iInterface: Index of string descriptor*/
/******************** Descriptor of HID *************************/
0x09, /*bLength: HID Descriptor size*/
HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
0x11, /*bHIDUSTOM_HID: HID Class Spec release number*/
0x01,
0x21, /*bCountryCode: Hardware target country*/ // 0x21: US, 0x08: FR, 0x0D: ISO Intl
0x01, /*bNumDescriptors: Number of HID class descriptors to follow*/
0x22, /*bDescriptorType*/
sizeof(HID_ReportDesc_fido),/*wItemLength: Total length of Report descriptor*/
0x00,
/******************** Descriptor of Custom HID endpoints ********************/
0x07, /*bLength: Endpoint Descriptor size*/
USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/
U2F_EPIN_ADDR, /*bEndpointAddress: Endpoint Address (IN)*/
0x03, /*bmAttributes: Interrupt endpoint*/
U2F_EPIN_SIZE, /*wMaxPacketSize: */
0x00,
0x01, /*bInterval: Polling Interval */
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: */
U2F_EPOUT_ADDR, /*bEndpointAddress: Endpoint Address (OUT)*/
0x03, /* bmAttributes: Interrupt endpoint */
U2F_EPOUT_SIZE, /* wMaxPacketSize: */
0x00,
0x01,/* bInterval: Polling Interval */
#endif // HAVE_IO_U2F
#ifdef HAVE_USB_CLASS_CCID
/* CCID ################################################################################################ */
/******************** CCID **** interface ********************/
0x09, /* bLength: Interface Descriptor size */
0x04, /* bDescriptorType: */
CCID_INTF, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints: 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 */
0xBA, 0x06, 0x02, 0x00,
//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*/
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*/
#endif // HAVE_USB_CLASS_CCID
#ifdef HAVE_WEBUSB
/* WEBUSB ################################################################################################ */
/************** Descriptor of WEBUSB interface ****************/
0x09, /*bLength: Interface Descriptor size*/
USB_DESC_TYPE_INTERFACE,/*bDescriptorType: Interface descriptor type*/
WEBUSB_INTF, /*bInterfaceNumber: Number of Interface*/
0x00, /*bAlternateSetting: Alternate setting*/
0x02, /*bNumEndpoints*/
0xFF, /*bInterfaceClass: WINUSB*/
0xFF, /*bInterfaceSubClass : WINUSB*/
0xFF, /*nInterfaceProtocol : WINUSB*/
USBD_IDX_PRODUCT_STR, /*iInterface: Index of string descriptor*/
/******************** Descriptor of endpoints ********************/
0x07, /*bLength: Endpoint Descriptor size*/
USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/
WEBUSB_EPIN_ADDR, /*bEndpointAddress: Endpoint Address (IN)*/
0x03, /*bmAttributes: Interrupt endpoint*/
WEBUSB_EPIN_SIZE, /*wMaxPacketSize: */
0x00,
0x01, /*bInterval: Polling Interval */
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: */
WEBUSB_EPOUT_ADDR, /*bEndpointAddress: Endpoint Address (OUT)*/
0x03, /* bmAttributes: Interrupt endpoint */
WEBUSB_EPOUT_SIZE, /* wMaxPacketSize: */
0x00,
0x01,/* bInterval: Polling Interval */
#endif // HAVE_WEBUSB
} ;
#ifdef HAVE_IO_U2F
/* USB HID device Configuration Descriptor */
__ALIGN_BEGIN uint8_t const USBD_HID_Desc_fido[] __ALIGN_END =
{
/******************** Descriptor of HID *************************/
0x09, /*bLength: HID Descriptor size*/
HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
0x11, /*bHIDUSTOM_HID: HID Class Spec release number*/
0x01,
0x21, /*bCountryCode: Hardware target country*/ // 0x21: US, 0x08: FR, 0x0D: ISO Intl
0x01, /*bNumDescriptors: Number of HID class descriptors to follow*/
0x22, /*bDescriptorType*/
sizeof(HID_ReportDesc_fido),/*wItemLength: Total length of Report descriptor*/
0x00,
};
#endif // HAVE_IO_U2F
#ifndef HAVE_USB_HIDKBD
/* USB HID device Configuration Descriptor */
__ALIGN_BEGIN uint8_t const USBD_HID_Desc[] __ALIGN_END =
{
/* 18 */
0x09, /*bLength: HID Descriptor size*/
HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
0x11, /*bHIDUSTOM_HID: HID Class Spec release number*/
0x01,
0x00, /*bCountryCode: Hardware target country*/
0x01, /*bNumDescriptors: Number of HID class descriptors to follow*/
0x22, /*bDescriptorType*/
sizeof(HID_ReportDesc),/*wItemLength: Total length of Report descriptor*/
0x00,
};
#else
/* USB HID device Configuration Descriptor */
__ALIGN_BEGIN uint8_t const USBD_HID_Desc_kbd[] __ALIGN_END =
{
/******************** Descriptor of HID *************************/
0x09, /*bLength: HID Descriptor size*/
HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
0x11, /*bHIDUSTOM_HID: HID Class Spec release number*/
0x01,
0x21, /*bCountryCode: Hardware target country*/ // 0x21: US, 0x08: FR, 0x0D: ISO Intl
0x01, /*bNumDescriptors: Number of HID class descriptors to follow*/
0x22, /*bDescriptorType*/
sizeof(HID_ReportDesc_kbd),/*wItemLength: Total length of Report descriptor*/
0x00,
};
#endif // HAVE_USB_HIDKBD
/* USB Standard Device Descriptor */
static __ALIGN_BEGIN 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 uint8_t const USBD_DeviceDesc[]= {
0x12, /* bLength */
USB_DESC_TYPE_DEVICE, /* bDescriptorType */
#ifdef HAVE_WEBUSB
0x10, /* bcdUSB */
#else // HAVE_WEBUSB
0x00, /* bcdUSB */
#endif // HAVE_WEBUSB
0x02,
0x00, /* bDeviceClass */
0x00, /* bDeviceSubClass */
0x00, /* bDeviceProtocol */
USB_MAX_EP0_SIZE, /* bMaxPacketSize */
LOBYTE(USBD_VID), /* idVendor */
HIBYTE(USBD_VID), /* idVendor */
#if defined(HAVE_VID_PID_PROBER) || defined(HAVE_LEGACY_PID)
LOBYTE(USBD_PID), /* idProduct */
#else // HAVE_VID_PID_PROBER || defined(HAVE_LEGACY_PID)
LOBYTE(USBD_PID
#ifndef HAVE_USB_HIDKBD
| 0x01
#else
| 0x02
#endif
#ifdef HAVE_IO_U2F
| 0x04
#endif // HAVE_IO_U2F
#ifdef HAVE_USB_CLASS_CCID
| 0x08
#endif // HAVE_USB_CLASS_CCID
#ifdef HAVE_WEBUSB
| 0x10
#endif // HAVE_WEBUSB
),
#endif // HAVE_VID_PID_PROBER || HAVE_LEGACY_PID
HIBYTE(USBD_PID), /* idProduct */
// Change this ID to make windows WINUSB/WEBUSB reenumerate when the
// descriptor changes and the PID/VID are not changed.
0x01, /* bcdDevice rel. 2.01 */
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 */
1 /* bNumConfigurations */
}; /* USB_DeviceDescriptor */
/**
* @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;
}
/**
* @brief USBD_CUSTOM_HID_GetCfgDesc
* return configuration descriptor
* @param speed : current device speed
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_GetCfgDesc_impl (uint16_t *length)
{
*length = sizeof (USBD_CfgDesc);
return (uint8_t*)USBD_CfgDesc;
}
uint8_t* USBD_HID_GetHidDescriptor_impl(uint16_t* len) {
switch (USBD_Device.request.wIndex&0xFF) {
#ifdef HAVE_IO_U2F
case U2F_INTF:
*len = sizeof(USBD_HID_Desc_fido);
return (uint8_t*)USBD_HID_Desc_fido;
#endif // HAVE_IO_U2F
#ifndef HAVE_USB_HIDKBD
case HID_INTF:
*len = sizeof(USBD_HID_Desc);
return (uint8_t*)USBD_HID_Desc;
#else
case HID_INTF:
*len = sizeof(USBD_HID_Desc_kbd);
return (uint8_t*)USBD_HID_Desc_kbd;
#endif // HAVE_USB_HIDKBD
}
*len = 0;
return 0;
}
uint8_t* USBD_HID_GetReportDescriptor_impl(uint16_t* len) {
switch (USBD_Device.request.wIndex&0xFF) {
#ifdef HAVE_IO_U2F
case U2F_INTF:
// very dirty work due to lack of callback when USB_HID_Init is called
USBD_LL_OpenEP(&USBD_Device,
U2F_EPIN_ADDR,
USBD_EP_TYPE_INTR,
U2F_EPIN_SIZE);
USBD_LL_OpenEP(&USBD_Device,
U2F_EPOUT_ADDR,
USBD_EP_TYPE_INTR,
U2F_EPOUT_SIZE);
/* Prepare Out endpoint to receive 1st packet */
USBD_LL_PrepareReceive(&USBD_Device, U2F_EPOUT_ADDR, U2F_EPOUT_SIZE);
*len = sizeof(HID_ReportDesc_fido);
return (uint8_t*)HID_ReportDesc_fido;
#endif // HAVE_IO_U2F
#ifndef HAVE_USB_HIDKBD
case HID_INTF:
*len = sizeof(HID_ReportDesc);
return (uint8_t*)HID_ReportDesc;
#else
case HID_INTF:
*len = sizeof(HID_ReportDesc_kbd);
return (uint8_t*)HID_ReportDesc_kbd;
#endif // HAVE_USB_HIDKBD
}
*len = 0;
return 0;
}
/**
* @}
*/
/**
* @brief USBD_HID_DataOut
* handle data OUT Stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*
* This function is the default behavior for our implementation when data are sent over the out hid endpoint
*/
#ifdef HAVE_IO_U2F
/**
* @brief USBD_HID_Init
* Initialize the HID interface
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
uint8_t USBD_U2F_Init (USBD_HandleTypeDef *pdev,
uint8_t cfgidx)
{
UNUSED(cfgidx);
/* Open EP IN */
USBD_LL_OpenEP(pdev,
U2F_EPIN_ADDR,
USBD_EP_TYPE_INTR,
U2F_EPIN_SIZE);
/* Open EP OUT */
USBD_LL_OpenEP(pdev,
U2F_EPOUT_ADDR,
USBD_EP_TYPE_INTR,
U2F_EPOUT_SIZE);
/* Prepare Out endpoint to receive 1st packet */
USBD_LL_PrepareReceive(pdev, U2F_EPOUT_ADDR, U2F_EPOUT_SIZE);
return USBD_OK;
}
uint8_t USBD_U2F_DataIn_impl (USBD_HandleTypeDef *pdev,
uint8_t epnum)
{
UNUSED(pdev);
// only the data hid endpoint will receive data
switch (epnum) {
// FIDO endpoint
case (U2F_EPIN_ADDR&0x7F):
// advance the u2f sending machine state
u2f_transport_sent(&G_io_u2f, U2F_MEDIA_USB);
break;
}
return USBD_OK;
}
uint8_t USBD_U2F_DataOut_impl (USBD_HandleTypeDef *pdev,
uint8_t epnum, uint8_t* buffer)
{
switch (epnum) {
// FIDO endpoint
case (U2F_EPOUT_ADDR&0x7F):
USBD_LL_PrepareReceive(pdev, U2F_EPOUT_ADDR , U2F_EPOUT_SIZE);
u2f_transport_received(&G_io_u2f, buffer, io_seproxyhal_get_ep_rx_size(U2F_EPOUT_ADDR), U2F_MEDIA_USB);
break;
}
return USBD_OK;
}
#endif // HAVE_IO_U2F
uint8_t USBD_HID_DataIn_impl (USBD_HandleTypeDef *pdev,
uint8_t epnum)
{
UNUSED(pdev);
switch (epnum) {
// HID gen endpoint
case (HID_EPIN_ADDR&0x7F):
io_usb_hid_sent(io_usb_send_apdu_data);
break;
}
return USBD_OK;
}
uint8_t USBD_HID_DataOut_impl (USBD_HandleTypeDef *pdev,
uint8_t epnum, uint8_t* buffer, apdu_buffer_t * apdu_buf)
{
// only the data hid endpoint will receive data
switch (epnum) {
// HID gen endpoint
case (HID_EPOUT_ADDR&0x7F):
// prepare receiving the next chunk (masked time)
USBD_LL_PrepareReceive(pdev, HID_EPOUT_ADDR , HID_EPOUT_SIZE);
#ifndef HAVE_USB_HIDKBD
// avoid troubles when an apdu has not been replied yet
if (G_io_app.apdu_media == IO_APDU_MEDIA_NONE) {
// add to the hid transport
switch(io_usb_hid_receive(io_usb_send_apdu_data, buffer, io_seproxyhal_get_ep_rx_size(HID_EPOUT_ADDR), apdu_buf)) {
default:
break;
case IO_USB_APDU_RECEIVED:
G_io_app.apdu_media = IO_APDU_MEDIA_USB_HID; // for application code
G_io_app.apdu_state = APDU_USB_HID; // for next call to io_exchange
G_io_app.apdu_length = G_io_usb_hid_total_length;
break;
}
}
#endif // HAVE_USB_HIDKBD
break;
}
return USBD_OK;
}
#ifdef HAVE_WEBUSB
uint8_t USBD_WEBUSB_Init (USBD_HandleTypeDef *pdev,
uint8_t cfgidx)
{
UNUSED(cfgidx);
/* Open EP IN */
USBD_LL_OpenEP(pdev,
WEBUSB_EPIN_ADDR,
USBD_EP_TYPE_INTR,
WEBUSB_EPIN_SIZE);
/* Open EP OUT */
USBD_LL_OpenEP(pdev,
WEBUSB_EPOUT_ADDR,
USBD_EP_TYPE_INTR,
WEBUSB_EPOUT_SIZE);
/* Prepare Out endpoint to receive 1st packet */
USBD_LL_PrepareReceive(pdev, WEBUSB_EPOUT_ADDR, WEBUSB_EPOUT_SIZE);
return USBD_OK;
}
uint8_t USBD_WEBUSB_DeInit (USBD_HandleTypeDef *pdev,
uint8_t cfgidx) {
UNUSED(pdev);
UNUSED(cfgidx);
return USBD_OK;
}
uint8_t USBD_WEBUSB_Setup (USBD_HandleTypeDef *pdev,
USBD_SetupReqTypedef *req)
{
UNUSED(pdev);
UNUSED(req);
return USBD_OK;
}
uint8_t USBD_WEBUSB_DataIn (USBD_HandleTypeDef *pdev,
uint8_t epnum)
{
UNUSED(pdev);
switch (epnum) {
// HID gen endpoint
case (WEBUSB_EPIN_ADDR&0x7F):
io_usb_hid_sent(io_usb_send_apdu_data_ep0x83);
break;
}
return USBD_OK;
}
uint8_t USBD_WEBUSB_DataOut (USBD_HandleTypeDef *pdev,
uint8_t epnum, uint8_t* buffer)
{
// only the data hid endpoint will receive data
switch (epnum) {
// HID gen endpoint
case (WEBUSB_EPOUT_ADDR&0x7F):
// prepare receiving the next chunk (masked time)
USBD_LL_PrepareReceive(pdev, WEBUSB_EPOUT_ADDR, WEBUSB_EPOUT_SIZE);
// avoid troubles when an apdu has not been replied yet
if (G_io_app.apdu_media == IO_APDU_MEDIA_NONE) {
// add to the hid transport
switch(io_usb_hid_receive(io_usb_send_apdu_data_ep0x83, buffer, io_seproxyhal_get_ep_rx_size(WEBUSB_EPOUT_ADDR))) {
default:
break;
case IO_USB_APDU_RECEIVED:
G_io_app.apdu_media = IO_APDU_MEDIA_USB_WEBUSB; // for application code
G_io_app.apdu_state = APDU_USB_WEBUSB; // for next call to io_exchange
G_io_app.apdu_length = G_io_usb_hid_total_length;
break;
}
}
break;
}
return USBD_OK;
}
// arbitrary vendor choosen
#define WEBUSB_VENDOR_CODE 0x1E
// from https://wicg.github.io/webusb/#webusb-platform-capability-descriptor
// see also this (for endianness explanation)
// https://github.com/WICG/webusb/issues/115#issuecomment-352206549
#define WEBUSB_UUID 0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47,0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65
#define WEBUSB_REQ_GET_URL 0x02
#define WEBUSB_DT_DESCRIPTOR_SET_HEADER 0
#define WEBUSB_DT_CONFIGURATION_SUBSET_HEADER 1
#define WEBUSB_DT_FUNCTION_SUBSET_HEADER 2
#define WEBUSB_DT_URL 3
#define WEBUSB_URL_SCHEME_HTTP 0
#define WEBUSB_URL_SCHEME_HTTPS 1
#define WEBUSB_URL_SCHEME_CUSTOM 255
unsigned char const C_webusb_url_descriptor[] = {
// bLength
3 + WEBUSB_URL_SIZE_B,
// bDescriptorType
WEBUSB_DT_URL,
// bScheme
WEBUSB_URL_SCHEME_HTTPS,
// URL
WEBUSB_URL
};
/* USB 3.1 Descriptor Types - Table 9-6 */
#define USB_DT_BOS 15
#define USB_DT_DEVICE_CAPABILITY 16
#define USB_DT_BOS_SIZE 5
/* USB Device Capability Types - USB 3.1 Table 9-14 */
#define USB_DC_PLATFORM 5
#define MS_OS_20_DESCRIPTOR_LENGTH (0xb2)
#define WINUSB_VENDOR_CODE 0x77
unsigned char const C_usb_bos[] = {
USB_DT_BOS_SIZE, // bLength (5)
USB_DT_BOS, // bDescriptorType
0x39, 0x00, // wTotalLength
2, //bNumberDeviceCapabilities
// capability descriptor
8+16, // bLength
USB_DT_DEVICE_CAPABILITY, // bDescriptorType
USB_DC_PLATFORM, // bDevCapability
0, // bReserved
WEBUSB_UUID, // UUID[16]
0x00, // bcdVersion
0x01,
WEBUSB_VENDOR_CODE, // bVencordCode
#if WEBUSB_URL_SIZE_B > 0
1, // iLandingPage
#else // WEBUSB_URL_SIZE_B
0, // iLandingPage, no url to retrieve
#endif // WEBUSB_URL_SIZE_B
// Microsoft OS 2.0 Platform Capability Descriptor
0x1C, // Descriptor size (28 bytes)
0x10, // Descriptor type (Device Capability)
0x05, // Capability type (Platform)
0x00, // Reserved
// MS OS 2.0 Platform Capability ID (D8DD60DF-4589-4CC7-9CD2-659D9E648A9F)
0xDF, 0x60, 0xDD, 0xD8,
0x89, 0x45,
0xC7, 0x4C,
0x9C, 0xD2,
0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F,
0x00, 0x00, 0x03, 0x06, // Windows version (8.1) (0x06030000)
MS_OS_20_DESCRIPTOR_LENGTH, 0x00,
WINUSB_VENDOR_CODE, // Vendor-assigned bMS_VendorCode
0x00 // Doesn’t support alternate enumeration
};
#endif // HAVE_WEBUSB
static uint8_t *USBD_BOSDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
UNUSED(speed);
#ifdef HAVE_WEBUSB
*length = sizeof(C_usb_bos);
return (uint8_t*)C_usb_bos;
#else
*length = 0;
return NULL;
#endif
}
/** @defgroup USBD_HID_Private_Functions
* @{
*/
// note: how core lib usb calls the hid class
USBD_DescriptorsTypeDef const HID_Desc = {
USBD_DeviceDescriptor,
USBD_LangIDStrDescriptor,
USBD_ManufacturerStrDescriptor,
USBD_ProductStrDescriptor,
USBD_SerialStrDescriptor,
USBD_ConfigStrDescriptor,
USBD_InterfaceStrDescriptor,
USBD_BOSDescriptor,
};
#ifdef HAVE_IO_U2F
static USBD_ClassTypeDef const USBD_U2F =
{
USBD_U2F_Init,
USBD_HID_DeInit,
USBD_HID_Setup,
NULL, /*EP0_TxSent*/
NULL, /*EP0_RxReady*/ /* STATUS STAGE IN */
USBD_U2F_DataIn_impl, /*DataIn*/
USBD_U2F_DataOut_impl, /*DataOut*/
NULL, /*SOF */
NULL,
NULL,
USBD_GetCfgDesc_impl,
USBD_GetCfgDesc_impl,
USBD_GetCfgDesc_impl,
USBD_GetDeviceQualifierDesc_impl,
};
#endif // HAVE_IO_U2F
static USBD_ClassTypeDef const USBD_HID =
{
USBD_HID_Init,
USBD_HID_DeInit,
USBD_HID_Setup,
NULL, /*EP0_TxSent*/
NULL, /*EP0_RxReady*/ /* STATUS STAGE IN */
USBD_HID_DataIn_impl, /*DataIn*/
USBD_HID_DataOut_impl, /*DataOut*/
NULL, /*SOF */
NULL,
NULL,
USBD_GetCfgDesc_impl,
USBD_GetCfgDesc_impl,
USBD_GetCfgDesc_impl,
USBD_GetDeviceQualifierDesc_impl,
};
#ifdef HAVE_WEBUSB
static const unsigned char C_winusb_string_descriptor[] = {
// bLength
0x12,
// bDescriptorType
USB_DESC_TYPE_STRING,
// wData
'M', 0x00, 'S', 0x00, 'F', 0x00, 'T', 0x00, '1', 0x00, '0', 0x00, '0', 0x00, WINUSB_VENDOR_CODE, 0x00, // MSFT100
};
// Microsoft OS 2.0 descriptor wIndex values
#define MS_OS_20_DESCRIPTOR_INDEX 0x07
// Microsoft OS 2.0 descriptor types
#define MS_OS_20_SUBSET_HEADER_CONFIGURATION 0x01
#define MS_OS_20_SUBSET_HEADER_FUNCTION 0x02
#define MS_OS_20_FEATURE_COMPATIBLE_ID 0x03
#define MS_OS_20_FEATURE_REG_PROPERTY 0x04
static const unsigned char C_winusb_request_descriptor[] = {
// Microsoft OS 2.0 descriptor set header (table 10)
0x0A,
0x00, // Descriptor size (10 bytes)
0x00,
0x00, // MS OS 2.0 descriptor set header
0x00,
0x00,
0x03,
0x06, // Windows version (8.1) (0x06030000)
MS_OS_20_DESCRIPTOR_LENGTH,
0x00, // Size, MS OS 2.0 descriptor set
// Microsoft OS 2.0 configuration subset header
0x08, 0x00, // Descriptor size (8 bytes)
MS_OS_20_SUBSET_HEADER_CONFIGURATION, 0x00, // MS OS 2.0 configuration subset header
0x00, // bConfigurationValue
0x00, // Reserved
0xA8, 0x00, // Size, MS OS 2.0 configuration subset
// Microsoft OS 2.0 function subset header
0x08, 0x00, // Descriptor size (8 bytes)
MS_OS_20_SUBSET_HEADER_FUNCTION, 0x00, // MS OS 2.0 function subset header
WEBUSB_INTF, // first Interface impacted by this function
0x00, // Reserved
0xA0, 0x00, // Size, MS OS 2.0 function subset
// Microsoft OS 2.0 compatible ID descriptor (table 13)
0x14, 0x00, // wLength
MS_OS_20_FEATURE_COMPATIBLE_ID, 0x00, // MS_OS_20_FEATURE_COMPATIBLE_ID
'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x84, 0x00, //wLength:
MS_OS_20_FEATURE_REG_PROPERTY, 0x00, // wDescriptorType: MS_OS_20_FEATURE_REG_PROPERTY: 0x04 (Table 9)
0x07, 0x00, //wPropertyDataType: REG_MULTI_SZ (Table 15)
0x2a, 0x00, //wPropertyNameLength:
//bPropertyName: “DeviceInterfaceGUID”
'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, 'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, 't', 0x00, 'e', 0x00,
'r', 0x00, 'f', 0x00, 'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, 'U', 0x00, 'I', 0x00, 'D', 0x00, 's', 0x00,
0x00, 0x00,
0x50, 0x00, // wPropertyDataLength
//bPropertyData: “{CE809264-4B24-4E81-A8B2-57ED01D580E1}”.
'{', 0x00, 'C', 0x00, 'E', 0x00, '8', 0x00, '0', 0x00, '9', 0x00, '2', 0x00, '6', 0x00, '4', 0x00, '-', 0x00,
'4', 0x00, 'B', 0x00, '2', 0x00, '4', 0x00, '-', 0x00, '4', 0x00, 'E', 0x00, '8', 0x00, '1', 0x00, '-', 0x00,
'A', 0x00, '8', 0x00, 'B', 0x00, '2', 0x00, '-', 0x00, '5', 0x00, '7', 0x00, 'E', 0x00, 'D', 0x00, '0', 0x00,
'1', 0x00, 'D', 0x00, '5', 0x00, '8', 0x00, '0', 0x00, 'E', 0x00, '1', 0x00, '}', 0x00, 0x00, 0x00, 0x00, 0x00
};
#define WINUSB_GET_COMPATIBLE_ID_FEATURE 0x04
static const unsigned char C_winusb_wcid[] = {
// header
0x28, 0x00, 0x00, 0x00, // dwLength
0x00, 0x01, // bcdVersion
0x04, 0x00, // wIndex
0x01, // bNumSections
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved
// functions
WEBUSB_INTF, // bInterfaceNumber
0x01, // reserved
'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, // compatibleId
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, // subCompatibleId
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved
};
#define WINUSB_GET_EXTENDED_PROPERTIES_OS_FEATURE 0x05
static const unsigned char C_winusb_guid[] = {
// header
0x92, 0x00, 0x00, 0x00, // dwLength
0x00, 0x01, // bcdVersion
0x05, 0x00, // wIndex
0x01, 0x00, // wNumFeatures
// features
0x88, 0x00, 0x00, 0x00, // dwLength
0x07, 0x00, 0x00, 0x00, // dwPropertyDataType
0x2A, 0x00, // wNameLength
'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, 'c', 0x00, 'e', 0x00,
'I', 0x00, 'n', 0x00, 't', 0x00, 'e', 0x00, 'r', 0x00, 'f', 0x00,
'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, 'U', 0x00, 'I', 0x00,
'D', 0x00, 's', 0x00, 0x00, 0x00, // .name, unicode nul terminated
0x50, 0x00, 0x00, 0x00, // dwPropertyDataLength
// Same as BLE char: 13d63400-2C97-0004-0000-4c6564676572
'{', 0x00, '1', 0x00, '3', 0x00, 'd', 0x00, '6', 0x00, '3', 0x00,
'4', 0x00, '0', 0x00, '0', 0x00, '-', 0x00, '2', 0x00, 'C', 0x00,
'9', 0x00, '7', 0x00, '-', 0x00, '0', 0x00, '0', 0x00, '0', 0x00,
'4', 0x00, '-', 0x00, '0', 0x00, '0', 0x00, '0', 0x00, '0', 0x00,
'-', 0x00, '4', 0x00, 'c', 0x00, '6', 0x00, '5', 0x00, '6', 0x00,
'4', 0x00, '6', 0x00, '7', 0x00, '6', 0x00, '5', 0x00, '7', 0x00,
'2', 0x00, '}', 0x00, 0x00, 0x00, 0x00, 0x00 // propertyData, double unicode nul terminated
};
// upon unsupported request, check for webusb request
void USBD_CtlError( USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req) {
#if WEBUSB_URL_SIZE_B > 0
if ((req->bmRequest & 0x80) && req->bRequest == WEBUSB_VENDOR_CODE && req->wIndex == WEBUSB_REQ_GET_URL
// HTTPS url
&& req->wValue == 1) {
// return the URL descriptor
USBD_CtlSendData (pdev, (unsigned char*)C_webusb_url_descriptor, MIN(req->wLength, sizeof(C_webusb_url_descriptor)));
}
else
#endif // WEBUSB_URL_SIZE_B
// SETUP (LE): 0x80 0x06 0x03 0x77 0x00 0x00 0xXX 0xXX
if ((req->bmRequest & 0x80)
&& req->bRequest == USB_REQ_GET_DESCRIPTOR
&& (req->wValue>>8) == USB_DESC_TYPE_STRING
&& (req->wValue & 0xFF) == 0xEE) {
USBD_CtlSendData(pdev, (unsigned char*)C_winusb_string_descriptor, MIN(req->wLength, sizeof(C_winusb_string_descriptor)));
}
// SETUP (LE): 0x80 0x77 0x04 0x00 0x00 0x00 0xXX 0xXX
else if ((req->bmRequest & 0x80)
&& req->bRequest == WINUSB_VENDOR_CODE
&& req->wIndex == WINUSB_GET_COMPATIBLE_ID_FEATURE) {
USBD_CtlSendData(pdev, (unsigned char*)C_winusb_wcid, MIN(req->wLength, sizeof(C_winusb_wcid)));
}
// SETUP (LE): 0x80 0x77 0x05 0x00 0x00 0x00 0xXX 0xXX
else if ((req->bmRequest & 0x80)
&& req->bRequest == WINUSB_VENDOR_CODE
&& req->wIndex == WINUSB_GET_EXTENDED_PROPERTIES_OS_FEATURE
) {
USBD_CtlSendData(pdev, (unsigned char*)C_winusb_guid, MIN(req->wLength, sizeof(C_winusb_guid)));
}
// Microsoft OS 2.0 Descriptors for Windows 8.1 and Windows 10
else if ((req->bmRequest & 0x80)
&& req->bRequest == WINUSB_VENDOR_CODE
&& req->wIndex == MS_OS_20_DESCRIPTOR_INDEX) {
USBD_CtlSendData(pdev, (unsigned char*)C_winusb_request_descriptor, MIN(req->wLength, sizeof(C_winusb_request_descriptor)));
}
else {
USBD_CtlStall(pdev);
}
}
static const USBD_ClassTypeDef USBD_WEBUSB =
{
USBD_WEBUSB_Init,
USBD_WEBUSB_DeInit,
USBD_WEBUSB_Setup,
NULL, /*EP0_TxSent*/
NULL, /*EP0_RxReady*/
USBD_WEBUSB_DataIn,
USBD_WEBUSB_DataOut,
NULL, /*SOF */
NULL, /*ISOIn*/
NULL, /*ISOOut*/
USBD_GetCfgDesc_impl,
USBD_GetCfgDesc_impl,
USBD_GetCfgDesc_impl,
USBD_GetDeviceQualifierDesc_impl,
};
#endif // HAVE_WEBUSB
#ifdef HAVE_USB_CLASS_CCID
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,
};
uint8_t SC_AnswerToReset (uint8_t voltage, uint8_t* atr_buffer) {
UNUSED(voltage);
// return the atr length
atr_buffer[0] = 0x3B;
atr_buffer[1] = 0;
return 2;
}
void SC_Poweroff(void) {
// nothing to do ?
}
uint8_t SC_ExecuteEscape (uint8_t* escapePtr, uint32_t escapeLen,
uint8_t* responseBuff,
uint16_t* responseLen) {
UNUSED(escapePtr);
UNUSED(escapeLen);
UNUSED(responseBuff);
UNUSED(responseLen);
// nothing to do ?
return 0;
}
#endif // HAVE_USB_CLASS_CCID
void USB_power(unsigned char enabled) {
memset(&USBD_Device, 0, sizeof(USBD_Device));
// init timeouts and other global fields
memset(G_io_app.usb_ep_xfer_len, 0, sizeof(G_io_app.usb_ep_xfer_len));
memset(G_io_app.usb_ep_timeouts, 0, sizeof(G_io_app.usb_ep_timeouts));
if (enabled) {
memset(&USBD_Device, 0, sizeof(USBD_Device));
/* Init Device Library */
USBD_Init(&USBD_Device, (USBD_DescriptorsTypeDef*)&HID_Desc, 0);
/* Register the HID class */
USBD_RegisterClassForInterface(HID_INTF, &USBD_Device, (USBD_ClassTypeDef*)&USBD_HID);
#ifdef HAVE_IO_U2F
USBD_RegisterClassForInterface(U2F_INTF, &USBD_Device, (USBD_ClassTypeDef*)&USBD_U2F);
// initialize the U2F tunnel transport
u2f_transport_init(&G_io_u2f, G_io_apdu_buffer, IO_APDU_BUFFER_SIZE);
#endif // HAVE_IO_U2F
#ifdef HAVE_USB_CLASS_CCID
USBD_RegisterClassForInterface(CCID_INTF, &USBD_Device, (USBD_ClassTypeDef*)&USBD_CCID);
#endif // HAVE_USB_CLASS_CCID
#ifdef HAVE_WEBUSB
USBD_RegisterClassForInterface(WEBUSB_INTF, &USBD_Device, (USBD_ClassTypeDef*)&USBD_WEBUSB);
#endif // HAVE_WEBUSB
/* Start Device Process */
USBD_Start(&USBD_Device);
}
else {
USBD_DeInit(&USBD_Device);
}
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/