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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.5