/[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 570 - (hide annotations) (download)
Tue Dec 16 10:11:09 2003 UTC (9 years, 5 months ago) by rousseau
File MIME type: text/plain
File size: 11454 byte(s)
read and write timeouts are not symmetric. write timout can be shorter
since the reader and card is not supposed to do anything before
receiving (write) a command.
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     DEBUG_COMM3("OpenUSB: Lun: %X, Channel: %X", lun, Channel);
106    
107     if (busses == NULL)
108     {
109     usb_init();
110     }
111    
112     usb_find_busses();
113     usb_find_devices();
114    
115     busses = usb_get_busses();
116    
117     if (busses == NULL)
118     {
119     DEBUG_CRITICAL("No USB busses found");
120     return STATUS_UNSUCCESSFUL;
121     }
122    
123     /* is the lun already used? */
124     if (usbDevice[reader].handle != NULL)
125     {
126     DEBUG_CRITICAL2("USB driver with lun %X already in use", lun);
127     return STATUS_UNSUCCESSFUL;
128     }
129    
130 rousseau 301 /* Info.plist full patch filename */
131 rousseau 406 snprintf(infofile, sizeof(infofile), "%s/%s/Contents/Info.plist",
132     PCSCLITE_HP_DROPDIR, BUNDLE);
133 rousseau 301
134 rousseau 269 /* general driver info */
135 rousseau 301 if (!LTPBundleFindValueWithKey(infofile, "ifdManufacturerString", keyValue, 0))
136 rousseau 269 DEBUG_CRITICAL2("Manufacturer: %s", keyValue);
137     else
138     {
139     DEBUG_CRITICAL2("LTPBundleFindValueWithKey error. Can't find %s?",
140 rousseau 301 infofile);
141 rousseau 269 return STATUS_UNSUCCESSFUL;
142     }
143 rousseau 301 if (!LTPBundleFindValueWithKey(infofile, "ifdProductString", keyValue, 0))
144 rousseau 269 DEBUG_CRITICAL2("ProductString: %s", keyValue);
145     else
146     return STATUS_UNSUCCESSFUL;
147 rousseau 301 if (!LTPBundleFindValueWithKey(infofile, "Copyright", keyValue, 0))
148 rousseau 269 DEBUG_CRITICAL2("Copyright: %s", keyValue);
149     else
150     return STATUS_UNSUCCESSFUL;
151     vendorID = strlen(keyValue);
152     alias = 0x1D;
153     for (; vendorID--;)
154     alias ^= keyValue[vendorID];
155    
156     /* for any supported reader */
157 rousseau 301 while (LTPBundleFindValueWithKey(infofile, PCSCLITE_MANUKEY_NAME, keyValue, alias) == 0)
158 rousseau 269 {
159 rousseau 301 vendorID = strtoul(keyValue, 0, 16);
160 rousseau 269
161 rousseau 301 if (LTPBundleFindValueWithKey(infofile, PCSCLITE_PRODKEY_NAME, keyValue, alias))
162 rousseau 269 goto end;
163 rousseau 301 productID = strtoul(keyValue, 0, 16);
164 rousseau 269
165 rousseau 301 if (LTPBundleFindValueWithKey(infofile, PCSCLITE_NAMEKEY_NAME, keyValue, alias))
166 rousseau 269 goto end;
167    
168     /* on any USB buses */
169     for (bus = busses; bus; bus = bus->next)
170     {
171     struct usb_device *dev;
172    
173     /* any device on this bus */
174     for (dev = bus->devices; dev; dev = dev->next)
175     {
176     if (dev->descriptor.idVendor == vendorID
177     && dev->descriptor.idProduct == productID)
178     {
179     int r, already_used;
180     char device_name[BUS_DEVICE_STRSIZE];
181    
182     if (snprintf(device_name, BUS_DEVICE_STRSIZE, "%s/%s",
183     bus->dirname, dev->filename) < 0)
184     {
185     DEBUG_CRITICAL2("Device name too long: %s", device_name);
186     return STATUS_UNSUCCESSFUL;
187     }
188    
189     /* is it already opened? */
190     already_used = FALSE;
191 rousseau 406 for (r=0; r<PCSCLITE_MAX_READERS; r++)
192 rousseau 269 {
193     if (usbDevice[r].dev)
194     {
195     DEBUG_COMM3("Checking new device '%s' against old '%s'",
196     device_name, usbDevice[r].device_name);
197     if (strcmp(usbDevice[r].device_name, device_name) == 0)
198     already_used = TRUE;
199     }
200     }
201    
202     if (!already_used)
203     {
204 rousseau 301 DEBUG_COMM2("Trying to open USB bus/device: %s",
205     device_name);
206    
207 rousseau 269 dev_handle = usb_open(dev);
208     if (dev_handle)
209     {
210     int interface;
211    
212     if (dev->config == NULL)
213     {
214 rousseau 301 DEBUG_CRITICAL2("No dev->config found for %s",
215     device_name);
216 rousseau 269 return STATUS_UNSUCCESSFUL;
217     }
218    
219     interface = dev->config->interface->altsetting->bInterfaceNumber;
220     if (usb_claim_interface(dev_handle, interface) < 0)
221     {
222     DEBUG_CRITICAL3("Can't claim interface %s: %s",
223 rousseau 525 device_name, strerror(errno));
224 rousseau 269 return STATUS_UNSUCCESSFUL;
225     }
226    
227     DEBUG_INFO4("Found Vendor/Product: %04X/%04X (%s)",
228     dev->descriptor.idVendor,
229     dev->descriptor.idProduct, keyValue);
230 rousseau 301 DEBUG_INFO2("Using USB bus/device: %s",
231     device_name);
232 rousseau 269
233     /* Get Endpoints values*/
234     get_end_points(dev, &usbDevice[reader]);
235    
236     /* store device information */
237     usbDevice[reader].handle = dev_handle;
238     usbDevice[reader].dev = dev;
239     strncpy(usbDevice[reader].device_name,
240     device_name, BUS_DEVICE_STRSIZE);
241    
242 rousseau 406 /* CCID common informations */
243     usbDevice[reader].ccid.bSeq = 1;
244     usbDevice[reader].ccid.readerID =
245     (dev->descriptor.idVendor << 16) +
246     dev->descriptor.idProduct;
247     usbDevice[reader].ccid.dwFeatures = dw2i(dev->config->interface->altsetting->extra, 40);
248     usbDevice[reader].ccid.dwMaxCCIDMessageLength = dw2i(dev->config->interface->altsetting->extra, 44);
249    
250     /* Maybe we have a special treatment
251     * for this reader */
252     ccid_open_hack(lun);
253    
254 rousseau 269 goto end;
255     }
256     else
257 rousseau 301 DEBUG_CRITICAL3("Can't usb_open(%s): %s",
258     device_name,
259 rousseau 269 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 rousseau 570 rv = usb_bulk_write(usbDevice[reader].handle, usbDevice[reader].bulk_out, buffer, length, USB_WRITE_TIMEOUT);
301 rousseau 269
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 rousseau 570 rv = usb_bulk_read(usbDevice[reader].handle, usbDevice[reader].bulk_in, buffer, *length, USB_READ_TIMEOUT);
330 rousseau 269 *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 rousseau 301 /*****************************************************************************
376     *
377 rousseau 406 * get_ccid_descriptor
378 rousseau 301 *
379     ****************************************************************************/
380 rousseau 406 _ccid_descriptor *get_ccid_descriptor(int lun)
381 rousseau 269 {
382 rousseau 406 return &usbDevice[LunToReaderIndex(lun)].ccid;
383     } /* get_ccid_descriptor */
384 rousseau 269
385    
386 rousseau 301 /*****************************************************************************
387     *
388     * get_desc
389     *
390     ****************************************************************************/
391 rousseau 269 int get_desc(int channel, char *device_name[], usb_dev_handle **handle, struct
392     usb_device **dev)
393     {
394 rousseau 406 if (channel < 0 || channel > PCSCLITE_MAX_READERS)
395 rousseau 269 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 rousseau 301 /*****************************************************************************
405     *
406     * get_end_points
407     *
408     ****************************************************************************/
409 rousseau 269 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