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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1327 by rousseau, Sun Feb 20 14:34:42 2005 UTC revision 2602 by rousseau, Thu Aug 2 20:04:12 2007 UTC
# Line 2  Line 2 
2      ccid_usb.c: USB access routines using the libusb library      ccid_usb.c: USB access routines using the libusb library
3      Copyright (C) 2003-2004   Ludovic Rousseau      Copyright (C) 2003-2004   Ludovic Rousseau
4    
5      This program is free software; you can redistribute it and/or modify      This library is free software; you can redistribute it and/or
6      it under the terms of the GNU General Public License as published by      modify it under the terms of the GNU Lesser General Public
7      the Free Software Foundation; either version 2 of the License, or      License as published by the Free Software Foundation; either
8      (at your option) any later version.      version 2.1 of the License, or (at your option) any later version.
9    
10      This program is distributed in the hope that it will be useful,      This library is distributed in the hope that it will be useful,
11      but WITHOUT ANY WARRANTY; without even the implied warranty of      but WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      GNU General Public License for more details.      Lesser General Public License for more details.
14    
15      You should have received a copy of the GNU General Public License      You should have received a copy of the GNU Lesser General Public
16      along with this program; if not, write to the Free Software      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      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
18  */  */
19    
20  /*  /*
# Line 24  Line 24 
24  #define __CCID_USB__  #define __CCID_USB__
25    
26  #include <stdio.h>  #include <stdio.h>
27  #include <string.h>  #include <string.h>
28  #include <errno.h>  #include <errno.h>
29  # ifdef S_SPLINT_S  # ifdef S_SPLINT_S
30  # include <sys/types.h>  # include <sys/types.h>
31  # endif  # endif
32  #include <usb.h>  #include <usb.h>
33    
34    #include "misc.h"
35  #include "ccid.h"  #include "ccid.h"
36  #include "config.h"  #include "config.h"
37  #include "debug.h"  #include "debug.h"
# Line 40  Line 41 
41  #include "ccid_ifdhandler.h"  #include "ccid_ifdhandler.h"
42    
43    
 /* read timeout  
  * we must wait enough so that the card can finish its calculation  
  * the card, and then the reader should send TIME REQUEST bytes  
  * so this timeout should never occur */  
 #define USB_READ_TIMEOUT (60 * 1000)    /* 1 minute timeout */  
   
44  /* write timeout  /* write timeout
45   * we don't have to wait a long time since the card was doing nothing */   * 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 */  #define USB_WRITE_TIMEOUT (5 * 1000)  /* 5 seconds timeout */
# Line 58  Line 53 
53   * Manufacturer and Product ID are also used to identify the device */   * Manufacturer and Product ID are also used to identify the device */
54  #define ALLOW_PROPRIETARY_CLASS  #define ALLOW_PROPRIETARY_CLASS
55    
 /*  
  * The O2Micro OZ776S reader has a wrong USB descriptor  
  * The extra[] field is associated with the last endpoint instead of the  
  * main USB descriptor  
  */  
 #define O2MICRO_OZ776_PATCH  
   
56  #define BUS_DEVICE_STRSIZE 32  #define BUS_DEVICE_STRSIZE 32
57    
58  typedef struct  typedef struct
59  {  {
60          usb_dev_handle *handle;          usb_dev_handle *handle;
61          struct usb_device *dev;          char *dirname;
62            char *filename;
63          int interface;          int interface;
64    
65          /*          /*
# Line 79  typedef struct Line 68  typedef struct
68          int bulk_in;          int bulk_in;
69          int bulk_out;          int bulk_out;
70    
71            /* Number of slots using the same device */
72            int real_nb_opened_slots;
73            int *nb_opened_slots;
74    
75          /*          /*
76           * CCID infos common to USB and serial           * CCID infos common to USB and serial
77           */           */
# Line 89  typedef struct Line 82  typedef struct
82  /* The _usbDevice structure must be defined before including ccid_usb.h */  /* The _usbDevice structure must be defined before including ccid_usb.h */
83  #include "ccid_usb.h"  #include "ccid_usb.h"
84    
85  static int get_end_points(struct usb_device *dev, _usbDevice *usb_device);  static int get_end_points(struct usb_device *dev, _usbDevice *usbdevice);
86  int ccid_check_firmware(struct usb_device *dev);  int ccid_check_firmware(struct usb_device *dev);
87    static unsigned int *get_data_rates(unsigned int reader_index,
88            struct usb_device *dev);
89    
90  /* ne need to initialize to 0 since it is static */  /* ne need to initialize to 0 since it is static */
91  static _usbDevice usbDevice[CCID_DRIVER_MAX_READERS];  static _usbDevice usbDevice[CCID_DRIVER_MAX_READERS];
# Line 107  struct _bogus_firmware Line 102  struct _bogus_firmware
102  };  };
103    
104  static struct _bogus_firmware Bogus_firmwares[] = {  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 */  #ifndef O2MICRO_OZ776_PATCH
106            { 0x0b97, 0x7762, 0x0111 },     /* Oz776S */ /* the firmware version is not correct since I do not have received a working reader yet */
107    #endif
108          { 0x04e6, 0xe001, 0x0516 },     /* SCR 331 */          { 0x04e6, 0xe001, 0x0516 },     /* SCR 331 */
109          { 0x04e6, 0x5111, 0x0620 },     /* SCR 331-DI */          { 0x04e6, 0x5111, 0x0620 },     /* SCR 331-DI */
110          { 0x04e6, 0x5115, 0x0514 },     /* SCR 335 */          { 0x04e6, 0x5115, 0x0514 },     /* SCR 335 */
111          { 0x04e6, 0xe003, 0x0504 },     /* SPR 532 */          { 0x04e6, 0xe003, 0x0510 },     /* SPR 532 */
112          { 0x0D46, 0x3001, 0x0037 },     /* KAAN Base */          { 0x0D46, 0x3001, 0x0037 },     /* KAAN Base */
113          { 0x0D46, 0x3002, 0x0037 },     /* KAAN Advanced */          { 0x0D46, 0x3002, 0x0037 },     /* KAAN Advanced */
114            { 0x09C3, 0x0008, 0x0203 },     /* ActivCard V2 */
115            { 0x0DC3, 0x1004, 0x0502 },     /* ASE IIIe USBv2 */
116            { 0x0DC3, 0x1102, 0x0607 },     /* ASE IIIe KB USB */
117            { 0x058F, 0x9520, 0x0102 },     /* Alcor AU9520-G */
118  };  };
119    
120    /* data rates supported by the secondary slots on the GemCore Pos Pro & SIM Pro */
121    unsigned int SerialCustomDataRates[] = { GEMPLUS_CUSTOM_DATA_RATES, 0 };
122    
123    
124  /*****************************************************************************  /*****************************************************************************
125   *   *
# Line 140  status_t OpenUSBByName(unsigned int read Line 144  status_t OpenUSBByName(unsigned int read
144          struct usb_bus *bus;          struct usb_bus *bus;
145          struct usb_dev_handle *dev_handle;          struct usb_dev_handle *dev_handle;
146          char keyValue[TOKEN_MAX_VALUE_SIZE];          char keyValue[TOKEN_MAX_VALUE_SIZE];
147          int vendorID, productID;          unsigned int vendorID, productID;
148          char infofile[FILENAME_MAX];          char infofile[FILENAME_MAX];
149          unsigned int device_vendor, device_product;          unsigned int device_vendor, device_product;
150          char *dirname = NULL, *filename = NULL;          char *dirname = NULL, *filename = NULL;
# Line 222  status_t OpenUSBByName(unsigned int read Line 226  status_t OpenUSBByName(unsigned int read
226          /* general driver info */          /* general driver info */
227          if (!LTPBundleFindValueWithKey(infofile, "ifdManufacturerString", keyValue, 0))          if (!LTPBundleFindValueWithKey(infofile, "ifdManufacturerString", keyValue, 0))
228          {          {
229                  DEBUG_CRITICAL2("Manufacturer: %s", keyValue);                  DEBUG_INFO2("Manufacturer: %s", keyValue);
230          }          }
231          else          else
232          {          {
233                  DEBUG_CRITICAL2("LTPBundleFindValueWithKey error. Can't find %s?",                  DEBUG_INFO2("LTPBundleFindValueWithKey error. Can't find %s?",
234                          infofile);                          infofile);
235                  return STATUS_UNSUCCESSFUL;                  return STATUS_UNSUCCESSFUL;
236          }          }
237          if (!LTPBundleFindValueWithKey(infofile, "ifdProductString", keyValue, 0))          if (!LTPBundleFindValueWithKey(infofile, "ifdProductString", keyValue, 0))
238          {          {
239                  DEBUG_CRITICAL2("ProductString: %s", keyValue);                  DEBUG_INFO2("ProductString: %s", keyValue);
240          }          }
241          else          else
242                  return STATUS_UNSUCCESSFUL;                  return STATUS_UNSUCCESSFUL;
243          if (!LTPBundleFindValueWithKey(infofile, "Copyright", keyValue, 0))          if (!LTPBundleFindValueWithKey(infofile, "Copyright", keyValue, 0))
244          {          {
245                  DEBUG_CRITICAL2("Copyright: %s", keyValue);                  DEBUG_INFO2("Copyright: %s", keyValue);
246          }          }
247          else          else
248                  return STATUS_UNSUCCESSFUL;                  return STATUS_UNSUCCESSFUL;
249          vendorID = strlen(keyValue);          vendorID = strlen(keyValue);
250          alias = 0x1D;          alias = 0x1C;
251          for (; vendorID--;)          for (; vendorID--;)
252                  alias ^= keyValue[vendorID];                  alias ^= keyValue[vendorID];
253    
# Line 290  status_t OpenUSBByName(unsigned int read Line 294  status_t OpenUSBByName(unsigned int read
294                                          /* is it already opened? */                                          /* is it already opened? */
295                                          already_used = FALSE;                                          already_used = FALSE;
296    
297                                            DEBUG_COMM3("Checking device: %s/%s",
298                                                    bus->dirname, dev->filename);
299                                          for (r=0; r<CCID_DRIVER_MAX_READERS; r++)                                          for (r=0; r<CCID_DRIVER_MAX_READERS; r++)
300                                          {                                          {
301                                                  if (usbDevice[r].dev)                                                  if (usbDevice[r].handle)
302                                                  {                                                  {
                                                         DEBUG_COMM3("Checking device: %s/%s",  
                                                                 bus->dirname, dev->filename);  
303                                                          /* same busname, same filename */                                                          /* same busname, same filename */
304                                                          if (strcmp(usbDevice[r].dev->bus->dirname, bus->dirname) == 0 && strcmp(usbDevice[r].dev->filename, dev->filename) == 0)                                                          if (strcmp(usbDevice[r].dirname, bus->dirname) == 0 && strcmp(usbDevice[r].filename, dev->filename) == 0)
305                                                                  already_used = TRUE;                                                                  already_used = TRUE;
306                                                  }                                                  }
307                                          }                                          }
# Line 306  status_t OpenUSBByName(unsigned int read Line 310  status_t OpenUSBByName(unsigned int read
310                                          if (already_used)                                          if (already_used)
311                                          {                                          {
312                                                  if ((previous_reader_index != -1)                                                  if ((previous_reader_index != -1)
313                                                          && (strcmp(usbDevice[previous_reader_index].dev->bus->dirname, bus->dirname)  == 0)                                                          && usbDevice[previous_reader_index].handle
314                                                          && (strcmp(usbDevice[previous_reader_index].dev->filename, dev->filename) == 0)                                                          && (strcmp(usbDevice[previous_reader_index].dirname, bus->dirname)  == 0)
315                                                            && (strcmp(usbDevice[previous_reader_index].filename, dev->filename) == 0)
316                                                          && usbDevice[previous_reader_index].ccid.bCurrentSlotIndex < usbDevice[previous_reader_index].ccid.bMaxSlotIndex)                                                          && usbDevice[previous_reader_index].ccid.bCurrentSlotIndex < usbDevice[previous_reader_index].ccid.bMaxSlotIndex)
317                                                  {                                                  {
318                                                          /* we reuse the same device                                                          /* we reuse the same device
319                                                           * and the reader is multi-slot */                                                           * and the reader is multi-slot */
320                                                          usbDevice[reader_index] = usbDevice[previous_reader_index];                                                          usbDevice[reader_index] = usbDevice[previous_reader_index];
321                                                          usbDevice[reader_index].ccid.pbSeq = usbDevice[previous_reader_index].ccid.pbSeq;                                                          /* the other slots do not have the same data rates */
322                                                            if ((GEMCOREPOSPRO == usbDevice[reader_index].ccid.readerID)
323                                                                    || (GEMCORESIMPRO == usbDevice[reader_index].ccid.readerID))
324                                                            {
325                                                                    usbDevice[reader_index].ccid.arrayOfSupportedDataRates = SerialCustomDataRates;
326                                                                    usbDevice[reader_index].ccid.dwMaxDataRate = 125000;
327                                                            }
328    
329                                                            *usbDevice[reader_index].nb_opened_slots += 1;
330                                                          usbDevice[reader_index].ccid.bCurrentSlotIndex++;                                                          usbDevice[reader_index].ccid.bCurrentSlotIndex++;
331                                                          DEBUG_INFO2("Opening slot: %d",                                                          DEBUG_INFO2("Opening slot: %d",
332                                                                  usbDevice[reader_index].ccid.bCurrentSlotIndex);                                                                  usbDevice[reader_index].ccid.bCurrentSlotIndex);
# Line 344  status_t OpenUSBByName(unsigned int read Line 357  status_t OpenUSBByName(unsigned int read
357                                          /* now we found a free reader and we try to use it */                                          /* now we found a free reader and we try to use it */
358                                          if (dev->config == NULL)                                          if (dev->config == NULL)
359                                          {                                          {
360                                                    usb_close(dev_handle);
361                                                  DEBUG_CRITICAL3("No dev->config found for %s/%s",                                                  DEBUG_CRITICAL3("No dev->config found for %s/%s",
362                                                           bus->dirname, dev->filename);                                                           bus->dirname, dev->filename);
363                                                  return STATUS_UNSUCCESSFUL;                                                  return STATUS_UNSUCCESSFUL;
# Line 352  status_t OpenUSBByName(unsigned int read Line 366  status_t OpenUSBByName(unsigned int read
366                                          usb_interface = get_ccid_usb_interface(dev);                                          usb_interface = get_ccid_usb_interface(dev);
367                                          if (usb_interface == NULL)                                          if (usb_interface == NULL)
368                                          {                                          {
369                                                    usb_close(dev_handle);
370                                                  DEBUG_CRITICAL3("Can't find a CCID interface on %s/%s",                                                  DEBUG_CRITICAL3("Can't find a CCID interface on %s/%s",
371                                                          bus->dirname, dev->filename);                                                          bus->dirname, dev->filename);
372                                                  return STATUS_UNSUCCESSFUL;                                                  return STATUS_UNSUCCESSFUL;
373                                          }                                          }
374    
375                                          if (usb_interface->altsetting->extralen != 54)                                          if (usb_interface->altsetting->extralen != 54)
376                                          {                                          {
377                                                    usb_close(dev_handle);
378                                                  DEBUG_CRITICAL4("Extra field for %s/%s has a wrong length: %d", bus->dirname, dev->filename, usb_interface->altsetting->extralen);                                                  DEBUG_CRITICAL4("Extra field for %s/%s has a wrong length: %d", bus->dirname, dev->filename, usb_interface->altsetting->extralen);
379                                                  return STATUS_UNSUCCESSFUL;                                                  return STATUS_UNSUCCESSFUL;
380                                          }                                          }
# Line 366  status_t OpenUSBByName(unsigned int read Line 382  status_t OpenUSBByName(unsigned int read
382                                          interface = usb_interface->altsetting->bInterfaceNumber;                                          interface = usb_interface->altsetting->bInterfaceNumber;
383                                          if (usb_claim_interface(dev_handle, interface) < 0)                                          if (usb_claim_interface(dev_handle, interface) < 0)
384                                          {                                          {
385                                                    usb_close(dev_handle);
386                                                  DEBUG_CRITICAL4("Can't claim interface %s/%s: %s",                                                  DEBUG_CRITICAL4("Can't claim interface %s/%s: %s",
387                                                          bus->dirname, dev->filename, strerror(errno));                                                          bus->dirname, dev->filename, strerror(errno));
388                                                  return STATUS_UNSUCCESSFUL;                                                  return STATUS_UNSUCCESSFUL;
# Line 379  status_t OpenUSBByName(unsigned int read Line 396  status_t OpenUSBByName(unsigned int read
396    
397                                          /* check for firmware bugs */                                          /* check for firmware bugs */
398                                          if (ccid_check_firmware(dev))                                          if (ccid_check_firmware(dev))
399                                            {
400                                                    usb_close(dev_handle);
401                                                  return STATUS_UNSUCCESSFUL;                                                  return STATUS_UNSUCCESSFUL;
402                                            }
403    
404                                          /* Get Endpoints values*/                                          /* Get Endpoints values*/
405                                          get_end_points(dev, &usbDevice[reader_index]);                                          get_end_points(dev, &usbDevice[reader_index]);
406    
407                                          /* store device information */                                          /* store device information */
408                                          usbDevice[reader_index].handle = dev_handle;                                          usbDevice[reader_index].handle = dev_handle;
409                                          usbDevice[reader_index].dev = dev;                                          usbDevice[reader_index].dirname = strdup(bus->dirname);
410                                            usbDevice[reader_index].filename = strdup(dev->filename);
411                                          usbDevice[reader_index].interface = interface;                                          usbDevice[reader_index].interface = interface;
412                                            usbDevice[reader_index].real_nb_opened_slots = 1;
413                                            usbDevice[reader_index].nb_opened_slots = &usbDevice[reader_index].real_nb_opened_slots;
414    
415                                          /* CCID common informations */                                          /* CCID common informations */
416                                          usbDevice[reader_index].ccid.real_bSeq = 0;                                          usbDevice[reader_index].ccid.real_bSeq = 0;
# Line 403  status_t OpenUSBByName(unsigned int read Line 426  status_t OpenUSBByName(unsigned int read
426                                          usbDevice[reader_index].ccid.dwMaxDataRate = dw2i(usb_interface->altsetting->extra, 23);                                          usbDevice[reader_index].ccid.dwMaxDataRate = dw2i(usb_interface->altsetting->extra, 23);
427                                          usbDevice[reader_index].ccid.bMaxSlotIndex = usb_interface->altsetting->extra[4];                                          usbDevice[reader_index].ccid.bMaxSlotIndex = usb_interface->altsetting->extra[4];
428                                          usbDevice[reader_index].ccid.bCurrentSlotIndex = 0;                                          usbDevice[reader_index].ccid.bCurrentSlotIndex = 0;
429                                            usbDevice[reader_index].ccid.readTimeout = DEFAULT_COM_READ_TIMEOUT;
430                                            usbDevice[reader_index].ccid.arrayOfSupportedDataRates = get_data_rates(reader_index, dev);
431                                            usbDevice[reader_index].ccid.bInterfaceProtocol = usb_interface->altsetting->bInterfaceProtocol;
432                                          goto end;                                          goto end;
433                                  }                                  }
434                          }                          }
# Line 429  status_t WriteUSB(unsigned int reader_in Line 455  status_t WriteUSB(unsigned int reader_in
455          unsigned char *buffer)          unsigned char *buffer)
456  {  {
457          int rv;          int rv;
 #ifdef DEBUG_LEVEL_COMM  
458          char debug_header[] = "-> 121234 ";          char debug_header[] = "-> 121234 ";
459    
460          sprintf(debug_header, "-> %06X ", (int)reader_index);          sprintf(debug_header, "-> %06X ", (int)reader_index);
 #endif  
461    
 #ifdef DEBUG_LEVEL_COMM  
462          DEBUG_XXD(debug_header, buffer, length);          DEBUG_XXD(debug_header, buffer, length);
 #endif  
463    
464          rv = usb_bulk_write(usbDevice[reader_index].handle,          rv = usb_bulk_write(usbDevice[reader_index].handle,
465                  usbDevice[reader_index].bulk_out, (char *)buffer, length,                  usbDevice[reader_index].bulk_out, (char *)buffer, length,
# Line 446  status_t WriteUSB(unsigned int reader_in Line 468  status_t WriteUSB(unsigned int reader_in
468          if (rv < 0)          if (rv < 0)
469          {          {
470                  DEBUG_CRITICAL4("usb_bulk_write(%s/%s): %s",                  DEBUG_CRITICAL4("usb_bulk_write(%s/%s): %s",
471                          usbDevice[reader_index].dev->bus->dirname,                          usbDevice[reader_index].dirname, usbDevice[reader_index].filename,
472                          usbDevice[reader_index].dev->filename, strerror(errno));                          strerror(errno));
473    
474                    if (ENODEV == errno)
475                            return STATUS_NO_SUCH_DEVICE;
476    
477                  return STATUS_UNSUCCESSFUL;                  return STATUS_UNSUCCESSFUL;
478          }          }
479    
# Line 464  status_t ReadUSB(unsigned int reader_ind Line 490  status_t ReadUSB(unsigned int reader_ind
490          unsigned char *buffer)          unsigned char *buffer)
491  {  {
492          int rv;          int rv;
 #ifdef DEBUG_LEVEL_COMM  
493          char debug_header[] = "<- 121234 ";          char debug_header[] = "<- 121234 ";
494            _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
495    
496    read_again:
497          sprintf(debug_header, "<- %06X ", (int)reader_index);          sprintf(debug_header, "<- %06X ", (int)reader_index);
 #endif  
498    
499          rv = usb_bulk_read(usbDevice[reader_index].handle,          rv = usb_bulk_read(usbDevice[reader_index].handle,
500                  usbDevice[reader_index].bulk_in, (char *)buffer, *length,                  usbDevice[reader_index].bulk_in, (char *)buffer, *length,
501                  USB_READ_TIMEOUT);                  usbDevice[reader_index].ccid.readTimeout * 1000);
502    
503          if (rv < 0)          if (rv < 0)
504          {          {
505                  *length = 0;                  *length = 0;
506                  DEBUG_CRITICAL4("usb_bulk_read(%s/%s): %s",                  DEBUG_CRITICAL4("usb_bulk_read(%s/%s): %s",
507                          usbDevice[reader_index].dev->bus->dirname,                          usbDevice[reader_index].dirname, usbDevice[reader_index].filename,
508                          usbDevice[reader_index].dev->filename, strerror(errno));                          strerror(errno));
509    
510                    if (ENODEV == errno)
511                            return STATUS_NO_SUCH_DEVICE;
512    
513                  return STATUS_UNSUCCESSFUL;                  return STATUS_UNSUCCESSFUL;
514          }          }
515    
516          *length = rv;          *length = rv;
517    
 #ifdef DEBUG_LEVEL_COMM  
518          DEBUG_XXD(debug_header, buffer, *length);          DEBUG_XXD(debug_header, buffer, *length);
519  #endif  
520    #define BSEQ_OFFSET 6
521            if ((*length >= BSEQ_OFFSET)
522                    && (buffer[BSEQ_OFFSET] < *ccid_descriptor->pbSeq -1))
523            {
524                    DEBUG_INFO("Duplicate frame detected");
525                    goto read_again;
526            }
527    
528          return STATUS_SUCCESS;          return STATUS_SUCCESS;
529  } /* ReadUSB */  } /* ReadUSB */
# Line 501  status_t ReadUSB(unsigned int reader_ind Line 537  status_t ReadUSB(unsigned int reader_ind
537  status_t CloseUSB(unsigned int reader_index)  status_t CloseUSB(unsigned int reader_index)
538  {  {
539          /* device not opened */          /* device not opened */
540          if (usbDevice[reader_index].dev == NULL)          if (usbDevice[reader_index].handle == NULL)
541                  return STATUS_UNSUCCESSFUL;                  return STATUS_UNSUCCESSFUL;
542    
543          DEBUG_COMM3("Closing USB device: %s/%s",          DEBUG_COMM3("Closing USB device: %s/%s",
544                  usbDevice[reader_index].dev->bus->dirname,                  usbDevice[reader_index].dirname,
545                  usbDevice[reader_index].dev->filename);                  usbDevice[reader_index].filename);
546    
547            if (usbDevice[reader_index].ccid.arrayOfSupportedDataRates
548                    && (usbDevice[reader_index].ccid.bCurrentSlotIndex == 0))
549            {
550                    free(usbDevice[reader_index].ccid.arrayOfSupportedDataRates);
551                    usbDevice[reader_index].ccid.arrayOfSupportedDataRates = NULL;
552            }
553    
554          /* reset so that bSeq starts at 0 again */          /* one slot closed */
555          usb_reset(usbDevice[reader_index].handle);          (*usbDevice[reader_index].nb_opened_slots)--;
556    
557          usb_release_interface(usbDevice[reader_index].handle,          /* release the allocated ressources for the last slot only */
558                  usbDevice[reader_index].interface);          if (0 == *usbDevice[reader_index].nb_opened_slots)
559          usb_close(usbDevice[reader_index].handle);          {
560                    DEBUG_COMM("Last slot closed. Release resources");
561    
562                    /* reset so that bSeq starts at 0 again */
563                    if (DriverOptions & DRIVER_OPTION_RESET_ON_CLOSE)
564                            usb_reset(usbDevice[reader_index].handle);
565    
566                    usb_release_interface(usbDevice[reader_index].handle,
567                            usbDevice[reader_index].interface);
568                    usb_close(usbDevice[reader_index].handle);
569    
570                    free(usbDevice[reader_index].dirname);
571                    free(usbDevice[reader_index].filename);
572            }
573    
574          /* mark the resource unused */          /* mark the resource unused */
575          usbDevice[reader_index].handle = NULL;          usbDevice[reader_index].handle = NULL;
576          usbDevice[reader_index].dev = NULL;          usbDevice[reader_index].dirname = NULL;
577            usbDevice[reader_index].filename = NULL;
578          usbDevice[reader_index].interface = 0;          usbDevice[reader_index].interface = 0;
579    
580          return STATUS_SUCCESS;          return STATUS_SUCCESS;
# Line 537  _ccid_descriptor *get_ccid_descriptor(un Line 594  _ccid_descriptor *get_ccid_descriptor(un
594    
595  /*****************************************************************************  /*****************************************************************************
596   *   *
  *                                      get_desc  
  *  
  ****************************************************************************/  
 int get_desc(int lun, usb_dev_handle **handle, struct  
         usb_device **dev)  
 {  
         int reader_index;  
   
         if (-1 == (reader_index = LunToReaderIndex(lun)))  
                 return FALSE;  
   
         *handle = usbDevice[reader_index].handle;  
         *dev = usbDevice[reader_index].dev;  
   
         return TRUE;  
 } /* get_desc */  
   
   
 /*****************************************************************************  
  *  
597   *                                      get_end_points   *                                      get_end_points
598   *   *
599   ****************************************************************************/   ****************************************************************************/
600  static int get_end_points(struct usb_device *dev, _usbDevice *usb_device)  static int get_end_points(struct usb_device *dev, _usbDevice *usbdevice)
601  {  {
602          int i;          int i;
603          int bEndpointAddress;          int bEndpointAddress;
604          struct usb_interface *usb_interface = get_ccid_usb_interface(dev);          struct usb_interface *usb_interface = get_ccid_usb_interface(dev);
605    
606          /*          /*
607           * 3 Endpoints maximum: Interrupt In, Bulk In, Bulk Out           * 3 Endpoints maximum: Interrupt In, Bulk In, Bulk Out
608           */           */
609          for (i=0; i<3; i++)          for (i=0; i<usb_interface->altsetting->bNumEndpoints; i++)
610          {          {
611                  if (usb_interface->altsetting->endpoint[i].bmAttributes != USB_ENDPOINT_TYPE_BULK)                  if (usb_interface->altsetting->endpoint[i].bmAttributes != USB_ENDPOINT_TYPE_BULK)
612                          continue;                          continue;
# Line 577  static int get_end_points(struct usb_dev Line 614  static int get_end_points(struct usb_dev
614                  bEndpointAddress = usb_interface->altsetting->endpoint[i].bEndpointAddress;                  bEndpointAddress = usb_interface->altsetting->endpoint[i].bEndpointAddress;
615    
616                  if ((bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_IN)                  if ((bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_IN)
617                          usb_device->bulk_in = bEndpointAddress;                          usbdevice->bulk_in = bEndpointAddress;
618    
619                  if ((bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_OUT)                  if ((bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_OUT)
620                          usb_device->bulk_out = bEndpointAddress;                          usbdevice->bulk_out = bEndpointAddress;
621          }          }
622    
623          return 0;          return 0;
# Line 592  static int get_end_points(struct usb_dev Line 629  static int get_end_points(struct usb_dev
629   *                                      get_ccid_usb_interface   *                                      get_ccid_usb_interface
630   *   *
631   ****************************************************************************/   ****************************************************************************/
632  /*@null@*/ struct usb_interface * get_ccid_usb_interface(struct usb_device *dev)  /*@null@*/ EXTERNAL struct usb_interface * get_ccid_usb_interface(struct usb_device *dev)
633  {  {
634          struct usb_interface *usb_interface = NULL;          struct usb_interface *usb_interface = NULL;
635            int i;
636    #ifdef O2MICRO_OZ776_PATCH
637            int readerID;
638    #endif
639    
640          /* if multiple interfaces use the first one with CCID class type */          /* if multiple interfaces use the first one with CCID class type */
641          if (dev->config->bNumInterfaces > 1)          for (i=0; i<dev->config->bNumInterfaces; i++)
642          {          {
643                  int ii;                  /* CCID Class? */
644                  for (ii=0; ii<dev->config->bNumInterfaces; ii++)                  if (dev->config->interface[i].altsetting->bInterfaceClass == 0xb
                 {  
                         /* CCID Class? */  
                         if (dev->config->interface[ii].altsetting->bInterfaceClass == 0xb  
645  #ifdef ALLOW_PROPRIETARY_CLASS  #ifdef ALLOW_PROPRIETARY_CLASS
646                                  || dev->config->interface[ii].altsetting->bInterfaceClass == 0xff                          || dev->config->interface[i].altsetting->bInterfaceClass == 0xff
647  #endif  #endif
648                                  )                          )
649                          {                  {
650                                  usb_interface = &dev->config->interface[ii];                          usb_interface = &dev->config->interface[i];
651                                  break;                          break;
                         }  
652                  }                  }
653          }          }
         else  
                 /* only one interface found */  
                 usb_interface = dev->config->interface;  
654    
655  #ifdef O2MICRO_OZ776_PATCH  #ifdef O2MICRO_OZ776_PATCH
656            readerID = (dev->descriptor.idVendor << 16) + dev->descriptor.idProduct;
657          if (usb_interface != NULL          if (usb_interface != NULL
658                  && (OZ776 == (dev->descriptor.idVendor << 16)                  && ((OZ776 == readerID) || (OZ776_7772 == readerID))
                 + dev->descriptor.idProduct)  
659                  && (0 == usb_interface->altsetting->extralen)) /* this is the bug */                  && (0 == usb_interface->altsetting->extralen)) /* this is the bug */
660          {          {
                 int i;  
   
661                  for (i=0; i<usb_interface->altsetting->bNumEndpoints; i++)                  for (i=0; i<usb_interface->altsetting->bNumEndpoints; i++)
662                  {                  {
663                          /* find the extra[] array */                          /* find the extra[] array */
# Line 635  static int get_end_points(struct usb_dev Line 667  static int get_end_points(struct usb_dev
667                                  usb_interface->altsetting->extralen = 54;                                  usb_interface->altsetting->extralen = 54;
668                                  usb_interface->altsetting->extra =                                  usb_interface->altsetting->extra =
669                                          usb_interface->altsetting->endpoint[i].extra;                                          usb_interface->altsetting->endpoint[i].extra;
670                                    /* avoid double free on close */
671                                    usb_interface->altsetting->endpoint[i].extra = NULL;
672                                    usb_interface->altsetting->endpoint[i].extralen = 0;
673                                  break;                                  break;
674                          }                          }
675                  }                  }
# Line 686  int ccid_check_firmware(struct usb_devic Line 721  int ccid_check_firmware(struct usb_devic
721          return FALSE;          return FALSE;
722  } /* ccid_check_firmware */  } /* ccid_check_firmware */
723    
724    /*****************************************************************************
725     *
726     *                                      get_data_rates
727     *
728     ****************************************************************************/
729    static unsigned int *get_data_rates(unsigned int reader_index,
730            struct usb_device *dev)
731    {
732            int n, i, len;
733            unsigned char buffer[256*sizeof(int)];  /* maximum is 256 records */
734            unsigned int *int_array;
735    
736            /* See CCID 3.7.3 page 25 */
737            n = ControlUSB(reader_index,
738                    0xA1, /* request type */
739                    0x03, /* GET_DATA_RATES */
740                    0x00, /* value */
741                    buffer, sizeof(buffer));
742    
743            /* we got an error? */
744            if (n <= 0)
745            {
746                    DEBUG_INFO2("IFD does not support GET_DATA_RATES request: %s",
747                            strerror(errno));
748                    return NULL;
749            }
750    
751            /* we got a strange value */
752            if (n % 4)
753            {
754                    DEBUG_INFO2("Wrong GET DATA RATES size: %d", n);
755                    return NULL;
756            }
757    
758            /* allocate the buffer (including the end marker) */
759            n /= sizeof(int);
760    
761            /* we do not get the expected number of data rates */
762            len = get_ccid_usb_interface(dev)->altsetting->extra[27]; /* bNumDataRatesSupported */
763            if ((n != len) && len)
764            {
765                    DEBUG_INFO3("Got %d data rates but was expecting %d", n, len);
766    
767                    /* we got more data than expected */
768                    if (n > len)
769                            n = len;
770            }
771    
772            int_array = calloc(n+1, sizeof(int));
773            if (NULL == int_array)
774            {
775                    DEBUG_CRITICAL("Memory allocation failed");
776                    return NULL;
777            }
778    
779            /* convert in correct endianess */
780            for (i=0; i<n; i++)
781            {
782                    int_array[i] = dw2i(buffer, i*4);
783                    DEBUG_INFO2("declared: %d bps", int_array[i]);
784            }
785    
786            /* end of array marker */
787            int_array[i] = 0;
788    
789            return int_array;
790    }
791    
792    int ControlUSB(int reader_index, int requesttype, int request, int value,
793            unsigned char *bytes, unsigned int size)
794    {
795            int ret;
796    
797            DEBUG_COMM2("request: 0x%02X", request);
798    
799            if (0 == (requesttype & 0x80))
800                    DEBUG_XXD("send: ", bytes, size);
801    
802            ret = usb_control_msg(usbDevice[reader_index].handle, requesttype,
803                    request, value, usbDevice[reader_index].interface, (char *)bytes, size,
804                    usbDevice[reader_index].ccid.readTimeout * 1000);
805    
806            if (requesttype & 0x80)
807                    DEBUG_XXD("receive: ", bytes, ret);
808    
809            return ret;
810    }
811    

Legend:
Removed from v.1327  
changed lines
  Added in v.2602

  ViewVC Help
Powered by ViewVC 1.1.5