/[pcsclite]/trunk/Drivers/ccid/src/ccid_usb.c
ViewVC logotype

Contents of /trunk/Drivers/ccid/src/ccid_usb.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1703 - (show annotations) (download)
Mon Nov 7 15:46:03 2005 UTC (7 years, 7 months ago) by rousseau
File MIME type: text/plain
File size: 21532 byte(s)
remove #ifdef DEBUG_LEVEL_COMM since DEBUG_LEVEL_COMM is a numeric value
and not a compilation flag anymore. Debug is always active and filtered
by pcscd.
1 /*
2 ccid_usb.c: USB access routines using the libusb library
3 Copyright (C) 2003-2004 Ludovic Rousseau
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20 /*
21 * $Id$
22 */
23
24 #define __CCID_USB__
25
26 #include <stdio.h>
27 #include <string.h>
28 #include <errno.h>
29 # ifdef S_SPLINT_S
30 # include <sys/types.h>
31 # endif
32 #include <usb.h>
33
34 #include "ccid.h"
35 #include "config.h"
36 #include "debug.h"
37 #include "defs.h"
38 #include "utils.h"
39 #include "parser.h"
40 #include "ccid_ifdhandler.h"
41
42
43 /* write timeout
44 * we don't have to wait a long time since the card was doing nothing */
45 #define USB_WRITE_TIMEOUT (5 * 1000) /* 5 seconds timeout */
46
47 /*
48 * Proprietary USB Class (0xFF) are (or are not) accepted
49 * A proprietary class is used for devices released before the final CCID
50 * specifications were ready.
51 * We should not have problems with non CCID devices becasue the
52 * Manufacturer and Product ID are also used to identify the device */
53 #define ALLOW_PROPRIETARY_CLASS
54
55 /*
56 * The O2Micro OZ776S reader has a wrong USB descriptor
57 * The extra[] field is associated with the last endpoint instead of the
58 * main USB descriptor
59 */
60 #define O2MICRO_OZ776_PATCH
61
62 #define BUS_DEVICE_STRSIZE 32
63
64 typedef struct
65 {
66 usb_dev_handle *handle;
67 struct usb_device *dev;
68 int interface;
69
70 /*
71 * Endpoints
72 */
73 int bulk_in;
74 int bulk_out;
75
76 /*
77 * CCID infos common to USB and serial
78 */
79 _ccid_descriptor ccid;
80
81 } _usbDevice;
82
83 /* The _usbDevice structure must be defined before including ccid_usb.h */
84 #include "ccid_usb.h"
85
86 static int get_end_points(struct usb_device *dev, _usbDevice *usb_device);
87 int ccid_check_firmware(struct usb_device *dev);
88 static unsigned int *get_data_rates(unsigned int reader_index);
89
90 /* ne need to initialize to 0 since it is static */
91 static _usbDevice usbDevice[CCID_DRIVER_MAX_READERS];
92
93 #define PCSCLITE_MANUKEY_NAME "ifdVendorID"
94 #define PCSCLITE_PRODKEY_NAME "ifdProductID"
95 #define PCSCLITE_NAMEKEY_NAME "ifdFriendlyName"
96
97 struct _bogus_firmware
98 {
99 int vendor; /* idVendor */
100 int product; /* idProduct */
101 int firmware; /* bcdDevice: previous firmwares have bugs */
102 };
103
104 static struct _bogus_firmware Bogus_firmwares[] = {
105 { 0x0b97, 0x7762, 0x0111 }, /* Oz776S */ /* the firmware version if not correct since I don't have received a working reader yet */
106 { 0x04e6, 0xe001, 0x0516 }, /* SCR 331 */
107 { 0x04e6, 0x5111, 0x0620 }, /* SCR 331-DI */
108 { 0x04e6, 0x5115, 0x0514 }, /* SCR 335 */
109 { 0x04e6, 0xe003, 0x0504 }, /* SPR 532 */
110 { 0x0D46, 0x3001, 0x0037 }, /* KAAN Base */
111 { 0x0D46, 0x3002, 0x0037 }, /* KAAN Advanced */
112 };
113
114
115 /*****************************************************************************
116 *
117 * OpenUSB
118 *
119 ****************************************************************************/
120 status_t OpenUSB(unsigned int reader_index, /*@unused@*/ int Channel)
121 {
122 return OpenUSBByName(reader_index, NULL);
123 } /* OpenUSB */
124
125
126 /*****************************************************************************
127 *
128 * OpenUSBByName
129 *
130 ****************************************************************************/
131 status_t OpenUSBByName(unsigned int reader_index, /*@null@*/ char *device)
132 {
133 static struct usb_bus *busses = NULL;
134 int alias = 0;
135 struct usb_bus *bus;
136 struct usb_dev_handle *dev_handle;
137 char keyValue[TOKEN_MAX_VALUE_SIZE];
138 unsigned int vendorID, productID;
139 char infofile[FILENAME_MAX];
140 unsigned int device_vendor, device_product;
141 char *dirname = NULL, *filename = NULL;
142 static int previous_reader_index = -1;
143
144 DEBUG_COMM3("Reader index: %X, Device: %s", reader_index, device);
145
146 /* device name specified */
147 if (device)
148 {
149 /* format: usb:%04x/%04x, vendor, product */
150 if (strncmp("usb:", device, 4) != 0)
151 {
152 DEBUG_CRITICAL2("device name does not start with \"usb:\": %s",
153 device);
154 return STATUS_UNSUCCESSFUL;
155 }
156
157 if (sscanf(device, "usb:%x/%x", &device_vendor, &device_product) != 2)
158 {
159 DEBUG_CRITICAL2("device name can't be parsed: %s", device);
160 return STATUS_UNSUCCESSFUL;
161 }
162
163 /* format usb:%04x/%04x:libusb:%s
164 * with %s set to %s:%s, dirname, filename */
165 if ((dirname = strstr(device, "libusb:")) != NULL)
166 {
167 /* dirname points to the first char after libusb: */
168 dirname += strlen("libusb:");
169
170 /* search the : (separation) char */
171 filename = strchr(dirname, ':');
172
173 if (filename)
174 {
175 /* end the dirname string */
176 *filename = '\0';
177
178 /* filename points to the first char after : */
179 filename++;
180 }
181 else
182 {
183 /* parse failed */
184 dirname = NULL;
185
186 DEBUG_CRITICAL2("can't parse using libusb scheme: %s", device);
187 }
188 }
189 }
190
191 if (busses == NULL)
192 usb_init();
193
194 usb_find_busses();
195 usb_find_devices();
196
197 busses = usb_get_busses();
198
199 if (busses == NULL)
200 {
201 DEBUG_CRITICAL("No USB busses found");
202 return STATUS_UNSUCCESSFUL;
203 }
204
205 /* is the reader_index already used? */
206 if (usbDevice[reader_index].handle != NULL)
207 {
208 DEBUG_CRITICAL2("USB driver with index %X already in use",
209 reader_index);
210 return STATUS_UNSUCCESSFUL;
211 }
212
213 /* Info.plist full patch filename */
214 snprintf(infofile, sizeof(infofile), "%s/%s/Contents/Info.plist",
215 PCSCLITE_HP_DROPDIR, BUNDLE);
216
217 /* general driver info */
218 if (!LTPBundleFindValueWithKey(infofile, "ifdManufacturerString", keyValue, 0))
219 {
220 DEBUG_CRITICAL2("Manufacturer: %s", keyValue);
221 }
222 else
223 {
224 DEBUG_CRITICAL2("LTPBundleFindValueWithKey error. Can't find %s?",
225 infofile);
226 return STATUS_UNSUCCESSFUL;
227 }
228 if (!LTPBundleFindValueWithKey(infofile, "ifdProductString", keyValue, 0))
229 {
230 DEBUG_CRITICAL2("ProductString: %s", keyValue);
231 }
232 else
233 return STATUS_UNSUCCESSFUL;
234 if (!LTPBundleFindValueWithKey(infofile, "Copyright", keyValue, 0))
235 {
236 DEBUG_CRITICAL2("Copyright: %s", keyValue);
237 }
238 else
239 return STATUS_UNSUCCESSFUL;
240 vendorID = strlen(keyValue);
241 alias = 0x1D;
242 for (; vendorID--;)
243 alias ^= keyValue[vendorID];
244
245 /* for any supported reader */
246 while (LTPBundleFindValueWithKey(infofile, PCSCLITE_MANUKEY_NAME, keyValue, alias) == 0)
247 {
248 vendorID = strtoul(keyValue, NULL, 0);
249
250 if (LTPBundleFindValueWithKey(infofile, PCSCLITE_PRODKEY_NAME, keyValue, alias))
251 goto end;
252 productID = strtoul(keyValue, NULL, 0);
253
254 if (LTPBundleFindValueWithKey(infofile, PCSCLITE_NAMEKEY_NAME, keyValue, alias))
255 goto end;
256
257 /* go to next supported reader for next round */
258 alias++;
259
260 /* the device was specified but is not the one we are trying to find */
261 if (device
262 && (vendorID != device_vendor || productID != device_product))
263 continue;
264
265 /* on any USB buses */
266 for (bus = busses; bus; bus = bus->next)
267 {
268 struct usb_device *dev;
269
270 /* any device on this bus */
271 for (dev = bus->devices; dev; dev = dev->next)
272 {
273 /* device defined by name? */
274 if (dirname && (strcmp(dirname, bus->dirname)
275 || strcmp(filename, dev->filename)))
276 continue;
277
278 if (dev->descriptor.idVendor == vendorID
279 && dev->descriptor.idProduct == productID)
280 {
281 int r, already_used;
282 struct usb_interface *usb_interface = NULL;
283 int interface;
284
285 /* is it already opened? */
286 already_used = FALSE;
287
288 for (r=0; r<CCID_DRIVER_MAX_READERS; r++)
289 {
290 if (usbDevice[r].dev)
291 {
292 DEBUG_COMM3("Checking device: %s/%s",
293 bus->dirname, dev->filename);
294 /* same busname, same filename */
295 if (strcmp(usbDevice[r].dev->bus->dirname, bus->dirname) == 0 && strcmp(usbDevice[r].dev->filename, dev->filename) == 0)
296 already_used = TRUE;
297 }
298 }
299
300 /* this reader is already managed by us */
301 if (already_used)
302 {
303 if ((previous_reader_index != -1)
304 && (strcmp(usbDevice[previous_reader_index].dev->bus->dirname, bus->dirname) == 0)
305 && (strcmp(usbDevice[previous_reader_index].dev->filename, dev->filename) == 0)
306 && usbDevice[previous_reader_index].ccid.bCurrentSlotIndex < usbDevice[previous_reader_index].ccid.bMaxSlotIndex)
307 {
308 /* we reuse the same device
309 * and the reader is multi-slot */
310 usbDevice[reader_index] = usbDevice[previous_reader_index];
311 usbDevice[reader_index].ccid.pbSeq = usbDevice[previous_reader_index].ccid.pbSeq;
312 usbDevice[reader_index].ccid.bCurrentSlotIndex++;
313 DEBUG_INFO2("Opening slot: %d",
314 usbDevice[reader_index].ccid.bCurrentSlotIndex);
315 goto end;
316 }
317 else
318 {
319 DEBUG_INFO3("USB device %s/%s already in use."
320 " Checking next one.",
321 bus->dirname, dev->filename);
322 }
323
324 continue;
325 }
326
327 DEBUG_COMM3("Trying to open USB bus/device: %s/%s",
328 bus->dirname, dev->filename);
329
330 dev_handle = usb_open(dev);
331 if (dev_handle == NULL)
332 {
333 DEBUG_CRITICAL4("Can't usb_open(%s/%s): %s",
334 bus->dirname, dev->filename, strerror(errno));
335
336 continue;
337 }
338
339 /* now we found a free reader and we try to use it */
340 if (dev->config == NULL)
341 {
342 usb_close(dev_handle);
343 DEBUG_CRITICAL3("No dev->config found for %s/%s",
344 bus->dirname, dev->filename);
345 return STATUS_UNSUCCESSFUL;
346 }
347
348 usb_interface = get_ccid_usb_interface(dev);
349 if (usb_interface == NULL)
350 {
351 usb_close(dev_handle);
352 DEBUG_CRITICAL3("Can't find a CCID interface on %s/%s",
353 bus->dirname, dev->filename);
354 return STATUS_UNSUCCESSFUL;
355 }
356
357 if (usb_interface->altsetting->extralen != 54)
358 {
359 usb_close(dev_handle);
360 DEBUG_CRITICAL4("Extra field for %s/%s has a wrong length: %d", bus->dirname, dev->filename, usb_interface->altsetting->extralen);
361 return STATUS_UNSUCCESSFUL;
362 }
363
364 interface = usb_interface->altsetting->bInterfaceNumber;
365 if (usb_claim_interface(dev_handle, interface) < 0)
366 {
367 usb_close(dev_handle);
368 DEBUG_CRITICAL4("Can't claim interface %s/%s: %s",
369 bus->dirname, dev->filename, strerror(errno));
370 return STATUS_UNSUCCESSFUL;
371 }
372
373 DEBUG_INFO4("Found Vendor/Product: %04X/%04X (%s)",
374 dev->descriptor.idVendor,
375 dev->descriptor.idProduct, keyValue);
376 DEBUG_INFO3("Using USB bus/device: %s/%s",
377 bus->dirname, dev->filename);
378
379 /* check for firmware bugs */
380 if (ccid_check_firmware(dev))
381 {
382 usb_close(dev_handle);
383 return STATUS_UNSUCCESSFUL;
384 }
385
386 /* Get Endpoints values*/
387 get_end_points(dev, &usbDevice[reader_index]);
388
389 /* store device information */
390 usbDevice[reader_index].handle = dev_handle;
391 usbDevice[reader_index].dev = dev;
392 usbDevice[reader_index].interface = interface;
393
394 /* CCID common informations */
395 usbDevice[reader_index].ccid.real_bSeq = 0;
396 usbDevice[reader_index].ccid.pbSeq = &usbDevice[reader_index].ccid.real_bSeq;
397 usbDevice[reader_index].ccid.readerID =
398 (dev->descriptor.idVendor << 16) +
399 dev->descriptor.idProduct;
400 usbDevice[reader_index].ccid.dwFeatures = dw2i(usb_interface->altsetting->extra, 40);
401 usbDevice[reader_index].ccid.bPINSupport = usb_interface->altsetting->extra[52];
402 usbDevice[reader_index].ccid.dwMaxCCIDMessageLength = dw2i(usb_interface->altsetting->extra, 44);
403 usbDevice[reader_index].ccid.dwMaxIFSD = dw2i(usb_interface->altsetting->extra, 28);
404 usbDevice[reader_index].ccid.dwDefaultClock = dw2i(usb_interface->altsetting->extra, 10);
405 usbDevice[reader_index].ccid.dwMaxDataRate = dw2i(usb_interface->altsetting->extra, 23);
406 usbDevice[reader_index].ccid.bMaxSlotIndex = usb_interface->altsetting->extra[4];
407 usbDevice[reader_index].ccid.bCurrentSlotIndex = 0;
408 usbDevice[reader_index].ccid.readTimeout = DEFAULT_COM_READ_TIMEOUT;
409 usbDevice[reader_index].ccid.arrayOfSupportedDataRates = get_data_rates(reader_index);
410 goto end;
411 }
412 }
413 }
414 }
415 end:
416 if (usbDevice[reader_index].handle == NULL)
417 return STATUS_UNSUCCESSFUL;
418
419 /* memorise the current reader_index so we can detect
420 * a new OpenUSBByName on a multi slot reader */
421 previous_reader_index = reader_index;
422
423 return STATUS_SUCCESS;
424 } /* OpenUSBByName */
425
426
427 /*****************************************************************************
428 *
429 * WriteUSB
430 *
431 ****************************************************************************/
432 status_t WriteUSB(unsigned int reader_index, unsigned int length,
433 unsigned char *buffer)
434 {
435 int rv;
436 char debug_header[] = "-> 121234 ";
437
438 sprintf(debug_header, "-> %06X ", (int)reader_index);
439
440 DEBUG_XXD(debug_header, buffer, length);
441
442 rv = usb_bulk_write(usbDevice[reader_index].handle,
443 usbDevice[reader_index].bulk_out, (char *)buffer, length,
444 USB_WRITE_TIMEOUT);
445
446 if (rv < 0)
447 {
448 if (usbDevice[reader_index].dev->bus)
449 {
450 DEBUG_CRITICAL4("usb_bulk_write(%s/%s): %s",
451 usbDevice[reader_index].dev->bus->dirname,
452 usbDevice[reader_index].dev->filename, strerror(errno));
453 }
454 else
455 DEBUG_CRITICAL2("usb_bulk_write(no device): %s", strerror(errno));
456
457 return STATUS_UNSUCCESSFUL;
458 }
459
460 return STATUS_SUCCESS;
461 } /* WriteUSB */
462
463
464 /*****************************************************************************
465 *
466 * ReadUSB
467 *
468 ****************************************************************************/
469 status_t ReadUSB(unsigned int reader_index, unsigned int * length,
470 unsigned char *buffer)
471 {
472 int rv;
473 char debug_header[] = "<- 121234 ";
474
475 sprintf(debug_header, "<- %06X ", (int)reader_index);
476
477 rv = usb_bulk_read(usbDevice[reader_index].handle,
478 usbDevice[reader_index].bulk_in, (char *)buffer, *length,
479 usbDevice[reader_index].ccid.readTimeout * 1000);
480
481 if (rv < 0)
482 {
483 *length = 0;
484 DEBUG_CRITICAL4("usb_bulk_read(%s/%s): %s",
485 usbDevice[reader_index].dev->bus->dirname,
486 usbDevice[reader_index].dev->filename, strerror(errno));
487 return STATUS_UNSUCCESSFUL;
488 }
489
490 *length = rv;
491
492 DEBUG_XXD(debug_header, buffer, *length);
493
494 return STATUS_SUCCESS;
495 } /* ReadUSB */
496
497
498 /*****************************************************************************
499 *
500 * CloseUSB
501 *
502 ****************************************************************************/
503 status_t CloseUSB(unsigned int reader_index)
504 {
505 /* device not opened */
506 if (usbDevice[reader_index].dev == NULL)
507 return STATUS_UNSUCCESSFUL;
508
509 DEBUG_COMM3("Closing USB device: %s/%s",
510 usbDevice[reader_index].dev->bus->dirname,
511 usbDevice[reader_index].dev->filename);
512
513 if (usbDevice[reader_index].ccid.arrayOfSupportedDataRates)
514 free(usbDevice[reader_index].ccid.arrayOfSupportedDataRates);
515
516 /* reset so that bSeq starts at 0 again */
517 if (DriverOptions & DRIVER_OPTION_RESET_ON_CLOSE)
518 usb_reset(usbDevice[reader_index].handle);
519
520 usb_release_interface(usbDevice[reader_index].handle,
521 usbDevice[reader_index].interface);
522 usb_close(usbDevice[reader_index].handle);
523
524 /* mark the resource unused */
525 usbDevice[reader_index].handle = NULL;
526 usbDevice[reader_index].dev = NULL;
527 usbDevice[reader_index].interface = 0;
528
529 return STATUS_SUCCESS;
530 } /* CloseUSB */
531
532
533 /*****************************************************************************
534 *
535 * get_ccid_descriptor
536 *
537 ****************************************************************************/
538 _ccid_descriptor *get_ccid_descriptor(unsigned int reader_index)
539 {
540 return &usbDevice[reader_index].ccid;
541 } /* get_ccid_descriptor */
542
543
544 /*****************************************************************************
545 *
546 * get_desc
547 *
548 ****************************************************************************/
549 int get_desc(int lun, usb_dev_handle **handle, struct
550 usb_device **dev)
551 {
552 int reader_index;
553
554 if (-1 == (reader_index = LunToReaderIndex(lun)))
555 return FALSE;
556
557 *handle = usbDevice[reader_index].handle;
558 *dev = usbDevice[reader_index].dev;
559
560 return TRUE;
561 } /* get_desc */
562
563
564 /*****************************************************************************
565 *
566 * get_end_points
567 *
568 ****************************************************************************/
569 static int get_end_points(struct usb_device *dev, _usbDevice *usb_device)
570 {
571 int i;
572 int bEndpointAddress;
573 struct usb_interface *usb_interface = get_ccid_usb_interface(dev);
574
575 /*
576 * 3 Endpoints maximum: Interrupt In, Bulk In, Bulk Out
577 */
578 for (i=0; i<3; i++)
579 {
580 if (usb_interface->altsetting->endpoint[i].bmAttributes != USB_ENDPOINT_TYPE_BULK)
581 continue;
582
583 bEndpointAddress = usb_interface->altsetting->endpoint[i].bEndpointAddress;
584
585 if ((bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_IN)
586 usb_device->bulk_in = bEndpointAddress;
587
588 if ((bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_OUT)
589 usb_device->bulk_out = bEndpointAddress;
590 }
591
592 return 0;
593 } /* get_end_points */
594
595
596 /*****************************************************************************
597 *
598 * get_ccid_usb_interface
599 *
600 ****************************************************************************/
601 /*@null@*/ struct usb_interface * get_ccid_usb_interface(struct usb_device *dev)
602 {
603 struct usb_interface *usb_interface = NULL;
604
605 /* if multiple interfaces use the first one with CCID class type */
606 if (dev->config->bNumInterfaces > 1)
607 {
608 int ii;
609 for (ii=0; ii<dev->config->bNumInterfaces; ii++)
610 {
611 /* CCID Class? */
612 if (dev->config->interface[ii].altsetting->bInterfaceClass == 0xb
613 #ifdef ALLOW_PROPRIETARY_CLASS
614 || dev->config->interface[ii].altsetting->bInterfaceClass == 0xff
615 #endif
616 )
617 {
618 usb_interface = &dev->config->interface[ii];
619 break;
620 }
621 }
622 }
623 else
624 /* only one interface found */
625 usb_interface = dev->config->interface;
626
627 #ifdef O2MICRO_OZ776_PATCH
628 if (usb_interface != NULL
629 && (OZ776 == (dev->descriptor.idVendor << 16)
630 + dev->descriptor.idProduct)
631 && (0 == usb_interface->altsetting->extralen)) /* this is the bug */
632 {
633 int i;
634
635 for (i=0; i<usb_interface->altsetting->bNumEndpoints; i++)
636 {
637 /* find the extra[] array */
638 if (54 == usb_interface->altsetting->endpoint[i].extralen)
639 {
640 /* get the extra[] from the endpoint */
641 usb_interface->altsetting->extralen = 54;
642 usb_interface->altsetting->extra =
643 usb_interface->altsetting->endpoint[i].extra;
644 break;
645 }
646 }
647 }
648 #endif
649
650 return usb_interface;
651 } /* get_ccid_usb_interface */
652
653
654 /*****************************************************************************
655 *
656 * ccid_check_firmware
657 *
658 ****************************************************************************/
659 int ccid_check_firmware(struct usb_device *dev)
660 {
661 int i;
662
663 for (i=0; i<sizeof(Bogus_firmwares)/sizeof(Bogus_firmwares[0]); i++)
664 {
665 if (dev->descriptor.idVendor != Bogus_firmwares[i].vendor)
666 continue;
667
668 if (dev->descriptor.idProduct != Bogus_firmwares[i].product)
669 continue;
670
671 /* firmware too old and buggy */
672 if (dev->descriptor.bcdDevice < Bogus_firmwares[i].firmware)
673 {
674 if (DriverOptions & DRIVER_OPTION_USE_BOGUS_FIRMWARE)
675 {
676 DEBUG_INFO3("Firmware (%X.%02X) is bogus! but you choosed to use it",
677 dev->descriptor.bcdDevice >> 8,
678 dev->descriptor.bcdDevice & 0xFF);
679 return FALSE;
680 }
681 else
682 {
683 DEBUG_CRITICAL3("Firmware (%X.%02X) is bogus! Upgrade the reader firmware or get a new reader.",
684 dev->descriptor.bcdDevice >> 8,
685 dev->descriptor.bcdDevice & 0xFF);
686 return TRUE;
687 }
688 }
689 }
690
691 /* by default the firmware is not bogus */
692 return FALSE;
693 } /* ccid_check_firmware */
694
695 /*****************************************************************************
696 *
697 * get_data_rates
698 *
699 ****************************************************************************/
700 static unsigned int *get_data_rates(unsigned int reader_index)
701 {
702 int n, i, len;
703 unsigned char buffer[256*sizeof(int)]; /* maximum is 256 records */
704 unsigned int *int_array;
705
706 /* See CCID 3.7.3 page 25 */
707 n = usb_control_msg(usbDevice[reader_index].handle,
708 0xA1, /* request type */
709 0x03, /* GET_DATA_RATES */
710 0x00, /* value */
711 usbDevice[reader_index].interface, /* interface */
712 (char *)buffer,
713 sizeof(buffer),
714 usbDevice[reader_index].ccid.readTimeout * 1000);
715
716 /* we got an error? */
717 if (n <= 0)
718 {
719 DEBUG_INFO2("IFD does not support GET_DATA_RATES request: %s",
720 strerror(errno));
721 return NULL;
722 }
723
724 /* we got a strange value */
725 if (n % 4)
726 {
727 DEBUG_INFO2("Wrong GET DATA RATES size: %d", n);
728 return NULL;
729 }
730
731 /* allocate the buffer (including the end marker) */
732 n /= sizeof(int);
733
734 /* we do not get the expected number of data rates */
735 len = get_ccid_usb_interface(usbDevice[reader_index].dev)
736 ->altsetting->extra[27]; /* bNumDataRatesSupported */
737 if ((n != len) && len)
738 {
739 DEBUG_INFO3("Got %d data rates but was expecting %d", n, len);
740
741 /* we got more data than expected */
742 if (n > len)
743 n = len;
744 }
745
746 int_array = calloc(n+1, sizeof(int));
747 if (NULL == int_array)
748 {
749 DEBUG_CRITICAL("Memory allocation failed");
750 return NULL;
751 }
752
753 /* convert in correct endianess */
754 for (i=0; i<n; i++)
755 {
756 int_array[i] = dw2i(buffer, i*4);
757 DEBUG_INFO2("declared: %d bps", int_array[i]);
758 }
759
760 /* end of array marker */
761 int_array[i] = 0;
762
763 return int_array;
764 }
765

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.5