wip broken atr
* ATR (and other communication) broken parity errors, flipped bits, too many/few bytes received * no logging due to blocking ringbuffer (full) * FSM timeout for atr bytes/missing tck for T=0 broken (GR1) * buffer handling broken (alloc/dealloc bandaid, OUT ep needs a buffer) * osmo_emb has a pool, check size/usage * temporary descriptor fixes (AUTO PPS), TPDU only, T=0 only * - ccid set parameters missing * - actual suppored baud rates needs fixing * temporarily large uart buffers, tpdu xfer waiting for > bufsize... * s(n)printf mysteriously broken? -> workaround * other stuff Change-Id: Ibd5bd76e4e2574f9f01a7e702013e82f134e491c
This commit is contained in:
parent
92e21c699e
commit
6a1b7fa698
|
@ -80,9 +80,10 @@ static void iso_fsm_slot_icc_power_on_async(struct ccid_slot *cs, struct msgb *m
|
|||
osmo_fsm_inst_dispatch(ss->fi, ISO7816_E_POWER_UP_IND, NULL);
|
||||
cs->icc_powered = true;
|
||||
card_uart_ctrl(ss->cuart, CUART_CTL_CLOCK, true);
|
||||
usleep(10000);
|
||||
card_uart_ctrl(ss->cuart, CUART_CTL_RST, false);
|
||||
delay_us(10000);
|
||||
|
||||
osmo_fsm_inst_dispatch(ss->fi, ISO7816_E_RESET_REL_IND, NULL);
|
||||
card_uart_ctrl(ss->cuart, CUART_CTL_RST, false);
|
||||
|
||||
msgb_free(msg);
|
||||
/* continues in iso_fsm_clot_user_cb once ATR is received */
|
||||
|
@ -151,8 +152,10 @@ static void iso_fsm_slot_set_power(struct ccid_slot *cs, bool enable)
|
|||
|
||||
if (enable) {
|
||||
card_uart_ctrl(ss->cuart, CUART_CTL_POWER, true);
|
||||
cs->icc_powered = true;
|
||||
} else {
|
||||
card_uart_ctrl(ss->cuart, CUART_CTL_POWER, false);
|
||||
cs->icc_powered = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -185,31 +188,35 @@ static int iso_fsm_slot_set_rate_and_clock(struct ccid_slot *cs, uint32_t freq_h
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
extern void *g_tall_ctx;
|
||||
static int iso_fsm_slot_init(struct ccid_slot *cs)
|
||||
{
|
||||
void *ctx = NULL; /* FIXME */
|
||||
void *ctx = g_tall_ctx; /* FIXME */
|
||||
struct iso_fsm_slot *ss = ccid_slot2iso_fsm_slot(cs);
|
||||
struct card_uart *cuart = talloc_zero(ctx, struct card_uart);
|
||||
char id_buf[16];
|
||||
char *devname = NULL;
|
||||
char id_buf[16] = "SIM0";
|
||||
char devname[] = "foobar";
|
||||
int rc;
|
||||
|
||||
LOGPCS(cs, LOGL_DEBUG, "%s\n", __func__);
|
||||
|
||||
/* HACK: make this in some way configurable so it works both in the firmware
|
||||
* and on the host (functionfs) */
|
||||
if (cs->slot_nr == 0) {
|
||||
cs->icc_present = true;
|
||||
devname = "/dev/ttyUSB5";
|
||||
}
|
||||
// if (cs->slot_nr == 0) {
|
||||
// cs->icc_present = true;
|
||||
// devname = "/dev/ttyUSB5";
|
||||
// }
|
||||
devname[0] = cs->slot_nr +0x30;
|
||||
devname[1] = 0;
|
||||
//sprintf(devname, "%d", cs->slot_nr);
|
||||
|
||||
if (!cuart)
|
||||
return -ENOMEM;
|
||||
|
||||
snprintf(id_buf, sizeof(id_buf), "SIM%d", cs->slot_nr);
|
||||
//snprintf(id_buf, sizeof(id_buf), "SIM%d", cs->slot_nr);
|
||||
id_buf[3] = cs->slot_nr +0x30;
|
||||
if (devname) {
|
||||
rc = card_uart_open(cuart, "tty", devname);
|
||||
rc = card_uart_open(cuart, "asf4", devname);
|
||||
if (rc < 0) {
|
||||
LOGPCS(cs, LOGL_ERROR, "Cannot open UART %s: %d\n", devname, rc);
|
||||
talloc_free(cuart);
|
||||
|
|
|
@ -633,6 +633,10 @@ static void atr_wait_tX_action(struct osmo_fsm_inst *fi, uint32_t event, void *d
|
|||
osmo_fsm_inst_state_chg_ms(fi, ATR_S_WAIT_TCK,
|
||||
guard_time_ms, T_GUARD);
|
||||
break;
|
||||
} else {
|
||||
/* no TCK present, ATR complete; notify parent */
|
||||
osmo_fsm_inst_state_chg(fi, ATR_S_DONE, 0, 0);
|
||||
osmo_fsm_inst_dispatch(fi->proc.parent, ISO7816_E_ATR_DONE_IND, atp->atr);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
|
|
|
@ -47,6 +47,15 @@ static void _SIM_tx_cb(const struct usart_async_descriptor *const io_descr, uint
|
|||
card_uart_notification(cuart, CUART_E_TX_COMPLETE, io_descr->tx_buffer);
|
||||
}
|
||||
|
||||
#include <hpl_usart_async.h>
|
||||
#include <hpl_usart_sync.h>
|
||||
|
||||
|
||||
static void _SIM_error_cb(const struct usart_async_descriptor *const descr){
|
||||
volatile uint32_t status = hri_sercomusart_read_STATUS_reg(descr->device.hw);
|
||||
volatile uint32_t data = hri_sercomusart_read_DATA_reg(descr->device.hw);
|
||||
OSMO_ASSERT(0 == 1)
|
||||
}
|
||||
|
||||
/* the below ugli-ness is required as the usart_async_descriptor doesn't have
|
||||
* some kind of 'private' member that could provide the call-back anty kind of
|
||||
|
@ -124,6 +133,139 @@ static usart_cb_t SIM_tx_cb[8] = {
|
|||
SIM4_tx_cb, SIM5_tx_cb, SIM6_tx_cb, SIM7_tx_cb,
|
||||
};
|
||||
|
||||
#include <math.h>
|
||||
#include "atmel_start.h"
|
||||
#include "atmel_start_pins.h"
|
||||
#include "config/hpl_gclk_config.h"
|
||||
#include "iso7816_3.h"
|
||||
|
||||
/** possible clock sources for the SERCOM peripheral
|
||||
* warning: the definition must match the GCLK configuration
|
||||
*/
|
||||
static const uint8_t sercom_glck_sources[] = {GCLK_PCHCTRL_GEN_GCLK2_Val, GCLK_PCHCTRL_GEN_GCLK4_Val, GCLK_PCHCTRL_GEN_GCLK6_Val};
|
||||
|
||||
/** possible clock frequencies in MHz for the SERCOM peripheral
|
||||
* warning: the definition must match the GCLK configuration
|
||||
*/
|
||||
static const double sercom_glck_freqs[] = {100E6 / CONF_GCLK_GEN_2_DIV, 100E6 / CONF_GCLK_GEN_4_DIV, 120E6 / CONF_GCLK_GEN_6_DIV};
|
||||
|
||||
/** the GCLK ID for the SERCOM SIM peripherals
|
||||
* @note: used as index for PCHCTRL
|
||||
*/
|
||||
static const uint8_t SIM_peripheral_GCLK_ID[] = {SERCOM0_GCLK_ID_CORE, SERCOM1_GCLK_ID_CORE, SERCOM2_GCLK_ID_CORE, SERCOM3_GCLK_ID_CORE, SERCOM4_GCLK_ID_CORE, SERCOM5_GCLK_ID_CORE, SERCOM6_GCLK_ID_CORE, SERCOM7_GCLK_ID_CORE};
|
||||
|
||||
|
||||
/** change baud rate of card slot
|
||||
* @param[in] slotnr slot number for which the baud rate should be set
|
||||
* @param[in] baudrate baud rate in bps to set
|
||||
* @return if the baud rate has been set, else a parameter is out of range
|
||||
*/
|
||||
static bool slot_set_baudrate(uint8_t slotnr, uint32_t baudrate)
|
||||
{
|
||||
ASSERT(slotnr < ARRAY_SIZE(SIM_peripheral_descriptors));
|
||||
|
||||
// calculate the error corresponding to the clock sources
|
||||
uint16_t bauds[ARRAY_SIZE(sercom_glck_freqs)];
|
||||
double errors[ARRAY_SIZE(sercom_glck_freqs)];
|
||||
for (uint8_t i = 0; i < ARRAY_SIZE(sercom_glck_freqs); i++) {
|
||||
double freq = sercom_glck_freqs[i]; // remember possible SERCOM frequency
|
||||
uint32_t min = freq / (2 * (255 + 1)); // calculate the minimum baud rate for this frequency
|
||||
uint32_t max = freq / (2 * (0 + 1)); // calculate the maximum baud rate for this frequency
|
||||
if (baudrate < min || baudrate > max) { // baud rate it out of supported range
|
||||
errors[i] = NAN;
|
||||
} else {
|
||||
uint16_t baud = round(freq / (2 * baudrate) - 1);
|
||||
bauds[i] = baud;
|
||||
double actual = freq / (2 * (baud + 1));
|
||||
errors[i] = fabs(1.0 - (actual / baudrate));
|
||||
}
|
||||
}
|
||||
|
||||
// find the smallest error
|
||||
uint8_t best = ARRAY_SIZE(sercom_glck_freqs);
|
||||
for (uint8_t i = 0; i < ARRAY_SIZE(sercom_glck_freqs); i++) {
|
||||
if (isnan(errors[i])) {
|
||||
continue;
|
||||
}
|
||||
if (best >= ARRAY_SIZE(sercom_glck_freqs)) {
|
||||
best = i;
|
||||
} else if (errors[i] < errors[best]) {
|
||||
best = i;
|
||||
}
|
||||
}
|
||||
if (best >= ARRAY_SIZE(sercom_glck_freqs)) { // found no clock supporting this baud rate
|
||||
return false;
|
||||
}
|
||||
|
||||
// set clock and baud rate
|
||||
struct usart_async_descriptor* slot = SIM_peripheral_descriptors[slotnr]; // get slot
|
||||
if (NULL == slot) {
|
||||
return false;
|
||||
}
|
||||
printf("(%u) switching SERCOM clock to GCLK%u (freq = %lu kHz) and baud rate to %lu bps (baud = %u)\r\n", slotnr, (best + 1) * 2, (uint32_t)(round(sercom_glck_freqs[best] / 1000)), baudrate, bauds[best]);
|
||||
while (!usart_async_is_tx_empty(slot)); // wait for transmission to complete (WARNING no timeout)
|
||||
usart_async_disable(slot); // disable SERCOM peripheral
|
||||
hri_gclk_clear_PCHCTRL_reg(GCLK, SIM_peripheral_GCLK_ID[slotnr], (1 << GCLK_PCHCTRL_CHEN_Pos)); // disable clock for this peripheral
|
||||
while (hri_gclk_get_PCHCTRL_reg(GCLK, SIM_peripheral_GCLK_ID[slotnr], (1 << GCLK_PCHCTRL_CHEN_Pos))); // wait until clock is really disabled
|
||||
// it does not seem we need to completely disable the peripheral using hri_mclk_clear_APBDMASK_SERCOMn_bit
|
||||
hri_gclk_write_PCHCTRL_reg(GCLK, SIM_peripheral_GCLK_ID[slotnr], sercom_glck_sources[best] | (1 << GCLK_PCHCTRL_CHEN_Pos)); // set peripheral core clock and re-enable it
|
||||
usart_async_set_baud_rate(slot, bauds[best]); // set the new baud rate
|
||||
usart_async_enable(slot); // re-enable SERCOM peripheral
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** change ISO baud rate of card slot
|
||||
* @param[in] slotnr slot number for which the baud rate should be set
|
||||
* @param[in] clkdiv can clock divider
|
||||
* @param[in] f clock rate conversion integer F
|
||||
* @param[in] d baud rate adjustment factor D
|
||||
* @return if the baud rate has been set, else a parameter is out of range
|
||||
*/
|
||||
static bool slot_set_isorate(uint8_t slotnr, enum ncn8025_sim_clkdiv clkdiv, uint16_t f, uint8_t d)
|
||||
{
|
||||
// input checks
|
||||
ASSERT(slotnr < ARRAY_SIZE(SIM_peripheral_descriptors));
|
||||
if (clkdiv != SIM_CLKDIV_1 && clkdiv != SIM_CLKDIV_2 && clkdiv != SIM_CLKDIV_4 && clkdiv != SIM_CLKDIV_8) {
|
||||
return false;
|
||||
}
|
||||
if (!iso7816_3_valid_f(f)) {
|
||||
return false;
|
||||
}
|
||||
if (!iso7816_3_valid_d(d)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// set clockdiv
|
||||
struct ncn8025_settings settings;
|
||||
ncn8025_get(slotnr, &settings);
|
||||
if (settings.clkdiv != clkdiv) {
|
||||
settings.clkdiv = clkdiv;
|
||||
ncn8025_set(slotnr, &settings);
|
||||
}
|
||||
|
||||
// calculate desired frequency
|
||||
uint32_t freq = 20000000UL; // maximum frequency
|
||||
switch (clkdiv) {
|
||||
case SIM_CLKDIV_1:
|
||||
freq /= 1;
|
||||
break;
|
||||
case SIM_CLKDIV_2:
|
||||
freq /= 2;
|
||||
break;
|
||||
case SIM_CLKDIV_4:
|
||||
freq /= 4;
|
||||
break;
|
||||
case SIM_CLKDIV_8:
|
||||
freq /= 8;
|
||||
break;
|
||||
}
|
||||
|
||||
// set baud rate
|
||||
uint32_t baudrate = (freq * d) / f; // calculate actual baud rate
|
||||
return slot_set_baudrate(slotnr, baudrate); // set baud rate
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* Interface with card_uart (cuart) core
|
||||
***********************************************************************/
|
||||
|
@ -146,10 +288,15 @@ static int asf4_usart_open(struct card_uart *cuart, const char *device_name)
|
|||
cuart->u.asf4.usa_pd = usa_pd;
|
||||
cuart->u.asf4.slot_nr = slot_nr;
|
||||
|
||||
|
||||
usart_async_register_callback(usa_pd, USART_ASYNC_RXC_CB, SIM_rx_cb[slot_nr]);
|
||||
usart_async_register_callback(usa_pd, USART_ASYNC_TXC_CB, SIM_tx_cb[slot_nr]);
|
||||
usart_async_register_callback(usa_pd, USART_ASYNC_ERROR_CB, _SIM_error_cb);
|
||||
usart_async_enable(usa_pd);
|
||||
|
||||
// set USART baud rate to match the interface (f = 2.5 MHz) and card default settings (Fd = 372, Dd = 1)
|
||||
slot_set_isorate(cuart->u.asf4.slot_nr, SIM_CLKDIV_8, ISO7816_3_DEFAULT_FD, ISO7816_3_DEFAULT_DD);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -206,10 +353,18 @@ static int asf4_usart_ctrl(struct card_uart *cuart, enum card_uart_ctl ctl, int
|
|||
ncn8025_get(cuart->u.asf4.slot_nr, &settings);
|
||||
settings.rstin = arg ? true : false;
|
||||
ncn8025_set(cuart->u.asf4.slot_nr, &settings);
|
||||
usart_async_flush_rx_buffer(cuart->u.asf4.usa_pd);
|
||||
break;
|
||||
case CUART_CTL_POWER:
|
||||
ncn8025_get(cuart->u.asf4.slot_nr, &settings);
|
||||
settings.cmdvcc = arg ? true : false;
|
||||
settings.led = arg ? true : false;
|
||||
settings.vsel = SIM_VOLT_5V0;
|
||||
|
||||
// set USART baud rate to match the interface (f = 2.5 MHz) and card default settings (Fd = 372, Dd = 1)
|
||||
if(arg)
|
||||
slot_set_isorate(cuart->u.asf4.slot_nr, SIM_CLKDIV_8, ISO7816_3_DEFAULT_FD, ISO7816_3_DEFAULT_DD);
|
||||
|
||||
ncn8025_set(cuart->u.asf4.slot_nr, &settings);
|
||||
break;
|
||||
case CUART_CTL_WTIME:
|
||||
|
|
|
@ -12,25 +12,25 @@
|
|||
#include <hal_init.h>
|
||||
|
||||
/*! The buffer size for USART */
|
||||
#define SIM0_BUFFER_SIZE 16
|
||||
#define SIM0_BUFFER_SIZE 512
|
||||
|
||||
/*! The buffer size for USART */
|
||||
#define SIM1_BUFFER_SIZE 16
|
||||
#define SIM1_BUFFER_SIZE 512
|
||||
|
||||
/*! The buffer size for USART */
|
||||
#define SIM2_BUFFER_SIZE 16
|
||||
#define SIM2_BUFFER_SIZE 512
|
||||
|
||||
/*! The buffer size for USART */
|
||||
#define SIM3_BUFFER_SIZE 16
|
||||
#define SIM3_BUFFER_SIZE 512
|
||||
|
||||
/*! The buffer size for USART */
|
||||
#define SIM4_BUFFER_SIZE 16
|
||||
#define SIM4_BUFFER_SIZE 512
|
||||
|
||||
/*! The buffer size for USART */
|
||||
#define SIM5_BUFFER_SIZE 16
|
||||
#define SIM5_BUFFER_SIZE 512
|
||||
|
||||
/*! The buffer size for USART */
|
||||
#define SIM6_BUFFER_SIZE 16
|
||||
#define SIM6_BUFFER_SIZE 512
|
||||
|
||||
/*! The buffer size for USART */
|
||||
#define UART_DEBUG_BUFFER_SIZE 256
|
||||
|
|
|
@ -8,7 +8,7 @@ EXTRA_CFLAGS=-I$(SYSTEM_PREFIX)/include -I../../ccid_common
|
|||
CROSS_COMPILE= arm-none-eabi-
|
||||
|
||||
CFLAGS_CPU=-D__SAME54N19A__ -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16
|
||||
CFLAGS=-x c -mthumb -DDEBUG -Os -ffunction-sections -fdata-sections -mlong-calls \
|
||||
CFLAGS=-x c -mthumb -DDEBUG -O0 -ffunction-sections -fdata-sections -mlong-calls \
|
||||
-g3 -Wall -c -std=gnu99 $(CFLAGS_CPU)
|
||||
|
||||
CC = $(CROSS_COMPILE)gcc
|
||||
|
|
|
@ -157,8 +157,8 @@ void libosmo_emb_init(void)
|
|||
/* logging */
|
||||
log_init(&log_info, g_tall_ctx);
|
||||
stderr_target = log_target_create_stderr_raw();
|
||||
log_add_target(stderr_target);
|
||||
log_set_all_filter(stderr_target, 1);
|
||||
//log_add_target(stderr_target);
|
||||
//log_set_all_filter(stderr_target, 1);
|
||||
|
||||
/* timer */
|
||||
SysTick_Config(SystemCoreClock / 1000);
|
||||
|
|
1472
sysmoOCTSIM/main.c
1472
sysmoOCTSIM/main.c
File diff suppressed because it is too large
Load Diff
|
@ -30,6 +30,10 @@
|
|||
inspired by http://swapped.cc/halloc/
|
||||
*/
|
||||
|
||||
#include <parts.h>
|
||||
#include <assert.h>
|
||||
#include <osmocom/core/utils.h>
|
||||
|
||||
#include "replace.h"
|
||||
#include "talloc.h"
|
||||
|
||||
|
@ -727,6 +731,9 @@ static inline void *__talloc_with_prefix(const void *context,
|
|||
size_t total_len = TC_HDR_SIZE + size + prefix_len;
|
||||
struct talloc_chunk *parent = NULL;
|
||||
|
||||
// do not allocate while handling interrupts!
|
||||
OSMO_ASSERT( !(SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) )
|
||||
|
||||
if (unlikely(context == NULL)) {
|
||||
context = null_context;
|
||||
}
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
#include "ccid_proto.h"
|
||||
#include "usb_includes.h"
|
||||
|
||||
#include "cdcdf_acm_desc.h"
|
||||
#include "usb_descriptors.h"
|
||||
|
||||
#ifndef USB_CLASS_CCID
|
||||
#define USB_CLASS_CCID 11
|
||||
#endif
|
||||
|
@ -40,9 +43,11 @@ struct ccid_df_func_data {
|
|||
static struct usbdf_driver _ccid_df;
|
||||
static struct ccid_df_func_data _ccid_df_funcd;
|
||||
|
||||
extern const struct usb_desc_collection usb_fs_descs;
|
||||
|
||||
/* FIXME: make those configurable, ensure they're sized according to
|
||||
* bNumClockSupported / bNumDataRatesSupported */
|
||||
static uint32_t ccid_clock_frequencies[] = { LE32(20000) };
|
||||
static uint32_t ccid_clock_frequencies[CCID_NUM_CLK_SUPPORTED] = { LE32(2500),LE32(5000),LE32(10000),LE32(20000) };
|
||||
static uint32_t ccid_baud_rates[] = { LE32(9600) };
|
||||
|
||||
static int32_t ccid_df_enable(struct usbdf_driver *drv, struct usbd_descriptors *desc)
|
||||
|
|
|
@ -4,51 +4,11 @@
|
|||
#include "usb_protocol_cdc.h"
|
||||
#include "ccid_proto.h"
|
||||
#include "cdcdf_acm_desc.h"
|
||||
#include "usb_descriptors.h"
|
||||
|
||||
/* aggregate descriptors for the combined CDC-ACM + CCID device that we expose
|
||||
* from sysmoQMOD */
|
||||
|
||||
enum str_desc_num {
|
||||
STR_DESC_MANUF = 1,
|
||||
STR_DESC_PRODUCT,
|
||||
STR_DESC_CONFIG,
|
||||
STR_DESC_INTF_ACM_COMM,
|
||||
STR_DESC_INTF_ACM_DATA,
|
||||
STR_DESC_INTF_CCID,
|
||||
STR_DESC_SERIAL,
|
||||
};
|
||||
|
||||
/* a struct of structs representing the concatenated collection of USB descriptors */
|
||||
struct usb_desc_collection {
|
||||
struct usb_dev_desc dev;
|
||||
struct usb_config_desc cfg;
|
||||
|
||||
/* CDC-ACM: Two interfaces, one with IRQ EP and one with BULK IN + OUT */
|
||||
struct {
|
||||
struct {
|
||||
struct usb_iface_desc iface;
|
||||
struct usb_cdc_hdr_desc cdc_hdr;
|
||||
struct usb_cdc_call_mgmt_desc cdc_call_mgmt;
|
||||
struct usb_cdc_acm_desc cdc_acm;
|
||||
struct usb_cdc_union_desc cdc_union;
|
||||
struct usb_ep_desc ep[1];
|
||||
} comm;
|
||||
struct {
|
||||
struct usb_iface_desc iface;
|
||||
struct usb_ep_desc ep[2];
|
||||
} data;
|
||||
} cdc;
|
||||
|
||||
/* CCID: One interface with CCID class descriptor and three endpoints */
|
||||
struct {
|
||||
struct usb_iface_desc iface;
|
||||
struct usb_ccid_class_descriptor class;
|
||||
struct usb_ep_desc ep[3];
|
||||
} ccid;
|
||||
uint8_t str[116];
|
||||
} __attribute__((packed));
|
||||
|
||||
static const struct usb_desc_collection usb_fs_descs = {
|
||||
const struct usb_desc_collection usb_fs_descs = {
|
||||
.dev = {
|
||||
.bLength = sizeof(struct usb_dev_desc),
|
||||
.bDescriptorType = USB_DT_DEVICE,
|
||||
|
@ -176,17 +136,19 @@ static const struct usb_desc_collection usb_fs_descs = {
|
|||
.bcdCCID = LE16(0x0110),
|
||||
.bMaxSlotIndex = 7,
|
||||
.bVoltageSupport = 0x07, /* 5/3/1.8V */
|
||||
.dwProtocols = 0x03,
|
||||
// .dwProtocols = 0x03,
|
||||
.dwProtocols = 0x01,
|
||||
.dwDefaultClock = LE32(2500),
|
||||
.dwMaximumClock = LE32(20000),
|
||||
.bNumClockSupported = 4,
|
||||
.bNumClockSupported = CCID_NUM_CLK_SUPPORTED,
|
||||
.dwDataRate = LE32(9600),
|
||||
.dwMaxDataRate = LE32(921600),
|
||||
.bNumDataRatesSupported = 0,
|
||||
.dwMaxIFSD = LE32(0),
|
||||
.dwSynchProtocols = LE32(0),
|
||||
.dwMechanical = LE32(0),
|
||||
.dwFeatures = LE32(0x10 | 0x00010000),
|
||||
.dwFeatures = LE32(0x10 | 0x00010080),
|
||||
// .dwFeatures = LE32(0x2 | 0x40),
|
||||
.dwMaxCCIDMessageLength = 272,
|
||||
.bClassGetResponse = 0xff,
|
||||
.bClassEnvelope = 0xff,
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* usb_descriptors.h
|
||||
*
|
||||
* Created on: Oct 11, 2019
|
||||
* Author: phi
|
||||
*/
|
||||
|
||||
#ifndef USB_DESCRIPTORS_H_
|
||||
#define USB_DESCRIPTORS_H_
|
||||
|
||||
#define CCID_NUM_CLK_SUPPORTED 4
|
||||
|
||||
/* aggregate descriptors for the combined CDC-ACM + CCID device that we expose
|
||||
* from sysmoQMOD */
|
||||
|
||||
enum str_desc_num {
|
||||
STR_DESC_MANUF = 1,
|
||||
STR_DESC_PRODUCT,
|
||||
STR_DESC_CONFIG,
|
||||
STR_DESC_INTF_ACM_COMM,
|
||||
STR_DESC_INTF_ACM_DATA,
|
||||
STR_DESC_INTF_CCID,
|
||||
STR_DESC_SERIAL,
|
||||
};
|
||||
|
||||
/* a struct of structs representing the concatenated collection of USB descriptors */
|
||||
struct usb_desc_collection {
|
||||
struct usb_dev_desc dev;
|
||||
struct usb_config_desc cfg;
|
||||
|
||||
/* CDC-ACM: Two interfaces, one with IRQ EP and one with BULK IN + OUT */
|
||||
struct {
|
||||
struct {
|
||||
struct usb_iface_desc iface;
|
||||
struct usb_cdc_hdr_desc cdc_hdr;
|
||||
struct usb_cdc_call_mgmt_desc cdc_call_mgmt;
|
||||
struct usb_cdc_acm_desc cdc_acm;
|
||||
struct usb_cdc_union_desc cdc_union;
|
||||
struct usb_ep_desc ep[1];
|
||||
} comm;
|
||||
struct {
|
||||
struct usb_iface_desc iface;
|
||||
struct usb_ep_desc ep[2];
|
||||
} data;
|
||||
} cdc;
|
||||
|
||||
/* CCID: One interface with CCID class descriptor and three endpoints */
|
||||
struct {
|
||||
struct usb_iface_desc iface;
|
||||
struct usb_ccid_class_descriptor class;
|
||||
struct usb_ep_desc ep[3];
|
||||
} ccid;
|
||||
uint8_t str[116];
|
||||
} __attribute__((packed));
|
||||
|
||||
#endif /* USB_DESCRIPTORS_H_ */
|
Loading…
Reference in New Issue