/[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 612 - (show annotations) (download)
Thu Jan 15 13:45:37 2004 UTC (9 years, 4 months ago) by rousseau
File MIME type: text/plain
File size: 11583 byte(s)
call ccid_open_hack() in IFDHCreateChannel() instead of in each OpenPort()
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 #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 * Used to store device name string %s/%s like:
59 * 001/002 (Linux)
60 * /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
71 /*
72 * CCID infos common to USB and serial
73 */
74 _ccid_descriptor ccid;
75
76 } _usbDevice;
77
78 /* The _usbDevice structure must be defined before including ccid_usb.h */
79 #include "ccid_usb.h"
80
81 static _usbDevice usbDevice[PCSCLITE_MAX_READERS] = {
82 [ 0 ... (PCSCLITE_MAX_READERS-1) ] = { NULL, NULL, "", 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 char infofile[FILENAME_MAX];
104
105 DEBUG_COMM3("Lun: %X, Channel: %X", lun, Channel);
106
107 if (busses == NULL)
108 usb_init();
109
110 usb_find_busses();
111 usb_find_devices();
112
113 busses = usb_get_busses();
114
115 if (busses == NULL)
116 {
117 DEBUG_CRITICAL("No USB busses found");
118 return STATUS_UNSUCCESSFUL;
119 }
120
121 /* is the lun already used? */
122 if (usbDevice[reader].handle != NULL)
123 {
124 DEBUG_CRITICAL2("USB driver with lun %X already in use", lun);
125 return STATUS_UNSUCCESSFUL;
126 }
127
128 /* Info.plist full patch filename */
129 snprintf(infofile, sizeof(infofile), "%s/%s/Contents/Info.plist",
130 PCSCLITE_HP_DROPDIR, BUNDLE);
131
132 /* general driver info */
133 if (!LTPBundleFindValueWithKey(infofile, "ifdManufacturerString", keyValue, 0))
134 DEBUG_CRITICAL2("Manufacturer: %s", keyValue);
135 else
136 {
137 DEBUG_CRITICAL2("LTPBundleFindValueWithKey error. Can't find %s?",
138 infofile);
139 return STATUS_UNSUCCESSFUL;
140 }
141 if (!LTPBundleFindValueWithKey(infofile, "ifdProductString", keyValue, 0))
142 DEBUG_CRITICAL2("ProductString: %s", keyValue);
143 else
144 return STATUS_UNSUCCESSFUL;
145 if (!LTPBundleFindValueWithKey(infofile, "Copyright", keyValue, 0))
146 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 while (LTPBundleFindValueWithKey(infofile, PCSCLITE_MANUKEY_NAME, keyValue, alias) == 0)
156 {
157 vendorID = strtoul(keyValue, 0, 16);
158
159 if (LTPBundleFindValueWithKey(infofile, PCSCLITE_PRODKEY_NAME, keyValue, alias))
160 goto end;
161 productID = strtoul(keyValue, 0, 16);
162
163 if (LTPBundleFindValueWithKey(infofile, PCSCLITE_NAMEKEY_NAME, keyValue, alias))
164 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_READERS; 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 DEBUG_COMM2("Trying to open USB bus/device: %s",
203 device_name);
204
205 dev_handle = usb_open(dev);
206 if (dev_handle)
207 {
208 int interface;
209
210 if (dev->config == NULL)
211 {
212 DEBUG_CRITICAL2("No dev->config found for %s",
213 device_name);
214 return STATUS_UNSUCCESSFUL;
215 }
216
217 if (dev->config->interface->altsetting->extralen != 54)
218 {
219 DEBUG_CRITICAL3("Extra field for %s has a wrong length: %d", device_name, dev->config->interface->altsetting->extralen);
220 return STATUS_UNSUCCESSFUL;
221 }
222
223 interface = dev->config->interface->altsetting->bInterfaceNumber;
224 if (usb_claim_interface(dev_handle, interface) < 0)
225 {
226 DEBUG_CRITICAL3("Can't claim interface %s: %s",
227 device_name, strerror(errno));
228 return STATUS_UNSUCCESSFUL;
229 }
230
231 DEBUG_INFO4("Found Vendor/Product: %04X/%04X (%s)",
232 dev->descriptor.idVendor,
233 dev->descriptor.idProduct, keyValue);
234 DEBUG_INFO2("Using USB bus/device: %s",
235 device_name);
236
237 /* Get Endpoints values*/
238 get_end_points(dev, &usbDevice[reader]);
239
240 /* store device information */
241 usbDevice[reader].handle = dev_handle;
242 usbDevice[reader].dev = dev;
243 strncpy(usbDevice[reader].device_name,
244 device_name, BUS_DEVICE_STRSIZE);
245
246 /* CCID common informations */
247 usbDevice[reader].ccid.bSeq = 1;
248 usbDevice[reader].ccid.readerID =
249 (dev->descriptor.idVendor << 16) +
250 dev->descriptor.idProduct;
251 usbDevice[reader].ccid.dwFeatures = dw2i(dev->config->interface->altsetting->extra, 40);
252 usbDevice[reader].ccid.dwMaxCCIDMessageLength = dw2i(dev->config->interface->altsetting->extra, 44);
253
254 goto end;
255 }
256 else
257 DEBUG_CRITICAL3("Can't usb_open(%s): %s",
258 device_name,
259 strerror(errno));
260 }
261 else
262 {
263 DEBUG_INFO2("USB device %s already in use. Checking next one.",
264 device_name);
265 }
266 }
267 }
268 }
269
270 /* go to next supported reader */
271 alias++;
272 }
273 end:
274 if (usbDevice[reader].handle == NULL)
275 return STATUS_UNSUCCESSFUL;
276
277 return STATUS_SUCCESS;
278 } /* OpenUSB */
279
280
281 /*****************************************************************************
282 *
283 * WriteUSB
284 *
285 ****************************************************************************/
286 status_t WriteUSB(int lun, int length, unsigned char *buffer)
287 {
288 int rv;
289 int reader = LunToReaderIndex(lun);
290 #ifdef DEBUG_LEVEL_COMM
291 char debug_header[] = "-> 121234 ";
292
293 sprintf(debug_header, "-> %06X ", (int)lun);
294 #endif
295
296 #ifdef DEBUG_LEVEL_COMM
297 DEBUG_XXD(debug_header, buffer, length);
298 #endif
299
300 rv = usb_bulk_write(usbDevice[reader].handle, usbDevice[reader].bulk_out, buffer, length, USB_WRITE_TIMEOUT);
301
302 if (rv < 0)
303 {
304 DEBUG_CRITICAL3("usb_bulk_write(%s): %s",
305 usbDevice[reader].device_name, strerror(errno));
306 return STATUS_UNSUCCESSFUL;
307 }
308
309 return STATUS_SUCCESS;
310 } /* WriteUSB */
311
312
313 /*****************************************************************************
314 *
315 * ReadUSB
316 *
317 ****************************************************************************/
318 status_t ReadUSB(int lun, int * length, unsigned char *buffer)
319 {
320 int rv;
321 int reader = LunToReaderIndex(lun);
322 #ifdef DEBUG_LEVEL_COMM
323 char debug_header[] = "<- 121234 ";
324
325 sprintf(debug_header, "<- %06X ", (int)lun);
326 #endif
327
328
329 rv = usb_bulk_read(usbDevice[reader].handle, usbDevice[reader].bulk_in, buffer, *length, USB_READ_TIMEOUT);
330 *length = rv;
331
332 if (rv < 0)
333 {
334 DEBUG_CRITICAL3("usb_bulk_read(%s): %s",
335 usbDevice[reader].device_name, strerror(errno));
336 return STATUS_UNSUCCESSFUL;
337 }
338
339 #ifdef DEBUG_LEVEL_COMM
340 DEBUG_XXD(debug_header, buffer, *length);
341 #endif
342
343 return STATUS_SUCCESS;
344 } /* ReadUSB */
345
346
347 /*****************************************************************************
348 *
349 * CloseUSB
350 *
351 ****************************************************************************/
352 status_t CloseUSB(int lun)
353 {
354 int reader = LunToReaderIndex(lun);
355
356 /* device not opened */
357 if (usbDevice[reader].dev == NULL)
358 return STATUS_UNSUCCESSFUL;
359
360 DEBUG_COMM2("Closing USB device: %s", usbDevice[reader].device_name);
361
362 usb_release_interface(usbDevice[reader].handle, usbDevice[reader].dev->config->interface->altsetting->bInterfaceNumber);
363
364 usb_close(usbDevice[reader].handle);
365
366 /* mark the resource unused */
367 usbDevice[reader].handle = NULL;
368 usbDevice[reader].dev = NULL;
369 usbDevice[reader].device_name[0] = '\0';
370
371 return STATUS_SUCCESS;
372 } /* CloseUSB */
373
374
375 /*****************************************************************************
376 *
377 * get_ccid_descriptor
378 *
379 ****************************************************************************/
380 _ccid_descriptor *get_ccid_descriptor(int lun)
381 {
382 return &usbDevice[LunToReaderIndex(lun)].ccid;
383 } /* get_ccid_descriptor */
384
385
386 /*****************************************************************************
387 *
388 * get_desc
389 *
390 ****************************************************************************/
391 int get_desc(int channel, char *device_name[], usb_dev_handle **handle, struct
392 usb_device **dev)
393 {
394 if (channel < 0 || channel > PCSCLITE_MAX_READERS)
395 return 1;
396
397 *device_name = usbDevice[channel].device_name;
398 *handle = usbDevice[channel].handle;
399 *dev = usbDevice[channel].dev;
400
401 return 0;
402 } /* get_desc */
403
404 /*****************************************************************************
405 *
406 * get_end_points
407 *
408 ****************************************************************************/
409 int get_end_points(struct usb_device *dev, _usbDevice *usb_device)
410 {
411 int i;
412 int bEndpointAddress;
413
414 /*
415 * 3 Endpoints maximum: Interrupt In, Bulk In, Bulk Out
416 */
417 for (i=0; i<3; i++)
418 {
419 if (dev->config->interface->altsetting->endpoint[i].bmAttributes != USB_ENDPOINT_TYPE_BULK)
420 continue;
421
422 bEndpointAddress = dev->config->interface->altsetting->endpoint[i].bEndpointAddress;
423
424 if ((bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_IN)
425 usb_device->bulk_in = bEndpointAddress;
426
427 if ((bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_OUT)
428 usb_device->bulk_out = bEndpointAddress;
429 }
430
431 return 0;
432 } /* get_end_points */
433

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.5