00001
00002
00003
00004
00005
00006
00007
00008
00009 #include <ccid.h>
00010
00011 #include <stdarg.h>
00012
00013 #include "ccid-internal.h"
00014
00015 static size_t x_rbuflen(struct _xfr *xfr)
00016 {
00017 return xfr->x_rxmax + sizeof(struct ccid_msg);
00018 }
00019 static size_t x_tbuflen(struct _xfr *xfr)
00020 {
00021 return xfr->x_txlen + sizeof(struct ccid_msg);
00022 }
00023
00024 int _cci_wait_for_interrupt(struct _cci *cci)
00025 {
00026 const uint8_t *buf;
00027 int ret;
00028 size_t len;
00029
00030 if ( libusb_interrupt_transfer(cci->cci_dev, cci->cci_intrp,
00031 (void *)cci->cci_xfr->x_rxhdr,
00032 x_rbuflen(cci->cci_xfr), &ret, 250) )
00033 return 0;
00034
00035 if ( ret == 0 )
00036 return 1;
00037
00038 buf = (void *)cci->cci_xfr->x_rxhdr;
00039 len = (size_t)ret;
00040
00041 trace(cci, " Intr: %u byte interrupt packet\n", len);
00042 if ( len < 1 )
00043 return 1;
00044
00045 switch( buf[0] ) {
00046 case RDR_to_PC_NotifySlotChange:
00047 assert(2 == len);
00048 if ( buf[1] & 0x2 ) {
00049 trace(cci, " : Slot status changed to %s\n",
00050 ((buf[1] & 0x1) == 0) ?
00051 "NOT present" : "present");
00052 cci->cci_slot[0].cc_status =
00053 ((buf[1] & 0x1) == 0) ?
00054 CHIPCARD_NOT_PRESENT :
00055 CHIPCARD_PRESENT;
00056 }
00057 break;
00058 case RDR_to_PC_HardwareError:
00059 trace(cci, " : HALT AND CATCH FIRE!!\n");
00060 break;
00061 default:
00062 fprintf(stderr, "*** error: unknown interrupt packet\n");
00063 break;
00064 }
00065
00066 return 1;
00067 }
00068
00069 unsigned int _RDR_to_PC_DataBlock(struct _cci *cci, struct _xfr *xfr)
00070 {
00071 assert(xfr->x_rxhdr->bMessageType == RDR_to_PC_DataBlock);
00072 trace(cci, " : RDR_to_PC_DataBlock: %u bytes\n", xfr->x_rxlen);
00073 _hex_dumpf(cci->cci_tf, xfr->x_rxbuf, xfr->x_rxlen, 16);
00074
00075 return xfr->x_rxhdr->in.bApp;
00076 }
00077
00078 unsigned int _RDR_to_PC_SlotStatus(struct _cci *cci, struct _xfr *xfr)
00079 {
00080 assert(xfr->x_rxhdr->bMessageType == RDR_to_PC_SlotStatus);
00081
00082 trace(cci, " : RDR_to_PC_SlotStatus: ");
00083 switch( xfr->x_rxhdr->in.bApp ) {
00084 case 0x00:
00085 trace(cci, "Clock running\n");
00086 return CHIPCARD_CLOCK_START;
00087 case 0x01:
00088 trace(cci, "Clock stopped in L state\n");
00089 return CHIPCARD_CLOCK_STOP_L;
00090 case 0x02:
00091 trace(cci, "Clock stopped in H state\n");
00092 return CHIPCARD_CLOCK_STOP_H;
00093 case 0x03:
00094 trace(cci, "Clock stopped in unknown state\n");
00095 return CHIPCARD_CLOCK_STOP;
00096 default:
00097 return CHIPCARD_CLOCK_ERR;
00098 }
00099 }
00100
00101 static int _cmd_result(struct _cci *cci, const struct ccid_msg *msg)
00102 {
00103 switch( msg->in.bStatus & CCID_STATUS_RESULT_MASK ) {
00104 case CCID_RESULT_SUCCESS:
00105 trace(cci, " : Command: SUCCESS\n");
00106 return 1;
00107 case CCID_RESULT_ERROR:
00108 switch ( msg->in.bError ) {
00109 case CCID_ERR_ABORT:
00110 trace(cci, " : Command: ERR: ICC Aborted\n");
00111 break;
00112 case CCID_ERR_MUTE:
00113 trace(cci, " : Command: ERR: ICC Timed Out\n");
00114 break;
00115 case CCID_ERR_PARITY:
00116 trace(cci, " : Command: ERR: ICC Parity Error\n");
00117 break;
00118 case CCID_ERR_OVERRUN:
00119 trace(cci, " : Command: ERR: ICC Buffer Overrun\n");
00120 break;
00121 case CCID_ERR_HARDWARE:
00122 trace(cci, " : Command: ERR: Hardware Error\n");
00123 break;
00124 case CCID_ERR_BAD_TS:
00125 trace(cci, " : Command: ERR: Bad ATR TS\n");
00126 break;
00127 case CCID_ERR_BAD_TCK:
00128 trace(cci, " : Command: ERR: Bad ATR TCK\n");
00129 break;
00130 case CCID_ERR_PROTOCOL:
00131 trace(cci, " : Command: ERR: "
00132 "Unsupported Protocol\n");
00133 break;
00134 case CCID_ERR_CLASS:
00135 trace(cci, " : Command: ERR: Unsupported CLA\n");
00136 break;
00137 case CCID_ERR_PROCEDURE:
00138 trace(cci, " : Command: ERR: "
00139 "Procedure Byte Conflict\n");
00140 break;
00141 case CCID_ERR_DEACTIVATED:
00142 trace(cci, " : Command: ERR: "
00143 "Deactivated Protocl\n");
00144 break;
00145 case CCID_ERR_AUTO_SEQ:
00146 trace(cci, " : Command: ERR: "
00147 "Busy with Auto-Sequencing\n");
00148 break;
00149 case CCID_ERR_PIN_TIMEOUT:
00150 trace(cci, " : Command: ERR: PIN timeout\n");
00151 break;
00152 case CCID_ERR_BUSY:
00153 trace(cci, " : Command: ERR: Slot Busy\n");
00154 break;
00155 case CCID_ERR_USR_MIN ... CCID_ERR_USR_MAX:
00156 trace(cci, " : Command: FAILED (0x%.2x)\n",
00157 msg->in.bError);
00158 break;
00159 default:
00160 trace(cci, " : Command: FAILED (RESERVED 0x%.2x)\n",
00161 msg->in.bError);
00162 break;
00163 }
00164 return 0;
00165 case CCID_RESULT_TIMEOUT:
00166 trace(cci, " : Command: Time Extension Request\n");
00167 return 0;
00168 default:
00169 fprintf(stderr, "*** error: unknown command result\n");
00170 return 0;
00171 }
00172 }
00173
00174 static int do_recv(struct _cci *cci, struct _xfr *xfr)
00175 {
00176 int ret;
00177 size_t len;
00178
00179 if ( libusb_bulk_transfer(cci->cci_dev, cci->cci_inp,
00180 (void *)xfr->x_rxhdr,
00181 x_rbuflen(xfr), &ret, 0) ) {
00182 fprintf(stderr, "*** error: libusb_bulk_read()\n");
00183 return 0;
00184 }
00185
00186 len = (size_t)ret;
00187
00188 if ( len < sizeof(*xfr->x_rxhdr) ) {
00189 fprintf(stderr, "*** error: truncated CCI msg\n");
00190 return 0;
00191 }
00192
00193 if ( sizeof(*xfr->x_rxhdr) + sys_le32(xfr->x_rxhdr->dwLength) > len ) {
00194 fprintf(stderr, "*** error: bad dwLength in CCI msg\n");
00195 return 0;
00196 }
00197
00198 xfr->x_rxlen = sys_le32(xfr->x_rxhdr->dwLength);
00199
00200 return 1;
00201 }
00202
00203 static void _chipcard_set_status(struct _chipcard *cc, unsigned int status)
00204 {
00205 switch( status & CCID_SLOT_STATUS_MASK ) {
00206 case CCID_STATUS_ICC_ACTIVE:
00207 trace(cc->cc_parent, " : ICC present and active\n");
00208 cc->cc_status = CHIPCARD_ACTIVE;
00209 break;
00210 case CCID_STATUS_ICC_PRESENT:
00211 trace(cc->cc_parent, " : ICC present and inactive\n");
00212 cc->cc_status = CHIPCARD_PRESENT;
00213 break;
00214 case CCID_STATUS_ICC_NOT_PRESENT:
00215 trace(cc->cc_parent, " : ICC not presnt\n");
00216 cc->cc_status = CHIPCARD_NOT_PRESENT;
00217 break;
00218 default:
00219 fprintf(stderr, "*** error: unknown chipcard status update\n");
00220 break;
00221 }
00222 }
00223
00224 int _RDR_to_PC(struct _cci *cci, unsigned int slot, struct _xfr *xfr)
00225 {
00226 const struct ccid_msg *msg;
00227 unsigned int try = 10;
00228
00229 again:
00230 if ( !do_recv(cci, xfr) )
00231 return 0;
00232
00233 msg = xfr->x_rxhdr;
00234
00235 trace(cci, " Recv: %d bytes for slot %u (seq = 0x%.2x)\n",
00236 xfr->x_rxlen, msg->bSlot, msg->bSeq);
00237
00238 if ( msg->bSlot != slot ) {
00239 fprintf(stderr, "*** error: bad slot %u (expected %u)\n",
00240 msg->bSlot, slot);
00241 return 0;
00242 }
00243
00244 if ( (uint8_t)(msg->bSeq + 1) != cci->cci_seq ) {
00245 fprintf(stderr, "*** error: expected seq 0x%.2x got 0x%.2x\n",
00246 cci->cci_seq, (uint8_t)(msg->bSeq + 1));
00247 return 0;
00248 }
00249
00250 _chipcard_set_status(&cci->cci_slot[msg->bSlot], msg->in.bStatus);
00251
00252 if ( xfr->x_rxhdr->in.bStatus == CCID_RESULT_TIMEOUT && --try )
00253 goto again;
00254
00255 return _cmd_result(cci, xfr->x_rxhdr);
00256 }
00257
00258 static int _PC_to_RDR(struct _cci *cci, unsigned int slot, struct _xfr *xfr)
00259 {
00260 int ret;
00261 size_t len;
00262
00263 assert(slot < cci->cci_num_slots);
00264
00265 xfr->x_txhdr->dwLength = sys_le32(xfr->x_txlen);
00266 xfr->x_txhdr->bSlot = slot;
00267 xfr->x_txhdr->bSeq = cci->cci_seq++;
00268
00269 if ( libusb_bulk_transfer(cci->cci_dev, cci->cci_outp,
00270 (void *)xfr->x_txhdr,
00271 x_tbuflen(xfr), &ret, 0) ) {
00272 fprintf(stderr, "*** error: libusb_bulk_write()\n");
00273 return 0;
00274 }
00275
00276 len = (size_t)ret;
00277
00278 if ( ret < x_tbuflen(xfr) ) {
00279 fprintf(stderr, "*** error: truncated TX: %u/%u\n",
00280 len, x_tbuflen(xfr));
00281 return 0;
00282 }
00283
00284 return 1;
00285 }
00286
00287 int _PC_to_RDR_XfrBlock(struct _cci *cci, unsigned int slot, struct _xfr *xfr)
00288 {
00289 int ret;
00290
00291 memset(xfr->x_txhdr, 0, sizeof(*xfr->x_txhdr));
00292 xfr->x_txhdr->bMessageType = PC_to_RDR_XfrBlock;
00293 ret = _PC_to_RDR(cci, slot, xfr);
00294 if ( ret ) {
00295 trace(cci, " Xmit: PC_to_RDR_XfrBlock(%u)\n", slot);
00296 _hex_dumpf(cci->cci_tf, xfr->x_txbuf, xfr->x_txlen, 16);
00297 }
00298 return ret;
00299 }
00300
00301 int _PC_to_RDR_GetSlotStatus(struct _cci *cci, unsigned int slot,
00302 struct _xfr *xfr)
00303 {
00304 int ret;
00305
00306 memset(xfr->x_txhdr, 0, sizeof(*xfr->x_txhdr));
00307 xfr->x_txhdr->bMessageType = PC_to_RDR_GetSlotStatus;
00308 ret = _PC_to_RDR(cci, slot, xfr);
00309 if ( ret )
00310 trace(cci, " Xmit: PC_to_RDR_GetSlotStatus(%u)\n", slot);
00311
00312 return ret;
00313 }
00314
00315 int _PC_to_RDR_IccPowerOn(struct _cci *cci, unsigned int slot,
00316 struct _xfr *xfr,
00317 unsigned int voltage)
00318 {
00319 int ret;
00320
00321 assert(voltage <= CHIPCARD_1_8V);
00322
00323 memset(xfr->x_txhdr, 0, sizeof(*xfr->x_txhdr));
00324 xfr->x_txhdr->bMessageType = PC_to_RDR_IccPowerOn;
00325 xfr->x_txhdr->out.bApp[0] = voltage & 0xff;
00326 ret = _PC_to_RDR(cci, slot, xfr);
00327 if ( ret ) {
00328 trace(cci, " Xmit: PC_to_RDR_IccPowerOn(%u)\n", slot);
00329 switch(voltage) {
00330 case CHIPCARD_AUTO_VOLTAGE:
00331 trace(cci, " : Automatic Voltage Selection\n");
00332 break;
00333 case CHIPCARD_5V:
00334 trace(cci, " : 5 Volts\n");
00335 break;
00336 case CHIPCARD_3V:
00337 trace(cci, " : 3 Volts\n");
00338 break;
00339 case CHIPCARD_1_8V:
00340 trace(cci, " : 1.8 Volts\n");
00341 break;
00342 }
00343 }
00344
00345 return ret;
00346 }
00347
00348 int _PC_to_RDR_IccPowerOff(struct _cci *cci, unsigned int slot,
00349 struct _xfr *xfr)
00350 {
00351 int ret;
00352
00353 memset(xfr->x_txhdr, 0, sizeof(*xfr->x_txhdr));
00354 xfr->x_txhdr->bMessageType = PC_to_RDR_IccPowerOff;
00355 ret = _PC_to_RDR(cci, slot, xfr);
00356 if ( ret ) {
00357 trace(cci, " Xmit: PC_to_RDR_IccPowerOff(%u)\n", slot);
00358 }
00359
00360 return ret;
00361 }
00362
00363 static void byteswap_desc(struct ccid_desc *desc)
00364 {
00365 #define _SWAP(field, func) desc->field = func (desc->field)
00366 _SWAP(bcdCCID, sys_le16);
00367 _SWAP(dwProtocols, sys_le32);
00368 _SWAP(dwDefaultClock, sys_le32);
00369 _SWAP(dwMaximumClock, sys_le32);
00370 _SWAP(dwDataRate, sys_le32);
00371 _SWAP(dwMaxDataRate, sys_le32);
00372 _SWAP(dwMaxIFSD, sys_le32);
00373 _SWAP(dwSynchProtocols, sys_le32);
00374 _SWAP(dwMechanical, sys_le32);
00375 _SWAP(dwFeatures, sys_le32);
00376 _SWAP(dwMaxCCIDMessageLength, sys_le32);
00377 _SWAP(wLcdLayout, sys_le16);
00378 #undef _SWAP
00379 }
00380
00381 static unsigned int bcd_hi(uint16_t word)
00382 {
00383 return (((word & 0xf000) >> 12) * 10) + ((word & 0xf00) >> 8);
00384 }
00385
00386 static unsigned int bcd_lo(uint16_t word)
00387 {
00388 return (((word & 0xf0) >> 4) * 10) + (word & 0xf);
00389 }
00390
00391
00392 static int get_endpoint(struct _cci *cci, const uint8_t *ptr, size_t len)
00393 {
00394 const struct libusb_endpoint_descriptor *ep;
00395
00396 if ( len < LIBUSB_DT_ENDPOINT_SIZE )
00397 return 0;
00398
00399 ep = (const struct libusb_endpoint_descriptor *)ptr;
00400
00401 switch( ep->bmAttributes ) {
00402 case LIBUSB_TRANSFER_TYPE_BULK:
00403 trace(cci, " o Bulk %s endpoint at 0x%.2x max=%u bytes\n",
00404 (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) ?
00405 "IN" : "OUT",
00406 ep->bEndpointAddress & LIBUSB_ENDPOINT_ADDRESS_MASK,
00407 sys_le16(ep->wMaxPacketSize));
00408 if ( ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) {
00409 cci->cci_inp = ep->bEndpointAddress;
00410 cci->cci_max_in = sys_le16(ep->wMaxPacketSize);
00411 }else{
00412 cci->cci_outp = ep->bEndpointAddress;
00413 cci->cci_max_out = sys_le16(ep->wMaxPacketSize);
00414 }
00415 break;
00416 case LIBUSB_TRANSFER_TYPE_INTERRUPT:
00417 trace(cci, " o Interrupt %s endpint 0x%.2x nax=%u bytes\n",
00418 (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) ?
00419 "IN" : "OUT",
00420 ep->bEndpointAddress & LIBUSB_ENDPOINT_ADDRESS_MASK,
00421 sys_le16(ep->wMaxPacketSize));
00422 cci->cci_intrp = ep->bEndpointAddress;
00423 cci->cci_max_intr = sys_le16(ep->wMaxPacketSize);
00424 break;
00425 default:
00426 return 0;
00427 }
00428
00429 return 1;
00430 }
00431
00432 static int fill_ccid_desc(struct _cci *cci, const uint8_t *ptr, size_t len)
00433 {
00434 if ( len < sizeof(cci->cci_desc) ) {
00435 fprintf(stderr, "*** error: truncated CCID descriptor\n");
00436 return 0;
00437 }
00438
00439
00440 memcpy(&cci->cci_desc, ptr, sizeof(cci->cci_desc));
00441
00442 byteswap_desc(&cci->cci_desc);
00443
00444 cci->cci_num_slots = cci->cci_desc.bMaxSlotIndex + 1;
00445 cci->cci_max_slots = cci->cci_desc.bMaxCCIDBusySlots;
00446
00447 trace(cci, " o got %u/%u byte desc of type 0x%.2x\n",
00448 len, sizeof(cci->cci_desc), cci->cci_desc.bDescriptorType);
00449 trace(cci, " o CCID version %u.%u device with %u/%u slots in parallel\n",
00450 bcd_hi(cci->cci_desc.bcdCCID),
00451 bcd_lo(cci->cci_desc.bcdCCID),
00452 cci->cci_max_slots, cci->cci_num_slots);
00453
00454
00455 trace(cci, " o Voltages:");
00456 if ( cci->cci_desc.bVoltageSupport & CCID_5V )
00457 trace(cci, " 5V");
00458 if ( cci->cci_desc.bVoltageSupport & CCID_3V )
00459 trace(cci, " 3V");
00460 if ( cci->cci_desc.bVoltageSupport & CCID_1_8V )
00461 trace(cci, " 1.8V");
00462 trace(cci, "\n");
00463
00464 trace(cci, " o Protocols: ");
00465 if ( cci->cci_desc.dwProtocols & CCID_T0 )
00466 trace(cci, " T=0");
00467 if ( cci->cci_desc.dwProtocols & CCID_T1 )
00468 trace(cci, " T=1");
00469 trace(cci, "\n");
00470
00471 trace(cci, " o Default Clock Freq.: %uKHz\n", cci->cci_desc.dwDefaultClock);
00472 trace(cci, " o Max. Clock Freq.: %uKHz\n", cci->cci_desc.dwMaximumClock);
00473
00474 trace(cci, " o Default Data Rate: %ubps\n", cci->cci_desc.dwDataRate);
00475 trace(cci, " o Max. Data Rate: %ubps\n", cci->cci_desc.dwMaxDataRate);
00476
00477 trace(cci, " o T=1 Max. IFSD = %u\n", cci->cci_desc.dwMaxIFSD);
00478
00479
00480
00481
00482 if ( cci->cci_desc.dwFeatures & CCID_ATR_CONFIG )
00483 trace(cci, " o Paramaters configured from ATR\n");
00484 if ( cci->cci_desc.dwFeatures & CCID_ACTIVATE )
00485 trace(cci, " o Chipcard auto-activate\n");
00486 if ( cci->cci_desc.dwFeatures & CCID_VOLTAGE )
00487 trace(cci, " o Auto Voltage Select\n");
00488 if ( cci->cci_desc.dwFeatures & CCID_FREQ )
00489 trace(cci, " o Auto Clock Freq. Select\n");
00490 if ( cci->cci_desc.dwFeatures & CCID_BAUD )
00491 trace(cci, " o Auto Data Rate Select\n");
00492 if ( cci->cci_desc.dwFeatures & CCID_CLOCK_STOP )
00493 trace(cci, " o Clock Stop Mode\n");
00494 if ( cci->cci_desc.dwFeatures & CCID_NAD )
00495 trace(cci, " o NAD value other than 0 permitted\n");
00496 if ( cci->cci_desc.dwFeatures & CCID_IFSD )
00497 trace(cci, " o Auto IFSD on first exchange\n");
00498
00499 switch ( cci->cci_desc.dwFeatures & (CCID_PPS_VENDOR|CCID_PPS) ) {
00500 case CCID_PPS_VENDOR:
00501 trace(cci, " o Proprietary parameter selection algorithm\n");
00502 break;
00503 case CCID_PPS:
00504 trace(cci, " o Chipcard automatic PPD\n");
00505 break;
00506 default:
00507 fprintf(stderr, "PPS/PPS_VENDOR conflict in descriptor\n");
00508 return 0;
00509 }
00510
00511 switch ( cci->cci_desc.dwFeatures &
00512 (CCID_T1_TPDU|CCID_T1_APDU|CCID_T1_APDU_EXT) ) {
00513 case CCID_T1_TPDU:
00514 trace(cci, " o T=1 TPDU\n");
00515 break;
00516 case CCID_T1_APDU:
00517 trace(cci, " o T=1 APDU (Short)\n");
00518 break;
00519 case CCID_T1_APDU_EXT:
00520 trace(cci, " o T=1 APDU (Short and Extended)\n");
00521 break;
00522 default:
00523 fprintf(stderr, "T=1 PDU conflict in descriptor\n");
00524 return 0;
00525 }
00526
00527
00528 trace(cci, " o Max. Message Length: %u bytes\n",
00529 cci->cci_desc.dwMaxCCIDMessageLength);
00530
00531 if ( cci->cci_desc.dwFeatures & (CCID_T1_APDU|CCID_T1_APDU_EXT) ) {
00532 trace(cci, " o APDU Default GetResponse: %u\n",
00533 cci->cci_desc.bClassGetResponse);
00534 trace(cci, " o APDU Default Envelope: %u\n",
00535 cci->cci_desc.bClassEnvelope);
00536 }
00537
00538 if ( cci->cci_desc.wLcdLayout ) {
00539 trace(cci, " o LCD Layout: %ux%u\n",
00540 bcd_hi(cci->cci_desc.wLcdLayout),
00541 bcd_lo(cci->cci_desc.wLcdLayout));
00542 }
00543
00544 switch ( cci->cci_desc.bPINSupport & (CCID_PIN_VER|CCID_PIN_MOD) ) {
00545 case CCID_PIN_VER:
00546 trace(cci, " o PIN verification supported\n");
00547 break;
00548 case CCID_PIN_MOD:
00549 trace(cci, " o PIN modification supported\n");
00550 break;
00551 case CCID_PIN_VER|CCID_PIN_MOD:
00552 trace(cci, " o PIN verification and modification supported\n");
00553 break;
00554 }
00555
00556 _hex_dumpf(cci->cci_tf, ptr, len, 16);
00557 return 1;
00558 }
00559
00560 static int probe_descriptors(struct _cci *cci)
00561 {
00562 uint8_t dbuf[512];
00563 uint8_t *ptr, *end;
00564 int sz, valid_ccid = 0;
00565
00566 sz = libusb_get_descriptor(cci->cci_dev, LIBUSB_DT_CONFIG, 0,
00567 dbuf, sizeof(dbuf));
00568 if ( sz < 0 )
00569 return 0;
00570
00571 trace(cci, " o Fetching config descriptor\n");
00572
00573 for(ptr = dbuf, end = ptr + sz; ptr + 2 < end; ) {
00574 if ( ptr + ptr[0] > end )
00575 return 0;
00576
00577 switch( ptr[1] ) {
00578 case LIBUSB_DT_DEVICE:
00579 break;
00580 case LIBUSB_DT_CONFIG:
00581 break;
00582 case LIBUSB_DT_STRING:
00583 break;
00584 case LIBUSB_DT_INTERFACE:
00585 break;
00586 case LIBUSB_DT_ENDPOINT:
00587 get_endpoint(cci, ptr, ptr[0]);
00588 break;
00589 case CCID_DT:
00590 if ( fill_ccid_desc(cci, dbuf + 18, ptr[0]) )
00591 valid_ccid = 1;
00592 break;
00593 default:
00594 trace(cci, " o Unknown descriptor 0x%.2x\n", ptr[1]);
00595 break;
00596 }
00597
00598 ptr += ptr[0];
00599
00600 }
00601
00602 if ( !valid_ccid ) {
00603 fprintf(stderr, "*** error: No CCID descriptor found\n");
00604 return 0;
00605 }
00606
00607 return 1;
00608 }
00609
00622 cci_t cci_probe(ccidev_t dev, const char *tracefile)
00623 {
00624 struct _cci *cci = NULL;
00625 unsigned int x;
00626 int c, i, a;
00627
00628 if ( !_probe_descriptors(dev, &c, &i, &a) ) {
00629 goto out;
00630 }
00631
00632
00633 cci = calloc(1, sizeof(*cci));
00634 if ( NULL == cci )
00635 goto out;
00636
00637 if ( tracefile ) {
00638 if ( !strcmp("-", tracefile) )
00639 cci->cci_tf = stdout;
00640 else
00641 cci->cci_tf = fopen(tracefile, "w");
00642 if ( cci->cci_tf == NULL )
00643 goto out_free;
00644 }
00645
00646 trace(cci, "Probe CCI on dev %u:%u %d/%d/%d\n",
00647 libusb_get_bus_number(dev),
00648 libusb_get_device_address(dev), c, i, a);
00649
00650 for(x = 0; x < CCID_MAX_SLOTS; x++) {
00651 cci->cci_slot[x].cc_parent = cci;
00652 cci->cci_slot[x].cc_idx = x;
00653 }
00654
00655
00656 if ( libusb_open(dev, &cci->cci_dev) ) {
00657 goto out_free;
00658 }
00659
00660 #if 1
00661 libusb_reset_device(cci->cci_dev);
00662 #endif
00663
00664 if ( libusb_set_configuration(cci->cci_dev, c) ) {
00665 trace(cci, "error setting configuration\n");
00666 goto out_close;
00667 }
00668
00669 if ( libusb_claim_interface(cci->cci_dev, i) ) {
00670 trace(cci, "error claiming interface\n");
00671 goto out_close;
00672 }
00673
00674 if ( libusb_set_interface_alt_setting(cci->cci_dev, i, a) ) {
00675 trace(cci, "error setting alternate settings\n");
00676 goto out_close;
00677 }
00678
00679
00680 if( !probe_descriptors(cci) ) {
00681 goto out_close;
00682 }
00683
00684 cci->cci_xfr = _xfr_do_alloc(cci->cci_max_out, cci->cci_max_in);
00685 if ( NULL == cci->cci_xfr )
00686 goto out_close;
00687
00688
00689 for(x = 0; x < cci->cci_num_slots; x++) {
00690 if ( !_PC_to_RDR_GetSlotStatus(cci, x, cci->cci_xfr) )
00691 goto out_freebuf;
00692 if ( !_RDR_to_PC(cci, x, cci->cci_xfr) )
00693 goto out_freebuf;
00694 if ( !_RDR_to_PC_SlotStatus(cci, cci->cci_xfr) )
00695 goto out_freebuf;
00696 }
00697
00698 goto out;
00699
00700 out_freebuf:
00701 _xfr_do_free(cci->cci_xfr);
00702 out_close:
00703 libusb_close(cci->cci_dev);
00704 out_free:
00705 free(cci);
00706 cci = NULL;
00707 fprintf(stderr, "cci: error probing device\n");
00708 out:
00709 return cci;
00710 }
00711
00719 void cci_close(cci_t cci)
00720 {
00721 if ( cci ) {
00722 if ( cci->cci_dev )
00723 libusb_close(cci->cci_dev);
00724 _xfr_do_free(cci->cci_xfr);
00725 }
00726 free(cci);
00727 }
00728
00734 unsigned int cci_slots(cci_t cci)
00735 {
00736 return cci->cci_num_slots;
00737 }
00738
00745 chipcard_t cci_get_slot(cci_t cci, unsigned int num)
00746 {
00747 if ( num < cci->cci_num_slots ) {
00748 return cci->cci_slot + num;
00749 }else{
00750 return NULL;
00751 }
00752 }
00753
00762 void cci_log(cci_t cci, const char *fmt, ...)
00763 {
00764 va_list va;
00765
00766 if ( NULL == cci->cci_tf )
00767 return;
00768
00769 va_start(va, fmt);
00770 vfprintf(cci->cci_tf, fmt, va);
00771 va_end(va);
00772 }