1.4.1 firmware port
Code update for 1.4.1 fw Fix PUT_DATA[serial] command
This commit is contained in:
parent
cf6e295e47
commit
81090d3f23
59
Makefile
59
Makefile
@ -1,4 +1,6 @@
|
|||||||
# Copyright 2017 Cedric Mesnil <cslashm@gmail.com>, Ledger SAS
|
#*******************************************************************************
|
||||||
|
# Ledger Nano S
|
||||||
|
# (c) 2016 Ledger
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@ -11,43 +13,62 @@
|
|||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
#*******************************************************************************
|
||||||
|
|
||||||
|
|
||||||
ifeq ($(BOLOS_SDK),)
|
ifeq ($(BOLOS_SDK),)
|
||||||
$(error Environment variable BOLOS_SDK is not set)
|
$(error Environment variable BOLOS_SDK is not set)
|
||||||
endif
|
endif
|
||||||
include $(BOLOS_SDK)/Makefile.defines
|
include $(BOLOS_SDK)/Makefile.defines
|
||||||
|
|
||||||
APPNAME = "OpenPGP"
|
APP_LOAD_PARAMS=--appFlags 0x40 --path "2152157255'" --curve secp256k1 $(COMMON_LOAD_PARAMS)
|
||||||
APP_LOAD_PARAMS=--appFlags 0x40 --path "2152157255" --curve secp256k1 $(COMMON_LOAD_PARAMS)
|
|
||||||
|
APPNAME = OpenPGP
|
||||||
|
|
||||||
|
SPECVERSION="3.3.1"
|
||||||
|
|
||||||
APPVERSION_M=1
|
APPVERSION_M=1
|
||||||
APPVERSION_N=1
|
APPVERSION_N=1
|
||||||
APPVERSION_P=0
|
APPVERSION_P=1
|
||||||
|
|
||||||
APPVERSION=$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)
|
APPVERSION=$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)
|
||||||
SPECVERSION="3.3.1"
|
|
||||||
ICONNAME=images/icon_pgp.gif
|
|
||||||
|
|
||||||
|
ifeq ($(TARGET_NAME),TARGET_BLUE)
|
||||||
|
ICONNAME=images/icon_pgp_blue.gif
|
||||||
|
else
|
||||||
|
ICONNAME=images/icon_pgp.gif
|
||||||
|
endif
|
||||||
|
|
||||||
|
DEFINES += $(GPG_CONFIG) GPG_VERSION=$(APPVERSION) GPG_NAME=$(APPNAME) SPEC_VERSION=$(SPECVERSION)
|
||||||
|
|
||||||
################
|
################
|
||||||
# Default rule #
|
# Default rule #
|
||||||
################
|
################
|
||||||
|
|
||||||
all: default
|
all: default
|
||||||
|
|
||||||
############
|
############
|
||||||
# Platform #
|
# Platform #
|
||||||
############
|
############
|
||||||
|
#SCRIPT_LD := script.ld
|
||||||
|
|
||||||
|
ifneq ($(NO_CONSENT),)
|
||||||
|
DEFINES += NO_CONSENT
|
||||||
|
endif
|
||||||
|
|
||||||
|
DEFINES += OS_IO_SEPROXYHAL IO_SEPROXYHAL_BUFFER_SIZE_B=300
|
||||||
|
DEFINES += HAVE_BAGL HAVE_SPRINTF
|
||||||
|
#DEFINES += HAVE_PRINTF PRINTF=screen_printf
|
||||||
|
DEFINES += PRINTF\(...\)=
|
||||||
|
DEFINES += HAVE_IO_USB HAVE_L4_USBLIB IO_USB_MAX_ENDPOINTS=6 IO_HID_EP_LENGTH=64 HAVE_USB_APDU
|
||||||
|
#DEFINES += HAVE_BLE
|
||||||
|
DEFINES += UNUSED\(x\)=\(void\)x
|
||||||
|
DEFINES += APPVERSION=\"$(APPVERSION)\"
|
||||||
|
DEFINES += CUSTOM_IO_APDU_BUFFER_SIZE=\(255+5+64\)
|
||||||
|
|
||||||
DEFINES += OS_IO_SEPROXYHAL IO_SEPROXYHAL_BUFFER_SIZE_B=128
|
|
||||||
DEFINES += HAVE_BAGL HAVE_PRINTF HAVE_SPRINTF
|
|
||||||
DEFINES += HAVE_IO_USB HAVE_L4_USBLIB IO_USB_MAX_ENDPOINTS=7 IO_HID_EP_LENGTH=64 HAVE_USB_APDU
|
|
||||||
DEFINES += HAVE_USB_CLASS_CCID
|
DEFINES += HAVE_USB_CLASS_CCID
|
||||||
|
|
||||||
DEFINES += $(GPG_CONFIG) GPG_VERSION=$(APPVERSION) GPG_NAME=$(APPNAME) SPEC_VERSION=$(SPECVERSION)
|
|
||||||
|
|
||||||
##############
|
##############
|
||||||
# Compiler #
|
# Compiler #
|
||||||
##############
|
##############
|
||||||
#GCCPATH := $(BOLOS_ENV)/gcc-arm-none-eabi-5_3-2016q1/bin/
|
#GCCPATH := $(BOLOS_ENV)/gcc-arm-none-eabi-5_3-2016q1/bin/
|
||||||
#CLANGPATH := $(BOLOS_ENV)/clang-arm-fropi/bin/
|
#CLANGPATH := $(BOLOS_ENV)/clang-arm-fropi/bin/
|
||||||
@ -55,6 +76,8 @@ CC := $(CLANGPATH)clang
|
|||||||
|
|
||||||
#CFLAGS += -O0 -gdwarf-2 -gstrict-dwarf
|
#CFLAGS += -O0 -gdwarf-2 -gstrict-dwarf
|
||||||
CFLAGS += -O3 -Os
|
CFLAGS += -O3 -Os
|
||||||
|
#CFLAGS += -fno-jump-tables -fno-lookup-tables -fsave-optimization-record
|
||||||
|
#$(info $(CFLAGS))
|
||||||
|
|
||||||
AS := $(GCCPATH)arm-none-eabi-gcc
|
AS := $(GCCPATH)arm-none-eabi-gcc
|
||||||
|
|
||||||
@ -66,9 +89,9 @@ LDLIBS += -lm -lgcc -lc
|
|||||||
# import rules to compile glyphs(/pone)
|
# import rules to compile glyphs(/pone)
|
||||||
include $(BOLOS_SDK)/Makefile.glyphs
|
include $(BOLOS_SDK)/Makefile.glyphs
|
||||||
|
|
||||||
### computed variables
|
### variables processed by the common makefile.rules of the SDK to grab source files and include dirs
|
||||||
APP_SOURCE_PATH += src
|
APP_SOURCE_PATH += src src/lib_stusb_impl
|
||||||
SDK_SOURCE_PATH += lib_stusb lib_stusb_impl
|
SDK_SOURCE_PATH += lib_stusb
|
||||||
|
|
||||||
|
|
||||||
load: all
|
load: all
|
||||||
@ -81,5 +104,5 @@ delete:
|
|||||||
include $(BOLOS_SDK)/Makefile.rules
|
include $(BOLOS_SDK)/Makefile.rules
|
||||||
|
|
||||||
#add dependency on custom makefile filename
|
#add dependency on custom makefile filename
|
||||||
dep/%.d: %.c Makefile.genericwallet
|
dep/%.d: %.c Makefile
|
||||||
|
|
||||||
|
@ -370,6 +370,7 @@ the reader and the delegated PIN support.
|
|||||||
Edit the file ~/.gnupg/scdaemon.conf and add the following lines:
|
Edit the file ~/.gnupg/scdaemon.conf and add the following lines:
|
||||||
|
|
||||||
| ``reader-port "Ledger Token [Nano S] (0001) 01 00"``
|
| ``reader-port "Ledger Token [Nano S] (0001) 01 00"``
|
||||||
|
| ``allow-admin``
|
||||||
| ``enable-pinpad-varlen``
|
| ``enable-pinpad-varlen``
|
||||||
|
|
||||||
|
|
||||||
|
167
script.ld
Normal file
167
script.ld
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Ledger Blue - Secure firmware
|
||||||
|
* (c) 2016, 2017 Ledger
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global chip memory layout and constants
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
DISCARD (rwx) : ORIGIN = 0xd0000000, LENGTH = 1M
|
||||||
|
|
||||||
|
FLASH (rx) : ORIGIN = 0xc0d00000, LENGTH = 400K
|
||||||
|
SRAM (rwx) : ORIGIN = 0x20001800, LENGTH = 4K
|
||||||
|
}
|
||||||
|
|
||||||
|
PAGE_SIZE = 64;
|
||||||
|
STACK_SIZE = 768;
|
||||||
|
END_STACK = ORIGIN(SRAM) + LENGTH(SRAM);
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
ENTRY(main)
|
||||||
|
|
||||||
|
/****************************************************************/
|
||||||
|
/* This section locates the code in FLASH */
|
||||||
|
/****************************************************************/
|
||||||
|
|
||||||
|
/** put text in Flash memory, VMA will be equal to LMA */
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
/* provide start code symbol, shall be zero */
|
||||||
|
_text = .;
|
||||||
|
_nvram = .;
|
||||||
|
|
||||||
|
PROVIDE(_setjmp = setjmp); /*thanks clang*/
|
||||||
|
|
||||||
|
/* ensure main is always @ 0xC0D00000 */
|
||||||
|
*(.boot*)
|
||||||
|
|
||||||
|
/* place the other code and rodata defined BUT nvram variables that are displaced in a r/w area */
|
||||||
|
*(.text*)
|
||||||
|
*(.rodata.[^UN]*) /*.data.rel.ro* not here to detect invalid PIC usage */
|
||||||
|
*(.rodata.N[^_]*)
|
||||||
|
|
||||||
|
. = ALIGN(4);
|
||||||
|
|
||||||
|
/* all code placed */
|
||||||
|
_etext = .;
|
||||||
|
|
||||||
|
. = ALIGN(PAGE_SIZE);
|
||||||
|
|
||||||
|
_nvram_data = .;
|
||||||
|
|
||||||
|
/* NVM data (ex-filesystem) */
|
||||||
|
*(.rodata.USBD_CfgDesc)
|
||||||
|
*(.bss.N_* .rodata.N_* .rodata.USBD_CfgDesc)
|
||||||
|
. = ALIGN(PAGE_SIZE);
|
||||||
|
_install_parameters = .;
|
||||||
|
PROVIDE(N_install_parameters = .);
|
||||||
|
_envram = .;
|
||||||
|
_nvram_data_size = _envram - _nvram_data;
|
||||||
|
|
||||||
|
} > FLASH = 0x00
|
||||||
|
|
||||||
|
.data (NOLOAD):
|
||||||
|
{
|
||||||
|
. = ALIGN(4);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Place RAM initialized variables
|
||||||
|
*/
|
||||||
|
_data = .;
|
||||||
|
|
||||||
|
*(vtable)
|
||||||
|
*(.data*)
|
||||||
|
|
||||||
|
_edata = .;
|
||||||
|
|
||||||
|
} > DISCARD /*> SRAM AT>FLASH = 0x00 */
|
||||||
|
|
||||||
|
.bss :
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Place RAM uninitialized variables
|
||||||
|
*/
|
||||||
|
_bss = .;
|
||||||
|
*(.bss*)
|
||||||
|
_ebss = .;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reserve stack size
|
||||||
|
*/
|
||||||
|
. = ALIGN(4);
|
||||||
|
app_stack_canary = .;
|
||||||
|
PROVIDE(app_stack_canary = .);
|
||||||
|
. += 4;
|
||||||
|
_stack = .;
|
||||||
|
. = _stack + STACK_SIZE;
|
||||||
|
PROVIDE( _stack_size = STACK_SIZE );
|
||||||
|
PROVIDE( _estack = ABSOLUTE(END_STACK) );
|
||||||
|
|
||||||
|
} > SRAM = 0x00
|
||||||
|
|
||||||
|
/****************************************************************/
|
||||||
|
/* DEBUG */
|
||||||
|
/****************************************************************/
|
||||||
|
|
||||||
|
/* remove the debugging information from the standard libraries */
|
||||||
|
DEBUG (NOLOAD) :
|
||||||
|
{
|
||||||
|
libc.a ( * )
|
||||||
|
libm.a ( * )
|
||||||
|
libgcc.a ( * )
|
||||||
|
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stabs debugging sections. */
|
||||||
|
.stab 0 : { *(.stab) }
|
||||||
|
.stabstr 0 : { *(.stabstr) }
|
||||||
|
.stab.excl 0 : { *(.stab.excl) }
|
||||||
|
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||||
|
.stab.index 0 : { *(.stab.index) }
|
||||||
|
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||||
|
.comment 0 : { *(.comment) }
|
||||||
|
/* DWARF debug sections.
|
||||||
|
Symbols in the DWARF debugging sections are relative to the beginning
|
||||||
|
of the section so we begin them at 0. */
|
||||||
|
/* DWARF 1 */
|
||||||
|
.debug 0 : { *(.debug) }
|
||||||
|
.line 0 : { *(.line) }
|
||||||
|
/* GNU DWARF 1 extensions */
|
||||||
|
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||||
|
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||||
|
/* DWARF 1.1 and DWARF 2 */
|
||||||
|
.debug_aranges 0 : { *(.debug_aranges) }
|
||||||
|
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||||
|
/* DWARF 2 */
|
||||||
|
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
|
||||||
|
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||||
|
.debug_line 0 : { *(.debug_line) }
|
||||||
|
.debug_frame 0 : { *(.debug_frame) }
|
||||||
|
.debug_str 0 : { *(.debug_str) }
|
||||||
|
.debug_loc 0 : { *(.debug_loc) }
|
||||||
|
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||||
|
/* SGI/MIPS DWARF 2 extensions */
|
||||||
|
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||||
|
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||||
|
.debug_typenames 0 : { *(.debug_typenames) }
|
||||||
|
.debug_varnames 0 : { *(.debug_varnames) }
|
||||||
|
|
||||||
|
}
|
@ -1,591 +0,0 @@
|
|||||||
/**
|
|
||||||
******************************************************************************
|
|
||||||
* @file usbd_ccid_if.c
|
|
||||||
* @author MCD Application Team
|
|
||||||
* @version V1.0.1
|
|
||||||
* @date 31-January-2014
|
|
||||||
* @brief This file provides all the functions for USB Interface for CCID
|
|
||||||
******************************************************************************
|
|
||||||
* @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_if.h"
|
|
||||||
|
|
||||||
#ifdef HAVE_USB_CLASS_CCID
|
|
||||||
|
|
||||||
/* Private typedef -----------------------------------------------------------*/
|
|
||||||
/* Private define ------------------------------------------------------------*/
|
|
||||||
/* Private macro -------------------------------------------------------------*/
|
|
||||||
/* Private variables ---------------------------------------------------------*/
|
|
||||||
uint8_t Ccid_BulkState;
|
|
||||||
uint8_t ccid_card_inserted;
|
|
||||||
uint8_t UsbIntMessageBuffer[INTR_MAX_PACKET_SIZE]; /* data buffer*/
|
|
||||||
__IO uint8_t PrevXferComplete_IntrIn;
|
|
||||||
usb_ccid_param_t usb_ccid_param;
|
|
||||||
|
|
||||||
uint8_t* pUsbMessageBuffer;
|
|
||||||
static uint32_t UsbMessageLength;
|
|
||||||
Ccid_SlotStatus_t Ccid_SlotStatus;
|
|
||||||
Protocol0_DataStructure_t Protocol0_DataStructure;
|
|
||||||
|
|
||||||
Ccid_bulk_data_t Ccid_bulk_data;
|
|
||||||
|
|
||||||
/* Private function prototypes -----------------------------------------------*/
|
|
||||||
static void CCID_Response_SendData (USBD_HandleTypeDef *pdev,
|
|
||||||
uint8_t* pbuf,
|
|
||||||
uint16_t len);
|
|
||||||
/* Private function ----------------------------------------------------------*/
|
|
||||||
/**
|
|
||||||
* @brief CCID_Init
|
|
||||||
* Initialize the CCID USB Layer
|
|
||||||
* @param pdev: device instance
|
|
||||||
* @retval None
|
|
||||||
*/
|
|
||||||
void CCID_Init (USBD_HandleTypeDef *pdev)
|
|
||||||
{
|
|
||||||
memset(&Ccid_BulkState, 0, sizeof(Ccid_BulkState));
|
|
||||||
memset(&UsbIntMessageBuffer, 0, sizeof(UsbIntMessageBuffer));
|
|
||||||
memset(&PrevXferComplete_IntrIn, 0, sizeof(PrevXferComplete_IntrIn));
|
|
||||||
memset(&usb_ccid_param, 0, sizeof(usb_ccid_param));
|
|
||||||
memset(&pUsbMessageBuffer, 0, sizeof(pUsbMessageBuffer));
|
|
||||||
memset(&UsbMessageLength, 0, sizeof(UsbMessageLength));
|
|
||||||
memset(&Ccid_SlotStatus, 0, sizeof(Ccid_SlotStatus));
|
|
||||||
memset(&Protocol0_DataStructure, 0, sizeof(Protocol0_DataStructure));
|
|
||||||
memset(&Ccid_bulk_data, 0, sizeof(Ccid_bulk_data));
|
|
||||||
ccid_card_inserted = 0;
|
|
||||||
/* CCID Related Initialization */
|
|
||||||
CCID_SetIntrTransferStatus(1); /* Transfer Complete Status */
|
|
||||||
CCID_UpdSlotChange(1);
|
|
||||||
SC_InitParams();
|
|
||||||
|
|
||||||
/* Prepare Out endpoint to receive 1st packet */
|
|
||||||
Ccid_BulkState = CCID_STATE_IDLE;
|
|
||||||
USBD_LL_PrepareReceive(pdev, CCID_BULK_OUT_EP, CCID_BULK_EPOUT_SIZE);
|
|
||||||
|
|
||||||
// send the smartcard as inserted state at boot time
|
|
||||||
io_usb_ccid_set_card_inserted(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief CCID_DeInit
|
|
||||||
* Uninitialize the CCID Machine
|
|
||||||
* @param pdev: device instance
|
|
||||||
* @retval None
|
|
||||||
*/
|
|
||||||
void CCID_DeInit (USBD_HandleTypeDef *pdev)
|
|
||||||
{
|
|
||||||
UNUSED(pdev);
|
|
||||||
Ccid_BulkState = CCID_STATE_IDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief CCID_Message_In
|
|
||||||
* Handle Bulk IN & Intr IN data stage
|
|
||||||
* @param pdev: device instance
|
|
||||||
* @param uint8_t epnum: endpoint index
|
|
||||||
* @retval None
|
|
||||||
*/
|
|
||||||
void CCID_BulkMessage_In (USBD_HandleTypeDef *pdev,
|
|
||||||
uint8_t epnum)
|
|
||||||
{
|
|
||||||
if (epnum == (CCID_BULK_IN_EP & 0x7F))
|
|
||||||
{/* Filter the epnum by masking with 0x7f (mask of IN Direction) */
|
|
||||||
|
|
||||||
/*************** Handle Bulk Transfer IN data completion *****************/
|
|
||||||
|
|
||||||
switch (Ccid_BulkState)
|
|
||||||
{
|
|
||||||
case CCID_STATE_SEND_RESP: {
|
|
||||||
unsigned int remLen = UsbMessageLength;
|
|
||||||
|
|
||||||
// advance with acknowledged sent chunk
|
|
||||||
pUsbMessageBuffer += MIN(CCID_BULK_EPIN_SIZE, UsbMessageLength);
|
|
||||||
UsbMessageLength -= MIN(CCID_BULK_EPIN_SIZE, UsbMessageLength);
|
|
||||||
|
|
||||||
// if remaining length is > EPIN_SIZE: send a filled bulk packet
|
|
||||||
if (UsbMessageLength >= CCID_BULK_EPIN_SIZE) {
|
|
||||||
CCID_Response_SendData(pdev, pUsbMessageBuffer,
|
|
||||||
// use the header declared size packet must be well formed
|
|
||||||
CCID_BULK_EPIN_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if remaining length is 0; send an empty packet and prepare to receive a new command
|
|
||||||
else if (UsbMessageLength == 0 && remLen == CCID_BULK_EPIN_SIZE) {
|
|
||||||
CCID_Response_SendData(pdev, pUsbMessageBuffer,
|
|
||||||
// use the header declared size packet must be well formed
|
|
||||||
0);
|
|
||||||
goto last_xfer; // won't wait ack to avoid missing a command
|
|
||||||
}
|
|
||||||
// else if no more data, then last packet sent, go back to idle (done on transfer ack)
|
|
||||||
else if (UsbMessageLength == 0) { // robustness only
|
|
||||||
last_xfer:
|
|
||||||
Ccid_BulkState = CCID_STATE_IDLE;
|
|
||||||
|
|
||||||
/* Prepare EP to Receive First Cmd */
|
|
||||||
USBD_LL_PrepareReceive(pdev, CCID_BULK_OUT_EP, CCID_BULK_EPOUT_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if remaining length is < EPIN_SIZE: send packet and prepare to receive a new command
|
|
||||||
else if (UsbMessageLength < CCID_BULK_EPIN_SIZE) {
|
|
||||||
CCID_Response_SendData(pdev, pUsbMessageBuffer,
|
|
||||||
// use the header declared size packet must be well formed
|
|
||||||
UsbMessageLength);
|
|
||||||
goto last_xfer; // won't wait ack to avoid missing a command
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (epnum == (CCID_INTR_IN_EP & 0x7F))
|
|
||||||
{
|
|
||||||
/* Filter the epnum by masking with 0x7f (mask of IN Direction) */
|
|
||||||
CCID_SetIntrTransferStatus(1); /* Transfer Complete Status */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief CCID_BulkMessage_Out
|
|
||||||
* Proccess CCID OUT data
|
|
||||||
* @param pdev: device instance
|
|
||||||
* @param uint8_t epnum: endpoint index
|
|
||||||
* @retval None
|
|
||||||
*/
|
|
||||||
void CCID_BulkMessage_Out (USBD_HandleTypeDef *pdev,
|
|
||||||
uint8_t epnum, uint8_t* buffer, uint16_t dataLen)
|
|
||||||
{
|
|
||||||
|
|
||||||
switch (Ccid_BulkState)
|
|
||||||
{
|
|
||||||
case CCID_STATE_IDLE:
|
|
||||||
if (dataLen == 0x00)
|
|
||||||
{ /* Zero Length Packet Received */
|
|
||||||
Ccid_BulkState = CCID_STATE_IDLE;
|
|
||||||
}
|
|
||||||
else if (dataLen >= CCID_MESSAGE_HEADER_SIZE)
|
|
||||||
{
|
|
||||||
UsbMessageLength = dataLen; /* Store for future use */
|
|
||||||
|
|
||||||
/* Expected Data Length Packet Received */
|
|
||||||
pUsbMessageBuffer = (uint8_t*) &Ccid_bulk_data;
|
|
||||||
|
|
||||||
/* Fill CCID_BulkOut Data Buffer from USB Buffer */
|
|
||||||
memmove(pUsbMessageBuffer, buffer, dataLen);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Refer : 6 CCID Messages
|
|
||||||
The response messages always contain the exact same slot number,
|
|
||||||
and sequence number fields from the header that was contained in
|
|
||||||
the Bulk-OUT command message.
|
|
||||||
*/
|
|
||||||
Ccid_bulk_data.header.bulkin.bSlot = Ccid_bulk_data.header.bulkout.bSlot;
|
|
||||||
Ccid_bulk_data.header.bulkin.bSeq = Ccid_bulk_data.header.bulkout.bSeq;
|
|
||||||
|
|
||||||
if (dataLen < CCID_BULK_EPOUT_SIZE)
|
|
||||||
{/* Short message, less than the EP Out Size, execute the command,
|
|
||||||
if parameter like dwLength is too big, the appropriate command will
|
|
||||||
give an error */
|
|
||||||
CCID_CmdDecode(pdev);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ /* Long message, receive additional data with command */
|
|
||||||
/* (u8dataLen == CCID_BULK_EPOUT_SIZE) */
|
|
||||||
|
|
||||||
if (Ccid_bulk_data.header.bulkout.dwLength > ABDATA_SIZE)
|
|
||||||
{ /* Check if length of data to be sent by host is > buffer size */
|
|
||||||
|
|
||||||
/* Too long data received.... Error ! */
|
|
||||||
Ccid_BulkState = CCID_STATE_UNCORRECT_LENGTH;
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
{ /* Expect more data on OUT EP */
|
|
||||||
Ccid_BulkState = CCID_STATE_RECEIVE_DATA;
|
|
||||||
pUsbMessageBuffer += dataLen; /* Point to new offset */
|
|
||||||
|
|
||||||
/* Prepare EP to Receive next Cmd */
|
|
||||||
USBD_LL_PrepareReceive(pdev, CCID_BULK_OUT_EP, CCID_BULK_EPOUT_SIZE);
|
|
||||||
|
|
||||||
} /* if (dataLen == CCID_BULK_EPOUT_SIZE) ends */
|
|
||||||
} /* if (dataLen >= CCID_BULK_EPOUT_SIZE) ends */
|
|
||||||
} /* if (dataLen >= CCID_MESSAGE_HEADER_SIZE) ends */
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CCID_STATE_RECEIVE_DATA:
|
|
||||||
|
|
||||||
UsbMessageLength += dataLen;
|
|
||||||
|
|
||||||
if (dataLen < CCID_BULK_EPOUT_SIZE)
|
|
||||||
{/* Short message, less than the EP Out Size, execute the command,
|
|
||||||
if parameter like dwLength is too big, the appropriate command will
|
|
||||||
give an error */
|
|
||||||
|
|
||||||
/* Full command is received, process the Command */
|
|
||||||
memmove(pUsbMessageBuffer, buffer, dataLen);
|
|
||||||
CCID_CmdDecode(pdev);
|
|
||||||
}
|
|
||||||
else if (dataLen == CCID_BULK_EPOUT_SIZE)
|
|
||||||
{
|
|
||||||
if (UsbMessageLength < (Ccid_bulk_data.header.bulkout.dwLength + CCID_CMD_HEADER_SIZE))
|
|
||||||
{
|
|
||||||
memmove(pUsbMessageBuffer, buffer, dataLen);
|
|
||||||
pUsbMessageBuffer += dataLen;
|
|
||||||
/* Increment the pointer to receive more data */
|
|
||||||
|
|
||||||
/* Prepare EP to Receive next Cmd */
|
|
||||||
USBD_LL_PrepareReceive(pdev, CCID_BULK_OUT_EP, CCID_BULK_EPOUT_SIZE);
|
|
||||||
}
|
|
||||||
else if (UsbMessageLength == (Ccid_bulk_data.header.bulkout.dwLength + CCID_CMD_HEADER_SIZE))
|
|
||||||
{
|
|
||||||
/* Full command is received, process the Command */
|
|
||||||
memmove(pUsbMessageBuffer, buffer, dataLen);
|
|
||||||
CCID_CmdDecode(pdev);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Too long data received.... Error ! */
|
|
||||||
Ccid_BulkState = CCID_STATE_UNCORRECT_LENGTH;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CCID_STATE_UNCORRECT_LENGTH:
|
|
||||||
Ccid_BulkState = CCID_STATE_IDLE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CCID_Send_Reply(USBD_HandleTypeDef *pdev) {
|
|
||||||
/********** Decide for all commands ***************/
|
|
||||||
if (Ccid_BulkState == CCID_STATE_SEND_RESP)
|
|
||||||
{
|
|
||||||
UsbMessageLength = Ccid_bulk_data.header.bulkin.dwLength+CCID_MESSAGE_HEADER_SIZE; /* Store for future use */
|
|
||||||
|
|
||||||
/* Expected Data Length Packet Received */
|
|
||||||
pUsbMessageBuffer = (uint8_t*) &Ccid_bulk_data;
|
|
||||||
|
|
||||||
CCID_Response_SendData(pdev, pUsbMessageBuffer,
|
|
||||||
// use the header declared size packet must be well formed
|
|
||||||
MIN(CCID_BULK_EPIN_SIZE, UsbMessageLength));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief CCID_CmdDecode
|
|
||||||
* Parse the commands and Proccess command
|
|
||||||
* @param pdev: device instance
|
|
||||||
* @retval None
|
|
||||||
*/
|
|
||||||
void CCID_CmdDecode(USBD_HandleTypeDef *pdev)
|
|
||||||
{
|
|
||||||
uint8_t errorCode;
|
|
||||||
|
|
||||||
switch (Ccid_bulk_data.header.bulkout.bMessageType)
|
|
||||||
{
|
|
||||||
case PC_TO_RDR_ICCPOWERON:
|
|
||||||
errorCode = PC_to_RDR_IccPowerOn();
|
|
||||||
RDR_to_PC_DataBlock(errorCode);
|
|
||||||
break;
|
|
||||||
case PC_TO_RDR_ICCPOWEROFF:
|
|
||||||
errorCode = PC_to_RDR_IccPowerOff();
|
|
||||||
RDR_to_PC_SlotStatus(errorCode);
|
|
||||||
break;
|
|
||||||
case PC_TO_RDR_GETSLOTSTATUS:
|
|
||||||
errorCode = PC_to_RDR_GetSlotStatus();
|
|
||||||
RDR_to_PC_SlotStatus(errorCode);
|
|
||||||
break;
|
|
||||||
case PC_TO_RDR_XFRBLOCK:
|
|
||||||
errorCode = PC_to_RDR_XfrBlock();
|
|
||||||
// asynchronous // RDR_to_PC_DataBlock(errorCode);
|
|
||||||
break;
|
|
||||||
case PC_TO_RDR_GETPARAMETERS:
|
|
||||||
errorCode = PC_to_RDR_GetParameters();
|
|
||||||
RDR_to_PC_Parameters(errorCode);
|
|
||||||
break;
|
|
||||||
case PC_TO_RDR_RESETPARAMETERS:
|
|
||||||
errorCode = PC_to_RDR_ResetParameters();
|
|
||||||
RDR_to_PC_Parameters(errorCode);
|
|
||||||
break;
|
|
||||||
case PC_TO_RDR_SETPARAMETERS:
|
|
||||||
errorCode = PC_to_RDR_SetParameters();
|
|
||||||
RDR_to_PC_Parameters(errorCode);
|
|
||||||
break;
|
|
||||||
case PC_TO_RDR_ESCAPE:
|
|
||||||
errorCode = PC_to_RDR_Escape();
|
|
||||||
RDR_to_PC_Escape(errorCode);
|
|
||||||
break;
|
|
||||||
case PC_TO_RDR_ICCCLOCK:
|
|
||||||
errorCode = PC_to_RDR_IccClock();
|
|
||||||
RDR_to_PC_SlotStatus(errorCode);
|
|
||||||
break;
|
|
||||||
case PC_TO_RDR_ABORT:
|
|
||||||
errorCode = PC_to_RDR_Abort();
|
|
||||||
RDR_to_PC_SlotStatus(errorCode);
|
|
||||||
break;
|
|
||||||
case PC_TO_RDR_T0APDU:
|
|
||||||
errorCode = PC_TO_RDR_T0Apdu();
|
|
||||||
RDR_to_PC_SlotStatus(errorCode);
|
|
||||||
break;
|
|
||||||
case PC_TO_RDR_MECHANICAL:
|
|
||||||
errorCode = PC_TO_RDR_Mechanical();
|
|
||||||
RDR_to_PC_SlotStatus(errorCode);
|
|
||||||
break;
|
|
||||||
case PC_TO_RDR_SETDATARATEANDCLOCKFREQUENCY:
|
|
||||||
errorCode = PC_TO_RDR_SetDataRateAndClockFrequency();
|
|
||||||
RDR_to_PC_DataRateAndClockFrequency(errorCode);
|
|
||||||
break;
|
|
||||||
case PC_TO_RDR_SECURE:
|
|
||||||
errorCode = PC_TO_RDR_Secure();
|
|
||||||
// asynchronous // RDR_to_PC_DataBlock(errorCode);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
RDR_to_PC_SlotStatus(SLOTERROR_CMD_NOT_SUPPORTED);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
CCID_Send_Reply(pdev);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Transfer_Data_Request
|
|
||||||
* Prepare the request response to be sent to the host
|
|
||||||
* @param uint8_t* dataPointer: Pointer to the data buffer to send
|
|
||||||
* @param uint16_t dataLen : number of bytes to send
|
|
||||||
* @retval None
|
|
||||||
*/
|
|
||||||
void Transfer_Data_Request(void)
|
|
||||||
{
|
|
||||||
/********** Update Global Variables ***************/
|
|
||||||
Ccid_BulkState = CCID_STATE_SEND_RESP;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief CCID_Response_SendData
|
|
||||||
* Send the data on bulk-in EP
|
|
||||||
* @param pdev: device instance
|
|
||||||
* @param uint8_t* buf: pointer to data buffer
|
|
||||||
* @param uint16_t len: Data Length
|
|
||||||
* @retval None
|
|
||||||
*/
|
|
||||||
static void CCID_Response_SendData(USBD_HandleTypeDef *pdev,
|
|
||||||
uint8_t* buf,
|
|
||||||
uint16_t len)
|
|
||||||
{
|
|
||||||
// don't ask the MCU to perform bulk split, we could quickly get into a buffer overflow
|
|
||||||
if (len > CCID_BULK_EPIN_SIZE) {
|
|
||||||
THROW(EXCEPTION_IO_OVERFLOW);
|
|
||||||
}
|
|
||||||
|
|
||||||
G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_USB_EP_PREPARE;
|
|
||||||
G_io_seproxyhal_spi_buffer[1] = (3+len)>>8;
|
|
||||||
G_io_seproxyhal_spi_buffer[2] = (3+len);
|
|
||||||
G_io_seproxyhal_spi_buffer[3] = CCID_BULK_IN_EP;
|
|
||||||
G_io_seproxyhal_spi_buffer[4] = SEPROXYHAL_TAG_USB_EP_PREPARE_DIR_IN;
|
|
||||||
G_io_seproxyhal_spi_buffer[5] = len;
|
|
||||||
io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 6);
|
|
||||||
io_seproxyhal_spi_send(buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief CCID_IntMessage
|
|
||||||
* Send the Interrupt-IN data to the host
|
|
||||||
* @param pdev: device instance
|
|
||||||
* @retval None
|
|
||||||
*/
|
|
||||||
void CCID_IntMessage(USBD_HandleTypeDef *pdev)
|
|
||||||
{
|
|
||||||
/* Check if there us change in Smartcard Slot status */
|
|
||||||
if ( CCID_IsSlotStatusChange() && CCID_IsIntrTransferComplete() )
|
|
||||||
{
|
|
||||||
/* Check Slot Status is changed. Card is Removed/ Fitted */
|
|
||||||
RDR_to_PC_NotifySlotChange();
|
|
||||||
|
|
||||||
CCID_SetIntrTransferStatus(0); /* Reset the Status */
|
|
||||||
CCID_UpdSlotChange(0); /* Reset the Status of Slot Change */
|
|
||||||
|
|
||||||
G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_USB_EP_PREPARE;
|
|
||||||
G_io_seproxyhal_spi_buffer[1] = (3+2)>>8;
|
|
||||||
G_io_seproxyhal_spi_buffer[2] = (3+2);
|
|
||||||
G_io_seproxyhal_spi_buffer[3] = CCID_INTR_IN_EP;
|
|
||||||
G_io_seproxyhal_spi_buffer[4] = SEPROXYHAL_TAG_USB_EP_PREPARE_DIR_IN;
|
|
||||||
G_io_seproxyhal_spi_buffer[5] = 2;
|
|
||||||
io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 6);
|
|
||||||
io_seproxyhal_spi_send(UsbIntMessageBuffer, 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief CCID_IsIntrTransferComplete
|
|
||||||
* Provides the status of previous Interrupt transfer status
|
|
||||||
* @param None
|
|
||||||
* @retval uint8_t PrevXferComplete_IntrIn: Value of the previous transfer status
|
|
||||||
*/
|
|
||||||
uint8_t CCID_IsIntrTransferComplete (void)
|
|
||||||
{
|
|
||||||
return PrevXferComplete_IntrIn;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief CCID_IsIntrTransferComplete
|
|
||||||
* Set the value of the Interrupt transfer status
|
|
||||||
* @param uint8_t xfer_Status: Value of the Interrupt transfer status to set
|
|
||||||
* @retval None
|
|
||||||
*/
|
|
||||||
void CCID_SetIntrTransferStatus (uint8_t xfer_Status)
|
|
||||||
{
|
|
||||||
PrevXferComplete_IntrIn = xfer_Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
uint8_t SC_Detect(void) {
|
|
||||||
return ccid_card_inserted;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SC_Poweroff(void) {
|
|
||||||
// nothing to do
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void SC_InitParams (void) {
|
|
||||||
// nothing to do
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t SC_SetParams (Protocol0_DataStructure_t* pt0) {
|
|
||||||
return SLOT_NO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t SC_ExecuteEscape (uint8_t* escapePtr, uint32_t escapeLen,
|
|
||||||
uint8_t* responseBuff,
|
|
||||||
uint16_t* responseLen) {
|
|
||||||
io_seproxyhal_se_reset();
|
|
||||||
}
|
|
||||||
uint8_t SC_SetClock (uint8_t bClockCommand) {
|
|
||||||
return SLOT_NO_ERROR;
|
|
||||||
}
|
|
||||||
uint8_t SC_Request_GetClockFrequencies(uint8_t* pbuf, uint16_t* len);
|
|
||||||
uint8_t SC_Request_GetDataRates(uint8_t* pbuf, uint16_t* len);
|
|
||||||
uint8_t SC_T0Apdu(uint8_t bmChanges, uint8_t bClassGetResponse,
|
|
||||||
uint8_t bClassEnvelope) {
|
|
||||||
return SLOTERROR_CMD_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
uint8_t SC_Mechanical(uint8_t bFunction) {
|
|
||||||
return SLOTERROR_CMD_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
uint8_t SC_SetDataRateAndClockFrequency(uint32_t dwClockFrequency,
|
|
||||||
uint32_t dwDataRate) {
|
|
||||||
return SLOT_NO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t SC_Secure(uint32_t dwLength, uint8_t bBWI, uint16_t wLevelParameter,
|
|
||||||
uint8_t* pbuf, uint32_t* returnLen ) {
|
|
||||||
// return SLOTERROR_CMD_NOT_SUPPORTED;
|
|
||||||
uint16_t ret_len,off;
|
|
||||||
switch(pbuf[0]) {
|
|
||||||
case 0: // verify pin
|
|
||||||
//ret_len = dwLength - 15;
|
|
||||||
ret_len = 5;
|
|
||||||
off = 15;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1: // modify pin
|
|
||||||
switch(pbuf[11]) {
|
|
||||||
case 3:
|
|
||||||
off = 20;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
case 1:
|
|
||||||
off = 19;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
off = 18;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
//ret_len = dwLength - off;
|
|
||||||
ret_len = 5;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: // unsupported
|
|
||||||
Ccid_bulk_data.header.bulkin.dwLength = 0;
|
|
||||||
RDR_to_PC_DataBlock(SLOTERROR_CMD_NOT_SUPPORTED);
|
|
||||||
CCID_Send_Reply(&USBD_Device);
|
|
||||||
return SLOTERROR_CMD_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
pbuf += off;
|
|
||||||
pbuf[0] = 0xEF;
|
|
||||||
return SC_XferBlock(pbuf, ret_len, &ret_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
// prepare the apdu to be processed by the application
|
|
||||||
uint8_t SC_XferBlock (uint8_t* ptrBlock, uint32_t blockLen, uint16_t* expectedLen) {
|
|
||||||
// check for overflow
|
|
||||||
if (blockLen > IO_APDU_BUFFER_SIZE) {
|
|
||||||
return SLOTERROR_BAD_LENTGH;
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy received apdu
|
|
||||||
memmove(G_io_apdu_buffer, ptrBlock, blockLen);
|
|
||||||
G_io_apdu_length = blockLen;
|
|
||||||
G_io_apdu_media = IO_APDU_MEDIA_USB_CCID; // for application code
|
|
||||||
G_io_apdu_state = APDU_USB_CCID; // for next call to io_exchange
|
|
||||||
|
|
||||||
return SLOT_NO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
void io_usb_ccid_reply(unsigned char* buffer, unsigned short length) {
|
|
||||||
// avoid memory overflow
|
|
||||||
if (length > sizeof(Ccid_bulk_data.abData)) {
|
|
||||||
THROW(EXCEPTION_IO_OVERFLOW);
|
|
||||||
}
|
|
||||||
// copy the responde apdu
|
|
||||||
memmove(Ccid_bulk_data.abData, buffer, length);
|
|
||||||
Ccid_bulk_data.header.bulkin.dwLength = length;
|
|
||||||
// forge reply
|
|
||||||
RDR_to_PC_DataBlock(SLOT_NO_ERROR);
|
|
||||||
|
|
||||||
// start sending rpely
|
|
||||||
CCID_Send_Reply(&USBD_Device);
|
|
||||||
}
|
|
||||||
// ask for power on
|
|
||||||
void io_usb_ccid_set_card_inserted(unsigned int inserted) {
|
|
||||||
ccid_card_inserted = inserted;
|
|
||||||
CCID_UpdSlotChange(1);
|
|
||||||
CCID_IntMessage(&USBD_Device);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif // HAVE_USB_CLASS_CCID
|
|
||||||
|
|
||||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
|
@ -1,209 +0,0 @@
|
|||||||
/**
|
|
||||||
******************************************************************************
|
|
||||||
* @file usbd_ccid_if.h
|
|
||||||
* @author MCD Application Team
|
|
||||||
* @version V1.0.1
|
|
||||||
* @date 31-January-2014
|
|
||||||
* @brief This file provides all the functions prototypes for USB CCID
|
|
||||||
******************************************************************************
|
|
||||||
* @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.
|
|
||||||
*
|
|
||||||
******************************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
|
||||||
#ifndef __USBD_CCID_IF_H
|
|
||||||
#define __USBD_CCID_IF_H
|
|
||||||
|
|
||||||
#include "usbd_core.h"
|
|
||||||
|
|
||||||
#ifdef HAVE_USB_CLASS_CCID
|
|
||||||
|
|
||||||
|
|
||||||
/* Exported defines ----------------------------------------------------------*/
|
|
||||||
/* Bulk-only Command Block Wrapper */
|
|
||||||
#define ABDATA_SIZE 261
|
|
||||||
#define CCID_CMD_HEADER_SIZE 10
|
|
||||||
#define CCID_RESPONSE_HEADER_SIZE 10
|
|
||||||
|
|
||||||
|
|
||||||
#define CCID_INT_BUFF_SIZ 2
|
|
||||||
|
|
||||||
#define CARD_SLOT_FITTED 1
|
|
||||||
#define CARD_SLOT_REMOVED 0
|
|
||||||
|
|
||||||
#define BULK_MAX_PACKET_SIZE 0x40
|
|
||||||
#define CCID_IN_EP_SIZE 0x40
|
|
||||||
#define INTR_MAX_PACKET_SIZE 8
|
|
||||||
#define CCID_MESSAGE_HEADER_SIZE 10
|
|
||||||
#define CCID_NUMBER_OF_SLOTS 1
|
|
||||||
/* Number of SLOTS. For single card, this value is 1 */
|
|
||||||
|
|
||||||
/* Following Parameters used in PC_to_RDR_IccPowerOn */
|
|
||||||
#define VOLTAGE_SELECTION_AUTOMATIC 0xFF
|
|
||||||
#define VOLTAGE_SELECTION_3V 0x02
|
|
||||||
#define VOLTAGE_SELECTION_5V 0x01
|
|
||||||
#define VOLTAGE_SELECTION_1V8 0x03
|
|
||||||
|
|
||||||
#define PC_TO_RDR_ICCPOWERON 0x62
|
|
||||||
#define PC_TO_RDR_ICCPOWEROFF 0x63
|
|
||||||
#define PC_TO_RDR_GETSLOTSTATUS 0x65
|
|
||||||
#define PC_TO_RDR_XFRBLOCK 0x6F
|
|
||||||
#define PC_TO_RDR_GETPARAMETERS 0x6C
|
|
||||||
#define PC_TO_RDR_RESETPARAMETERS 0x6D
|
|
||||||
#define PC_TO_RDR_SETPARAMETERS 0x61
|
|
||||||
#define PC_TO_RDR_ESCAPE 0x6B
|
|
||||||
#define PC_TO_RDR_ICCCLOCK 0x6E
|
|
||||||
#define PC_TO_RDR_T0APDU 0x6A
|
|
||||||
#define PC_TO_RDR_SECURE 0x69
|
|
||||||
#define PC_TO_RDR_MECHANICAL 0x71
|
|
||||||
#define PC_TO_RDR_ABORT 0x72
|
|
||||||
#define PC_TO_RDR_SETDATARATEANDCLOCKFREQUENCY 0x73
|
|
||||||
|
|
||||||
#define RDR_TO_PC_DATABLOCK 0x80
|
|
||||||
#define RDR_TO_PC_SLOTSTATUS 0x81
|
|
||||||
#define RDR_TO_PC_PARAMETERS 0x82
|
|
||||||
#define RDR_TO_PC_ESCAPE 0x83
|
|
||||||
#define RDR_TO_PC_DATARATEANDCLOCKFREQUENCY 0x84
|
|
||||||
|
|
||||||
#define RDR_TO_PC_NOTIFYSLOTCHANGE 0x50
|
|
||||||
#define RDR_TO_PC_HARDWAREERROR 0x51
|
|
||||||
|
|
||||||
#define OFFSET_INT_BMESSAGETYPE 0
|
|
||||||
#define OFFSET_INT_BMSLOTICCSTATE 1
|
|
||||||
#define SLOT_ICC_PRESENT 0x01
|
|
||||||
/* LSb : (0b = no ICC present, 1b = ICC present) */
|
|
||||||
|
|
||||||
#define SLOT_ICC_CHANGE 0x02 /* MSb : (0b = no change, 1b = change) */
|
|
||||||
/*****************************************************************************/
|
|
||||||
/*********************** CCID Bulk Transfer State machine ********************/
|
|
||||||
/*****************************************************************************/
|
|
||||||
#define CCID_STATE_IDLE 0 /* Idle state */
|
|
||||||
#define CCID_STATE_DATA_OUT 1 /* Data Out state */
|
|
||||||
#define CCID_STATE_RECEIVE_DATA 2
|
|
||||||
#define CCID_STATE_SEND_RESP 3
|
|
||||||
#define CCID_STATE_DATAIN 4
|
|
||||||
#define CCID_STATE_UNCORRECT_LENGTH 5
|
|
||||||
|
|
||||||
#define DIR_IN 0
|
|
||||||
#define DIR_OUT 1
|
|
||||||
#define BOTH_DIR 2
|
|
||||||
|
|
||||||
/* Exported types ------------------------------------------------------------*/
|
|
||||||
#pragma pack(1)
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
#pragma pack(1)
|
|
||||||
union {
|
|
||||||
#pragma pack(1)
|
|
||||||
struct {
|
|
||||||
uint8_t bMessageType; /* Offset = 0*/
|
|
||||||
uint32_t dwLength; /* Offset = 1, The length field (dwLength) is the length
|
|
||||||
of the message not including the 10-byte header.*/
|
|
||||||
uint8_t bSlot; /* Offset = 5*/
|
|
||||||
uint8_t bSeq; /* Offset = 6*/
|
|
||||||
uint8_t bSpecific_0; /* Offset = 7*/
|
|
||||||
uint8_t bSpecific_1; /* Offset = 8*/
|
|
||||||
uint8_t bSpecific_2; /* Offset = 9*/
|
|
||||||
} bulkout;
|
|
||||||
#pragma pack(1)
|
|
||||||
struct {
|
|
||||||
uint8_t bMessageType; /* Offset = 0*/
|
|
||||||
uint32_t dwLength; /* Offset = 1*/
|
|
||||||
uint8_t bSlot; /* Offset = 5, Same as Bulk-OUT message */
|
|
||||||
uint8_t bSeq; /* Offset = 6, Same as Bulk-OUT message */
|
|
||||||
uint8_t bStatus; /* Offset = 7, Slot status as defined in § 6.2.6*/
|
|
||||||
uint8_t bError; /* Offset = 8, Slot error as defined in § 6.2.6*/
|
|
||||||
uint8_t bSpecific; /* Offset = 9*/
|
|
||||||
} bulkin;
|
|
||||||
} header;
|
|
||||||
uint8_t abData [ABDATA_SIZE]; /* Offset = 10, For reference, the absolute
|
|
||||||
maximum block size for a TPDU T=0 block is 260 bytes
|
|
||||||
(5 bytes command; 255 bytes data),
|
|
||||||
or for a TPDU T=1 block is 259 bytes,
|
|
||||||
or for a short APDU T=1 block is 261 bytes,
|
|
||||||
or for an extended APDU T=1 block is 65544 bytes.*/
|
|
||||||
} Ccid_bulk_data_t;
|
|
||||||
#pragma pack()
|
|
||||||
|
|
||||||
|
|
||||||
#pragma pack()
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
__IO uint8_t SlotStatus;
|
|
||||||
__IO uint8_t SlotStatusChange;
|
|
||||||
} Ccid_SlotStatus_t;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
__IO uint8_t bAbortRequestFlag;
|
|
||||||
__IO uint8_t bSeq;
|
|
||||||
__IO uint8_t bSlot;
|
|
||||||
} usb_ccid_param_t;
|
|
||||||
|
|
||||||
|
|
||||||
#pragma pack(1)
|
|
||||||
typedef struct _Protocol0_DataStructure_t
|
|
||||||
{
|
|
||||||
uint8_t bmFindexDindex;
|
|
||||||
uint8_t bmTCCKST0;
|
|
||||||
uint8_t bGuardTimeT0;
|
|
||||||
uint8_t bWaitingIntegerT0;
|
|
||||||
uint8_t bClockStop;
|
|
||||||
} Protocol0_DataStructure_t;
|
|
||||||
#pragma pack()
|
|
||||||
|
|
||||||
/* Includes ------------------------------------------------------------------*/
|
|
||||||
#include "usbd_ccid_core.h"
|
|
||||||
|
|
||||||
extern usb_ccid_param_t usb_ccid_param;
|
|
||||||
extern Ccid_bulk_data_t Ccid_bulk_data; /* Buffer for the Out Data */
|
|
||||||
extern Ccid_SlotStatus_t Ccid_SlotStatus;
|
|
||||||
extern uint8_t UsbIntMessageBuffer[];
|
|
||||||
|
|
||||||
extern Protocol0_DataStructure_t Protocol0_DataStructure;
|
|
||||||
|
|
||||||
/* Exported macros -----------------------------------------------------------*/
|
|
||||||
/* Exported variables --------------------------------------------------------*/
|
|
||||||
/* Exported functions ------------------------------------------------------- */
|
|
||||||
void CCID_BulkMessage_In (USBD_HandleTypeDef *pdev,
|
|
||||||
uint8_t epnum);
|
|
||||||
|
|
||||||
void CCID_BulkMessage_Out (USBD_HandleTypeDef *pdev,
|
|
||||||
uint8_t epnum, uint8_t* buffer, uint16_t buflen);
|
|
||||||
|
|
||||||
void CCID_ReceiveCmdHeader(uint8_t* pDst, uint8_t u8length);
|
|
||||||
void CCID_CmdDecode(USBD_HandleTypeDef *pdev);
|
|
||||||
|
|
||||||
void CCID_IntMessage(USBD_HandleTypeDef *pdev);
|
|
||||||
void CCID_Init(USBD_HandleTypeDef *pdev);
|
|
||||||
void CCID_DeInit(USBD_HandleTypeDef *pdev);
|
|
||||||
|
|
||||||
uint8_t CCID_IsIntrTransferComplete(void);
|
|
||||||
void CCID_SetIntrTransferStatus (uint8_t );
|
|
||||||
void Transfer_Data_Request(void);
|
|
||||||
void Set_CSW (uint8_t CSW_Status, uint8_t Send_Permission);
|
|
||||||
|
|
||||||
void io_usb_ccid_set_card_inserted(unsigned int inserted);
|
|
||||||
|
|
||||||
#endif // HAVE_USB_CLASS_CCID
|
|
||||||
|
|
||||||
#endif /* __USBD_CCID_IF_H */
|
|
||||||
|
|
||||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
|
@ -16,6 +16,8 @@
|
|||||||
#ifndef GPG_API_H
|
#ifndef GPG_API_H
|
||||||
#define GPG_API_H
|
#define GPG_API_H
|
||||||
|
|
||||||
|
void USBD_CCID_activate_pinpad(int enabled);
|
||||||
|
|
||||||
int gpg_oid2curve(unsigned char* oid, unsigned int len);
|
int gpg_oid2curve(unsigned char* oid, unsigned int len);
|
||||||
|
|
||||||
void gpg_init(void);
|
void gpg_init(void);
|
||||||
|
@ -282,7 +282,7 @@ int gpg_apdu_put_data(unsigned int ref) {
|
|||||||
if (G_gpg_vstate.io_length != 4) {
|
if (G_gpg_vstate.io_length != 4) {
|
||||||
THROW(SW_WRONG_LENGTH);
|
THROW(SW_WRONG_LENGTH);
|
||||||
}
|
}
|
||||||
G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset] &= ~0x07;
|
G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset+3] &= ~0x07;
|
||||||
nvm_write(&N_gpg_pstate->AID[10], &G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset], 4);
|
nvm_write(&N_gpg_pstate->AID[10], &G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset], 4);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -18,7 +18,8 @@
|
|||||||
#include "gpg_types.h"
|
#include "gpg_types.h"
|
||||||
#include "gpg_api.h"
|
#include "gpg_api.h"
|
||||||
#include "gpg_vars.h"
|
#include "gpg_vars.h"
|
||||||
#include "usbd_ccid_impl.h"
|
#include "usbd_impl.h"
|
||||||
|
|
||||||
#define SHORT(x) ((x)>>8)&0xFF, (x)&0xFF
|
#define SHORT(x) ((x)>>8)&0xFF, (x)&0xFF
|
||||||
/* ----------------------*/
|
/* ----------------------*/
|
||||||
/* -- A Kind of Magic -- */
|
/* -- A Kind of Magic -- */
|
||||||
@ -322,3 +323,15 @@ int gpg_install(unsigned char app_state) {
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define USBD_OFFSET_CfgDesc_bPINSupport (sizeof(USBD_CfgDesc)-16)
|
||||||
|
void USBD_CCID_activate_pinpad(int enabled) {
|
||||||
|
unsigned short length;
|
||||||
|
uint8_t *cfgDesc;
|
||||||
|
unsigned char e;
|
||||||
|
e = enabled?3:0;
|
||||||
|
length = 0;
|
||||||
|
cfgDesc = USBD_GetCfgDesc_impl(&length);
|
||||||
|
nvm_write(cfgDesc+(length-16), &e,1);
|
||||||
|
}
|
@ -165,7 +165,7 @@ __attribute__((section(".boot"))) int main(void) {
|
|||||||
//start communication with MCU
|
//start communication with MCU
|
||||||
io_seproxyhal_init();
|
io_seproxyhal_init();
|
||||||
|
|
||||||
USB_CCID_power(1);
|
USB_power(1);
|
||||||
io_usb_ccid_set_card_inserted(1);
|
io_usb_ccid_set_card_inserted(1);
|
||||||
|
|
||||||
|
|
||||||
|
@ -97,7 +97,8 @@ static int gpg_sign(gpg_key_t *sigkey) {
|
|||||||
CX_RND_TRNG,
|
CX_RND_TRNG,
|
||||||
CX_NONE,
|
CX_NONE,
|
||||||
G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length,
|
G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length,
|
||||||
G_gpg_vstate.work.io_buffer);
|
G_gpg_vstate.work.io_buffer,
|
||||||
|
NULL);
|
||||||
//reencode r,s in MPI format
|
//reencode r,s in MPI format
|
||||||
gpg_io_discard(0);
|
gpg_io_discard(0);
|
||||||
|
|
||||||
@ -116,11 +117,12 @@ static int gpg_sign(gpg_key_t *sigkey) {
|
|||||||
rs += 2;
|
rs += 2;
|
||||||
}
|
}
|
||||||
} else{
|
} else{
|
||||||
sz = cx_eddsa_sign(key, NULL,
|
sz = cx_eddsa_sign(key,
|
||||||
CX_NONE,
|
CX_NONE,
|
||||||
CX_SHA512,
|
CX_SHA512, G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length,
|
||||||
G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length,
|
NULL, 0,
|
||||||
G_gpg_vstate.work.io_buffer+128);
|
G_gpg_vstate.work.io_buffer+128,
|
||||||
|
NULL);
|
||||||
gpg_io_discard(0);
|
gpg_io_discard(0);
|
||||||
gpg_io_insert(G_gpg_vstate.work.io_buffer+128, sz);
|
gpg_io_insert(G_gpg_vstate.work.io_buffer+128, sz);
|
||||||
}
|
}
|
||||||
|
32
src/lib_stusb_impl/usbd_ccid_impl.h
Normal file
32
src/lib_stusb_impl/usbd_ccid_impl.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#ifndef USBD_CCID_IMPL_H
|
||||||
|
#define USBD_CCID_IMPL_H
|
||||||
|
|
||||||
|
#ifdef HAVE_USB_CLASS_CCID
|
||||||
|
|
||||||
|
// ================================================
|
||||||
|
// CCID
|
||||||
|
|
||||||
|
#define TPDU_EXCHANGE 0x01
|
||||||
|
#define SHORT_APDU_EXCHANGE 0x02
|
||||||
|
#define EXTENDED_APDU_EXCHANGE 0x04
|
||||||
|
#define CHARACTER_EXCHANGE 0x00
|
||||||
|
|
||||||
|
#define EXCHANGE_LEVEL_FEATURE SHORT_APDU_EXCHANGE
|
||||||
|
|
||||||
|
#define CCID_INTF 2
|
||||||
|
#define CCID_BULK_IN_EP 0x83
|
||||||
|
#define CCID_BULK_EPIN_SIZE 64
|
||||||
|
#define CCID_BULK_OUT_EP 0x03
|
||||||
|
#define CCID_BULK_EPOUT_SIZE 64
|
||||||
|
|
||||||
|
#ifdef HAVE_CCID_INTERRUPT
|
||||||
|
#define CCID_INTR_IN_EP 0x84
|
||||||
|
#define CCID_INTR_EPIN_SIZE 16
|
||||||
|
#endif // HAVE_CCID_INTERRUPT
|
||||||
|
|
||||||
|
#define IO_CCID_DATA_BUFFER_SIZE IO_APDU_BUFFER_SIZE
|
||||||
|
#define G_io_ccid_data_buffer G_io_apdu_buffer
|
||||||
|
|
||||||
|
#endif // HAVE_USB_CLASS_CCID
|
||||||
|
|
||||||
|
#endif // USBD_CCID_IMPL_H
|
29
src/lib_stusb_impl/usbd_hid_impl.h
Normal file
29
src/lib_stusb_impl/usbd_hid_impl.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#ifndef USBD_HID_IMPL_H
|
||||||
|
#define USBD_HID_IMPL_H
|
||||||
|
|
||||||
|
// ================================================
|
||||||
|
// HIDGEN
|
||||||
|
|
||||||
|
#define HID_INTF 0
|
||||||
|
|
||||||
|
#define HID_EPIN_ADDR 0x82
|
||||||
|
#define HID_EPIN_SIZE 0x40
|
||||||
|
|
||||||
|
#define HID_EPOUT_ADDR 0x02
|
||||||
|
#define HID_EPOUT_SIZE 0x40
|
||||||
|
|
||||||
|
#ifdef HAVE_IO_U2F
|
||||||
|
// ================================================
|
||||||
|
// HID U2F
|
||||||
|
|
||||||
|
#define U2F_INTF 1
|
||||||
|
|
||||||
|
#define U2F_EPIN_ADDR 0x81
|
||||||
|
#define U2F_EPIN_SIZE 0x40
|
||||||
|
|
||||||
|
#define U2F_EPOUT_ADDR 0x01
|
||||||
|
#define U2F_EPOUT_SIZE 0x40
|
||||||
|
#endif // HAVE_IO_U2F
|
||||||
|
|
||||||
|
#endif // USBD_HID_IMPL_H
|
||||||
|
|
913
src/lib_stusb_impl/usbd_impl.c
Normal file
913
src/lib_stusb_impl/usbd_impl.c
Normal file
@ -0,0 +1,913 @@
|
|||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* @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
|
||||||
|
*
|
||||||
|
* <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.
|
||||||
|
*
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
#include "os.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 HID_EPIN_ADDR 0x82
|
||||||
|
#define HID_EPIN_SIZE 0x40
|
||||||
|
|
||||||
|
#define HID_EPOUT_ADDR 0x02
|
||||||
|
#define HID_EPOUT_SIZE 0x40
|
||||||
|
|
||||||
|
#define USBD_LANGID_STRING 0x409
|
||||||
|
|
||||||
|
#ifdef HAVE_VID_PID_PROBER
|
||||||
|
#define USBD_VID 0x2581
|
||||||
|
#define USBD_PID 0xf1d1
|
||||||
|
#else
|
||||||
|
#define USBD_VID 0x2C97
|
||||||
|
#if defined(TARGET_BLUE) // 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 defined(TARGET_NANOS) // 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 defined(TARGET_ARAMIS) // 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
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
|
||||||
|
static const 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
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef HAVE_IO_U2F
|
||||||
|
static const 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 const uint8_t const N_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
|
||||||
|
),
|
||||||
|
1
|
||||||
|
#ifdef HAVE_IO_U2F
|
||||||
|
+1
|
||||||
|
#endif // HAVE_IO_U2F
|
||||||
|
#ifdef HAVE_USB_CLASS_CCID
|
||||||
|
+1
|
||||||
|
#endif // HAVE_USB_CLASS_CCID
|
||||||
|
, /*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*/
|
||||||
|
|
||||||
|
/* 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) */
|
||||||
|
|
||||||
|
#ifdef HAVE_IO_U2F
|
||||||
|
/* HID FIDO ################################################################################################ */
|
||||||
|
|
||||||
|
/************** Descriptor of KBD HID 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_IO_U2F
|
||||||
|
/* USB HID device Configuration Descriptor */
|
||||||
|
__ALIGN_BEGIN const 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
|
||||||
|
|
||||||
|
/* USB HID device Configuration Descriptor */
|
||||||
|
__ALIGN_BEGIN const 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,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 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_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 */
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
uint8_t *USBD_GetCfgDesc_impl (uint16_t *length)
|
||||||
|
{
|
||||||
|
*length = sizeof (N_USBD_CfgDesc);
|
||||||
|
return (uint8_t*)N_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
|
||||||
|
case HID_INTF:
|
||||||
|
*len = sizeof(USBD_HID_Desc);
|
||||||
|
return (uint8_t*)USBD_HID_Desc;
|
||||||
|
}
|
||||||
|
*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
|
||||||
|
case HID_INTF:
|
||||||
|
*len = sizeof(HID_ReportDesc);
|
||||||
|
return (uint8_t*)HID_ReportDesc;
|
||||||
|
}
|
||||||
|
*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
|
||||||
|
*/
|
||||||
|
extern volatile unsigned short G_io_apdu_length;
|
||||||
|
|
||||||
|
#ifdef HAVE_IO_U2F
|
||||||
|
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_DataOut_impl (USBD_HandleTypeDef *pdev,
|
||||||
|
uint8_t epnum, uint8_t* buffer)
|
||||||
|
{
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// avoid troubles when an apdu has not been replied yet
|
||||||
|
if (G_io_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))) {
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IO_USB_APDU_RECEIVED:
|
||||||
|
G_io_apdu_media = IO_APDU_MEDIA_USB_HID; // for application code
|
||||||
|
G_io_apdu_state = APDU_USB_HID; // for next call to io_exchange
|
||||||
|
G_io_apdu_length = G_io_usb_hid_total_length;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return USBD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @defgroup USBD_HID_Private_Functions
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
// note: how core lib usb calls the hid class
|
||||||
|
const USBD_DescriptorsTypeDef const HID_Desc = {
|
||||||
|
USBD_DeviceDescriptor,
|
||||||
|
USBD_LangIDStrDescriptor,
|
||||||
|
USBD_ManufacturerStrDescriptor,
|
||||||
|
USBD_ProductStrDescriptor,
|
||||||
|
USBD_SerialStrDescriptor,
|
||||||
|
USBD_ConfigStrDescriptor,
|
||||||
|
USBD_InterfaceStrDescriptor,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef HAVE_IO_U2F
|
||||||
|
static const USBD_ClassTypeDef const USBD_U2F =
|
||||||
|
{
|
||||||
|
USBD_HID_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 const USBD_ClassTypeDef const USBD_HID =
|
||||||
|
{
|
||||||
|
USBD_HID_Init,
|
||||||
|
USBD_HID_DeInit,
|
||||||
|
USBD_HID_Setup,
|
||||||
|
NULL, /*EP0_TxSent*/
|
||||||
|
NULL, /*EP0_RxReady*/ /* STATUS STAGE IN */
|
||||||
|
NULL, /*DataIn*/
|
||||||
|
USBD_HID_DataOut_impl, /*DataOut*/
|
||||||
|
NULL, /*SOF */
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
USBD_GetCfgDesc_impl,
|
||||||
|
USBD_GetCfgDesc_impl,
|
||||||
|
USBD_GetCfgDesc_impl,
|
||||||
|
USBD_GetDeviceQualifierDesc_impl,
|
||||||
|
};
|
||||||
|
|
||||||
|
#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) {
|
||||||
|
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*)&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
|
||||||
|
|
||||||
|
|
||||||
|
/* Start Device Process */
|
||||||
|
USBD_Start(&USBD_Device);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
USBD_DeInit(&USBD_Device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
7
src/lib_stusb_impl/usbd_impl.h
Normal file
7
src/lib_stusb_impl/usbd_impl.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#ifndef USBD_IMPL_H
|
||||||
|
#define USBD_IMPL_H
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t *USBD_GetCfgDesc_impl (uint16_t *length);
|
||||||
|
|
||||||
|
#endif //USBD_IMPL_H
|
@ -1,463 +0,0 @@
|
|||||||
/**
|
|
||||||
******************************************************************************
|
|
||||||
* @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
|
|
@ -1,24 +0,0 @@
|
|||||||
#ifndef USBD_CCID_IMPL_H
|
|
||||||
#define USBD_CCID_IMPL_H
|
|
||||||
|
|
||||||
#define TPDU_EXCHANGE 0x01
|
|
||||||
#define SHORT_APDU_EXCHANGE 0x02
|
|
||||||
#define EXTENDED_APDU_EXCHANGE 0x04
|
|
||||||
#define CHARACTER_EXCHANGE 0x00
|
|
||||||
|
|
||||||
#define EXCHANGE_LEVEL_FEATURE SHORT_APDU_EXCHANGE
|
|
||||||
|
|
||||||
|
|
||||||
#define CCID_BULK_IN_EP 0x82
|
|
||||||
#define CCID_BULK_EPIN_SIZE 64
|
|
||||||
#define CCID_BULK_OUT_EP 0x02
|
|
||||||
#define CCID_BULK_EPOUT_SIZE 64
|
|
||||||
#define CCID_INTR_IN_EP 0x81
|
|
||||||
#define CCID_INTR_EPIN_SIZE 16
|
|
||||||
|
|
||||||
#define CCID_EP0_BUFF_SIZ 64
|
|
||||||
|
|
||||||
void USB_CCID_power(unsigned char enabled);
|
|
||||||
void USBD_CCID_activate_pinpad(int enabled);
|
|
||||||
|
|
||||||
#endif // USBD_CCID_IMPL_H
|
|
Loading…
Reference in New Issue
Block a user