1.4.1 firmware port

Code update for 1.4.1 fw
Fix PUT_DATA[serial] command
1.1.0_fw.1.4.1
Cédric 6 years ago
parent cf6e295e47
commit 81090d3f23

@ -1,53 +1,74 @@
# 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");
# 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.
#
#*******************************************************************************
ifeq ($(BOLOS_SDK),)
$(error Environment variable BOLOS_SDK is not set)
endif
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_N=1
APPVERSION_P=0
APPVERSION_P=1
APPVERSION=$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)
SPECVERSION="3.3.1"
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 #
################
all: default
############
# Platform #
############
#SCRIPT_LD := script.ld
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
ifneq ($(NO_CONSENT),)
DEFINES += NO_CONSENT
endif
DEFINES += $(GPG_CONFIG) GPG_VERSION=$(APPVERSION) GPG_NAME=$(APPNAME) SPEC_VERSION=$(SPECVERSION)
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 += HAVE_USB_CLASS_CCID
##############
# Compiler #
# Compiler #
##############
#GCCPATH := $(BOLOS_ENV)/gcc-arm-none-eabi-5_3-2016q1/bin/
#CLANGPATH := $(BOLOS_ENV)/clang-arm-fropi/bin/
@ -55,6 +76,8 @@ CC := $(CLANGPATH)clang
#CFLAGS += -O0 -gdwarf-2 -gstrict-dwarf
CFLAGS += -O3 -Os
#CFLAGS += -fno-jump-tables -fno-lookup-tables -fsave-optimization-record
#$(info $(CFLAGS))
AS := $(GCCPATH)arm-none-eabi-gcc
@ -66,9 +89,9 @@ LDLIBS += -lm -lgcc -lc
# import rules to compile glyphs(/pone)
include $(BOLOS_SDK)/Makefile.glyphs
### computed variables
APP_SOURCE_PATH += src
SDK_SOURCE_PATH += lib_stusb lib_stusb_impl
### variables processed by the common makefile.rules of the SDK to grab source files and include dirs
APP_SOURCE_PATH += src src/lib_stusb_impl
SDK_SOURCE_PATH += lib_stusb
load: all
@ -81,5 +104,5 @@ delete:
include $(BOLOS_SDK)/Makefile.rules
#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:
| ``reader-port "Ledger Token [Nano S] (0001) 01 00"``
| ``allow-admin``
| ``enable-pinpad-varlen``

@ -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>&copy; 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>&copy; 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
#define GPG_API_H
void USBD_CCID_activate_pinpad(int enabled);
int gpg_oid2curve(unsigned char* oid, unsigned int len);
void gpg_init(void);

@ -282,7 +282,7 @@ int gpg_apdu_put_data(unsigned int ref) {
if (G_gpg_vstate.io_length != 4) {
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);
break;

@ -18,7 +18,8 @@
#include "gpg_types.h"
#include "gpg_api.h"
#include "gpg_vars.h"
#include "usbd_ccid_impl.h"
#include "usbd_impl.h"
#define SHORT(x) ((x)>>8)&0xFF, (x)&0xFF
/* ----------------------*/
/* -- A Kind of Magic -- */
@ -322,3 +323,15 @@ int gpg_install(unsigned char app_state) {
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
io_seproxyhal_init();
USB_CCID_power(1);
USB_power(1);
io_usb_ccid_set_card_inserted(1);

@ -97,7 +97,8 @@ static int gpg_sign(gpg_key_t *sigkey) {
CX_RND_TRNG,
CX_NONE,
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
gpg_io_discard(0);
@ -116,11 +117,12 @@ static int gpg_sign(gpg_key_t *sigkey) {
rs += 2;
}
} else{
sz = cx_eddsa_sign(key, NULL,
sz = cx_eddsa_sign(key,
CX_NONE,
CX_SHA512,
G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length,
G_gpg_vstate.work.io_buffer+128);
CX_SHA512, G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length,
NULL, 0,
G_gpg_vstate.work.io_buffer+128,
NULL);
gpg_io_discard(0);
gpg_io_insert(G_gpg_vstate.work.io_buffer+128, sz);
}

@ -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

@ -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

@ -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>&copy; 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****/

@ -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>&copy; 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…
Cancel
Save