mirror of
git://git.gnupg.org/gnupg.git
synced 2025-03-28 22:49:59 +01:00
scd: Remove "special transport" support.
* scd/ccid-driver.c (transports, my_sleep, prepare_special_transport) (writen): Remove. (ccid_dev_scan, ccid_dev_scan_finish, ccid_get_BAI): Only for USB. (ccid_open_reader, do_close_reader, bulk_out, bulk_in, abort_cmd) (ccid_poll, ccid_transceive): Likewise. Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
parent
8640fa880d
commit
34199ef677
@ -218,31 +218,11 @@ enum {
|
|||||||
#define CCID_ERROR_CODE(buf) (((unsigned char *)(buf))[8])
|
#define CCID_ERROR_CODE(buf) (((unsigned char *)(buf))[8])
|
||||||
|
|
||||||
|
|
||||||
/* A list and a table with special transport descriptions. */
|
|
||||||
enum {
|
|
||||||
TRANSPORT_USB = 0, /* Standard USB transport. */
|
|
||||||
TRANSPORT_CM4040 = 1 /* As used by the Cardman 4040. */
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct
|
|
||||||
{
|
|
||||||
char *name; /* Device name. */
|
|
||||||
int type;
|
|
||||||
|
|
||||||
} transports[] = {
|
|
||||||
{ "/dev/cmx0", TRANSPORT_CM4040 },
|
|
||||||
{ "/dev/cmx1", TRANSPORT_CM4040 },
|
|
||||||
{ NULL },
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* Store information on the driver's state. A pointer to such a
|
/* Store information on the driver's state. A pointer to such a
|
||||||
structure is used as handle for most functions. */
|
structure is used as handle for most functions. */
|
||||||
struct ccid_driver_s
|
struct ccid_driver_s
|
||||||
{
|
{
|
||||||
libusb_device_handle *idev;
|
libusb_device_handle *idev;
|
||||||
int dev_fd; /* -1 for USB transport or file descriptor of the
|
|
||||||
transport device. */
|
|
||||||
unsigned int bai;
|
unsigned int bai;
|
||||||
unsigned short id_vendor;
|
unsigned short id_vendor;
|
||||||
unsigned short id_product;
|
unsigned short id_product;
|
||||||
@ -329,20 +309,6 @@ set_msg_len (unsigned char *msg, unsigned int length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
my_sleep (int seconds)
|
|
||||||
{
|
|
||||||
#ifdef USE_NPTH
|
|
||||||
npth_sleep (seconds);
|
|
||||||
#else
|
|
||||||
# ifdef HAVE_W32_SYSTEM
|
|
||||||
Sleep (seconds*1000);
|
|
||||||
# else
|
|
||||||
sleep (seconds);
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_progress (ccid_driver_t handle)
|
print_progress (ccid_driver_t handle)
|
||||||
{
|
{
|
||||||
@ -717,31 +683,6 @@ print_r2p_unknown (const unsigned char *msg, size_t msglen)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Given a handle used for special transport prepare it for use. In
|
|
||||||
particular setup all information in way that resembles what
|
|
||||||
parse_cccid_descriptor does. */
|
|
||||||
static void
|
|
||||||
prepare_special_transport (ccid_driver_t handle)
|
|
||||||
{
|
|
||||||
assert (!handle->id_vendor);
|
|
||||||
|
|
||||||
handle->nonnull_nad = 0;
|
|
||||||
handle->auto_ifsd = 0;
|
|
||||||
handle->max_ifsd = 32;
|
|
||||||
handle->max_ccid_msglen = CCID_MAX_BUF;
|
|
||||||
handle->has_pinpad = 0;
|
|
||||||
handle->apdu_level = 0;
|
|
||||||
switch (handle->id_product)
|
|
||||||
{
|
|
||||||
case TRANSPORT_CM4040:
|
|
||||||
DEBUGOUT ("setting up transport for CardMan 4040\n");
|
|
||||||
handle->apdu_level = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: assert (!"transport not defined");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Parse a CCID descriptor, optionally print all available features
|
/* Parse a CCID descriptor, optionally print all available features
|
||||||
and test whether this reader is usable by this driver. Returns 0
|
and test whether this reader is usable by this driver. Returns 0
|
||||||
if it is usable.
|
if it is usable.
|
||||||
@ -1328,7 +1269,6 @@ ccid_vendor_specific_init (ccid_driver_t handle)
|
|||||||
|
|
||||||
struct ccid_dev_table {
|
struct ccid_dev_table {
|
||||||
int n; /* Index to ccid_usb_dev_list */
|
int n; /* Index to ccid_usb_dev_list */
|
||||||
int transport;
|
|
||||||
int interface_number;
|
int interface_number;
|
||||||
int setting_number;
|
int setting_number;
|
||||||
unsigned char *ifcdesc_extra;
|
unsigned char *ifcdesc_extra;
|
||||||
@ -1407,7 +1347,6 @@ ccid_dev_scan (int *idx_max_p, struct ccid_dev_table **t_p)
|
|||||||
}
|
}
|
||||||
memcpy (ifcdesc_extra, ifcdesc->extra, ifcdesc->extra_length);
|
memcpy (ifcdesc_extra, ifcdesc->extra, ifcdesc->extra_length);
|
||||||
|
|
||||||
ccid_dev_table[idx].transport = TRANSPORT_USB;
|
|
||||||
ccid_dev_table[idx].n = i;
|
ccid_dev_table[idx].n = i;
|
||||||
ccid_dev_table[idx].interface_number = ifc_no;
|
ccid_dev_table[idx].interface_number = ifc_no;
|
||||||
ccid_dev_table[idx].setting_number = set_no;
|
ccid_dev_table[idx].setting_number = set_no;
|
||||||
@ -1430,30 +1369,6 @@ ccid_dev_scan (int *idx_max_p, struct ccid_dev_table **t_p)
|
|||||||
libusb_free_config_descriptor (config);
|
libusb_free_config_descriptor (config);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now check whether there are any devices with special transport types. */
|
|
||||||
for (i=0; transports[i].name; i++)
|
|
||||||
{
|
|
||||||
if (access (transports[i].name, (R_OK|W_OK)) == 0)
|
|
||||||
{
|
|
||||||
/* Found a device. */
|
|
||||||
DEBUGOUT_1 ("Found CCID reader %d\n", idx);
|
|
||||||
|
|
||||||
ccid_dev_table[idx].transport = TRANSPORT_CM4040;
|
|
||||||
ccid_dev_table[idx].n = i;
|
|
||||||
ccid_dev_table[idx].interface_number = 0;
|
|
||||||
ccid_dev_table[idx].setting_number = 0;
|
|
||||||
ccid_dev_table[idx].ifcdesc_extra = NULL;
|
|
||||||
ccid_dev_table[idx].ifcdesc_extra_len = 0;
|
|
||||||
ccid_dev_table[idx].ep_bulk_out = 0;
|
|
||||||
ccid_dev_table[idx].ep_bulk_in = 0;
|
|
||||||
ccid_dev_table[idx].ep_intr = 0;
|
|
||||||
|
|
||||||
idx++;
|
|
||||||
if (idx >= MAX_DEVICE)
|
|
||||||
goto scan_finish;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
scan_finish:
|
scan_finish:
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
@ -1463,7 +1378,6 @@ ccid_dev_scan (int *idx_max_p, struct ccid_dev_table **t_p)
|
|||||||
for (i = 0; i < idx; i++)
|
for (i = 0; i < idx; i++)
|
||||||
{
|
{
|
||||||
free (ccid_dev_table[idx].ifcdesc_extra);
|
free (ccid_dev_table[idx].ifcdesc_extra);
|
||||||
ccid_dev_table[idx].transport = 0;
|
|
||||||
ccid_dev_table[idx].n = 0;
|
ccid_dev_table[idx].n = 0;
|
||||||
ccid_dev_table[idx].interface_number = 0;
|
ccid_dev_table[idx].interface_number = 0;
|
||||||
ccid_dev_table[idx].setting_number = 0;
|
ccid_dev_table[idx].setting_number = 0;
|
||||||
@ -1496,7 +1410,6 @@ ccid_dev_scan_finish (struct ccid_dev_table *tbl, int max)
|
|||||||
for (i = 0; i < max; i++)
|
for (i = 0; i < max; i++)
|
||||||
{
|
{
|
||||||
free (tbl[i].ifcdesc_extra);
|
free (tbl[i].ifcdesc_extra);
|
||||||
tbl[i].transport = 0;
|
|
||||||
tbl[i].n = 0;
|
tbl[i].n = 0;
|
||||||
tbl[i].interface_number = 0;
|
tbl[i].interface_number = 0;
|
||||||
tbl[i].setting_number = 0;
|
tbl[i].setting_number = 0;
|
||||||
@ -1516,9 +1429,6 @@ ccid_get_BAI (int idx, struct ccid_dev_table *tbl)
|
|||||||
int n;
|
int n;
|
||||||
int bus, addr, intf;
|
int bus, addr, intf;
|
||||||
unsigned int bai;
|
unsigned int bai;
|
||||||
|
|
||||||
if (tbl[idx].transport == TRANSPORT_USB)
|
|
||||||
{
|
|
||||||
libusb_device *dev;
|
libusb_device *dev;
|
||||||
|
|
||||||
n = tbl[idx].n;
|
n = tbl[idx].n;
|
||||||
@ -1528,12 +1438,6 @@ ccid_get_BAI (int idx, struct ccid_dev_table *tbl)
|
|||||||
addr = libusb_get_device_address (dev);
|
addr = libusb_get_device_address (dev);
|
||||||
intf = tbl[idx].interface_number;
|
intf = tbl[idx].interface_number;
|
||||||
bai = (bus << 16) | (addr << 8) | intf;
|
bai = (bus << 16) | (addr << 8) | intf;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
n = tbl[idx].n;
|
|
||||||
bai = 0xFFFF0000 | n;
|
|
||||||
}
|
|
||||||
|
|
||||||
return bai;
|
return bai;
|
||||||
}
|
}
|
||||||
@ -1710,7 +1614,6 @@ ccid_open_usb_reader (const char *spec_reader_name,
|
|||||||
(*handle)->id_vendor = desc.idVendor;
|
(*handle)->id_vendor = desc.idVendor;
|
||||||
(*handle)->id_product = desc.idProduct;
|
(*handle)->id_product = desc.idProduct;
|
||||||
(*handle)->idev = idev;
|
(*handle)->idev = idev;
|
||||||
(*handle)->dev_fd = -1;
|
|
||||||
(*handle)->bai = bai;
|
(*handle)->bai = bai;
|
||||||
(*handle)->ifc_no = ifc_no;
|
(*handle)->ifc_no = ifc_no;
|
||||||
(*handle)->ep_bulk_out = ccid_table[idx].ep_bulk_out;
|
(*handle)->ep_bulk_out = ccid_table[idx].ep_bulk_out;
|
||||||
@ -1779,10 +1682,6 @@ ccid_open_reader (const char *spec_reader_name, int idx,
|
|||||||
struct ccid_dev_table *ccid_table,
|
struct ccid_dev_table *ccid_table,
|
||||||
ccid_driver_t *handle, char **rdrname_p)
|
ccid_driver_t *handle, char **rdrname_p)
|
||||||
{
|
{
|
||||||
int n;
|
|
||||||
int fd;
|
|
||||||
char *rid;
|
|
||||||
|
|
||||||
*handle = calloc (1, sizeof **handle);
|
*handle = calloc (1, sizeof **handle);
|
||||||
if (!*handle)
|
if (!*handle)
|
||||||
{
|
{
|
||||||
@ -1790,58 +1689,8 @@ ccid_open_reader (const char *spec_reader_name, int idx,
|
|||||||
return CCID_DRIVER_ERR_OUT_OF_CORE;
|
return CCID_DRIVER_ERR_OUT_OF_CORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ccid_table[idx].transport == TRANSPORT_USB)
|
|
||||||
return ccid_open_usb_reader (spec_reader_name, idx, ccid_table,
|
return ccid_open_usb_reader (spec_reader_name, idx, ccid_table,
|
||||||
handle, rdrname_p);
|
handle, rdrname_p);
|
||||||
|
|
||||||
/* Special transport support. */
|
|
||||||
|
|
||||||
n = ccid_table[idx].n;
|
|
||||||
fd = open (transports[n].name, O_RDWR);
|
|
||||||
if (fd < 0)
|
|
||||||
{
|
|
||||||
DEBUGOUT_2 ("failed to open '%s': %s\n",
|
|
||||||
transports[n].name, strerror (errno));
|
|
||||||
free (*handle);
|
|
||||||
*handle = NULL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
rid = malloc (strlen (transports[n].name) + 30 + 10);
|
|
||||||
if (!rid)
|
|
||||||
{
|
|
||||||
close (fd);
|
|
||||||
free (*handle);
|
|
||||||
*handle = NULL;
|
|
||||||
return -1; /* Error. */
|
|
||||||
}
|
|
||||||
|
|
||||||
sprintf (rid, "0000:%04X:%s:0", transports[n].type, transports[n].name);
|
|
||||||
|
|
||||||
/* Check to see if reader name matches the spec. */
|
|
||||||
if (spec_reader_name
|
|
||||||
&& strncmp (rid, spec_reader_name, strlen (spec_reader_name)))
|
|
||||||
{
|
|
||||||
DEBUGOUT ("device not matched\n");
|
|
||||||
free (rid);
|
|
||||||
close (fd);
|
|
||||||
free (*handle);
|
|
||||||
*handle = NULL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
(*handle)->id_vendor = 0;
|
|
||||||
(*handle)->id_product = transports[n].type;
|
|
||||||
(*handle)->idev = NULL;
|
|
||||||
(*handle)->dev_fd = fd;
|
|
||||||
(*handle)->bai = 0xFFFF0000 | n;
|
|
||||||
prepare_special_transport (*handle);
|
|
||||||
if (rdrname_p)
|
|
||||||
*rdrname_p = rid;
|
|
||||||
else
|
|
||||||
free (rid);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1898,8 +1747,7 @@ do_close_reader (ccid_driver_t handle)
|
|||||||
bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_SlotStatus,
|
bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_SlotStatus,
|
||||||
seqno, 2000, 0);
|
seqno, 2000, 0);
|
||||||
}
|
}
|
||||||
if (handle->idev)
|
|
||||||
{
|
|
||||||
if (handle->transfer)
|
if (handle->transfer)
|
||||||
{
|
{
|
||||||
if (!handle->powered_off)
|
if (!handle->powered_off)
|
||||||
@ -1928,12 +1776,6 @@ do_close_reader (ccid_driver_t handle)
|
|||||||
libusb_close (handle->idev);
|
libusb_close (handle->idev);
|
||||||
handle->idev = NULL;
|
handle->idev = NULL;
|
||||||
}
|
}
|
||||||
if (handle->dev_fd != -1)
|
|
||||||
{
|
|
||||||
close (handle->dev_fd);
|
|
||||||
handle->dev_fd = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -1954,7 +1796,7 @@ ccid_set_progress_cb (ccid_driver_t handle,
|
|||||||
int
|
int
|
||||||
ccid_close_reader (ccid_driver_t handle)
|
ccid_close_reader (ccid_driver_t handle)
|
||||||
{
|
{
|
||||||
if (!handle || (!handle->idev && handle->dev_fd == -1))
|
if (!handle)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
do_close_reader (handle);
|
do_close_reader (handle);
|
||||||
@ -1972,31 +1814,6 @@ ccid_check_card_presence (ccid_driver_t handle)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Write NBYTES of BUF to file descriptor FD. */
|
|
||||||
static int
|
|
||||||
writen (int fd, const void *buf, size_t nbytes)
|
|
||||||
{
|
|
||||||
size_t nleft = nbytes;
|
|
||||||
int nwritten;
|
|
||||||
|
|
||||||
while (nleft > 0)
|
|
||||||
{
|
|
||||||
nwritten = write (fd, buf, nleft);
|
|
||||||
if (nwritten < 0)
|
|
||||||
{
|
|
||||||
if (errno == EINTR)
|
|
||||||
nwritten = 0;
|
|
||||||
else
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
nleft -= nwritten;
|
|
||||||
buf = (const char*)buf + nwritten;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Write a MSG of length MSGLEN to the designated bulk out endpoint.
|
/* Write a MSG of length MSGLEN to the designated bulk out endpoint.
|
||||||
Returns 0 on success. */
|
Returns 0 on success. */
|
||||||
static int
|
static int
|
||||||
@ -2004,6 +1821,7 @@ bulk_out (ccid_driver_t handle, unsigned char *msg, size_t msglen,
|
|||||||
int no_debug)
|
int no_debug)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
int transferred;
|
||||||
|
|
||||||
/* No need to continue and clutter the log with USB write error
|
/* No need to continue and clutter the log with USB write error
|
||||||
messages after we got the first ENODEV. */
|
messages after we got the first ENODEV. */
|
||||||
@ -2062,10 +1880,6 @@ bulk_out (ccid_driver_t handle, unsigned char *msg, size_t msglen,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handle->idev)
|
|
||||||
{
|
|
||||||
int transferred;
|
|
||||||
|
|
||||||
#ifdef USE_NPTH
|
#ifdef USE_NPTH
|
||||||
npth_unprotect ();
|
npth_unprotect ();
|
||||||
#endif
|
#endif
|
||||||
@ -2087,17 +1901,8 @@ bulk_out (ccid_driver_t handle, unsigned char *msg, size_t msglen,
|
|||||||
return CCID_DRIVER_ERR_NO_READER;
|
return CCID_DRIVER_ERR_NO_READER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rc = writen (handle->dev_fd, msg, msglen);
|
|
||||||
if (!rc)
|
|
||||||
return 0;
|
|
||||||
DEBUGOUT_2 ("writen to %d failed: %s\n",
|
|
||||||
handle->dev_fd, strerror (errno));
|
|
||||||
|
|
||||||
}
|
return 0;
|
||||||
return CCID_DRIVER_ERR_CARD_IO_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2115,14 +1920,12 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
|
|||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
int msglen;
|
int msglen;
|
||||||
int eagain_retries = 0;
|
|
||||||
|
|
||||||
/* Fixme: The next line for the current Valgrind without support
|
/* Fixme: The next line for the current Valgrind without support
|
||||||
for USB IOCTLs. */
|
for USB IOCTLs. */
|
||||||
memset (buffer, 0, length);
|
memset (buffer, 0, length);
|
||||||
retry:
|
retry:
|
||||||
if (handle->idev)
|
|
||||||
{
|
|
||||||
#ifdef USE_NPTH
|
#ifdef USE_NPTH
|
||||||
npth_unprotect ();
|
npth_unprotect ();
|
||||||
#endif
|
#endif
|
||||||
@ -2145,25 +1948,6 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
|
|||||||
if (msglen < 0)
|
if (msglen < 0)
|
||||||
return CCID_DRIVER_ERR_INV_VALUE; /* Faulty libusb. */
|
return CCID_DRIVER_ERR_INV_VALUE; /* Faulty libusb. */
|
||||||
*nread = msglen;
|
*nread = msglen;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rc = read (handle->dev_fd, buffer, length);
|
|
||||||
if (rc < 0)
|
|
||||||
{
|
|
||||||
rc = errno;
|
|
||||||
DEBUGOUT_2 ("read from %d failed: %s\n",
|
|
||||||
handle->dev_fd, strerror (rc));
|
|
||||||
if (rc == EAGAIN && eagain_retries++ < 5)
|
|
||||||
{
|
|
||||||
my_sleep (1);
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
return CCID_DRIVER_ERR_CARD_IO_ERROR;
|
|
||||||
}
|
|
||||||
*nread = msglen = rc;
|
|
||||||
}
|
|
||||||
eagain_retries = 0;
|
|
||||||
|
|
||||||
if (msglen < 10)
|
if (msglen < 10)
|
||||||
{
|
{
|
||||||
@ -2254,12 +2038,6 @@ abort_cmd (ccid_driver_t handle, int seqno)
|
|||||||
unsigned char msg[100];
|
unsigned char msg[100];
|
||||||
int msglen;
|
int msglen;
|
||||||
|
|
||||||
if (!handle->idev)
|
|
||||||
{
|
|
||||||
/* I don't know how to send an abort to non-USB devices. */
|
|
||||||
return CCID_DRIVER_ERR_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
seqno &= 0xff;
|
seqno &= 0xff;
|
||||||
DEBUGOUT_1 ("sending abort sequence for seqno %d\n", seqno);
|
DEBUGOUT_1 ("sending abort sequence for seqno %d\n", seqno);
|
||||||
/* Send the abort command to the control pipe. Note that we don't
|
/* Send the abort command to the control pipe. Note that we don't
|
||||||
@ -2445,16 +2223,11 @@ ccid_poll (ccid_driver_t handle)
|
|||||||
int msglen;
|
int msglen;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
if (handle->idev)
|
|
||||||
{
|
|
||||||
rc = libusb_interrupt_transfer (handle->idev, handle->ep_intr,
|
rc = libusb_interrupt_transfer (handle->idev, handle->ep_intr,
|
||||||
(char*)msg, sizeof msg, &msglen,
|
(char*)msg, sizeof msg, &msglen,
|
||||||
0 /* ms timeout */ );
|
0 /* ms timeout */ );
|
||||||
if (rc == LIBUSB_ERROR_TIMEOUT)
|
if (rc == LIBUSB_ERROR_TIMEOUT)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
@ -3187,8 +2960,7 @@ ccid_transceive (ccid_driver_t handle,
|
|||||||
ccid_transceive_secure which leads to a loss of sync on the
|
ccid_transceive_secure which leads to a loss of sync on the
|
||||||
CCID level. If Cherry wants to make their keyboard work
|
CCID level. If Cherry wants to make their keyboard work
|
||||||
again, they should hand over some docs. */
|
again, they should hand over some docs. */
|
||||||
if ((handle->id_vendor == VENDOR_OMNIKEY
|
if ((handle->id_vendor == VENDOR_OMNIKEY)
|
||||||
|| (!handle->idev && handle->id_product == TRANSPORT_CM4040))
|
|
||||||
&& handle->apdu_level < 2
|
&& handle->apdu_level < 2
|
||||||
&& is_exlen_apdu (apdu_buf, apdu_buflen))
|
&& is_exlen_apdu (apdu_buf, apdu_buflen))
|
||||||
via_escape = 1;
|
via_escape = 1;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user