Add Initial CCID support (#3048)

* Add Initial CCID support
* Sync api symbols
* Format sources

Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
Filipe Paz Rodrigues
2023-09-21 02:09:00 -07:00
committed by GitHub
parent 182c8defb1
commit a089aeb2bd
11 changed files with 789 additions and 3 deletions

View File

@@ -1,5 +1,5 @@
entry,status,name,type,params
Version,+,39.0,,
Version,+,39.1,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,,
Header,+,applications/services/cli/cli_vcp.h,,
@@ -76,6 +76,7 @@ Header,+,firmware/targets/furi_hal_include/furi_hal_sd.h,,
Header,+,firmware/targets/furi_hal_include/furi_hal_speaker.h,,
Header,+,firmware/targets/furi_hal_include/furi_hal_spi.h,,
Header,+,firmware/targets/furi_hal_include/furi_hal_usb.h,,
Header,+,firmware/targets/furi_hal_include/furi_hal_usb_ccid.h,,
Header,+,firmware/targets/furi_hal_include/furi_hal_usb_hid.h,,
Header,+,firmware/targets/furi_hal_include/furi_hal_usb_hid_u2f.h,,
Header,+,firmware/targets/furi_hal_include/furi_hal_version.h,,
@@ -105,6 +106,7 @@ Header,+,lib/libusb_stm32/inc/hid_usage_telephony.h,,
Header,+,lib/libusb_stm32/inc/hid_usage_vr.h,,
Header,-,lib/libusb_stm32/inc/stm32_compat.h,,
Header,+,lib/libusb_stm32/inc/usb.h,,
Header,+,lib/libusb_stm32/inc/usb_ccid.h,,
Header,+,lib/libusb_stm32/inc/usb_cdc.h,,
Header,+,lib/libusb_stm32/inc/usb_cdca.h,,
Header,+,lib/libusb_stm32/inc/usb_cdce.h,,
@@ -1008,6 +1010,9 @@ Function,+,furi_hal_bus_enable,void,FuriHalBus
Function,+,furi_hal_bus_init_early,void,
Function,+,furi_hal_bus_is_enabled,_Bool,FuriHalBus
Function,+,furi_hal_bus_reset,void,FuriHalBus
Function,+,furi_hal_ccid_ccid_insert_smartcard,void,
Function,+,furi_hal_ccid_ccid_remove_smartcard,void,
Function,+,furi_hal_ccid_set_callbacks,void,CcidCallbacks*
Function,+,furi_hal_cdc_get_ctrl_line_state,uint8_t,uint8_t
Function,+,furi_hal_cdc_get_port_settings,usb_cdc_line_coding*,uint8_t
Function,+,furi_hal_cdc_receive,int32_t,"uint8_t, uint8_t*, uint16_t"
@@ -2692,6 +2697,7 @@ Variable,+,sequence_single_vibro,const NotificationSequence,
Variable,+,sequence_solid_yellow,const NotificationSequence,
Variable,+,sequence_success,const NotificationSequence,
Variable,-,suboptarg,char*,
Variable,+,usb_ccid,FuriHalUsbInterface,
Variable,+,usb_cdc_dual,FuriHalUsbInterface,
Variable,+,usb_cdc_single,FuriHalUsbInterface,
Variable,+,usb_hid,FuriHalUsbInterface,
1 entry status name type params
2 Version + 39.0 39.1
3 Header + applications/services/bt/bt_service/bt.h
4 Header + applications/services/cli/cli.h
5 Header + applications/services/cli/cli_vcp.h
76 Header + firmware/targets/furi_hal_include/furi_hal_speaker.h
77 Header + firmware/targets/furi_hal_include/furi_hal_spi.h
78 Header + firmware/targets/furi_hal_include/furi_hal_usb.h
79 Header + firmware/targets/furi_hal_include/furi_hal_usb_ccid.h
80 Header + firmware/targets/furi_hal_include/furi_hal_usb_hid.h
81 Header + firmware/targets/furi_hal_include/furi_hal_usb_hid_u2f.h
82 Header + firmware/targets/furi_hal_include/furi_hal_version.h
106 Header + lib/libusb_stm32/inc/hid_usage_vr.h
107 Header - lib/libusb_stm32/inc/stm32_compat.h
108 Header + lib/libusb_stm32/inc/usb.h
109 Header + lib/libusb_stm32/inc/usb_ccid.h
110 Header + lib/libusb_stm32/inc/usb_cdc.h
111 Header + lib/libusb_stm32/inc/usb_cdca.h
112 Header + lib/libusb_stm32/inc/usb_cdce.h
1010 Function + furi_hal_bus_init_early void
1011 Function + furi_hal_bus_is_enabled _Bool FuriHalBus
1012 Function + furi_hal_bus_reset void FuriHalBus
1013 Function + furi_hal_ccid_ccid_insert_smartcard void
1014 Function + furi_hal_ccid_ccid_remove_smartcard void
1015 Function + furi_hal_ccid_set_callbacks void CcidCallbacks*
1016 Function + furi_hal_cdc_get_ctrl_line_state uint8_t uint8_t
1017 Function + furi_hal_cdc_get_port_settings usb_cdc_line_coding* uint8_t
1018 Function + furi_hal_cdc_receive int32_t uint8_t, uint8_t*, uint16_t
2697 Variable + sequence_solid_yellow const NotificationSequence
2698 Variable + sequence_success const NotificationSequence
2699 Variable - suboptarg char*
2700 Variable + usb_ccid FuriHalUsbInterface
2701 Variable + usb_cdc_dual FuriHalUsbInterface
2702 Variable + usb_cdc_single FuriHalUsbInterface
2703 Variable + usb_hid FuriHalUsbInterface

View File

@@ -1,5 +1,5 @@
entry,status,name,type,params
Version,+,39.0,,
Version,+,39.1,,
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,,
@@ -82,6 +82,7 @@ Header,+,firmware/targets/furi_hal_include/furi_hal_sd.h,,
Header,+,firmware/targets/furi_hal_include/furi_hal_speaker.h,,
Header,+,firmware/targets/furi_hal_include/furi_hal_spi.h,,
Header,+,firmware/targets/furi_hal_include/furi_hal_usb.h,,
Header,+,firmware/targets/furi_hal_include/furi_hal_usb_ccid.h,,
Header,+,firmware/targets/furi_hal_include/furi_hal_usb_hid.h,,
Header,+,firmware/targets/furi_hal_include/furi_hal_usb_hid_u2f.h,,
Header,+,firmware/targets/furi_hal_include/furi_hal_version.h,,
@@ -123,6 +124,7 @@ Header,+,lib/libusb_stm32/inc/hid_usage_telephony.h,,
Header,+,lib/libusb_stm32/inc/hid_usage_vr.h,,
Header,-,lib/libusb_stm32/inc/stm32_compat.h,,
Header,+,lib/libusb_stm32/inc/usb.h,,
Header,+,lib/libusb_stm32/inc/usb_ccid.h,,
Header,+,lib/libusb_stm32/inc/usb_cdc.h,,
Header,+,lib/libusb_stm32/inc/usb_cdca.h,,
Header,+,lib/libusb_stm32/inc/usb_cdce.h,,
@@ -1079,6 +1081,9 @@ Function,+,furi_hal_bus_enable,void,FuriHalBus
Function,+,furi_hal_bus_init_early,void,
Function,+,furi_hal_bus_is_enabled,_Bool,FuriHalBus
Function,+,furi_hal_bus_reset,void,FuriHalBus
Function,+,furi_hal_ccid_ccid_insert_smartcard,void,
Function,+,furi_hal_ccid_ccid_remove_smartcard,void,
Function,+,furi_hal_ccid_set_callbacks,void,CcidCallbacks*
Function,+,furi_hal_cdc_get_ctrl_line_state,uint8_t,uint8_t
Function,+,furi_hal_cdc_get_port_settings,usb_cdc_line_coding*,uint8_t
Function,+,furi_hal_cdc_receive,int32_t,"uint8_t, uint8_t*, uint16_t"
@@ -3479,6 +3484,7 @@ Variable,+,subghz_protocol_raw_decoder,const SubGhzProtocolDecoder,
Variable,+,subghz_protocol_raw_encoder,const SubGhzProtocolEncoder,
Variable,+,subghz_protocol_registry,const SubGhzProtocolRegistry,
Variable,-,suboptarg,char*,
Variable,+,usb_ccid,FuriHalUsbInterface,
Variable,+,usb_cdc_dual,FuriHalUsbInterface,
Variable,+,usb_cdc_single,FuriHalUsbInterface,
Variable,+,usb_hid,FuriHalUsbInterface,
1 entry status name type params
2 Version + 39.0 39.1
3 Header + applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h
4 Header + applications/services/bt/bt_service/bt.h
5 Header + applications/services/cli/cli.h
82 Header + firmware/targets/furi_hal_include/furi_hal_speaker.h
83 Header + firmware/targets/furi_hal_include/furi_hal_spi.h
84 Header + firmware/targets/furi_hal_include/furi_hal_usb.h
85 Header + firmware/targets/furi_hal_include/furi_hal_usb_ccid.h
86 Header + firmware/targets/furi_hal_include/furi_hal_usb_hid.h
87 Header + firmware/targets/furi_hal_include/furi_hal_usb_hid_u2f.h
88 Header + firmware/targets/furi_hal_include/furi_hal_version.h
124 Header + lib/libusb_stm32/inc/hid_usage_vr.h
125 Header - lib/libusb_stm32/inc/stm32_compat.h
126 Header + lib/libusb_stm32/inc/usb.h
127 Header + lib/libusb_stm32/inc/usb_ccid.h
128 Header + lib/libusb_stm32/inc/usb_cdc.h
129 Header + lib/libusb_stm32/inc/usb_cdca.h
130 Header + lib/libusb_stm32/inc/usb_cdce.h
1081 Function + furi_hal_bus_init_early void
1082 Function + furi_hal_bus_is_enabled _Bool FuriHalBus
1083 Function + furi_hal_bus_reset void FuriHalBus
1084 Function + furi_hal_ccid_ccid_insert_smartcard void
1085 Function + furi_hal_ccid_ccid_remove_smartcard void
1086 Function + furi_hal_ccid_set_callbacks void CcidCallbacks*
1087 Function + furi_hal_cdc_get_ctrl_line_state uint8_t uint8_t
1088 Function + furi_hal_cdc_get_port_settings usb_cdc_line_coding* uint8_t
1089 Function + furi_hal_cdc_receive int32_t uint8_t, uint8_t*, uint16_t
3484 Variable + subghz_protocol_raw_encoder const SubGhzProtocolEncoder
3485 Variable + subghz_protocol_registry const SubGhzProtocolRegistry
3486 Variable - suboptarg char*
3487 Variable + usb_ccid FuriHalUsbInterface
3488 Variable + usb_cdc_dual FuriHalUsbInterface
3489 Variable + usb_cdc_single FuriHalUsbInterface
3490 Variable + usb_hid FuriHalUsbInterface

View File

@@ -0,0 +1,498 @@
#include <furi_hal_version.h>
#include <furi_hal_usb_i.h>
#include <furi_hal_usb.h>
#include <furi_hal_usb_ccid.h>
#include <furi.h>
#include "usb.h"
#include "usb_ccid.h"
static const uint8_t USB_DEVICE_NO_CLASS = 0x0;
static const uint8_t USB_DEVICE_NO_SUBCLASS = 0x0;
static const uint8_t USB_DEVICE_NO_PROTOCOL = 0x0;
#define FIXED_CONTROL_ENDPOINT_SIZE 8
#define IF_NUM_MAX 1
#define CCID_VID_DEFAULT 0x1234
#define CCID_PID_DEFAULT 0xABCD
#define CCID_TOTAL_SLOTS 1
#define CCID_SLOT_INDEX 0
#define CCID_DATABLOCK_SIZE 256
#define ENDPOINT_DIR_IN 0x80
#define ENDPOINT_DIR_OUT 0x00
#define INTERFACE_ID_CCID 0
#define CCID_IN_EPADDR (ENDPOINT_DIR_IN | 2)
/** Endpoint address of the CCID data OUT endpoint, for host-to-device data transfers. */
#define CCID_OUT_EPADDR (ENDPOINT_DIR_OUT | 1)
/** Endpoint size in bytes of the CCID data being sent between IN and OUT endpoints. */
#define CCID_EPSIZE 64
struct CcidIntfDescriptor {
struct usb_interface_descriptor ccid;
struct usb_ccid_descriptor ccid_desc;
struct usb_endpoint_descriptor ccid_bulk_in;
struct usb_endpoint_descriptor ccid_bulk_out;
} __attribute__((packed));
struct CcidConfigDescriptor {
struct usb_config_descriptor config;
struct CcidIntfDescriptor intf_0;
} __attribute__((packed));
enum CCID_Features_Auto_t {
CCID_Features_Auto_None = 0x0,
CCID_Features_Auto_ParameterConfiguration = 0x2,
CCID_Features_Auto_ICCActivation = 0x4,
CCID_Features_Auto_VoltageSelection = 0x8,
CCID_Features_Auto_ICCClockFrequencyChange = 0x10,
CCID_Features_Auto_ICCBaudRateChange = 0x20,
CCID_Features_Auto_ParameterNegotiation = 0x40,
CCID_Features_Auto_PPS = 0x80,
};
enum CCID_Features_ExchangeLevel_t {
CCID_Features_ExchangeLevel_TPDU = 0x00010000,
CCID_Features_ExchangeLevel_ShortAPDU = 0x00020000,
CCID_Features_ExchangeLevel_ShortExtendedAPDU = 0x00040000
};
/* Device descriptor */
static struct usb_device_descriptor ccid_device_desc = {
.bLength = sizeof(struct usb_device_descriptor),
.bDescriptorType = USB_DTYPE_DEVICE,
.bcdUSB = VERSION_BCD(2, 0, 0),
.bDeviceClass = USB_DEVICE_NO_CLASS,
.bDeviceSubClass = USB_DEVICE_NO_SUBCLASS,
.bDeviceProtocol = USB_DEVICE_NO_PROTOCOL,
.bMaxPacketSize0 = FIXED_CONTROL_ENDPOINT_SIZE,
.idVendor = CCID_VID_DEFAULT,
.idProduct = CCID_PID_DEFAULT,
.bcdDevice = VERSION_BCD(1, 0, 0),
.iManufacturer = UsbDevManuf,
.iProduct = UsbDevProduct,
.iSerialNumber = UsbDevSerial,
.bNumConfigurations = 1,
};
/* Device configuration descriptor*/
static const struct CcidConfigDescriptor ccid_cfg_desc = {
.config =
{
.bLength = sizeof(struct usb_config_descriptor),
.bDescriptorType = USB_DTYPE_CONFIGURATION,
.wTotalLength = sizeof(struct CcidConfigDescriptor),
.bNumInterfaces = 1,
.bConfigurationValue = 1,
.iConfiguration = NO_DESCRIPTOR,
.bmAttributes = USB_CFG_ATTR_RESERVED | USB_CFG_ATTR_SELFPOWERED,
.bMaxPower = USB_CFG_POWER_MA(100),
},
.intf_0 =
{
.ccid =
{.bLength = sizeof(struct usb_interface_descriptor),
.bDescriptorType = USB_DTYPE_INTERFACE,
.bInterfaceNumber = INTERFACE_ID_CCID,
.bAlternateSetting = 0x00,
.bNumEndpoints = 2,
.bInterfaceClass = USB_CLASS_CCID,
.bInterfaceSubClass = 0,
.bInterfaceProtocol = 0,
.iInterface = NO_DESCRIPTOR
},
.ccid_desc =
{.bLength = sizeof(struct usb_ccid_descriptor),
.bDescriptorType = USB_DTYPE_CCID_FUNCTIONAL,
.bcdCCID = CCID_CURRENT_SPEC_RELEASE_NUMBER,
.bMaxSlotIndex = 0x00,
.bVoltageSupport = CCID_VOLTAGESUPPORT_5V,
.dwProtocols = 0x01, //T0
.dwDefaultClock = 16000, //16MHz
.dwMaximumClock = 16000, //16MHz
.bNumClockSupported = 0,
.dwDataRate = 307200,
.dwMaxDataRate = 307200,
.bNumDataRatesSupported = 0,
.dwMaxIFSD = 2038,
.dwSynchProtocols = 0,
.dwMechanical = 0,
.dwFeatures = CCID_Features_ExchangeLevel_ShortAPDU |
CCID_Features_Auto_ParameterConfiguration |
CCID_Features_Auto_ICCActivation |
CCID_Features_Auto_VoltageSelection,
.dwMaxCCIDMessageLength = 0x0c00,
.bClassGetResponse = 0xff,
.bClassEnvelope = 0xff,
.wLcdLayout = 0,
.bPINSupport = 0,
.bMaxCCIDBusySlots = 1},
.ccid_bulk_in =
{.bLength = sizeof(struct usb_endpoint_descriptor),
.bDescriptorType = USB_DTYPE_ENDPOINT,
.bEndpointAddress = CCID_IN_EPADDR,
.bmAttributes = USB_EPTYPE_BULK,
.wMaxPacketSize = CCID_EPSIZE,
.bInterval = 0x05
},
.ccid_bulk_out =
{.bLength = sizeof(struct usb_endpoint_descriptor),
.bDescriptorType = USB_DTYPE_ENDPOINT,
.bEndpointAddress = CCID_OUT_EPADDR,
.bmAttributes = USB_EPTYPE_BULK,
.wMaxPacketSize = CCID_EPSIZE,
.bInterval = 0x05},
},
};
static void ccid_init(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx);
static void ccid_deinit(usbd_device* dev);
static void ccid_on_wakeup(usbd_device* dev);
static void ccid_on_suspend(usbd_device* dev);
FuriHalUsbInterface usb_ccid = {
.init = ccid_init,
.deinit = ccid_deinit,
.wakeup = ccid_on_wakeup,
.suspend = ccid_on_suspend,
.dev_descr = (struct usb_device_descriptor*)&ccid_device_desc,
.str_manuf_descr = NULL,
.str_prod_descr = NULL,
.str_serial_descr = NULL,
.cfg_descr = (void*)&ccid_cfg_desc,
};
static usbd_respond ccid_ep_config(usbd_device* dev, uint8_t cfg);
static usbd_respond ccid_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_callback* callback);
static usbd_device* usb_dev;
static bool connected = false;
static bool smartcard_inserted = true;
static CcidCallbacks* callbacks[CCID_TOTAL_SLOTS] = {NULL};
static void* ccid_set_string_descr(char* str) {
furi_assert(str);
size_t len = strlen(str);
struct usb_string_descriptor* dev_str_desc = malloc(len * 2 + 2);
dev_str_desc->bLength = len * 2 + 2;
dev_str_desc->bDescriptorType = USB_DTYPE_STRING;
for(size_t i = 0; i < len; i++) dev_str_desc->wString[i] = str[i];
return dev_str_desc;
}
static void ccid_init(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx) {
UNUSED(intf);
FuriHalUsbCcidConfig* cfg = (FuriHalUsbCcidConfig*)ctx;
usb_dev = dev;
usb_ccid.dev_descr->iManufacturer = 0;
usb_ccid.dev_descr->iProduct = 0;
usb_ccid.str_manuf_descr = NULL;
usb_ccid.str_prod_descr = NULL;
usb_ccid.dev_descr->idVendor = CCID_VID_DEFAULT;
usb_ccid.dev_descr->idProduct = CCID_PID_DEFAULT;
if(cfg != NULL) {
usb_ccid.dev_descr->idVendor = cfg->vid;
usb_ccid.dev_descr->idProduct = cfg->pid;
if(cfg->manuf[0] != '\0') {
usb_ccid.str_manuf_descr = ccid_set_string_descr(cfg->manuf);
usb_ccid.dev_descr->iManufacturer = UsbDevManuf;
}
if(cfg->product[0] != '\0') {
usb_ccid.str_prod_descr = ccid_set_string_descr(cfg->product);
usb_ccid.dev_descr->iProduct = UsbDevProduct;
}
}
usbd_reg_config(dev, ccid_ep_config);
usbd_reg_control(dev, ccid_control);
usbd_connect(dev, true);
}
static void ccid_deinit(usbd_device* dev) {
usbd_reg_config(dev, NULL);
usbd_reg_control(dev, NULL);
free(usb_ccid.str_prod_descr);
free(usb_ccid.str_serial_descr);
}
static void ccid_on_wakeup(usbd_device* dev) {
UNUSED(dev);
connected = true;
}
static void ccid_on_suspend(usbd_device* dev) {
UNUSED(dev);
connected = false;
}
struct ccid_bulk_message_header {
uint8_t bMessageType;
uint32_t dwLength;
uint8_t bSlot;
uint8_t bSeq;
} __attribute__((packed));
static struct rdr_to_pc_slot_status responseSlotStatus;
static struct rdr_to_pc_data_block responseDataBlock;
static struct rdr_to_pc_parameters_t0 responseParameters;
uint8_t SendDataBlock[CCID_DATABLOCK_SIZE];
uint8_t CALLBACK_CCID_GetSlotStatus(uint8_t slot, uint8_t* error) {
if(slot == CCID_SLOT_INDEX) {
*error = CCID_ERROR_NOERROR;
if(smartcard_inserted) {
return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_PRESENTANDACTIVE;
} else {
return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_NOICCPRESENT;
}
} else {
*error = CCID_ERROR_SLOTNOTFOUND;
return CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_NOICCPRESENT;
}
}
uint8_t
CALLBACK_CCID_IccPowerOn(uint8_t slot, uint8_t* atrBuffer, uint32_t* atrlen, uint8_t* error) {
if(slot == CCID_SLOT_INDEX) {
*error = CCID_ERROR_NOERROR;
if(smartcard_inserted) {
if(callbacks[CCID_SLOT_INDEX] != NULL) {
callbacks[CCID_SLOT_INDEX]->icc_power_on_callback(atrBuffer, atrlen, NULL);
} else {
return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR |
CCID_ICCSTATUS_PRESENTANDINACTIVE;
}
return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_PRESENTANDACTIVE;
} else {
return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_NOICCPRESENT;
}
} else {
*error = CCID_ERROR_SLOTNOTFOUND;
return CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_NOICCPRESENT;
}
}
uint8_t CALLBACK_CCID_XfrBlock(
uint8_t slot,
uint8_t* dataBlock,
uint32_t* dataBlockLen,
uint8_t* error) {
if(slot == CCID_SLOT_INDEX) {
*error = CCID_ERROR_NOERROR;
if(smartcard_inserted) {
if(callbacks[CCID_SLOT_INDEX] != NULL) {
callbacks[CCID_SLOT_INDEX]->xfr_datablock_callback(dataBlock, dataBlockLen, NULL);
} else {
return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR |
CCID_ICCSTATUS_PRESENTANDINACTIVE;
}
return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_PRESENTANDACTIVE;
} else {
return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_NOICCPRESENT;
}
} else {
*error = CCID_ERROR_SLOTNOTFOUND;
return CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_NOICCPRESENT;
}
}
void furi_hal_ccid_ccid_insert_smartcard() {
smartcard_inserted = true;
}
void furi_hal_ccid_ccid_remove_smartcard() {
smartcard_inserted = false;
}
void furi_hal_ccid_set_callbacks(CcidCallbacks* cb) {
callbacks[CCID_SLOT_INDEX] = cb;
}
static void ccid_rx_ep_callback(usbd_device* dev, uint8_t event, uint8_t ep) {
UNUSED(dev);
UNUSED(event);
UNUSED(ep);
}
static void ccid_tx_ep_callback(usbd_device* dev, uint8_t event, uint8_t ep) {
UNUSED(dev);
if(event == usbd_evt_eprx) {
if(connected == false) return;
struct ccid_bulk_message_header message;
usbd_ep_read(usb_dev, ep, &message, sizeof(message));
uint8_t Status;
uint8_t Error = CCID_ERROR_NOERROR;
uint32_t dataBlockLen = 0;
uint8_t* dataBlockBuffer = NULL;
if(message.bMessageType == PC_TO_RDR_GETSLOTSTATUS) {
responseSlotStatus.bMessageType = RDR_TO_PC_SLOTSTATUS;
responseSlotStatus.dwLength = 0;
responseSlotStatus.bSlot = message.bSlot;
responseSlotStatus.bSeq = message.bSeq;
responseSlotStatus.bClockStatus = 0;
Status = CALLBACK_CCID_GetSlotStatus(message.bSlot, &Error);
responseSlotStatus.bStatus = Status;
responseSlotStatus.bError = Error;
usbd_ep_write(
usb_dev, CCID_IN_EPADDR, &responseSlotStatus, sizeof(responseSlotStatus));
} else if(message.bMessageType == PC_TO_RDR_ICCPOWERON) {
responseDataBlock.bMessageType = RDR_TO_PC_DATABLOCK;
responseDataBlock.bSlot = message.bSlot;
responseDataBlock.bSeq = message.bSeq;
responseDataBlock.bChainParameter = 0;
dataBlockLen = 0;
dataBlockBuffer = (uint8_t*)SendDataBlock;
Status = CALLBACK_CCID_IccPowerOn(
message.bSlot, (uint8_t*)dataBlockBuffer, &dataBlockLen, &Error);
furi_assert(dataBlockLen < CCID_DATABLOCK_SIZE);
responseDataBlock.dwLength = dataBlockLen;
responseSlotStatus.bStatus = Status;
responseSlotStatus.bError = Error;
memcpy(responseDataBlock.abData, SendDataBlock, dataBlockLen);
usbd_ep_write(
usb_dev,
CCID_IN_EPADDR,
&responseDataBlock,
sizeof(struct rdr_to_pc_data_block) + (sizeof(uint8_t) * dataBlockLen));
} else if(message.bMessageType == PC_TO_RDR_ICCPOWEROFF) {
responseSlotStatus.bMessageType = RDR_TO_PC_SLOTSTATUS;
responseSlotStatus.dwLength = 0;
responseSlotStatus.bSlot = message.bSlot;
responseSlotStatus.bSeq = message.bSeq;
responseSlotStatus.bClockStatus = 0;
uint8_t Status;
uint8_t Error = CCID_ERROR_NOERROR;
Status = CALLBACK_CCID_GetSlotStatus(message.bSlot, &Error);
responseSlotStatus.bStatus = Status;
responseSlotStatus.bError = Error;
usbd_ep_write(
usb_dev, CCID_IN_EPADDR, &responseSlotStatus, sizeof(responseSlotStatus));
} else if(message.bMessageType == PC_TO_RDR_SETPARAMETERS) {
responseParameters.bMessageType = RDR_TO_PC_PARAMETERS;
responseParameters.bSlot = message.bSlot;
responseParameters.bSeq = message.bSeq;
responseParameters.bProtocolNum = 0; //T0
uint8_t Status = CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR;
uint8_t Error = CCID_ERROR_NOERROR;
responseParameters.bStatus = Status;
responseParameters.bError = Error;
responseParameters.dwLength = sizeof(struct rdr_to_pc_parameters_t0);
usbd_ep_write(
usb_dev, CCID_IN_EPADDR, &responseParameters, sizeof(responseParameters));
} else if(message.bMessageType == PC_TO_RDR_XFRBLOCK) {
responseDataBlock.bMessageType = RDR_TO_PC_DATABLOCK;
responseDataBlock.bSlot = message.bSlot;
responseDataBlock.bSeq = message.bSeq;
responseDataBlock.bChainParameter = 0;
dataBlockLen = 0;
dataBlockBuffer = (uint8_t*)SendDataBlock;
Status = CALLBACK_CCID_XfrBlock(
message.bSlot, (uint8_t*)dataBlockBuffer, &dataBlockLen, &Error);
furi_assert(dataBlockLen < CCID_DATABLOCK_SIZE);
responseDataBlock.dwLength = dataBlockLen;
responseSlotStatus.bStatus = Status;
responseSlotStatus.bError = Error;
memcpy(responseDataBlock.abData, SendDataBlock, dataBlockLen);
usbd_ep_write(
usb_dev,
CCID_IN_EPADDR,
&responseDataBlock,
sizeof(struct rdr_to_pc_data_block) + (sizeof(uint8_t) * dataBlockLen));
}
}
}
/* Configure endpoints */
static usbd_respond ccid_ep_config(usbd_device* dev, uint8_t cfg) {
switch(cfg) {
case 0:
/* deconfiguring device */
usbd_ep_deconfig(dev, CCID_IN_EPADDR);
usbd_ep_deconfig(dev, CCID_OUT_EPADDR);
usbd_reg_endpoint(dev, CCID_IN_EPADDR, 0);
usbd_reg_endpoint(dev, CCID_OUT_EPADDR, 0);
return usbd_ack;
case 1:
/* configuring device */
usbd_ep_config(dev, CCID_IN_EPADDR, USB_EPTYPE_BULK, CCID_EPSIZE);
usbd_ep_config(dev, CCID_OUT_EPADDR, USB_EPTYPE_BULK, CCID_EPSIZE);
usbd_reg_endpoint(dev, CCID_IN_EPADDR, ccid_rx_ep_callback);
usbd_reg_endpoint(dev, CCID_OUT_EPADDR, ccid_tx_ep_callback);
return usbd_ack;
default:
return usbd_fail;
}
}
/* Control requests handler */
static usbd_respond ccid_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_callback* callback) {
UNUSED(callback);
/* CDC control requests */
if(((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) ==
(USB_REQ_INTERFACE | USB_REQ_CLASS) &&
(req->wIndex == 0 || req->wIndex == 2)) {
switch(req->bRequest) {
case CCID_ABORT:
return usbd_fail;
case CCID_GET_CLOCK_FREQUENCIES:
dev->status.data_ptr = (void*)&(ccid_cfg_desc.intf_0.ccid_desc.dwDefaultClock);
dev->status.data_count = sizeof(ccid_cfg_desc.intf_0.ccid_desc.dwDefaultClock);
return usbd_ack;
default:
return usbd_fail;
}
}
return usbd_fail;
}

View File

@@ -35,6 +35,7 @@ struct STOP_EXTERNING_ME {};
#include <furi_hal_vibro.h>
#include <furi_hal_usb.h>
#include <furi_hal_usb_hid.h>
#include <furi_hal_usb_ccid.h>
#include <furi_hal_uart.h>
#include <furi_hal_info.h>
#include <furi_hal_random.h>

View File

@@ -28,6 +28,7 @@ extern FuriHalUsbInterface usb_cdc_single;
extern FuriHalUsbInterface usb_cdc_dual;
extern FuriHalUsbInterface usb_hid;
extern FuriHalUsbInterface usb_hid_u2f;
extern FuriHalUsbInterface usb_ccid;
typedef enum {
FuriHalUsbStateEventReset,

View File

@@ -0,0 +1,31 @@
#pragma once
#include "hid_usage_desktop.h"
#include "hid_usage_button.h"
#include "hid_usage_keyboard.h"
#include "hid_usage_consumer.h"
#include "hid_usage_led.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
uint16_t vid;
uint16_t pid;
char manuf[32];
char product[32];
} FuriHalUsbCcidConfig;
typedef struct {
void (*icc_power_on_callback)(uint8_t* dataBlock, uint32_t* dataBlockLen, void* context);
void (*xfr_datablock_callback)(uint8_t* dataBlock, uint32_t* dataBlockLen, void* context);
} CcidCallbacks;
void furi_hal_ccid_set_callbacks(CcidCallbacks* cb);
void furi_hal_ccid_ccid_insert_smartcard();
void furi_hal_ccid_ccid_remove_smartcard();
#ifdef __cplusplus
}
#endif