/[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 301 - (hide annotations) (download)
Wed Aug 20 08:37:34 2003 UTC (9 years, 9 months ago) by rousseau
File MIME type: text/plain
File size: 12736 byte(s)
do not duplicate the Info.plist filename but "calculate" it once
1 rousseau 269 /*
2     ccid_usb.c: USB access routines using the libusb library
3     Copyright (C) 2003 Ludovic Rousseau
4    
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    
37    
38 rousseau 279 #define USB_TIMEOUT 60000 /* 1 minute timeout */
39 rousseau 269
40     #define BUS_DEVICE_STRSIZE 32
41    
42     typedef struct
43     {
44     usb_dev_handle *handle;
45     struct usb_device *dev;
46    
47     /*
48     * Used to store device name string %s/%s like:
49     * 001/002 (Linux)
50     * /dev/usb0//dev/ (FreeBSD)
51     * /dev/usb0//dev/ugen0 (OpenBSD)
52     */
53     char device_name[BUS_DEVICE_STRSIZE];
54    
55     /*
56     * CCID Sequence number
57     */
58     int bSeq;
59    
60     /*
61     * Endpoints
62     */
63     int bulk_in;
64     int bulk_out;
65     } _usbDevice;
66    
67     // The _usbDevice structure must be defined before including ccid_usb.h
68     #include "ccid_usb.h"
69    
70     #if (PCSCLITE_MAX_CHANNELS-16)
71     #error Edit this file and set the number of initialiser to PCSCLITE_MAX_CHANNELS (default was 16 but it has changed)
72     #endif
73     static _usbDevice usbDevice[PCSCLITE_MAX_CHANNELS] = {
74     { NULL, NULL, "", 0, 0, 0 }, { NULL, NULL, "", 0, 0, 0 },
75     { NULL, NULL, "", 0, 0, 0 }, { NULL, NULL, "", 0, 0, 0 },
76     { NULL, NULL, "", 0, 0, 0 }, { NULL, NULL, "", 0, 0, 0 },
77     { NULL, NULL, "", 0, 0, 0 }, { NULL, NULL, "", 0, 0, 0 },
78     { NULL, NULL, "", 0, 0, 0 }, { NULL, NULL, "", 0, 0, 0 },
79     { NULL, NULL, "", 0, 0, 0 }, { NULL, NULL, "", 0, 0, 0 },
80     { NULL, NULL, "", 0, 0, 0 }, { NULL, NULL, "", 0, 0, 0 },
81     { NULL, NULL, "", 0, 0, 0 }, { NULL, NULL, "", 0, 0, 0 }
82     };
83    
84     #define PCSCLITE_MANUKEY_NAME "ifdVendorID"
85     #define PCSCLITE_PRODKEY_NAME "ifdProductID"
86     #define PCSCLITE_NAMEKEY_NAME "ifdFriendlyName"
87    
88     /*****************************************************************************
89     *
90     * OpenUSB
91     *
92     ****************************************************************************/
93     status_t OpenUSB(int lun, int Channel)
94     {
95     static struct usb_bus *busses = NULL;
96     int reader = LunToReaderIndex(lun);
97     int alias = 0;
98     struct usb_bus *bus;
99     struct usb_dev_handle *dev_handle;
100     char keyValue[TOKEN_MAX_VALUE_SIZE];
101     int vendorID, productID;
102 rousseau 301 char infofile[FILENAME_MAX];
103 rousseau 269
104     DEBUG_COMM3("OpenUSB: Lun: %X, Channel: %X", lun, Channel);
105    
106     if (busses == NULL)
107     {
108     usb_init();
109     }
110    
111     usb_find_busses();
112     usb_find_devices();
113    
114     busses = usb_get_busses();
115    
116     if (busses == NULL)
117     {
118     DEBUG_CRITICAL("No USB busses found");
119     return STATUS_UNSUCCESSFUL;
120     }
121    
122     /* is the lun already used? */
123     if (usbDevice[reader].handle != NULL)
124     {
125     DEBUG_CRITICAL2("USB driver with lun %X already in use", lun);
126     return STATUS_UNSUCCESSFUL;
127     }
128    
129 rousseau 301 /* Info.plist full patch filename */
130     snprintf(infofile, sizeof(infofile), "%s/Contents/Info.plist", PCSCLITE_HP_DROPDIR);
131    
132 rousseau 269 /* general driver info */
133 rousseau 301 if (!LTPBundleFindValueWithKey(infofile, "ifdManufacturerString", keyValue, 0))
134 rousseau 269 DEBUG_CRITICAL2("Manufacturer: %s", keyValue);
135     else
136     {
137     DEBUG_CRITICAL2("LTPBundleFindValueWithKey error. Can't find %s?",
138 rousseau 301 infofile);
139 rousseau 269 return STATUS_UNSUCCESSFUL;
140     }
141 rousseau 301 if (!LTPBundleFindValueWithKey(infofile, "ifdProductString", keyValue, 0))
142 rousseau 269 DEBUG_CRITICAL2("ProductString: %s", keyValue);
143     else
144     return STATUS_UNSUCCESSFUL;
145 rousseau 301 if (!LTPBundleFindValueWithKey(infofile, "Copyright", keyValue, 0))
146 rousseau 269 DEBUG_CRITICAL2("Copyright: %s", keyValue);
147     else
148     return STATUS_UNSUCCESSFUL;
149     vendorID = strlen(keyValue);
150     alias = 0x1D;
151     for (; vendorID--;)
152     alias ^= keyValue[vendorID];
153    
154     /* for any supported reader */
155 rousseau 301 while (LTPBundleFindValueWithKey(infofile, PCSCLITE_MANUKEY_NAME, keyValue, alias) == 0)
156 rousseau 269 {
157 rousseau 301 vendorID = strtoul(keyValue, 0, 16);
158 rousseau 269
159 rousseau 301 if (LTPBundleFindValueWithKey(infofile, PCSCLITE_PRODKEY_NAME, keyValue, alias))
160 rousseau 269 goto end;
161 rousseau 301 productID = strtoul(keyValue, 0, 16);
162 rousseau 269
163 rousseau 301 if (LTPBundleFindValueWithKey(infofile, PCSCLITE_NAMEKEY_NAME, keyValue, alias))
164 rousseau 269 goto end;
165    
166     /* on any USB buses */
167     for (bus = busses; bus; bus = bus->next)
168     {
169     struct usb_device *dev;
170    
171     /* any device on this bus */
172     for (dev = bus->devices; dev; dev = dev->next)
173     {
174     if (dev->descriptor.idVendor == vendorID
175     && dev->descriptor.idProduct == productID)
176     {
177     int r, already_used;
178     char device_name[BUS_DEVICE_STRSIZE];
179    
180     if (snprintf(device_name, BUS_DEVICE_STRSIZE, "%s/%s",
181     bus->dirname, dev->filename) < 0)
182     {
183     DEBUG_CRITICAL2("Device name too long: %s", device_name);
184     return STATUS_UNSUCCESSFUL;
185     }
186    
187     /* is it already opened? */
188     already_used = FALSE;
189     for (r=0; r<PCSCLITE_MAX_CHANNELS; r++)
190     {
191     if (usbDevice[r].dev)
192     {
193     DEBUG_COMM3("Checking new device '%s' against old '%s'",
194     device_name, usbDevice[r].device_name);
195     if (strcmp(usbDevice[r].device_name, device_name) == 0)
196     already_used = TRUE;
197     }
198     }
199    
200     if (!already_used)
201     {
202 rousseau 301 DEBUG_COMM2("Trying to open USB bus/device: %s",
203     device_name);
204    
205 rousseau 269 dev_handle = usb_open(dev);
206     if (dev_handle)
207     {
208     int interface;
209    
210     if (dev->config == NULL)
211     {
212 rousseau 301 DEBUG_CRITICAL2("No dev->config found for %s",
213     device_name);
214 rousseau 269 return STATUS_UNSUCCESSFUL;
215     }
216    
217     interface = dev->config->interface->altsetting->bInterfaceNumber;
218     if (usb_claim_interface(dev_handle, interface) < 0)
219     {
220     DEBUG_CRITICAL3("Can't claim interface %s: %s",
221     usbDevice[reader].device_name,
222     strerror(errno));
223     return STATUS_UNSUCCESSFUL;
224     }
225    
226     DEBUG_INFO4("Found Vendor/Product: %04X/%04X (%s)",
227     dev->descriptor.idVendor,
228     dev->descriptor.idProduct, keyValue);
229 rousseau 301 DEBUG_INFO2("Using USB bus/device: %s",
230     device_name);
231 rousseau 269
232     /* Get Endpoints values*/
233     get_end_points(dev, &usbDevice[reader]);
234    
235     /* store device information */
236     usbDevice[reader].handle = dev_handle;
237     usbDevice[reader].dev = dev;
238     strncpy(usbDevice[reader].device_name,
239     device_name, BUS_DEVICE_STRSIZE);
240     usbDevice[reader].bSeq = 1;
241    
242     goto end;
243     }
244     else
245 rousseau 301 DEBUG_CRITICAL3("Can't usb_open(%s): %s",
246     device_name,
247 rousseau 269 strerror(errno));
248     }
249     else
250     {
251     DEBUG_INFO2("USB device %s already in use. Checking next one.",
252     device_name);
253     }
254     }
255     }
256     }
257    
258     /* go to next supported reader */
259     alias++;
260     }
261     end:
262     if (usbDevice[reader].handle == NULL)
263     return STATUS_UNSUCCESSFUL;
264    
265     return STATUS_SUCCESS;
266     } /* OpenUSB */
267    
268    
269     /*****************************************************************************
270     *
271     * WriteUSB
272     *
273     ****************************************************************************/
274     status_t WriteUSB(int lun, int length, unsigned char *buffer)
275     {
276     int rv;
277     int reader = LunToReaderIndex(lun);
278     #ifdef DEBUG_LEVEL_COMM
279     char debug_header[] = "-> 121234 ";
280    
281     sprintf(debug_header, "-> %06X ", (int)lun);
282     #endif
283    
284     #ifdef DEBUG_LEVEL_COMM
285     DEBUG_XXD(debug_header, buffer, length);
286     #endif
287    
288     rv = usb_bulk_write(usbDevice[reader].handle, usbDevice[reader].bulk_out, buffer, length, USB_TIMEOUT);
289    
290     if (rv < 0)
291     {
292     DEBUG_CRITICAL3("usb_bulk_write(%s): %s",
293     usbDevice[reader].device_name, strerror(errno));
294     return STATUS_UNSUCCESSFUL;
295     }
296    
297     return STATUS_SUCCESS;
298     } /* WriteUSB */
299    
300    
301     /*****************************************************************************
302     *
303     * ReadUSB
304     *
305     ****************************************************************************/
306     status_t ReadUSB(int lun, int * length, unsigned char *buffer)
307     {
308     int rv;
309     int reader = LunToReaderIndex(lun);
310     #ifdef DEBUG_LEVEL_COMM
311     char debug_header[] = "<- 121234 ";
312    
313     sprintf(debug_header, "<- %06X ", (int)lun);
314     #endif
315    
316    
317     rv = usb_bulk_read(usbDevice[reader].handle, usbDevice[reader].bulk_in, buffer, *length, USB_TIMEOUT);
318     *length = rv;
319    
320     if (rv < 0)
321     {
322     DEBUG_CRITICAL3("usb_bulk_read(%s): %s",
323     usbDevice[reader].device_name, strerror(errno));
324     return STATUS_UNSUCCESSFUL;
325     }
326    
327     #ifdef DEBUG_LEVEL_COMM
328     DEBUG_XXD(debug_header, buffer, *length);
329     #endif
330    
331     return STATUS_SUCCESS;
332     } /* ReadUSB */
333    
334    
335     /*****************************************************************************
336     *
337     * CloseUSB
338     *
339     ****************************************************************************/
340     status_t CloseUSB(int lun)
341     {
342     int reader = LunToReaderIndex(lun);
343    
344     /* device not opened */
345     if (usbDevice[reader].dev == NULL)
346     return STATUS_UNSUCCESSFUL;
347    
348     DEBUG_COMM2("Closing USB device: %s", usbDevice[reader].device_name);
349    
350     usb_release_interface(usbDevice[reader].handle, usbDevice[reader].dev->config->interface->altsetting->bInterfaceNumber);
351    
352     usb_close(usbDevice[reader].handle);
353    
354     /* mark the resource unused */
355     usbDevice[reader].handle = NULL;
356     usbDevice[reader].dev = NULL;
357     usbDevice[reader].device_name[0] = '\0';
358    
359     return STATUS_SUCCESS;
360     } /* CloseUSB */
361    
362    
363 rousseau 301 /*****************************************************************************
364     *
365     * ccid_get_seq
366     *
367     ****************************************************************************/
368 rousseau 269 int ccid_get_seq(int lun)
369     {
370     return usbDevice[LunToReaderIndex(lun)].bSeq++;
371     } /* ccid_get_seq */
372    
373    
374 rousseau 301 /*****************************************************************************
375     *
376     * ccid_error
377     *
378     ****************************************************************************/
379 rousseau 269 void ccid_error(int error, char *file, int line)
380     {
381     char *text;
382    
383     switch (error)
384     {
385     case 0x00:
386     text = "Command not supported or not allowed";
387     break;
388    
389     case 0x01:
390     text = "Wrong command length";
391     break;
392    
393     case 0x02:
394     text = "Reader detects an excessive current. Card powered off";
395     break;
396    
397     case 0x03:
398     text = "Reader detects a defective voltage. Card powered off";
399     break;
400    
401     case 0x05:
402     text = "Slot number is invalid (it must be set to 0)";
403     break;
404    
405     case 0x07:
406     case 0x08:
407     case 0x09:
408     case 0x0A:
409     case 0x15:
410     text = "Byte displayed is invalid";
411     break;
412    
413     case 0xA2:
414     text = "Card short-circuiting. Card powered off";
415     break;
416    
417     case 0xA3:
418     text = "ATR too long (> 33)";
419     break;
420    
421     case 0xB0:
422     text = "Reader in EMV mode and T=1 message too long";
423     break;
424    
425     case 0xBB:
426     text = "Protocol error in EMV mode";
427     break;
428    
429     case 0xBD:
430     text = "Card error during T=1 exchange";
431     break;
432    
433     case 0xBE:
434     text = "Wrong APDU command length";
435     break;
436    
437     case 0xF4:
438     text = "Procedure byte conflict";
439     break;
440    
441     case 0xF7:
442     text = "Invalid ATR checksum byte (TCK)";
443     break;
444    
445     case 0xF8:
446     text = "Invalid ATR first byte";
447     break;
448    
449     case 0xFD:
450     text = "Parity error during exchange";
451     break;
452    
453     case 0xFE:
454     text = "Card absent or mute";
455     break;
456    
457     default:
458     text = "Unknown CCID error";
459     break;
460    
461     }
462     debug_msg("%s:%d %s", file, line, text);
463    
464     } /* ccid_error */
465    
466 rousseau 301 /*****************************************************************************
467     *
468     * get_desc
469     *
470     ****************************************************************************/
471 rousseau 269 int get_desc(int channel, char *device_name[], usb_dev_handle **handle, struct
472     usb_device **dev)
473     {
474     if (channel < 0 || channel > PCSCLITE_MAX_CHANNELS)
475     return 1;
476    
477     *device_name = usbDevice[channel].device_name;
478     *handle = usbDevice[channel].handle;
479     *dev = usbDevice[channel].dev;
480    
481     return 0;
482     } /* get_desc */
483    
484 rousseau 301 /*****************************************************************************
485     *
486     * get_end_points
487     *
488     ****************************************************************************/
489 rousseau 269 int get_end_points(struct usb_device *dev, _usbDevice *usb_device)
490     {
491     int i;
492     int bEndpointAddress;
493    
494     /*
495     * 3 Endpoints maximum: Interrupt In, Bulk In, Bulk Out
496     */
497     for (i=0; i<3; i++)
498     {
499     if (dev->config->interface->altsetting->endpoint[i].bmAttributes != USB_ENDPOINT_TYPE_BULK)
500     continue;
501    
502     bEndpointAddress = dev->config->interface->altsetting->endpoint[i].bEndpointAddress;
503    
504     if ((bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_IN)
505     usb_device->bulk_in = bEndpointAddress;
506    
507     if ((bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_OUT)
508     usb_device->bulk_out = bEndpointAddress;
509     }
510    
511     return 0;
512     } /* get_end_points */
513    

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.5