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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.5