/[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 1613 - (show annotations) (download)
Sat Aug 13 14:26:22 2005 UTC (7 years, 9 months ago) by rousseau
File MIME type: text/plain
File size: 21647 byte(s)
CloseUSB(): call usb_reset() only if DRIVER_OPTION_RESET_ON_CLOSE is
set.

The problem was that a device reset also disconnects the keyboard on a
keyboard + reader device.
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 #ifdef DEBUG_LEVEL_COMM
437 char debug_header[] = "-> 121234 ";
438
439 sprintf(debug_header, "-> %06X ", (int)reader_index);
440 #endif
441
442 #ifdef DEBUG_LEVEL_COMM
443 DEBUG_XXD(debug_header, buffer, length);
444 #endif
445
446 rv = usb_bulk_write(usbDevice[reader_index].handle,
447 usbDevice[reader_index].bulk_out, (char *)buffer, length,
448 USB_WRITE_TIMEOUT);
449
450 if (rv < 0)
451 {
452 if (usbDevice[reader_index].dev->bus)
453 {
454 DEBUG_CRITICAL4("usb_bulk_write(%s/%s): %s",
455 usbDevice[reader_index].dev->bus->dirname,
456 usbDevice[reader_index].dev->filename, strerror(errno));
457 }
458 else
459 DEBUG_CRITICAL2("usb_bulk_write(no device): %s", strerror(errno));
460
461 return STATUS_UNSUCCESSFUL;
462 }
463
464 return STATUS_SUCCESS;
465 } /* WriteUSB */
466
467
468 /*****************************************************************************
469 *
470 * ReadUSB
471 *
472 ****************************************************************************/
473 status_t ReadUSB(unsigned int reader_index, unsigned int * length,
474 unsigned char *buffer)
475 {
476 int rv;
477 #ifdef DEBUG_LEVEL_COMM
478 char debug_header[] = "<- 121234 ";
479
480 sprintf(debug_header, "<- %06X ", (int)reader_index);
481 #endif
482
483 rv = usb_bulk_read(usbDevice[reader_index].handle,
484 usbDevice[reader_index].bulk_in, (char *)buffer, *length,
485 usbDevice[reader_index].ccid.readTimeout * 1000);
486
487 if (rv < 0)
488 {
489 *length = 0;
490 DEBUG_CRITICAL4("usb_bulk_read(%s/%s): %s",
491 usbDevice[reader_index].dev->bus->dirname,
492 usbDevice[reader_index].dev->filename, strerror(errno));
493 return STATUS_UNSUCCESSFUL;
494 }
495
496 *length = rv;
497
498 #ifdef DEBUG_LEVEL_COMM
499 DEBUG_XXD(debug_header, buffer, *length);
500 #endif
501
502 return STATUS_SUCCESS;
503 } /* ReadUSB */
504
505
506 /*****************************************************************************
507 *
508 * CloseUSB
509 *
510 ****************************************************************************/
511 status_t CloseUSB(unsigned int reader_index)
512 {
513 /* device not opened */
514 if (usbDevice[reader_index].dev == NULL)
515 return STATUS_UNSUCCESSFUL;
516
517 DEBUG_COMM3("Closing USB device: %s/%s",
518 usbDevice[reader_index].dev->bus->dirname,
519 usbDevice[reader_index].dev->filename);
520
521 if (usbDevice[reader_index].ccid.arrayOfSupportedDataRates)
522 free(usbDevice[reader_index].ccid.arrayOfSupportedDataRates);
523
524 /* reset so that bSeq starts at 0 again */
525 if (DriverOptions & DRIVER_OPTION_RESET_ON_CLOSE)
526 usb_reset(usbDevice[reader_index].handle);
527
528 usb_release_interface(usbDevice[reader_index].handle,
529 usbDevice[reader_index].interface);
530 usb_close(usbDevice[reader_index].handle);
531
532 /* mark the resource unused */
533 usbDevice[reader_index].handle = NULL;
534 usbDevice[reader_index].dev = NULL;
535 usbDevice[reader_index].interface = 0;
536
537 return STATUS_SUCCESS;
538 } /* CloseUSB */
539
540
541 /*****************************************************************************
542 *
543 * get_ccid_descriptor
544 *
545 ****************************************************************************/
546 _ccid_descriptor *get_ccid_descriptor(unsigned int reader_index)
547 {
548 return &usbDevice[reader_index].ccid;
549 } /* get_ccid_descriptor */
550
551
552 /*****************************************************************************
553 *
554 * get_desc
555 *
556 ****************************************************************************/
557 int get_desc(int lun, usb_dev_handle **handle, struct
558 usb_device **dev)
559 {
560 int reader_index;
561
562 if (-1 == (reader_index = LunToReaderIndex(lun)))
563 return FALSE;
564
565 *handle = usbDevice[reader_index].handle;
566 *dev = usbDevice[reader_index].dev;
567
568 return TRUE;
569 } /* get_desc */
570
571
572 /*****************************************************************************
573 *
574 * get_end_points
575 *
576 ****************************************************************************/
577 static int get_end_points(struct usb_device *dev, _usbDevice *usb_device)
578 {
579 int i;
580 int bEndpointAddress;
581 struct usb_interface *usb_interface = get_ccid_usb_interface(dev);
582
583 /*
584 * 3 Endpoints maximum: Interrupt In, Bulk In, Bulk Out
585 */
586 for (i=0; i<3; i++)
587 {
588 if (usb_interface->altsetting->endpoint[i].bmAttributes != USB_ENDPOINT_TYPE_BULK)
589 continue;
590
591 bEndpointAddress = usb_interface->altsetting->endpoint[i].bEndpointAddress;
592
593 if ((bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_IN)
594 usb_device->bulk_in = bEndpointAddress;
595
596 if ((bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_OUT)
597 usb_device->bulk_out = bEndpointAddress;
598 }
599
600 return 0;
601 } /* get_end_points */
602
603
604 /*****************************************************************************
605 *
606 * get_ccid_usb_interface
607 *
608 ****************************************************************************/
609 /*@null@*/ struct usb_interface * get_ccid_usb_interface(struct usb_device *dev)
610 {
611 struct usb_interface *usb_interface = NULL;
612
613 /* if multiple interfaces use the first one with CCID class type */
614 if (dev->config->bNumInterfaces > 1)
615 {
616 int ii;
617 for (ii=0; ii<dev->config->bNumInterfaces; ii++)
618 {
619 /* CCID Class? */
620 if (dev->config->interface[ii].altsetting->bInterfaceClass == 0xb
621 #ifdef ALLOW_PROPRIETARY_CLASS
622 || dev->config->interface[ii].altsetting->bInterfaceClass == 0xff
623 #endif
624 )
625 {
626 usb_interface = &dev->config->interface[ii];
627 break;
628 }
629 }
630 }
631 else
632 /* only one interface found */
633 usb_interface = dev->config->interface;
634
635 #ifdef O2MICRO_OZ776_PATCH
636 if (usb_interface != NULL
637 && (OZ776 == (dev->descriptor.idVendor << 16)
638 + dev->descriptor.idProduct)
639 && (0 == usb_interface->altsetting->extralen)) /* this is the bug */
640 {
641 int i;
642
643 for (i=0; i<usb_interface->altsetting->bNumEndpoints; i++)
644 {
645 /* find the extra[] array */
646 if (54 == usb_interface->altsetting->endpoint[i].extralen)
647 {
648 /* get the extra[] from the endpoint */
649 usb_interface->altsetting->extralen = 54;
650 usb_interface->altsetting->extra =
651 usb_interface->altsetting->endpoint[i].extra;
652 break;
653 }
654 }
655 }
656 #endif
657
658 return usb_interface;
659 } /* get_ccid_usb_interface */
660
661
662 /*****************************************************************************
663 *
664 * ccid_check_firmware
665 *
666 ****************************************************************************/
667 int ccid_check_firmware(struct usb_device *dev)
668 {
669 int i;
670
671 for (i=0; i<sizeof(Bogus_firmwares)/sizeof(Bogus_firmwares[0]); i++)
672 {
673 if (dev->descriptor.idVendor != Bogus_firmwares[i].vendor)
674 continue;
675
676 if (dev->descriptor.idProduct != Bogus_firmwares[i].product)
677 continue;
678
679 /* firmware too old and buggy */
680 if (dev->descriptor.bcdDevice < Bogus_firmwares[i].firmware)
681 {
682 if (DriverOptions & DRIVER_OPTION_USE_BOGUS_FIRMWARE)
683 {
684 DEBUG_INFO3("Firmware (%X.%02X) is bogus! but you choosed to use it",
685 dev->descriptor.bcdDevice >> 8,
686 dev->descriptor.bcdDevice & 0xFF);
687 return FALSE;
688 }
689 else
690 {
691 DEBUG_CRITICAL3("Firmware (%X.%02X) is bogus! Upgrade the reader firmware or get a new reader.",
692 dev->descriptor.bcdDevice >> 8,
693 dev->descriptor.bcdDevice & 0xFF);
694 return TRUE;
695 }
696 }
697 }
698
699 /* by default the firmware is not bogus */
700 return FALSE;
701 } /* ccid_check_firmware */
702
703 /*****************************************************************************
704 *
705 * get_data_rates
706 *
707 ****************************************************************************/
708 static unsigned int *get_data_rates(unsigned int reader_index)
709 {
710 int n, i, len;
711 unsigned char buffer[256*sizeof(int)]; /* maximum is 256 records */
712 unsigned int *int_array;
713
714 /* See CCID 3.7.3 page 25 */
715 n = usb_control_msg(usbDevice[reader_index].handle,
716 0xA1, /* request type */
717 0x03, /* GET_DATA_RATES */
718 0x00, /* value */
719 usbDevice[reader_index].interface, /* interface */
720 (char *)buffer,
721 sizeof(buffer),
722 usbDevice[reader_index].ccid.readTimeout * 1000);
723
724 /* we got an error? */
725 if (n <= 0)
726 {
727 DEBUG_INFO2("IFD does not support GET_DATA_RATES request: %s",
728 strerror(errno));
729 return NULL;
730 }
731
732 /* we got a strange value */
733 if (n % 4)
734 {
735 DEBUG_INFO2("Wrong GET DATA RATES size: %d", n);
736 return NULL;
737 }
738
739 /* allocate the buffer (including the end marker) */
740 n /= sizeof(int);
741
742 /* we do not get the expected number of data rates */
743 len = get_ccid_usb_interface(usbDevice[reader_index].dev)
744 ->altsetting->extra[27]; /* bNumDataRatesSupported */
745 if (n != len)
746 {
747 DEBUG_INFO3("Got %d data rates but was expecting %d", n, len);
748
749 /* we got more data than expected */
750 if (n > len)
751 n = len;
752 }
753
754 int_array = calloc(n+1, sizeof(int));
755 if (NULL == int_array)
756 {
757 DEBUG_CRITICAL("Memory allocation failed");
758 return NULL;
759 }
760
761 /* convert in correct endianess */
762 for (i=0; i<n; i++)
763 {
764 int_array[i] = dw2i(buffer, i*4);
765 DEBUG_INFO2("declared: %d bps", int_array[i]);
766 }
767
768 /* end of array marker */
769 int_array[i] = 0;
770
771 return int_array;
772 }
773

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.5