/[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 738 - (hide annotations) (download)
Tue Mar 30 13:01:05 2004 UTC (9 years, 1 month ago) by rousseau
File MIME type: text/plain
File size: 13944 byte(s)
allow proprietary CCID Class byte but only if ALLOW_PROPRIETARY_CLASS is
defined. You should know what you do. Only useful for pre-CCID devices.
1 rousseau 269 /*
2     ccid_usb.c: USB access routines using the libusb library
3 rousseau 649 Copyright (C) 2003-2004 Ludovic Rousseau
4 rousseau 269
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9    
10     This program 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
13     GNU General Public License for more details.
14    
15     You should have received a copy of the GNU General Public License
16     along with this program; 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     #include <usb.h>
30    
31     #include "pcscdefines.h"
32     #include "config.h"
33     #include "debug.h"
34     #include "utils.h"
35     #include "parser.h"
36 rousseau 406 #include "ccid.h"
37 rousseau 269
38    
39 rousseau 570 /* read timeout
40     * we must wait enough so that the card can finish its calculation
41     * the card, and then the reader should send TIME REQUEST bytes
42     * so this timeout should never occur */
43     #define USB_READ_TIMEOUT (60 * 1000) /* 1 minute timeout */
44 rousseau 269
45 rousseau 570 /* write timeout
46     * we don't have to wait a long time since the card was doing nothing */
47     #define USB_WRITE_TIMEOUT (5 * 1000) /* 5 seconds timeout */
48    
49    
50 rousseau 269 #define BUS_DEVICE_STRSIZE 32
51    
52     typedef struct
53     {
54     usb_dev_handle *handle;
55     struct usb_device *dev;
56    
57     /*
58     * Endpoints
59     */
60     int bulk_in;
61     int bulk_out;
62 rousseau 406
63     /*
64     * CCID infos common to USB and serial
65     */
66     _ccid_descriptor ccid;
67    
68 rousseau 269 } _usbDevice;
69    
70 rousseau 406 /* The _usbDevice structure must be defined before including ccid_usb.h */
71 rousseau 269 #include "ccid_usb.h"
72    
73 rousseau 406 static _usbDevice usbDevice[PCSCLITE_MAX_READERS] = {
74 rousseau 662 [ 0 ... (PCSCLITE_MAX_READERS-1) ] = { NULL, NULL, 0, 0 }
75 rousseau 269 };
76    
77     #define PCSCLITE_MANUKEY_NAME "ifdVendorID"
78     #define PCSCLITE_PRODKEY_NAME "ifdProductID"
79     #define PCSCLITE_NAMEKEY_NAME "ifdFriendlyName"
80    
81 rousseau 649
82 rousseau 269 /*****************************************************************************
83     *
84     * OpenUSB
85     *
86     ****************************************************************************/
87     status_t OpenUSB(int lun, int Channel)
88     {
89 rousseau 649 return OpenUSBByName(lun, NULL);
90     } /* OpenUSB */
91    
92    
93     /*****************************************************************************
94     *
95     * OpenUSBByName
96     *
97     ****************************************************************************/
98     status_t OpenUSBByName(int lun, char *device)
99     {
100 rousseau 269 static struct usb_bus *busses = NULL;
101     int reader = LunToReaderIndex(lun);
102     int alias = 0;
103     struct usb_bus *bus;
104     struct usb_dev_handle *dev_handle;
105     char keyValue[TOKEN_MAX_VALUE_SIZE];
106     int vendorID, productID;
107 rousseau 301 char infofile[FILENAME_MAX];
108 rousseau 662 int device_vendor, device_product;
109 rousseau 269
110 rousseau 662 DEBUG_COMM3("Lun: %X, Device: %s", lun, device);
111 rousseau 269
112 rousseau 662 /* device name specified */
113     if (device)
114     {
115     if (strncmp("usb:", device, 4) != 0)
116     {
117     DEBUG_CRITICAL2("device name does not start with \"usb:\": %s",
118     device);
119     return STATUS_UNSUCCESSFUL;
120     }
121    
122     if (sscanf(device, "usb:%x/%x", &device_vendor, &device_product) != 2)
123     {
124     DEBUG_CRITICAL2("device name can't be parsed: %s", device);
125     return STATUS_UNSUCCESSFUL;
126     }
127     }
128    
129 rousseau 269 if (busses == NULL)
130     usb_init();
131    
132     usb_find_busses();
133     usb_find_devices();
134    
135     busses = usb_get_busses();
136    
137     if (busses == NULL)
138     {
139     DEBUG_CRITICAL("No USB busses found");
140     return STATUS_UNSUCCESSFUL;
141     }
142    
143     /* is the lun already used? */
144     if (usbDevice[reader].handle != NULL)
145     {
146     DEBUG_CRITICAL2("USB driver with lun %X already in use", lun);
147     return STATUS_UNSUCCESSFUL;
148     }
149    
150 rousseau 301 /* Info.plist full patch filename */
151 rousseau 406 snprintf(infofile, sizeof(infofile), "%s/%s/Contents/Info.plist",
152     PCSCLITE_HP_DROPDIR, BUNDLE);
153 rousseau 301
154 rousseau 269 /* general driver info */
155 rousseau 301 if (!LTPBundleFindValueWithKey(infofile, "ifdManufacturerString", keyValue, 0))
156 rousseau 269 DEBUG_CRITICAL2("Manufacturer: %s", keyValue);
157     else
158     {
159     DEBUG_CRITICAL2("LTPBundleFindValueWithKey error. Can't find %s?",
160 rousseau 301 infofile);
161 rousseau 269 return STATUS_UNSUCCESSFUL;
162     }
163 rousseau 301 if (!LTPBundleFindValueWithKey(infofile, "ifdProductString", keyValue, 0))
164 rousseau 269 DEBUG_CRITICAL2("ProductString: %s", keyValue);
165     else
166     return STATUS_UNSUCCESSFUL;
167 rousseau 301 if (!LTPBundleFindValueWithKey(infofile, "Copyright", keyValue, 0))
168 rousseau 269 DEBUG_CRITICAL2("Copyright: %s", keyValue);
169     else
170     return STATUS_UNSUCCESSFUL;
171     vendorID = strlen(keyValue);
172     alias = 0x1D;
173     for (; vendorID--;)
174     alias ^= keyValue[vendorID];
175    
176     /* for any supported reader */
177 rousseau 301 while (LTPBundleFindValueWithKey(infofile, PCSCLITE_MANUKEY_NAME, keyValue, alias) == 0)
178 rousseau 269 {
179 rousseau 301 vendorID = strtoul(keyValue, 0, 16);
180 rousseau 269
181 rousseau 301 if (LTPBundleFindValueWithKey(infofile, PCSCLITE_PRODKEY_NAME, keyValue, alias))
182 rousseau 269 goto end;
183 rousseau 301 productID = strtoul(keyValue, 0, 16);
184 rousseau 269
185 rousseau 301 if (LTPBundleFindValueWithKey(infofile, PCSCLITE_NAMEKEY_NAME, keyValue, alias))
186 rousseau 269 goto end;
187    
188 rousseau 662 /* go to next supported reader for next round */
189     alias++;
190    
191     /* the device was specified but is not the one we are trying to find */
192     if (device
193     && (vendorID != device_vendor || productID != device_product))
194     continue;
195    
196 rousseau 269 /* on any USB buses */
197     for (bus = busses; bus; bus = bus->next)
198     {
199     struct usb_device *dev;
200    
201     /* any device on this bus */
202     for (dev = bus->devices; dev; dev = dev->next)
203     {
204     if (dev->descriptor.idVendor == vendorID
205     && dev->descriptor.idProduct == productID)
206     {
207     int r, already_used;
208 rousseau 662 struct usb_interface *usb_interface = NULL;
209     int interface;
210 rousseau 269
211     /* is it already opened? */
212     already_used = FALSE;
213 rousseau 649
214 rousseau 662 for (r=0; r<PCSCLITE_MAX_READERS; r++)
215 rousseau 269 {
216 rousseau 662 if (usbDevice[r].dev)
217 rousseau 269 {
218 rousseau 662 DEBUG_COMM3("Checking device: %s/%s",
219     bus->dirname, dev->filename);
220     /* same busname, same filename */
221     if (strcmp(usbDevice[r].dev->bus->dirname, bus->dirname) == 0 && strcmp(usbDevice[r].dev->filename, dev->filename) == 0)
222     already_used = TRUE;
223 rousseau 269 }
224     }
225    
226 rousseau 662 /* this reader is already managed by us */
227     if (already_used)
228 rousseau 269 {
229 rousseau 662 DEBUG_INFO3("USB device %s/%s already in use. Checking next one.",
230     bus->dirname, dev->filename);
231 rousseau 301
232 rousseau 662 continue;
233     }
234 rousseau 269
235 rousseau 662 DEBUG_COMM3("Trying to open USB bus/device: %s/%s",
236     bus->dirname, dev->filename);
237 rousseau 269
238 rousseau 662 dev_handle = usb_open(dev);
239     if (dev_handle == NULL)
240     {
241     DEBUG_CRITICAL4("Can't usb_open(%s/%s): %s",
242     bus->dirname, dev->filename, strerror(errno));
243 rousseau 650
244 rousseau 662 continue;
245     }
246 rousseau 579
247 rousseau 662 /* now we found a free reader and we try to use it */
248     if (dev->config == NULL)
249     {
250     DEBUG_CRITICAL3("No dev->config found for %s/%s",
251     bus->dirname, dev->filename);
252     return STATUS_UNSUCCESSFUL;
253     }
254 rousseau 269
255 rousseau 662 usb_interface = get_ccid_usb_interface(dev);
256     if (usb_interface == NULL)
257     {
258     DEBUG_CRITICAL3("Can't find a CCID interface on %s/%s",
259     bus->dirname, dev->filename);
260     return STATUS_UNSUCCESSFUL;
261     }
262 rousseau 269
263 rousseau 662 if (usb_interface->altsetting->extralen != 54)
264     {
265     DEBUG_CRITICAL4("Extra field for %s/%s has a wrong length: %d", bus->dirname, dev->filename, usb_interface->altsetting->extralen);
266     return STATUS_UNSUCCESSFUL;
267 rousseau 269 }
268 rousseau 662
269     interface = usb_interface->altsetting->bInterfaceNumber;
270     if (usb_claim_interface(dev_handle, interface) < 0)
271 rousseau 269 {
272 rousseau 662 DEBUG_CRITICAL4("Can't claim interface %s/%s: %s",
273     bus->dirname, dev->filename, strerror(errno));
274     return STATUS_UNSUCCESSFUL;
275 rousseau 269 }
276 rousseau 662
277     DEBUG_INFO4("Found Vendor/Product: %04X/%04X (%s)",
278     dev->descriptor.idVendor,
279     dev->descriptor.idProduct, keyValue);
280     DEBUG_INFO3("Using USB bus/device: %s/%s",
281     bus->dirname, dev->filename);
282    
283     /* Get Endpoints values*/
284     get_end_points(dev, &usbDevice[reader]);
285    
286     /* store device information */
287     usbDevice[reader].handle = dev_handle;
288     usbDevice[reader].dev = dev;
289    
290     /* CCID common informations */
291 rousseau 683 usbDevice[reader].ccid.bSeq = 0;
292 rousseau 662 usbDevice[reader].ccid.readerID =
293     (dev->descriptor.idVendor << 16) +
294     dev->descriptor.idProduct;
295     usbDevice[reader].ccid.dwFeatures = dw2i(usb_interface->altsetting->extra, 40);
296     usbDevice[reader].ccid.dwMaxCCIDMessageLength = dw2i(usb_interface->altsetting->extra, 44);
297 rousseau 672 usbDevice[reader].ccid.dwMaxIFSD = dw2i(usb_interface->altsetting->extra, 28);
298 rousseau 694 usbDevice[reader].ccid.dwDefaultClock = dw2i(usb_interface->altsetting->extra, 10);
299     usbDevice[reader].ccid.dwMaxDataRate = dw2i(usb_interface->altsetting->extra, 23);
300 rousseau 662
301     goto end;
302 rousseau 269 }
303     }
304     }
305     }
306     end:
307     if (usbDevice[reader].handle == NULL)
308     return STATUS_UNSUCCESSFUL;
309    
310     return STATUS_SUCCESS;
311 rousseau 649 } /* OpenUSBByName */
312 rousseau 269
313    
314     /*****************************************************************************
315     *
316     * WriteUSB
317     *
318     ****************************************************************************/
319     status_t WriteUSB(int lun, int length, unsigned char *buffer)
320     {
321     int rv;
322     int reader = LunToReaderIndex(lun);
323     #ifdef DEBUG_LEVEL_COMM
324     char debug_header[] = "-> 121234 ";
325    
326     sprintf(debug_header, "-> %06X ", (int)lun);
327     #endif
328    
329     #ifdef DEBUG_LEVEL_COMM
330     DEBUG_XXD(debug_header, buffer, length);
331     #endif
332    
333 rousseau 570 rv = usb_bulk_write(usbDevice[reader].handle, usbDevice[reader].bulk_out, buffer, length, USB_WRITE_TIMEOUT);
334 rousseau 269
335     if (rv < 0)
336     {
337 rousseau 662 DEBUG_CRITICAL4("usb_bulk_write(%s/%s): %s",
338     usbDevice[reader].dev->bus->dirname,
339     usbDevice[reader].dev->filename, strerror(errno));
340 rousseau 269 return STATUS_UNSUCCESSFUL;
341     }
342    
343     return STATUS_SUCCESS;
344     } /* WriteUSB */
345    
346    
347     /*****************************************************************************
348     *
349     * ReadUSB
350     *
351     ****************************************************************************/
352     status_t ReadUSB(int lun, int * length, unsigned char *buffer)
353     {
354     int rv;
355     int reader = LunToReaderIndex(lun);
356     #ifdef DEBUG_LEVEL_COMM
357     char debug_header[] = "<- 121234 ";
358    
359     sprintf(debug_header, "<- %06X ", (int)lun);
360     #endif
361    
362    
363 rousseau 570 rv = usb_bulk_read(usbDevice[reader].handle, usbDevice[reader].bulk_in, buffer, *length, USB_READ_TIMEOUT);
364 rousseau 269 *length = rv;
365    
366     if (rv < 0)
367     {
368 rousseau 662 DEBUG_CRITICAL4("usb_bulk_read(%s/%s): %s",
369     usbDevice[reader].dev->bus->dirname,
370     usbDevice[reader].dev->filename, strerror(errno));
371 rousseau 269 return STATUS_UNSUCCESSFUL;
372     }
373    
374     #ifdef DEBUG_LEVEL_COMM
375     DEBUG_XXD(debug_header, buffer, *length);
376     #endif
377    
378     return STATUS_SUCCESS;
379     } /* ReadUSB */
380    
381    
382     /*****************************************************************************
383     *
384     * CloseUSB
385     *
386     ****************************************************************************/
387     status_t CloseUSB(int lun)
388     {
389 rousseau 650 struct usb_interface *usb_interface;
390     int interface;
391 rousseau 269 int reader = LunToReaderIndex(lun);
392    
393     /* device not opened */
394     if (usbDevice[reader].dev == NULL)
395     return STATUS_UNSUCCESSFUL;
396    
397 rousseau 662 DEBUG_COMM3("Closing USB device: %s/%s",
398     usbDevice[reader].dev->bus->dirname, usbDevice[reader].dev->filename);
399 rousseau 269
400 rousseau 650 usb_interface = get_ccid_usb_interface(usbDevice[reader].dev);
401     interface = usb_interface ?
402     usb_interface->altsetting->bInterfaceNumber :
403     usbDevice[reader].dev->config->interface->altsetting->bInterfaceNumber;
404    
405     usb_release_interface(usbDevice[reader].handle, interface);
406 rousseau 269
407 rousseau 682 usb_reset(usbDevice[reader].handle);
408 rousseau 269 usb_close(usbDevice[reader].handle);
409    
410     /* mark the resource unused */
411     usbDevice[reader].handle = NULL;
412     usbDevice[reader].dev = NULL;
413    
414     return STATUS_SUCCESS;
415     } /* CloseUSB */
416    
417    
418 rousseau 301 /*****************************************************************************
419     *
420 rousseau 406 * get_ccid_descriptor
421 rousseau 301 *
422     ****************************************************************************/
423 rousseau 406 _ccid_descriptor *get_ccid_descriptor(int lun)
424 rousseau 269 {
425 rousseau 406 return &usbDevice[LunToReaderIndex(lun)].ccid;
426     } /* get_ccid_descriptor */
427 rousseau 269
428    
429 rousseau 301 /*****************************************************************************
430     *
431     * get_desc
432     *
433     ****************************************************************************/
434 rousseau 662 int get_desc(int channel, usb_dev_handle **handle, struct
435 rousseau 269 usb_device **dev)
436     {
437 rousseau 406 if (channel < 0 || channel > PCSCLITE_MAX_READERS)
438 rousseau 269 return 1;
439    
440     *handle = usbDevice[channel].handle;
441     *dev = usbDevice[channel].dev;
442    
443     return 0;
444     } /* get_desc */
445    
446 rousseau 649
447 rousseau 301 /*****************************************************************************
448     *
449     * get_end_points
450     *
451     ****************************************************************************/
452 rousseau 269 int get_end_points(struct usb_device *dev, _usbDevice *usb_device)
453     {
454     int i;
455     int bEndpointAddress;
456 rousseau 650 struct usb_interface *usb_interface = get_ccid_usb_interface(dev);
457    
458 rousseau 269 /*
459     * 3 Endpoints maximum: Interrupt In, Bulk In, Bulk Out
460     */
461     for (i=0; i<3; i++)
462     {
463 rousseau 650 if (usb_interface->altsetting->endpoint[i].bmAttributes != USB_ENDPOINT_TYPE_BULK)
464 rousseau 269 continue;
465    
466 rousseau 650 bEndpointAddress = usb_interface->altsetting->endpoint[i].bEndpointAddress;
467 rousseau 269
468     if ((bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_IN)
469     usb_device->bulk_in = bEndpointAddress;
470    
471     if ((bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_OUT)
472     usb_device->bulk_out = bEndpointAddress;
473     }
474    
475     return 0;
476     } /* get_end_points */
477    
478 rousseau 650
479     /*****************************************************************************
480     *
481     * get_ccid_usb_interface
482     *
483     ****************************************************************************/
484     struct usb_interface * get_ccid_usb_interface(struct usb_device *dev)
485     {
486     struct usb_interface *usb_interface = NULL;
487    
488     /* if multiple interfaces use the first one with CCID class type */
489     if (dev->config->bNumInterfaces > 1)
490     {
491     int ii;
492     for (ii=0; ii<dev->config->bNumInterfaces; ii++)
493     {
494 rousseau 738 /* CCID Class? */
495     if (dev->config->interface[ii].altsetting->bInterfaceClass == 0xb
496     #ifdef ALLOW_PROPRIETARY_CLASS
497     || dev->config->interface[ii].altsetting->bInterfaceClass == 0xff
498     #endif
499     )
500 rousseau 650 {
501     usb_interface = &dev->config->interface[ii];
502     break;
503     }
504     }
505     }
506     else
507     /* we keep this in case a reader reports a bad class value */
508     usb_interface = dev->config->interface;
509    
510     return usb_interface;
511     } /* get_ccid_usb_interface */
512    

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.5