/***************************************************************************** * * WriteUSB * ****************************************************************************/ status_t WriteUSB(unsigned int reader_index, unsigned int length, unsigned char *buffer) { int rv; int actual_length; char debug_header[] = "-> 121234 "; (void)snprintf(debug_header, sizeof(debug_header), "-> %06X ", (int)reader_index); DEBUG_XXD(debug_header, buffer, length); rv = libusb_bulk_transfer(usbDevice[reader_index].dev_handle, usbDevice[reader_index].bulk_out, buffer, length, &actual_length, USB_WRITE_TIMEOUT); if (rv < 0) { DEBUG_CRITICAL5("write failed (%d/%d): %d %s", usbDevice[reader_index].bus_number, usbDevice[reader_index].device_address, rv, strerror(errno)); if (ENODEV == errno) return STATUS_NO_SUCH_DEVICE; return STATUS_UNSUCCESSFUL; } return STATUS_SUCCESS; } /* WriteUSB */
/***************************************************************************** * * WriteUSB * ****************************************************************************/ status_t WriteUSB(unsigned int reader_index, unsigned int length, unsigned char *buffer) { int rv; char debug_header[] = "-> 121234 "; (void)snprintf(debug_header, sizeof(debug_header), "-> %06X ", (int)reader_index); DEBUG_XXD(debug_header, buffer, length); rv = usb_bulk_write(usbDevice[reader_index].handle, usbDevice[reader_index].bulk_out, (char *)buffer, length, USB_WRITE_TIMEOUT); if (rv < 0) { DEBUG_CRITICAL4("usb_bulk_write(%s/%s): %s", usbDevice[reader_index].dirname, usbDevice[reader_index].filename, strerror(errno)); if (ENODEV == errno) return STATUS_NO_SUCH_DEVICE; return STATUS_UNSUCCESSFUL; } return STATUS_SUCCESS; } /* WriteUSB */
/***************************************************************************** * * WriteUSB * ****************************************************************************/ status_t WriteUSB(unsigned int reader_index, unsigned int length, unsigned char *buffer) { int rv; char debug_header[] = "-> 121234 "; int pos; int len; int delayed = FALSE; (void)snprintf(debug_header, sizeof(debug_header), "-> %06X ", (int)reader_index); DEBUG_XXD(debug_header, buffer, length); // Fix APG8201 and ACR85 ICC cannot receive command properly // Add delay for APG8201 and ACR85 ICC if ((usbDevice[reader_index].ccid.readerID == ACS_APG8201) || (usbDevice[reader_index].ccid.readerID == ACS_ACR85_PINPAD_READER_ICC)) { delayed = TRUE; } // Send command by dividing number of packets pos = 0; while (length > 0) { if (length > usbDevice[reader_index].bulkOutMaxPacketSize) len = usbDevice[reader_index].bulkOutMaxPacketSize; else len = length; rv = usb_bulk_write(usbDevice[reader_index].handle, usbDevice[reader_index].bulk_out, (char *)buffer + pos, len, USB_WRITE_TIMEOUT); if (rv < 0) { DEBUG_CRITICAL4("usb_bulk_write(%s/%s): %s", usbDevice[reader_index].dirname, usbDevice[reader_index].filename, strerror(errno)); if (ENODEV == errno) return STATUS_NO_SUCH_DEVICE; return STATUS_UNSUCCESSFUL; } if (delayed) { // Delay 10 ms if (length > usbDevice[reader_index].bulkOutMaxPacketSize) usleep(10 * 1000); } pos += len; length -= len; } return STATUS_SUCCESS; } /* WriteUSB */
int PPS_Exchange (int lun, BYTE * params, unsigned *length, unsigned char *pps1) { BYTE confirm[PPS_MAX_LENGTH]; unsigned len_request, len_confirm; int ret; len_request = PPS_GetLength (params); params[len_request - 1] = PPS_GetPCK(params, len_request - 1); DEBUG_XXD ("PPS: Sending request: ", params, len_request); /* Send PPS request */ if (CCID_Transmit (lun, len_request, params, isCharLevel(lun) ? 4 : 0, 0) != IFD_SUCCESS) return PPS_ICC_ERROR; /* Get PPS confirm */ len_confirm = sizeof(confirm); if (CCID_Receive (lun, &len_confirm, confirm, NULL) != IFD_SUCCESS) return PPS_ICC_ERROR; DEBUG_XXD ("PPS: Receiving confirm: ", confirm, len_confirm); if (!PPS_Match (params, len_request, confirm, len_confirm)) ret = PPS_HANDSAKE_ERROR; else ret = PPS_OK; *pps1 = 0x11; /* default TA1 */ /* if PPS1 is echoed */ if (PPS_HAS_PPS1 (params) && PPS_HAS_PPS1 (confirm)) *pps1 = confirm[2]; /* Copy PPS handsake */ memcpy (params, confirm, len_confirm); (*length) = len_confirm; return ret; }
/***************************************************************************** * * ReadChunk: read a minimum number of bytes * *****************************************************************************/ static int ReadChunk(unsigned int reader_index, unsigned char *buffer, int buffer_length, int min_length) { int fd = serialDevice[reader_index].fd; # ifndef S_SPLINT_S fd_set fdset; # endif struct timeval t; int i, rv = 0; int already_read; char debug_header[] = "<- 123456 "; (void)snprintf(debug_header, sizeof(debug_header), "<- %06X ", reader_index); already_read = 0; while (already_read < min_length) { /* use select() to, eventually, timeout */ FD_ZERO(&fdset); FD_SET(fd, &fdset); t.tv_sec = serialDevice[reader_index].ccid.readTimeout / 1000; t.tv_usec = (serialDevice[reader_index].ccid.readTimeout - t.tv_sec*1000)*1000; i = select(fd+1, &fdset, NULL, NULL, &t); if (i == -1) { DEBUG_CRITICAL2("select: %s", strerror(errno)); return -1; } else if (i == 0) { DEBUG_COMM2("Timeout! (%d ms)", serialDevice[reader_index].ccid.readTimeout); return -1; } rv = read(fd, buffer + already_read, buffer_length - already_read); if (rv < 0) { DEBUG_COMM2("read error: %s", strerror(errno)); return -1; } DEBUG_XXD(debug_header, buffer + already_read, rv); already_read += rv; DEBUG_COMM3("read: %d, to read: %d", already_read, min_length); } return already_read; } /* ReadChunk */
/***************************************************************************** * * ReadUSB * ****************************************************************************/ status_t ReadUSB(unsigned int reader_index, unsigned int * length, unsigned char *buffer) { int rv; int actual_length; char debug_header[] = "<- 121234 "; _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index); int duplicate_frame = 0; read_again: (void)snprintf(debug_header, sizeof(debug_header), "<- %06X ", (int)reader_index); rv = libusb_bulk_transfer(usbDevice[reader_index].dev_handle, usbDevice[reader_index].bulk_in, buffer, *length, &actual_length, usbDevice[reader_index].ccid.readTimeout); if (rv < 0) { *length = 0; DEBUG_CRITICAL5("read failed (%d/%d): %d %s", usbDevice[reader_index].bus_number, usbDevice[reader_index].device_address, rv, strerror(errno)); if (ENODEV == errno) return STATUS_NO_SUCH_DEVICE; return STATUS_UNSUCCESSFUL; } *length = actual_length; DEBUG_XXD(debug_header, buffer, *length); #define BSEQ_OFFSET 6 if ((*length >= BSEQ_OFFSET) && (buffer[BSEQ_OFFSET] < *ccid_descriptor->pbSeq -1)) { duplicate_frame++; if (duplicate_frame > 10) { DEBUG_CRITICAL("Too many duplicate frame detected"); return STATUS_UNSUCCESSFUL; } DEBUG_INFO("Duplicate frame detected"); goto read_again; } return STATUS_SUCCESS; } /* ReadUSB */
/***************************************************************************** * * ReadUSB * ****************************************************************************/ status_t ReadUSB(unsigned int reader_index, unsigned int * length, unsigned char *buffer) { int rv; char debug_header[] = "<- 121234 "; _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index); int duplicate_frame = 0; read_again: (void)snprintf(debug_header, sizeof(debug_header), "<- %06X ", (int)reader_index); rv = usb_bulk_read(usbDevice[reader_index].handle, usbDevice[reader_index].bulk_in, (char *)buffer, *length, usbDevice[reader_index].ccid.readTimeout * 1000); if (rv < 0) { *length = 0; DEBUG_CRITICAL4("usb_bulk_read(%s/%s): %s", usbDevice[reader_index].dirname, usbDevice[reader_index].filename, strerror(errno)); if (ENODEV == errno) return STATUS_NO_SUCH_DEVICE; return STATUS_UNSUCCESSFUL; } *length = rv; DEBUG_XXD(debug_header, buffer, *length); #define BSEQ_OFFSET 6 if ((*length >= BSEQ_OFFSET) && (buffer[BSEQ_OFFSET] < *ccid_descriptor->pbSeq -1)) { duplicate_frame++; if (duplicate_frame > 10) { DEBUG_CRITICAL("Too many duplicate frame detected"); return STATUS_UNSUCCESSFUL; } DEBUG_INFO("Duplicate frame detected"); goto read_again; } return STATUS_SUCCESS; } /* ReadUSB */
/***************************************************************************** * * WriteSerial: Send bytes to the card reader * *****************************************************************************/ status_t WriteSerial(unsigned int reader_index, unsigned int length, unsigned char *buffer) { unsigned int i; unsigned char lrc; unsigned char low_level_buffer[GEMPCTWIN_MAXBUF]; char debug_header[] = "-> 123456 "; (void)snprintf(debug_header, sizeof(debug_header), "-> %06X ", reader_index); if (length > GEMPCTWIN_MAXBUF-3) { DEBUG_CRITICAL3("command too long: %d for max %d", length, GEMPCTWIN_MAXBUF-3); return STATUS_UNSUCCESSFUL; } /* header */ low_level_buffer[0] = 0x03; /* SYNC */ low_level_buffer[1] = 0x06; /* ACK */ /* CCID command */ memcpy(low_level_buffer+2, buffer, length); /* checksum */ lrc = 0; for(i=0; i<length+2; i++) lrc ^= low_level_buffer[i]; low_level_buffer[length+2] = lrc; DEBUG_XXD(debug_header, low_level_buffer, length+3); if (write(serialDevice[reader_index].fd, low_level_buffer, length+3) != length+3) { DEBUG_CRITICAL2("write error: %s", strerror(errno)); return STATUS_UNSUCCESSFUL; } return STATUS_SUCCESS; } /* WriteSerial */
/***************************************************************************** * * WriteUSB * ****************************************************************************/ status_t WriteUSB(unsigned int reader_index, unsigned int length, unsigned char *buffer) { int rv; int actual_length; char debug_header[] = "-> 121234 "; (void)snprintf(debug_header, sizeof(debug_header), "-> %06X ", (int)reader_index); if (usbDevice[reader_index].ccid.zlp) { /* Zero Length Packet */ int dummy_length; /* try to read a ZLP so transfer length = 0 * timeout of 1 ms */ (void)libusb_bulk_transfer(usbDevice[reader_index].dev_handle, usbDevice[reader_index].bulk_in, NULL, 0, &dummy_length, 1); } DEBUG_XXD(debug_header, buffer, length); rv = libusb_bulk_transfer(usbDevice[reader_index].dev_handle, usbDevice[reader_index].bulk_out, buffer, length, &actual_length, USB_WRITE_TIMEOUT); if (rv < 0) { DEBUG_CRITICAL5("write failed (%d/%d): %d %s", usbDevice[reader_index].bus_number, usbDevice[reader_index].device_address, rv, strerror(errno)); if ((ENODEV == errno) || (LIBUSB_ERROR_NO_DEVICE == rv)) return STATUS_NO_SUCH_DEVICE; return STATUS_UNSUCCESSFUL; } return STATUS_SUCCESS; } /* WriteUSB */
/***************************************************************************** * * ReadSerial: Receive bytes from the card reader * *****************************************************************************/ status_t ReadSerial(unsigned int reader_index, unsigned int *length, unsigned char *buffer) { unsigned char c; int rv; int echo; int to_read; int i; /* we get the echo first */ echo = serialDevice[reader_index].echo; start: DEBUG_COMM("start"); if ((rv = get_bytes(reader_index, &c, 1)) != STATUS_SUCCESS) return rv; if (c == RDR_to_PC_NotifySlotChange) goto slot_change; if (c == SYNC) goto sync; if (c >= 0x80) { DEBUG_COMM2("time request: 0x%02X", c); goto start; } DEBUG_CRITICAL2("Got 0x%02X", c); return STATUS_COMM_ERROR; slot_change: DEBUG_COMM("slot change"); if ((rv = get_bytes(reader_index, &c, 1)) != STATUS_SUCCESS) return rv; if (c == CARD_ABSENT) { DEBUG_COMM("Card removed"); } else if (c == CARD_PRESENT) { DEBUG_COMM("Card inserted"); } else { DEBUG_COMM2("Unknown card movement: %d", c); } goto start; sync: DEBUG_COMM("sync"); if ((rv = get_bytes(reader_index, &c, 1)) != STATUS_SUCCESS) return rv; if (c == CTRL_ACK) goto ack; if (c == CTRL_NAK) goto nak; DEBUG_CRITICAL2("Got 0x%02X instead of ACK/NAK", c); return STATUS_COMM_ERROR; nak: DEBUG_COMM("nak"); if ((rv = get_bytes(reader_index, &c, 1)) != STATUS_SUCCESS) return rv; if (c != (SYNC ^ CTRL_NAK)) { DEBUG_CRITICAL2("Wrong LRC: 0x%02X", c); return STATUS_COMM_ERROR; } else { DEBUG_COMM("NAK requested"); return STATUS_COMM_NAK; } ack: DEBUG_COMM("ack"); /* normal CCID frame */ if ((rv = get_bytes(reader_index, buffer, 5)) != STATUS_SUCCESS) return rv; /* total frame size */ to_read = 10+dw2i(buffer, 1); if ((to_read < 10) || (to_read > (int)*length)) { DEBUG_CRITICAL2("Wrong value for frame size: %d", to_read); return STATUS_COMM_ERROR; } DEBUG_COMM2("frame size: %d", to_read); if ((rv = get_bytes(reader_index, buffer+5, to_read-5)) != STATUS_SUCCESS) return rv; DEBUG_XXD("frame: ", buffer, to_read); /* lrc */ DEBUG_COMM("lrc"); if ((rv = get_bytes(reader_index, &c, 1)) != STATUS_SUCCESS) return rv; DEBUG_COMM2("lrc: 0x%02X", c); for (i=0; i<to_read; i++) c ^= buffer[i]; if (c != (SYNC ^ CTRL_ACK)) DEBUG_CRITICAL2("Wrong LRC: 0x%02X", c); if (echo) { echo = FALSE; goto start; } /* length of data read */ *length = to_read; return STATUS_SUCCESS; } /* ReadSerial */
/* * Send/receive block */ static int t1_xcv(t1_state_t * t1, unsigned char *block, size_t slen, size_t rmax) { int n, m; _ccid_descriptor *ccid_desc ; int oldReadTimeout; unsigned int rmax_int; DEBUG_XXD("sending: ", block, slen); ccid_desc = get_ccid_descriptor(t1->lun); oldReadTimeout = ccid_desc->readTimeout; if (t1->wtx > 1) { /* set the new temporary timeout at WTX card request */ ccid_desc->readTimeout *= t1->wtx; DEBUG_INFO2("New timeout at WTX request: %d sec", ccid_desc->readTimeout); } if (isCharLevel(t1->lun)) { rmax = 3; n = CCID_Transmit(t1 -> lun, slen, block, rmax, t1->wtx); if (n != IFD_SUCCESS) return n; /* the second argument of CCID_Receive() is (unsigned int *) * so we can't use &rmax since &rmax is a (size_t *) and may not * be the same on 64-bits architectures for example (iMac G5) */ rmax_int = rmax; n = CCID_Receive(t1 -> lun, &rmax_int, block, NULL); rmax = rmax_int; if (n == IFD_PARITY_ERROR) return -2; if (n != IFD_SUCCESS) return -1; rmax = block[2] + 1; n = CCID_Transmit(t1 -> lun, 0, block, rmax, t1->wtx); if (n != IFD_SUCCESS) return n; rmax_int = rmax; n = CCID_Receive(t1 -> lun, &rmax_int, &block[3], NULL); rmax = rmax_int; if (n == IFD_PARITY_ERROR) return -2; if (n != IFD_SUCCESS) return -1; n = rmax + 3; } else { n = CCID_Transmit(t1 -> lun, slen, block, 0, t1->wtx); t1->wtx = 0; /* reset to default value */ if (n != IFD_SUCCESS) return n; /* Get the response en bloc */ rmax_int = rmax; n = CCID_Receive(t1 -> lun, &rmax_int, block, NULL); rmax = rmax_int; if (n == IFD_PARITY_ERROR) return -2; if (n != IFD_SUCCESS) return -1; n = rmax; } if (n >= 0) { m = block[2] + 3 + t1->rc_bytes; if (m < n) n = m; } if (n >= 0) DEBUG_XXD("received: ", block, n); /* Restore initial timeout */ ccid_desc->readTimeout = oldReadTimeout; return n; }