/[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 682 - (show annotations) (download)
Mon Feb 9 13:55:09 2004 UTC (9 years, 3 months ago) by rousseau
File MIME type: text/plain
File size: 13685 byte(s)
usb_reset() the device before usb_close()
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 #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
63 /*
64 * CCID infos common to USB and serial
65 */
66 _ccid_descriptor ccid;
67
68 } _usbDevice;
69
70 /* The _usbDevice structure must be defined before including ccid_usb.h */
71 #include "ccid_usb.h"
72
73 static _usbDevice usbDevice[PCSCLITE_MAX_READERS] = {
74 [ 0 ... (PCSCLITE_MAX_READERS-1) ] = { NULL, NULL, 0, 0 }
75 };
76
77 #define PCSCLITE_MANUKEY_NAME "ifdVendorID"
78 #define PCSCLITE_PRODKEY_NAME "ifdProductID"
79 #define PCSCLITE_NAMEKEY_NAME "ifdFriendlyName"
80
81
82 /*****************************************************************************
83 *
84 * OpenUSB
85 *
86 ****************************************************************************/
87 status_t OpenUSB(int lun, int Channel)
88 {
89 return OpenUSBByName(lun, NULL);
90 } /* OpenUSB */
91
92
93 /*****************************************************************************
94 *
95 * OpenUSBByName
96 *
97 ****************************************************************************/
98 status_t OpenUSBByName(int lun, char *device)
99 {
100 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 char infofile[FILENAME_MAX];
108 int device_vendor, device_product;
109
110 DEBUG_COMM3("Lun: %X, Device: %s", lun, device);
111
112 /* 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 printf("%x %x\n", device_vendor, device_product);
129 }
130
131 if (busses == NULL)
132 usb_init();
133
134 usb_find_busses();
135 usb_find_devices();
136
137 busses = usb_get_busses();
138
139 if (busses == NULL)
140 {
141 DEBUG_CRITICAL("No USB busses found");
142 return STATUS_UNSUCCESSFUL;
143 }
144
145 /* is the lun already used? */
146 if (usbDevice[reader].handle != NULL)
147 {
148 DEBUG_CRITICAL2("USB driver with lun %X already in use", lun);
149 return STATUS_UNSUCCESSFUL;
150 }
151
152 /* Info.plist full patch filename */
153 snprintf(infofile, sizeof(infofile), "%s/%s/Contents/Info.plist",
154 PCSCLITE_HP_DROPDIR, BUNDLE);
155
156 /* general driver info */
157 if (!LTPBundleFindValueWithKey(infofile, "ifdManufacturerString", keyValue, 0))
158 DEBUG_CRITICAL2("Manufacturer: %s", keyValue);
159 else
160 {
161 DEBUG_CRITICAL2("LTPBundleFindValueWithKey error. Can't find %s?",
162 infofile);
163 return STATUS_UNSUCCESSFUL;
164 }
165 if (!LTPBundleFindValueWithKey(infofile, "ifdProductString", keyValue, 0))
166 DEBUG_CRITICAL2("ProductString: %s", keyValue);
167 else
168 return STATUS_UNSUCCESSFUL;
169 if (!LTPBundleFindValueWithKey(infofile, "Copyright", keyValue, 0))
170 DEBUG_CRITICAL2("Copyright: %s", keyValue);
171 else
172 return STATUS_UNSUCCESSFUL;
173 vendorID = strlen(keyValue);
174 alias = 0x1D;
175 for (; vendorID--;)
176 alias ^= keyValue[vendorID];
177
178 /* for any supported reader */
179 while (LTPBundleFindValueWithKey(infofile, PCSCLITE_MANUKEY_NAME, keyValue, alias) == 0)
180 {
181 vendorID = strtoul(keyValue, 0, 16);
182
183 if (LTPBundleFindValueWithKey(infofile, PCSCLITE_PRODKEY_NAME, keyValue, alias))
184 goto end;
185 productID = strtoul(keyValue, 0, 16);
186
187 if (LTPBundleFindValueWithKey(infofile, PCSCLITE_NAMEKEY_NAME, keyValue, alias))
188 goto end;
189
190 /* go to next supported reader for next round */
191 alias++;
192
193 /* the device was specified but is not the one we are trying to find */
194 if (device
195 && (vendorID != device_vendor || productID != device_product))
196 continue;
197
198 /* on any USB buses */
199 for (bus = busses; bus; bus = bus->next)
200 {
201 struct usb_device *dev;
202
203 /* any device on this bus */
204 for (dev = bus->devices; dev; dev = dev->next)
205 {
206 if (dev->descriptor.idVendor == vendorID
207 && dev->descriptor.idProduct == productID)
208 {
209 int r, already_used;
210 struct usb_interface *usb_interface = NULL;
211 int interface;
212
213 /* is it already opened? */
214 already_used = FALSE;
215
216 for (r=0; r<PCSCLITE_MAX_READERS; r++)
217 {
218 if (usbDevice[r].dev)
219 {
220 DEBUG_COMM3("Checking device: %s/%s",
221 bus->dirname, dev->filename);
222 /* same busname, same filename */
223 if (strcmp(usbDevice[r].dev->bus->dirname, bus->dirname) == 0 && strcmp(usbDevice[r].dev->filename, dev->filename) == 0)
224 already_used = TRUE;
225 }
226 }
227
228 /* this reader is already managed by us */
229 if (already_used)
230 {
231 DEBUG_INFO3("USB device %s/%s already in use. Checking next one.",
232 bus->dirname, dev->filename);
233
234 continue;
235 }
236
237 DEBUG_COMM3("Trying to open USB bus/device: %s/%s",
238 bus->dirname, dev->filename);
239
240 dev_handle = usb_open(dev);
241 if (dev_handle == NULL)
242 {
243 DEBUG_CRITICAL4("Can't usb_open(%s/%s): %s",
244 bus->dirname, dev->filename, strerror(errno));
245
246 continue;
247 }
248
249 /* now we found a free reader and we try to use it */
250 if (dev->config == NULL)
251 {
252 DEBUG_CRITICAL3("No dev->config found for %s/%s",
253 bus->dirname, dev->filename);
254 return STATUS_UNSUCCESSFUL;
255 }
256
257 usb_interface = get_ccid_usb_interface(dev);
258 if (usb_interface == NULL)
259 {
260 DEBUG_CRITICAL3("Can't find a CCID interface on %s/%s",
261 bus->dirname, dev->filename);
262 return STATUS_UNSUCCESSFUL;
263 }
264
265 if (usb_interface->altsetting->extralen != 54)
266 {
267 DEBUG_CRITICAL4("Extra field for %s/%s has a wrong length: %d", bus->dirname, dev->filename, usb_interface->altsetting->extralen);
268 return STATUS_UNSUCCESSFUL;
269 }
270
271 interface = usb_interface->altsetting->bInterfaceNumber;
272 if (usb_claim_interface(dev_handle, interface) < 0)
273 {
274 DEBUG_CRITICAL4("Can't claim interface %s/%s: %s",
275 bus->dirname, dev->filename, strerror(errno));
276 return STATUS_UNSUCCESSFUL;
277 }
278
279 DEBUG_INFO4("Found Vendor/Product: %04X/%04X (%s)",
280 dev->descriptor.idVendor,
281 dev->descriptor.idProduct, keyValue);
282 DEBUG_INFO3("Using USB bus/device: %s/%s",
283 bus->dirname, dev->filename);
284
285 /* Get Endpoints values*/
286 get_end_points(dev, &usbDevice[reader]);
287
288 /* store device information */
289 usbDevice[reader].handle = dev_handle;
290 usbDevice[reader].dev = dev;
291
292 /* CCID common informations */
293 usbDevice[reader].ccid.bSeq = 1;
294 usbDevice[reader].ccid.readerID =
295 (dev->descriptor.idVendor << 16) +
296 dev->descriptor.idProduct;
297 usbDevice[reader].ccid.dwFeatures = dw2i(usb_interface->altsetting->extra, 40);
298 usbDevice[reader].ccid.dwMaxCCIDMessageLength = dw2i(usb_interface->altsetting->extra, 44);
299 usbDevice[reader].ccid.dwMaxIFSD = dw2i(usb_interface->altsetting->extra, 28);
300
301 goto end;
302 }
303 }
304 }
305 }
306 end:
307 if (usbDevice[reader].handle == NULL)
308 return STATUS_UNSUCCESSFUL;
309
310 return STATUS_SUCCESS;
311 } /* OpenUSBByName */
312
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 rv = usb_bulk_write(usbDevice[reader].handle, usbDevice[reader].bulk_out, buffer, length, USB_WRITE_TIMEOUT);
334
335 if (rv < 0)
336 {
337 DEBUG_CRITICAL4("usb_bulk_write(%s/%s): %s",
338 usbDevice[reader].dev->bus->dirname,
339 usbDevice[reader].dev->filename, strerror(errno));
340 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 rv = usb_bulk_read(usbDevice[reader].handle, usbDevice[reader].bulk_in, buffer, *length, USB_READ_TIMEOUT);
364 *length = rv;
365
366 if (rv < 0)
367 {
368 DEBUG_CRITICAL4("usb_bulk_read(%s/%s): %s",
369 usbDevice[reader].dev->bus->dirname,
370 usbDevice[reader].dev->filename, strerror(errno));
371 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 struct usb_interface *usb_interface;
390 int interface;
391 int reader = LunToReaderIndex(lun);
392
393 /* device not opened */
394 if (usbDevice[reader].dev == NULL)
395 return STATUS_UNSUCCESSFUL;
396
397 DEBUG_COMM3("Closing USB device: %s/%s",
398 usbDevice[reader].dev->bus->dirname, usbDevice[reader].dev->filename);
399
400 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
407 usb_reset(usbDevice[reader].handle);
408 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 /*****************************************************************************
419 *
420 * get_ccid_descriptor
421 *
422 ****************************************************************************/
423 _ccid_descriptor *get_ccid_descriptor(int lun)
424 {
425 return &usbDevice[LunToReaderIndex(lun)].ccid;
426 } /* get_ccid_descriptor */
427
428
429 /*****************************************************************************
430 *
431 * get_desc
432 *
433 ****************************************************************************/
434 int get_desc(int channel, usb_dev_handle **handle, struct
435 usb_device **dev)
436 {
437 if (channel < 0 || channel > PCSCLITE_MAX_READERS)
438 return 1;
439
440 *handle = usbDevice[channel].handle;
441 *dev = usbDevice[channel].dev;
442
443 return 0;
444 } /* get_desc */
445
446
447 /*****************************************************************************
448 *
449 * get_end_points
450 *
451 ****************************************************************************/
452 int get_end_points(struct usb_device *dev, _usbDevice *usb_device)
453 {
454 int i;
455 int bEndpointAddress;
456 struct usb_interface *usb_interface = get_ccid_usb_interface(dev);
457
458 /*
459 * 3 Endpoints maximum: Interrupt In, Bulk In, Bulk Out
460 */
461 for (i=0; i<3; i++)
462 {
463 if (usb_interface->altsetting->endpoint[i].bmAttributes != USB_ENDPOINT_TYPE_BULK)
464 continue;
465
466 bEndpointAddress = usb_interface->altsetting->endpoint[i].bEndpointAddress;
467
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
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 if (dev->config->interface[ii].altsetting->bInterfaceClass == 0xb)
495 {
496 usb_interface = &dev->config->interface[ii];
497 break;
498 }
499 }
500 }
501 else
502 /* we keep this in case a reader reports a bad class value */
503 usb_interface = dev->config->interface;
504
505 return usb_interface;
506 } /* get_ccid_usb_interface */
507

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.5