/[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 655 - (hide annotations) (download)
Tue Jan 27 14:46:01 2004 UTC (9 years, 3 months ago) by rousseau
File MIME type: text/plain
File size: 13753 byte(s)
use DEBUG_CRITICAL2() instead of DEBUG_CRITICAL()
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 rousseau 649 * Used to store device name string %s/%s (dirname/filename) like:
59     * (/proc/bus/usb/) 001/002 (Linux)
60 rousseau 269 * /dev/usb0//dev/ (FreeBSD)
61     * /dev/usb0//dev/ugen0 (OpenBSD)
62     */
63     char device_name[BUS_DEVICE_STRSIZE];
64    
65     /*
66     * Endpoints
67     */
68     int bulk_in;
69     int bulk_out;
70 rousseau 406
71     /*
72     * CCID infos common to USB and serial
73     */
74     _ccid_descriptor ccid;
75    
76 rousseau 269 } _usbDevice;
77    
78 rousseau 406 /* The _usbDevice structure must be defined before including ccid_usb.h */
79 rousseau 269 #include "ccid_usb.h"
80    
81 rousseau 406 static _usbDevice usbDevice[PCSCLITE_MAX_READERS] = {
82     [ 0 ... (PCSCLITE_MAX_READERS-1) ] = { NULL, NULL, "", 0, 0 }
83 rousseau 269 };
84    
85     #define PCSCLITE_MANUKEY_NAME "ifdVendorID"
86     #define PCSCLITE_PRODKEY_NAME "ifdProductID"
87     #define PCSCLITE_NAMEKEY_NAME "ifdFriendlyName"
88    
89 rousseau 649
90 rousseau 269 /*****************************************************************************
91     *
92     * OpenUSB
93     *
94     ****************************************************************************/
95     status_t OpenUSB(int lun, int Channel)
96     {
97 rousseau 649 return OpenUSBByName(lun, NULL);
98     } /* OpenUSB */
99    
100    
101     /*****************************************************************************
102     *
103     * OpenUSBByName
104     *
105     ****************************************************************************/
106     status_t OpenUSBByName(int lun, char *device)
107     {
108 rousseau 269 static struct usb_bus *busses = NULL;
109     int reader = LunToReaderIndex(lun);
110     int alias = 0;
111     struct usb_bus *bus;
112     struct usb_dev_handle *dev_handle;
113     char keyValue[TOKEN_MAX_VALUE_SIZE];
114     int vendorID, productID;
115 rousseau 301 char infofile[FILENAME_MAX];
116 rousseau 269
117 rousseau 649 DEBUG_COMM3("Lun: %X, Device: %X", lun, device);
118 rousseau 269
119     if (busses == NULL)
120     usb_init();
121    
122     usb_find_busses();
123     usb_find_devices();
124    
125     busses = usb_get_busses();
126    
127     if (busses == NULL)
128     {
129     DEBUG_CRITICAL("No USB busses found");
130     return STATUS_UNSUCCESSFUL;
131     }
132    
133     /* is the lun already used? */
134     if (usbDevice[reader].handle != NULL)
135     {
136     DEBUG_CRITICAL2("USB driver with lun %X already in use", lun);
137     return STATUS_UNSUCCESSFUL;
138     }
139    
140 rousseau 301 /* Info.plist full patch filename */
141 rousseau 406 snprintf(infofile, sizeof(infofile), "%s/%s/Contents/Info.plist",
142     PCSCLITE_HP_DROPDIR, BUNDLE);
143 rousseau 301
144 rousseau 269 /* general driver info */
145 rousseau 301 if (!LTPBundleFindValueWithKey(infofile, "ifdManufacturerString", keyValue, 0))
146 rousseau 269 DEBUG_CRITICAL2("Manufacturer: %s", keyValue);
147     else
148     {
149     DEBUG_CRITICAL2("LTPBundleFindValueWithKey error. Can't find %s?",
150 rousseau 301 infofile);
151 rousseau 269 return STATUS_UNSUCCESSFUL;
152     }
153 rousseau 301 if (!LTPBundleFindValueWithKey(infofile, "ifdProductString", keyValue, 0))
154 rousseau 269 DEBUG_CRITICAL2("ProductString: %s", keyValue);
155     else
156     return STATUS_UNSUCCESSFUL;
157 rousseau 301 if (!LTPBundleFindValueWithKey(infofile, "Copyright", keyValue, 0))
158 rousseau 269 DEBUG_CRITICAL2("Copyright: %s", keyValue);
159     else
160     return STATUS_UNSUCCESSFUL;
161     vendorID = strlen(keyValue);
162     alias = 0x1D;
163     for (; vendorID--;)
164     alias ^= keyValue[vendorID];
165    
166     /* for any supported reader */
167 rousseau 301 while (LTPBundleFindValueWithKey(infofile, PCSCLITE_MANUKEY_NAME, keyValue, alias) == 0)
168 rousseau 269 {
169 rousseau 301 vendorID = strtoul(keyValue, 0, 16);
170 rousseau 269
171 rousseau 301 if (LTPBundleFindValueWithKey(infofile, PCSCLITE_PRODKEY_NAME, keyValue, alias))
172 rousseau 269 goto end;
173 rousseau 301 productID = strtoul(keyValue, 0, 16);
174 rousseau 269
175 rousseau 301 if (LTPBundleFindValueWithKey(infofile, PCSCLITE_NAMEKEY_NAME, keyValue, alias))
176 rousseau 269 goto end;
177    
178     /* on any USB buses */
179     for (bus = busses; bus; bus = bus->next)
180     {
181     struct usb_device *dev;
182    
183     /* any device on this bus */
184     for (dev = bus->devices; dev; dev = dev->next)
185     {
186     if (dev->descriptor.idVendor == vendorID
187     && dev->descriptor.idProduct == productID)
188     {
189     int r, already_used;
190     char device_name[BUS_DEVICE_STRSIZE];
191    
192 rousseau 649 if (snprintf(device_name, BUS_DEVICE_STRSIZE,
193     /* This need to be in sync with PCSC/src/hotplug_libusb.c */ #ifdef __linux__
194     #define LINUX_USB_PATH "/proc/bus/usb/"
195     LINUX_USB_PATH "%s/%s", bus->dirname, dev->filename
196     #else
197     #ifdef __FreeBSD__
198     "%s", dev->filename
199     #else
200     "%s.00", dev->filename
201     #endif
202     #endif
203     ) < 0)
204 rousseau 269 {
205     DEBUG_CRITICAL2("Device name too long: %s", device_name);
206     return STATUS_UNSUCCESSFUL;
207     }
208    
209     /* is it already opened? */
210     already_used = FALSE;
211 rousseau 649
212     /* select by name? */
213     if (device)
214 rousseau 269 {
215 rousseau 649 if (strcmp(device, device_name) != 0)
216     /* not the good reader, try next one */
217     already_used = TRUE;
218     }
219     else
220     {
221     for (r=0; r<PCSCLITE_MAX_READERS; r++)
222 rousseau 269 {
223 rousseau 649 if (usbDevice[r].dev)
224     {
225     DEBUG_COMM3("Checking new device '%s' against old '%s'",
226     device_name, usbDevice[r].device_name);
227     if (strcmp(usbDevice[r].device_name, device_name) == 0)
228     already_used = TRUE;
229     }
230 rousseau 269 }
231     }
232    
233     if (!already_used)
234     {
235 rousseau 301 DEBUG_COMM2("Trying to open USB bus/device: %s",
236     device_name);
237    
238 rousseau 269 dev_handle = usb_open(dev);
239     if (dev_handle)
240     {
241 rousseau 650 struct usb_interface *usb_interface = NULL;
242 rousseau 269 int interface;
243    
244     if (dev->config == NULL)
245     {
246 rousseau 301 DEBUG_CRITICAL2("No dev->config found for %s",
247     device_name);
248 rousseau 269 return STATUS_UNSUCCESSFUL;
249     }
250    
251 rousseau 650 usb_interface = get_ccid_usb_interface(dev);
252     if (usb_interface == NULL)
253 rousseau 579 {
254 rousseau 655 DEBUG_CRITICAL2("Can't find a CCID interface on %s", device_name);
255 rousseau 579 return STATUS_UNSUCCESSFUL;
256 rousseau 650 }
257    
258     if (usb_interface->altsetting->extralen != 54)
259     {
260     DEBUG_CRITICAL3("Extra field for %s has a wrong length: %d", device_name, usb_interface->altsetting->extralen);
261     return STATUS_UNSUCCESSFUL;
262 rousseau 579 }
263    
264 rousseau 650 interface = usb_interface->altsetting->bInterfaceNumber;
265 rousseau 269 if (usb_claim_interface(dev_handle, interface) < 0)
266     {
267     DEBUG_CRITICAL3("Can't claim interface %s: %s",
268 rousseau 525 device_name, strerror(errno));
269 rousseau 269 return STATUS_UNSUCCESSFUL;
270     }
271    
272     DEBUG_INFO4("Found Vendor/Product: %04X/%04X (%s)",
273     dev->descriptor.idVendor,
274     dev->descriptor.idProduct, keyValue);
275 rousseau 301 DEBUG_INFO2("Using USB bus/device: %s",
276     device_name);
277 rousseau 269
278     /* Get Endpoints values*/
279     get_end_points(dev, &usbDevice[reader]);
280    
281     /* store device information */
282     usbDevice[reader].handle = dev_handle;
283     usbDevice[reader].dev = dev;
284     strncpy(usbDevice[reader].device_name,
285     device_name, BUS_DEVICE_STRSIZE);
286    
287 rousseau 406 /* CCID common informations */
288     usbDevice[reader].ccid.bSeq = 1;
289     usbDevice[reader].ccid.readerID =
290     (dev->descriptor.idVendor << 16) +
291     dev->descriptor.idProduct;
292 rousseau 650 usbDevice[reader].ccid.dwFeatures = dw2i(usb_interface->altsetting->extra, 40);
293     usbDevice[reader].ccid.dwMaxCCIDMessageLength = dw2i(usb_interface->altsetting->extra, 44);
294 rousseau 406
295 rousseau 269 goto end;
296     }
297     else
298 rousseau 301 DEBUG_CRITICAL3("Can't usb_open(%s): %s",
299     device_name,
300 rousseau 269 strerror(errno));
301     }
302     else
303     {
304     DEBUG_INFO2("USB device %s already in use. Checking next one.",
305     device_name);
306     }
307     }
308     }
309     }
310    
311     /* go to next supported reader */
312     alias++;
313     }
314     end:
315     if (usbDevice[reader].handle == NULL)
316     return STATUS_UNSUCCESSFUL;
317    
318     return STATUS_SUCCESS;
319 rousseau 649 } /* OpenUSBByName */
320 rousseau 269
321    
322     /*****************************************************************************
323     *
324     * WriteUSB
325     *
326     ****************************************************************************/
327     status_t WriteUSB(int lun, int length, unsigned char *buffer)
328     {
329     int rv;
330     int reader = LunToReaderIndex(lun);
331     #ifdef DEBUG_LEVEL_COMM
332     char debug_header[] = "-> 121234 ";
333    
334     sprintf(debug_header, "-> %06X ", (int)lun);
335     #endif
336    
337     #ifdef DEBUG_LEVEL_COMM
338     DEBUG_XXD(debug_header, buffer, length);
339     #endif
340    
341 rousseau 570 rv = usb_bulk_write(usbDevice[reader].handle, usbDevice[reader].bulk_out, buffer, length, USB_WRITE_TIMEOUT);
342 rousseau 269
343     if (rv < 0)
344     {
345     DEBUG_CRITICAL3("usb_bulk_write(%s): %s",
346     usbDevice[reader].device_name, strerror(errno));
347     return STATUS_UNSUCCESSFUL;
348     }
349    
350     return STATUS_SUCCESS;
351     } /* WriteUSB */
352    
353    
354     /*****************************************************************************
355     *
356     * ReadUSB
357     *
358     ****************************************************************************/
359     status_t ReadUSB(int lun, int * length, unsigned char *buffer)
360     {
361     int rv;
362     int reader = LunToReaderIndex(lun);
363     #ifdef DEBUG_LEVEL_COMM
364     char debug_header[] = "<- 121234 ";
365    
366     sprintf(debug_header, "<- %06X ", (int)lun);
367     #endif
368    
369    
370 rousseau 570 rv = usb_bulk_read(usbDevice[reader].handle, usbDevice[reader].bulk_in, buffer, *length, USB_READ_TIMEOUT);
371 rousseau 269 *length = rv;
372    
373     if (rv < 0)
374     {
375     DEBUG_CRITICAL3("usb_bulk_read(%s): %s",
376     usbDevice[reader].device_name, strerror(errno));
377     return STATUS_UNSUCCESSFUL;
378     }
379    
380     #ifdef DEBUG_LEVEL_COMM
381     DEBUG_XXD(debug_header, buffer, *length);
382     #endif
383    
384     return STATUS_SUCCESS;
385     } /* ReadUSB */
386    
387    
388     /*****************************************************************************
389     *
390     * CloseUSB
391     *
392     ****************************************************************************/
393     status_t CloseUSB(int lun)
394     {
395 rousseau 650 struct usb_interface *usb_interface;
396     int interface;
397 rousseau 269 int reader = LunToReaderIndex(lun);
398    
399     /* device not opened */
400     if (usbDevice[reader].dev == NULL)
401     return STATUS_UNSUCCESSFUL;
402    
403     DEBUG_COMM2("Closing USB device: %s", usbDevice[reader].device_name);
404    
405 rousseau 650 usb_interface = get_ccid_usb_interface(usbDevice[reader].dev);
406     interface = usb_interface ?
407     usb_interface->altsetting->bInterfaceNumber :
408     usbDevice[reader].dev->config->interface->altsetting->bInterfaceNumber;
409    
410     usb_release_interface(usbDevice[reader].handle, interface);
411 rousseau 269
412     usb_close(usbDevice[reader].handle);
413    
414     /* mark the resource unused */
415     usbDevice[reader].handle = NULL;
416     usbDevice[reader].dev = NULL;
417     usbDevice[reader].device_name[0] = '\0';
418    
419     return STATUS_SUCCESS;
420     } /* CloseUSB */
421    
422    
423 rousseau 301 /*****************************************************************************
424     *
425 rousseau 406 * get_ccid_descriptor
426 rousseau 301 *
427     ****************************************************************************/
428 rousseau 406 _ccid_descriptor *get_ccid_descriptor(int lun)
429 rousseau 269 {
430 rousseau 406 return &usbDevice[LunToReaderIndex(lun)].ccid;
431     } /* get_ccid_descriptor */
432 rousseau 269
433    
434 rousseau 301 /*****************************************************************************
435     *
436     * get_desc
437     *
438     ****************************************************************************/
439 rousseau 269 int get_desc(int channel, char *device_name[], usb_dev_handle **handle, struct
440     usb_device **dev)
441     {
442 rousseau 406 if (channel < 0 || channel > PCSCLITE_MAX_READERS)
443 rousseau 269 return 1;
444    
445     *device_name = usbDevice[channel].device_name;
446     *handle = usbDevice[channel].handle;
447     *dev = usbDevice[channel].dev;
448    
449     return 0;
450     } /* get_desc */
451    
452 rousseau 649
453 rousseau 301 /*****************************************************************************
454     *
455     * get_end_points
456     *
457     ****************************************************************************/
458 rousseau 269 int get_end_points(struct usb_device *dev, _usbDevice *usb_device)
459     {
460     int i;
461     int bEndpointAddress;
462 rousseau 650 struct usb_interface *usb_interface = get_ccid_usb_interface(dev);
463    
464 rousseau 269 /*
465     * 3 Endpoints maximum: Interrupt In, Bulk In, Bulk Out
466     */
467     for (i=0; i<3; i++)
468     {
469 rousseau 650 if (usb_interface->altsetting->endpoint[i].bmAttributes != USB_ENDPOINT_TYPE_BULK)
470 rousseau 269 continue;
471    
472 rousseau 650 bEndpointAddress = usb_interface->altsetting->endpoint[i].bEndpointAddress;
473 rousseau 269
474     if ((bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_IN)
475     usb_device->bulk_in = bEndpointAddress;
476    
477     if ((bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_OUT)
478     usb_device->bulk_out = bEndpointAddress;
479     }
480    
481     return 0;
482     } /* get_end_points */
483    
484 rousseau 650
485     /*****************************************************************************
486     *
487     * get_ccid_usb_interface
488     *
489     ****************************************************************************/
490     struct usb_interface * get_ccid_usb_interface(struct usb_device *dev)
491     {
492     struct usb_interface *usb_interface = NULL;
493    
494     /* if multiple interfaces use the first one with CCID class type */
495     if (dev->config->bNumInterfaces > 1)
496     {
497     int ii;
498     for (ii=0; ii<dev->config->bNumInterfaces; ii++)
499     {
500     if (dev->config->interface[ii].altsetting->bInterfaceClass == 0xb)
501     {
502     usb_interface = &dev->config->interface[ii];
503     break;
504     }
505     }
506     }
507     else
508     /* we keep this in case a reader reports a bad class value */
509     usb_interface = dev->config->interface;
510    
511     return usb_interface;
512     } /* get_ccid_usb_interface */
513    

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.5