/[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 608 - (hide annotations) (download)
Thu Jan 15 08:30:31 2004 UTC (9 years, 4 months ago) by rousseau
File MIME type: text/plain
File size: 11685 byte(s)
remove function name from debug message since __FUNCTION__ is now used in
DEBUG_* macro definition
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 rousseau 406 #include "ccid.h"
37 rousseau 269
38    
39 rousseau 570 /* 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 rousseau 269
45 rousseau 570 /* 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 rousseau 269 #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 rousseau 406
71     /*
72     * CCID infos common to USB and serial
73     */
74     _ccid_descriptor ccid;
75    
76 rousseau 269 } _usbDevice;
77    
78 rousseau 406 /* The _usbDevice structure must be defined before including ccid_usb.h */
79 rousseau 269 #include "ccid_usb.h"
80    
81 rousseau 406 static _usbDevice usbDevice[PCSCLITE_MAX_READERS] = {
82     [ 0 ... (PCSCLITE_MAX_READERS-1) ] = { NULL, NULL, "", 0, 0 }
83 rousseau 269 };
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 rousseau 301 char infofile[FILENAME_MAX];
104 rousseau 269
105 rousseau 608 DEBUG_COMM3("Lun: %X, Channel: %X", lun, Channel);
106 rousseau 269
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 rousseau 301 /* Info.plist full patch filename */
129 rousseau 406 snprintf(infofile, sizeof(infofile), "%s/%s/Contents/Info.plist",
130     PCSCLITE_HP_DROPDIR, BUNDLE);
131 rousseau 301
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 rousseau 406 for (r=0; r<PCSCLITE_MAX_READERS; r++)
190 rousseau 269 {
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 rousseau 581 if (dev->config->interface->altsetting->extralen != 54)
218 rousseau 579 {
219 rousseau 581 DEBUG_CRITICAL3("Extra field for %s has a wrong length: %d", device_name, dev->config->interface->altsetting->extralen);
220 rousseau 579 return STATUS_UNSUCCESSFUL;
221     }
222    
223 rousseau 269 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 rousseau 525 device_name, strerror(errno));
228 rousseau 269 return STATUS_UNSUCCESSFUL;
229     }
230    
231     DEBUG_INFO4("Found Vendor/Product: %04X/%04X (%s)",
232     dev->descriptor.idVendor,
233     dev->descriptor.idProduct, keyValue);
234 rousseau 301 DEBUG_INFO2("Using USB bus/device: %s",
235     device_name);
236 rousseau 269
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 rousseau 406 /* 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     /* Maybe we have a special treatment
255     * for this reader */
256     ccid_open_hack(lun);
257    
258 rousseau 269 goto end;
259     }
260     else
261 rousseau 301 DEBUG_CRITICAL3("Can't usb_open(%s): %s",
262     device_name,
263 rousseau 269 strerror(errno));
264     }
265     else
266     {
267     DEBUG_INFO2("USB device %s already in use. Checking next one.",
268     device_name);
269     }
270     }
271     }
272     }
273    
274     /* go to next supported reader */
275     alias++;
276     }
277     end:
278     if (usbDevice[reader].handle == NULL)
279     return STATUS_UNSUCCESSFUL;
280    
281     return STATUS_SUCCESS;
282     } /* OpenUSB */
283    
284    
285     /*****************************************************************************
286     *
287     * WriteUSB
288     *
289     ****************************************************************************/
290     status_t WriteUSB(int lun, int length, unsigned char *buffer)
291     {
292     int rv;
293     int reader = LunToReaderIndex(lun);
294     #ifdef DEBUG_LEVEL_COMM
295     char debug_header[] = "-> 121234 ";
296    
297     sprintf(debug_header, "-> %06X ", (int)lun);
298     #endif
299    
300     #ifdef DEBUG_LEVEL_COMM
301     DEBUG_XXD(debug_header, buffer, length);
302     #endif
303    
304 rousseau 570 rv = usb_bulk_write(usbDevice[reader].handle, usbDevice[reader].bulk_out, buffer, length, USB_WRITE_TIMEOUT);
305 rousseau 269
306     if (rv < 0)
307     {
308     DEBUG_CRITICAL3("usb_bulk_write(%s): %s",
309     usbDevice[reader].device_name, strerror(errno));
310     return STATUS_UNSUCCESSFUL;
311     }
312    
313     return STATUS_SUCCESS;
314     } /* WriteUSB */
315    
316    
317     /*****************************************************************************
318     *
319     * ReadUSB
320     *
321     ****************************************************************************/
322     status_t ReadUSB(int lun, int * length, unsigned char *buffer)
323     {
324     int rv;
325     int reader = LunToReaderIndex(lun);
326     #ifdef DEBUG_LEVEL_COMM
327     char debug_header[] = "<- 121234 ";
328    
329     sprintf(debug_header, "<- %06X ", (int)lun);
330     #endif
331    
332    
333 rousseau 570 rv = usb_bulk_read(usbDevice[reader].handle, usbDevice[reader].bulk_in, buffer, *length, USB_READ_TIMEOUT);
334 rousseau 269 *length = rv;
335    
336     if (rv < 0)
337     {
338     DEBUG_CRITICAL3("usb_bulk_read(%s): %s",
339     usbDevice[reader].device_name, strerror(errno));
340     return STATUS_UNSUCCESSFUL;
341     }
342    
343     #ifdef DEBUG_LEVEL_COMM
344     DEBUG_XXD(debug_header, buffer, *length);
345     #endif
346    
347     return STATUS_SUCCESS;
348     } /* ReadUSB */
349    
350    
351     /*****************************************************************************
352     *
353     * CloseUSB
354     *
355     ****************************************************************************/
356     status_t CloseUSB(int lun)
357     {
358     int reader = LunToReaderIndex(lun);
359    
360     /* device not opened */
361     if (usbDevice[reader].dev == NULL)
362     return STATUS_UNSUCCESSFUL;
363    
364     DEBUG_COMM2("Closing USB device: %s", usbDevice[reader].device_name);
365    
366     usb_release_interface(usbDevice[reader].handle, usbDevice[reader].dev->config->interface->altsetting->bInterfaceNumber);
367    
368     usb_close(usbDevice[reader].handle);
369    
370     /* mark the resource unused */
371     usbDevice[reader].handle = NULL;
372     usbDevice[reader].dev = NULL;
373     usbDevice[reader].device_name[0] = '\0';
374    
375     return STATUS_SUCCESS;
376     } /* CloseUSB */
377    
378    
379 rousseau 301 /*****************************************************************************
380     *
381 rousseau 406 * get_ccid_descriptor
382 rousseau 301 *
383     ****************************************************************************/
384 rousseau 406 _ccid_descriptor *get_ccid_descriptor(int lun)
385 rousseau 269 {
386 rousseau 406 return &usbDevice[LunToReaderIndex(lun)].ccid;
387     } /* get_ccid_descriptor */
388 rousseau 269
389    
390 rousseau 301 /*****************************************************************************
391     *
392     * get_desc
393     *
394     ****************************************************************************/
395 rousseau 269 int get_desc(int channel, char *device_name[], usb_dev_handle **handle, struct
396     usb_device **dev)
397     {
398 rousseau 406 if (channel < 0 || channel > PCSCLITE_MAX_READERS)
399 rousseau 269 return 1;
400    
401     *device_name = usbDevice[channel].device_name;
402     *handle = usbDevice[channel].handle;
403     *dev = usbDevice[channel].dev;
404    
405     return 0;
406     } /* get_desc */
407    
408 rousseau 301 /*****************************************************************************
409     *
410     * get_end_points
411     *
412     ****************************************************************************/
413 rousseau 269 int get_end_points(struct usb_device *dev, _usbDevice *usb_device)
414     {
415     int i;
416     int bEndpointAddress;
417    
418     /*
419     * 3 Endpoints maximum: Interrupt In, Bulk In, Bulk Out
420     */
421     for (i=0; i<3; i++)
422     {
423     if (dev->config->interface->altsetting->endpoint[i].bmAttributes != USB_ENDPOINT_TYPE_BULK)
424     continue;
425    
426     bEndpointAddress = dev->config->interface->altsetting->endpoint[i].bEndpointAddress;
427    
428     if ((bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_IN)
429     usb_device->bulk_in = bEndpointAddress;
430    
431     if ((bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_OUT)
432     usb_device->bulk_out = bEndpointAddress;
433     }
434    
435     return 0;
436     } /* get_end_points */
437    

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.5