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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.5