/[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 1485 - (show annotations) (download)
Mon May 2 09:17:53 2005 UTC (8 years ago) by rousseau
File MIME type: text/plain
File size: 21312 byte(s)
Open*ByName(): initialise dwMaxDataRate field
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 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 DEBUG_CRITICAL3("No dev->config found for %s/%s",
343 bus->dirname, dev->filename);
344 return STATUS_UNSUCCESSFUL;
345 }
346
347 usb_interface = get_ccid_usb_interface(dev);
348 if (usb_interface == NULL)
349 {
350 DEBUG_CRITICAL3("Can't find a CCID interface on %s/%s",
351 bus->dirname, dev->filename);
352 return STATUS_UNSUCCESSFUL;
353 }
354
355 if (usb_interface->altsetting->extralen != 54)
356 {
357 DEBUG_CRITICAL4("Extra field for %s/%s has a wrong length: %d", bus->dirname, dev->filename, usb_interface->altsetting->extralen);
358 return STATUS_UNSUCCESSFUL;
359 }
360
361 interface = usb_interface->altsetting->bInterfaceNumber;
362 if (usb_claim_interface(dev_handle, interface) < 0)
363 {
364 DEBUG_CRITICAL4("Can't claim interface %s/%s: %s",
365 bus->dirname, dev->filename, strerror(errno));
366 return STATUS_UNSUCCESSFUL;
367 }
368
369 DEBUG_INFO4("Found Vendor/Product: %04X/%04X (%s)",
370 dev->descriptor.idVendor,
371 dev->descriptor.idProduct, keyValue);
372 DEBUG_INFO3("Using USB bus/device: %s/%s",
373 bus->dirname, dev->filename);
374
375 /* check for firmware bugs */
376 if (ccid_check_firmware(dev))
377 return STATUS_UNSUCCESSFUL;
378
379 /* Get Endpoints values*/
380 get_end_points(dev, &usbDevice[reader_index]);
381
382 /* store device information */
383 usbDevice[reader_index].handle = dev_handle;
384 usbDevice[reader_index].dev = dev;
385 usbDevice[reader_index].interface = interface;
386
387 /* CCID common informations */
388 usbDevice[reader_index].ccid.real_bSeq = 0;
389 usbDevice[reader_index].ccid.pbSeq = &usbDevice[reader_index].ccid.real_bSeq;
390 usbDevice[reader_index].ccid.readerID =
391 (dev->descriptor.idVendor << 16) +
392 dev->descriptor.idProduct;
393 usbDevice[reader_index].ccid.dwFeatures = dw2i(usb_interface->altsetting->extra, 40);
394 usbDevice[reader_index].ccid.bPINSupport = usb_interface->altsetting->extra[52];
395 usbDevice[reader_index].ccid.dwMaxCCIDMessageLength = dw2i(usb_interface->altsetting->extra, 44);
396 usbDevice[reader_index].ccid.dwMaxIFSD = dw2i(usb_interface->altsetting->extra, 28);
397 usbDevice[reader_index].ccid.dwDefaultClock = dw2i(usb_interface->altsetting->extra, 10);
398 usbDevice[reader_index].ccid.dwMaxDataRate = dw2i(usb_interface->altsetting->extra, 23);
399 usbDevice[reader_index].ccid.bMaxSlotIndex = usb_interface->altsetting->extra[4];
400 usbDevice[reader_index].ccid.bCurrentSlotIndex = 0;
401 usbDevice[reader_index].ccid.readTimeout = DEFAULT_COM_READ_TIMEOUT;
402 usbDevice[reader_index].ccid.arrayOfSupportedDataRates = get_data_rates(reader_index);
403 goto end;
404 }
405 }
406 }
407 }
408 end:
409 if (usbDevice[reader_index].handle == NULL)
410 return STATUS_UNSUCCESSFUL;
411
412 /* memorise the current reader_index so we can detect
413 * a new OpenUSBByName on a multi slot reader */
414 previous_reader_index = reader_index;
415
416 return STATUS_SUCCESS;
417 } /* OpenUSBByName */
418
419
420 /*****************************************************************************
421 *
422 * WriteUSB
423 *
424 ****************************************************************************/
425 status_t WriteUSB(unsigned int reader_index, unsigned int length,
426 unsigned char *buffer)
427 {
428 int rv;
429 #ifdef DEBUG_LEVEL_COMM
430 char debug_header[] = "-> 121234 ";
431
432 sprintf(debug_header, "-> %06X ", (int)reader_index);
433 #endif
434
435 #ifdef DEBUG_LEVEL_COMM
436 DEBUG_XXD(debug_header, buffer, length);
437 #endif
438
439 rv = usb_bulk_write(usbDevice[reader_index].handle,
440 usbDevice[reader_index].bulk_out, (char *)buffer, length,
441 USB_WRITE_TIMEOUT);
442
443 if (rv < 0)
444 {
445 DEBUG_CRITICAL4("usb_bulk_write(%s/%s): %s",
446 usbDevice[reader_index].dev->bus->dirname,
447 usbDevice[reader_index].dev->filename, strerror(errno));
448 return STATUS_UNSUCCESSFUL;
449 }
450
451 return STATUS_SUCCESS;
452 } /* WriteUSB */
453
454
455 /*****************************************************************************
456 *
457 * ReadUSB
458 *
459 ****************************************************************************/
460 status_t ReadUSB(unsigned int reader_index, unsigned int * length,
461 unsigned char *buffer)
462 {
463 int rv;
464 #ifdef DEBUG_LEVEL_COMM
465 char debug_header[] = "<- 121234 ";
466
467 sprintf(debug_header, "<- %06X ", (int)reader_index);
468 #endif
469
470 rv = usb_bulk_read(usbDevice[reader_index].handle,
471 usbDevice[reader_index].bulk_in, (char *)buffer, *length,
472 usbDevice[reader_index].ccid.readTimeout * 1000);
473
474 if (rv < 0)
475 {
476 *length = 0;
477 DEBUG_CRITICAL4("usb_bulk_read(%s/%s): %s",
478 usbDevice[reader_index].dev->bus->dirname,
479 usbDevice[reader_index].dev->filename, strerror(errno));
480 return STATUS_UNSUCCESSFUL;
481 }
482
483 *length = rv;
484
485 #ifdef DEBUG_LEVEL_COMM
486 DEBUG_XXD(debug_header, buffer, *length);
487 #endif
488
489 return STATUS_SUCCESS;
490 } /* ReadUSB */
491
492
493 /*****************************************************************************
494 *
495 * CloseUSB
496 *
497 ****************************************************************************/
498 status_t CloseUSB(unsigned int reader_index)
499 {
500 /* device not opened */
501 if (usbDevice[reader_index].dev == NULL)
502 return STATUS_UNSUCCESSFUL;
503
504 DEBUG_COMM3("Closing USB device: %s/%s",
505 usbDevice[reader_index].dev->bus->dirname,
506 usbDevice[reader_index].dev->filename);
507
508 if (usbDevice[reader_index].ccid.arrayOfSupportedDataRates)
509 free(usbDevice[reader_index].ccid.arrayOfSupportedDataRates);
510
511 /* reset so that bSeq starts at 0 again */
512 usb_reset(usbDevice[reader_index].handle);
513
514 usb_release_interface(usbDevice[reader_index].handle,
515 usbDevice[reader_index].interface);
516 usb_close(usbDevice[reader_index].handle);
517
518 /* mark the resource unused */
519 usbDevice[reader_index].handle = NULL;
520 usbDevice[reader_index].dev = NULL;
521 usbDevice[reader_index].interface = 0;
522
523 return STATUS_SUCCESS;
524 } /* CloseUSB */
525
526
527 /*****************************************************************************
528 *
529 * get_ccid_descriptor
530 *
531 ****************************************************************************/
532 _ccid_descriptor *get_ccid_descriptor(unsigned int reader_index)
533 {
534 return &usbDevice[reader_index].ccid;
535 } /* get_ccid_descriptor */
536
537
538 /*****************************************************************************
539 *
540 * get_desc
541 *
542 ****************************************************************************/
543 int get_desc(int lun, usb_dev_handle **handle, struct
544 usb_device **dev)
545 {
546 int reader_index;
547
548 if (-1 == (reader_index = LunToReaderIndex(lun)))
549 return FALSE;
550
551 *handle = usbDevice[reader_index].handle;
552 *dev = usbDevice[reader_index].dev;
553
554 return TRUE;
555 } /* get_desc */
556
557
558 /*****************************************************************************
559 *
560 * get_end_points
561 *
562 ****************************************************************************/
563 static int get_end_points(struct usb_device *dev, _usbDevice *usb_device)
564 {
565 int i;
566 int bEndpointAddress;
567 struct usb_interface *usb_interface = get_ccid_usb_interface(dev);
568
569 /*
570 * 3 Endpoints maximum: Interrupt In, Bulk In, Bulk Out
571 */
572 for (i=0; i<3; i++)
573 {
574 if (usb_interface->altsetting->endpoint[i].bmAttributes != USB_ENDPOINT_TYPE_BULK)
575 continue;
576
577 bEndpointAddress = usb_interface->altsetting->endpoint[i].bEndpointAddress;
578
579 if ((bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_IN)
580 usb_device->bulk_in = bEndpointAddress;
581
582 if ((bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_OUT)
583 usb_device->bulk_out = bEndpointAddress;
584 }
585
586 return 0;
587 } /* get_end_points */
588
589
590 /*****************************************************************************
591 *
592 * get_ccid_usb_interface
593 *
594 ****************************************************************************/
595 /*@null@*/ struct usb_interface * get_ccid_usb_interface(struct usb_device *dev)
596 {
597 struct usb_interface *usb_interface = NULL;
598
599 /* if multiple interfaces use the first one with CCID class type */
600 if (dev->config->bNumInterfaces > 1)
601 {
602 int ii;
603 for (ii=0; ii<dev->config->bNumInterfaces; ii++)
604 {
605 /* CCID Class? */
606 if (dev->config->interface[ii].altsetting->bInterfaceClass == 0xb
607 #ifdef ALLOW_PROPRIETARY_CLASS
608 || dev->config->interface[ii].altsetting->bInterfaceClass == 0xff
609 #endif
610 )
611 {
612 usb_interface = &dev->config->interface[ii];
613 break;
614 }
615 }
616 }
617 else
618 /* only one interface found */
619 usb_interface = dev->config->interface;
620
621 #ifdef O2MICRO_OZ776_PATCH
622 if (usb_interface != NULL
623 && (OZ776 == (dev->descriptor.idVendor << 16)
624 + dev->descriptor.idProduct)
625 && (0 == usb_interface->altsetting->extralen)) /* this is the bug */
626 {
627 int i;
628
629 for (i=0; i<usb_interface->altsetting->bNumEndpoints; i++)
630 {
631 /* find the extra[] array */
632 if (54 == usb_interface->altsetting->endpoint[i].extralen)
633 {
634 /* get the extra[] from the endpoint */
635 usb_interface->altsetting->extralen = 54;
636 usb_interface->altsetting->extra =
637 usb_interface->altsetting->endpoint[i].extra;
638 break;
639 }
640 }
641 }
642 #endif
643
644 return usb_interface;
645 } /* get_ccid_usb_interface */
646
647
648 /*****************************************************************************
649 *
650 * ccid_check_firmware
651 *
652 ****************************************************************************/
653 int ccid_check_firmware(struct usb_device *dev)
654 {
655 int i;
656
657 for (i=0; i<sizeof(Bogus_firmwares)/sizeof(Bogus_firmwares[0]); i++)
658 {
659 if (dev->descriptor.idVendor != Bogus_firmwares[i].vendor)
660 continue;
661
662 if (dev->descriptor.idProduct != Bogus_firmwares[i].product)
663 continue;
664
665 /* firmware too old and buggy */
666 if (dev->descriptor.bcdDevice < Bogus_firmwares[i].firmware)
667 {
668 if (DriverOptions & DRIVER_OPTION_USE_BOGUS_FIRMWARE)
669 {
670 DEBUG_INFO3("Firmware (%X.%02X) is bogus! but you choosed to use it",
671 dev->descriptor.bcdDevice >> 8,
672 dev->descriptor.bcdDevice & 0xFF);
673 return FALSE;
674 }
675 else
676 {
677 DEBUG_CRITICAL3("Firmware (%X.%02X) is bogus! Upgrade the reader firmware or get a new reader.",
678 dev->descriptor.bcdDevice >> 8,
679 dev->descriptor.bcdDevice & 0xFF);
680 return TRUE;
681 }
682 }
683 }
684
685 /* by default the firmware is not bogus */
686 return FALSE;
687 } /* ccid_check_firmware */
688
689 /*****************************************************************************
690 *
691 * get_data_rates
692 *
693 ****************************************************************************/
694 static unsigned int *get_data_rates(unsigned int reader_index)
695 {
696 int n, i;
697 unsigned char buffer[256*sizeof(int)]; /* maximum is 256 records */
698 unsigned int *int_array;
699
700 /* See CCID 3.7.3 page 25 */
701 n = usb_control_msg(usbDevice[reader_index].handle,
702 0xA1, /* request type */
703 0x03, /* GET_DATA_RATES */
704 0x00, /* value */
705 usbDevice[reader_index].interface, /* interface */
706 (char *)buffer,
707 sizeof(buffer),
708 usbDevice[reader_index].ccid.readTimeout * 1000);
709
710 if ((n <= 0) /* we got an error? */
711 || (n%4)) /* or a strange value */
712 {
713 struct usb_interface *usb_interface;
714
715 if (n <= 0)
716 DEBUG_INFO2("IFD does not support GET_DATA_RATES request: %s",
717 strerror(errno));
718
719 if (n%4)
720 DEBUG_INFO2("Wrong GET DATA RATES size: %d", n);
721
722 /* create a fake answer with only two values */
723 n = 2*4;
724
725 usb_interface = get_ccid_usb_interface(usbDevice[reader_index].dev);
726
727 /* dwDataRate (default data rate) */
728 memcpy(buffer, usb_interface->altsetting->extra +19, 4);
729
730 /* dwMaxDataRate */
731 memcpy(buffer+4, usb_interface->altsetting->extra +23, 4);
732 }
733
734 /* allocate the buffer (including the end marker) */
735 n /= sizeof(int);
736 int_array = calloc(n+1, sizeof(int));
737 if (NULL == int_array)
738 {
739 DEBUG_CRITICAL("Memory allocation failed");
740 return NULL;
741 }
742
743 /* convert in correct endianess */
744 for (i=0; i<n; i++)
745 {
746 int_array[i] = dw2i(buffer, i*4);
747 DEBUG_INFO2("declared: %d bps", int_array[i]);
748 }
749
750 /* end of array marker */
751 int_array[i] = 0;
752
753 return int_array;
754 }
755

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.5