/[pcsclite]/trunk/Drivers/ccid/src/parse.c
ViewVC logotype

Contents of /trunk/Drivers/ccid/src/parse.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3408 - (show annotations) (download)
Thu Apr 2 07:27:13 2009 UTC (4 years, 1 month ago) by rousseau
File MIME type: text/plain
File size: 15313 byte(s)
get the iInterface string instead of just printing the string number
1 /*
2 parse.c: parse CCID structure
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 along
16 with this program; if not, write to the Free Software Foundation, Inc., 51
17 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 /*
21 * $Id$
22 */
23
24 #include <stdio.h>
25 #include <string.h>
26 # ifdef S_SPLINT_S
27 # include <sys/types.h>
28 # endif
29 #include <usb.h>
30 #include <errno.h>
31
32 #include "defs.h"
33 #include "ccid.h"
34
35 #ifndef TRUE
36 #define TRUE 1
37 #define FALSE 0
38 #endif
39
40 #define BLUE "\33[34m"
41 #define RED "\33[31m"
42 #define BRIGHT_RED "\33[01;31m"
43 #define GREEN "\33[32m"
44 #define MAGENTA "\33[35m"
45 #define NORMAL "\33[0m"
46
47 static int ccid_parse_interface_descriptor(usb_dev_handle *handle,
48 struct usb_device *dev, int num);
49
50
51 /*****************************************************************************
52 *
53 * main
54 *
55 ****************************************************************************/
56 int main(int argc, char *argv[])
57 {
58 static struct usb_bus *busses = NULL;
59 struct usb_bus *bus;
60 struct usb_dev_handle *dev_handle;
61 int nb = 0;
62 char buffer[256];
63 char class_ff = FALSE;
64
65 if ((argc > 1) && (0 == strcmp(argv[1], "-p")))
66 class_ff = TRUE;
67
68 usb_init();
69 (void)usb_find_busses();
70 (void)usb_find_devices();
71
72 busses = usb_get_busses();
73 if (busses == NULL)
74 {
75 (void)printf("No USB buses found\n");
76 return -1;
77 }
78
79 /* on any USB buses */
80 for (bus = busses; bus; bus = bus->next)
81 {
82 struct usb_device *dev;
83
84 /* any device on this bus */
85 for (dev = bus->devices; dev; dev = dev->next)
86 {
87 struct usb_interface *usb_interface = NULL;
88 int interface;
89 int num = 0;
90
91 dev_handle = usb_open(dev);
92 if (NULL == dev_handle)
93 {
94 (void)fprintf(stderr, "Can't usb_open(%s/%s): %s\n",
95 bus->dirname, dev->filename, strerror(errno));
96 if (getuid())
97 {
98 (void)fprintf(stderr, BRIGHT_RED "Please, restart the command as root\n" NORMAL);
99 return 1;
100 }
101 continue;
102 }
103
104 (void)fprintf(stderr, "Parsing USB bus/device: %s/%s\n",
105 bus->dirname, dev->filename);
106
107 (void)fprintf(stderr, " idVendor: 0x%04X", dev->descriptor.idVendor);
108 if (usb_get_string_simple(dev_handle, dev->descriptor.iManufacturer,
109 buffer, sizeof(buffer)) < 0)
110 {
111 (void)fprintf(stderr, " Can't get iManufacturer string\n");
112 if (getuid())
113 {
114 (void)fprintf(stderr, BRIGHT_RED "Please, restart the command as root\n" NORMAL);
115 return 1;
116 }
117 }
118 else
119 (void)fprintf(stderr, " iManufacturer: " BLUE "%s\n" NORMAL, buffer);
120
121 (void)fprintf(stderr, " idProduct: 0x%04X", dev->descriptor.idProduct);
122 if (usb_get_string_simple(dev_handle, dev->descriptor.iProduct,
123 buffer, sizeof(buffer)) < 0)
124 (void)fprintf(stderr, " Can't get iProduct string\n");
125 else
126 (void)fprintf(stderr, " iProduct: " BLUE "%s\n" NORMAL, buffer);
127
128 again:
129 /* check if the device has bInterfaceClass == 11 */
130 usb_interface = get_ccid_usb_interface(dev, &num);
131 if (NULL == usb_interface)
132 {
133 (void)usb_close(dev_handle);
134 /* only if we found no CCID interface */
135 if (0 == num)
136 (void)fprintf(stderr, RED " NOT a CCID/ICCD device\n" NORMAL);
137 continue;
138 }
139 if (!class_ff && (0xFF == usb_interface->altsetting->bInterfaceClass))
140 {
141 (void)fprintf(stderr, MAGENTA " Found a possibly CCID/ICCD device (bInterfaceClass = 0xFF). Use -p\n" NORMAL);
142 continue;
143 }
144 (void)fprintf(stderr, GREEN " Found a CCID/ICCD device at interface %d\n" NORMAL, num);
145
146 /* now we found a free reader and we try to use it */
147 if (NULL == dev->config)
148 {
149 (void)usb_close(dev_handle);
150 (void)fprintf(stderr, "No dev->config found for %s/%s\n",
151 bus->dirname, dev->filename);
152 continue;
153 }
154
155 interface = usb_interface->altsetting->bInterfaceNumber;
156 #ifndef __APPLE__
157 if (usb_claim_interface(dev_handle, interface) < 0)
158 {
159 (void)usb_close(dev_handle);
160 (void)fprintf(stderr, "Can't claim interface %s/%s: %s\n",
161 bus->dirname, dev->filename, strerror(errno));
162 if (EBUSY == errno)
163 {
164 (void)fprintf(stderr,
165 BRIGHT_RED " Please, stop pcscd and retry\n\n" NORMAL);
166 return TRUE;
167 }
168 continue;
169 }
170 #endif
171
172 (void)ccid_parse_interface_descriptor(dev_handle, dev, num);
173
174 #ifndef __APPLE__
175 (void)usb_release_interface(dev_handle, interface);
176 #endif
177 /* check for another CCID interface on the same device */
178 num++;
179 goto again;
180
181 (void)usb_close(dev_handle);
182 nb++;
183 }
184 }
185
186 if ((0 == nb) && (0 != geteuid()))
187 (void)fprintf(stderr, "Can't find any CCID device.\nMaybe you must run parse as root?\n");
188 return 0;
189 } /* main */
190
191
192 /*****************************************************************************
193 *
194 * Parse a CCID USB Descriptor
195 *
196 ****************************************************************************/
197 static int ccid_parse_interface_descriptor(usb_dev_handle *handle,
198 struct usb_device *dev, int num)
199 {
200 struct usb_interface_descriptor *usb_interface;
201 unsigned char *extra;
202 char buffer[256*sizeof(int)]; /* maximum is 256 records */
203 /* unsigned version of buffer[] used for multi-bytes conversions */
204 unsigned char *ubuffer = (unsigned char *)buffer;
205
206 /*
207 * Vendor/model name
208 */
209 (void)printf(" idVendor: 0x%04X\n", dev->descriptor.idVendor);
210 if (usb_get_string_simple(handle, dev->descriptor.iManufacturer,
211 buffer, sizeof(buffer)) < 0)
212 {
213 (void)printf(" Can't get iManufacturer string\n");
214 if (getuid())
215 {
216 (void)fprintf(stderr,
217 BRIGHT_RED "Please, restart the command as root\n\n" NORMAL);
218 return TRUE;
219 }
220 }
221 else
222 (void)printf(" iManufacturer: %s\n", buffer);
223
224 (void)printf(" idProduct: 0x%04X\n", dev->descriptor.idProduct);
225 if (usb_get_string_simple(handle, dev->descriptor.iProduct,
226 buffer, sizeof(buffer)) < 0)
227 (void)printf(" Can't get iProduct string\n");
228 else
229 (void)printf(" iProduct: %s\n", buffer);
230
231 (void)printf(" bcdDevice: %X.%02X (firmware release?)\n",
232 dev->descriptor.bcdDevice >> 8, dev->descriptor.bcdDevice & 0xFF);
233
234 usb_interface = get_ccid_usb_interface(dev, &num)->altsetting;
235
236 (void)printf(" bLength: %d\n", usb_interface->bLength);
237
238 (void)printf(" bDescriptorType: %d\n", usb_interface->bDescriptorType);
239
240 (void)printf(" bInterfaceNumber: %d\n", usb_interface->bInterfaceNumber);
241
242 (void)printf(" bAlternateSetting: %d\n", usb_interface->bAlternateSetting);
243
244 (void)printf(" bNumEndpoints: %d\n", usb_interface->bNumEndpoints);
245 switch (usb_interface->bNumEndpoints)
246 {
247 case 0:
248 (void)printf(" Control only\n");
249 break;
250 case 1:
251 (void)printf(" Interrupt-IN\n");
252 break;
253 case 2:
254 (void)printf(" bulk-IN and bulk-OUT\n");
255 break;
256 case 3:
257 (void)printf(" bulk-IN, bulk-OUT and Interrupt-IN\n");
258 break;
259 default:
260 (void)printf(" UNKNOWN value\n");
261 }
262
263 (void)printf(" bInterfaceClass: 0x%02X", usb_interface->bInterfaceClass);
264 if (usb_interface->bInterfaceClass == 0x0b)
265 (void)printf(" [Chip Card Interface Device Class (CCID)]\n");
266 else
267 {
268 (void)printf("\n NOT A CCID DEVICE\n");
269 if (usb_interface->bInterfaceClass != 0xFF)
270 return TRUE;
271 else
272 (void)printf(" Class is 0xFF (proprietary)\n");
273 }
274
275 (void)printf(" bInterfaceSubClass: %d\n", usb_interface->bInterfaceSubClass);
276 if (usb_interface->bInterfaceSubClass)
277 (void)printf(" UNSUPPORTED SubClass\n");
278
279 (void)printf(" bInterfaceProtocol: %d\n", usb_interface->bInterfaceProtocol);
280 switch (usb_interface->bInterfaceProtocol)
281 {
282 case 0:
283 (void)printf(" bulk transfer, optional interrupt-IN (CCID)\n");
284 break;
285 case 1:
286 (void)printf(" ICCD Version A, Control transfers, (no interrupt-IN)\n");
287 break;
288 case 2:
289 (void)printf(" ICCD Version B, Control transfers, (optional interrupt-IN)\n");
290 break;
291 default:
292 (void)printf(" UNSUPPORTED InterfaceProtocol\n");
293 }
294
295 if (usb_get_string_simple(handle, usb_interface->iInterface,
296 buffer, sizeof(buffer)) < 0)
297 (void)printf(" Can't get iInterface string\n");
298 else
299 (void)printf(" iInterface: %s\n", buffer);
300
301 if (usb_interface->extralen < 54)
302 {
303 (void)printf("USB extra length is too short: %d\n", usb_interface->extralen);
304 (void)printf("\n NOT A CCID DEVICE\n");
305 return TRUE;
306 }
307
308 /*
309 * CCID Class Descriptor
310 */
311 (void)printf(" CCID Class Descriptor\n");
312 extra = usb_interface->extra;
313
314 (void)printf(" bLength: 0x%02X\n", extra[0]);
315 if (extra[0] != 0x36)
316 {
317 (void)printf(" UNSUPPORTED bLength\n");
318 return TRUE;
319 }
320
321 (void)printf(" bDescriptorType: 0x%02X\n", extra[1]);
322 if (extra[1] != 0x21)
323 {
324 if (0xFF == extra[1])
325 (void)printf(" PROPRIETARY bDescriptorType\n");
326 else
327 {
328 (void)printf(" UNSUPPORTED bDescriptorType\n");
329 return TRUE;
330 }
331 }
332
333 (void)printf(" bcdCCID: %X.%02X\n", extra[3], extra[2]);
334 (void)printf(" bMaxSlotIndex: 0x%02X\n", extra[4]);
335 (void)printf(" bVoltageSupport: 0x%02X\n", extra[5]);
336 if (extra[5] & 0x01)
337 (void)printf(" 5.0V\n");
338 if (extra[5] & 0x02)
339 (void)printf(" 3.0V\n");
340 if (extra[5] & 0x04)
341 (void)printf(" 1.8V\n");
342
343 (void)printf(" dwProtocols: 0x%02X%02X 0x%02X%02X\n", extra[9], extra[8],
344 extra[7], extra[6]);
345 if (extra[6] & 0x01)
346 (void)printf(" T=0\n");
347 if (extra[6] & 0x02)
348 (void)printf(" T=1\n");
349
350 (void)printf(" dwDefaultClock: %.3f MHz\n", dw2i(extra, 10)/1000.0);
351 (void)printf(" dwMaximumClock: %.3f MHz\n", dw2i(extra, 14)/1000.0);
352 (void)printf(" bNumClockSupported: %d %s\n", extra[18],
353 extra[18] ? "" : "(will use whatever is returned)");
354 {
355 int n;
356
357 /* See CCID 3.7.2 page 25 */
358 n = usb_control_msg(handle,
359 0xA1, /* request type */
360 0x02, /* GET CLOCK FREQUENCIES */
361 0x00, /* value */
362 usb_interface->bInterfaceNumber, /* interface */
363 buffer,
364 sizeof(buffer),
365 2 * 1000);
366
367 /* we got an error? */
368 if (n <= 0)
369 {
370 (void)(void)printf(" IFD does not support GET CLOCK FREQUENCIES request: %s\n", strerror(errno));
371 if (EBUSY == errno)
372 {
373 (void)fprintf(stderr,
374 BRIGHT_RED " Please, stop pcscd and retry\n\n" NORMAL);
375 return TRUE;
376 }
377 }
378 else
379 if (n % 4) /* not a multiple of 4 */
380 (void)printf(" wrong size for GET CLOCK FREQUENCIES: %d\n", n);
381 else
382 {
383 int i;
384
385 /* we do not get the expected number of data rates */
386 if ((n != extra[18]*4) && extra[18])
387 {
388 (void)printf(" Got %d clock frequencies but was expecting %d\n",
389 n/4, extra[18]);
390
391 /* we got more data than expected */
392 if (n > extra[18]*4)
393 n = extra[18]*4;
394 }
395
396 for (i=0; i<n; i+=4)
397 (void)printf(" Support %d kHz\n", dw2i(ubuffer, i));
398 }
399 }
400 (void)printf(" dwDataRate: %d bps\n", dw2i(extra, 19));
401 (void)printf(" dwMaxDataRate: %d bps\n", dw2i(extra, 23));
402 (void)printf(" bNumDataRatesSupported: %d %s\n", extra[27],
403 extra[27] ? "" : "(will use whatever is returned)");
404 {
405 int n;
406
407 /* See CCID 3.7.3 page 25 */
408 n = usb_control_msg(handle,
409 0xA1, /* request type */
410 0x03, /* GET DATA RATES */
411 0x00, /* value */
412 usb_interface->bInterfaceNumber, /* interface */
413 buffer,
414 sizeof(buffer),
415 2 * 1000);
416
417 /* we got an error? */
418 if (n <= 0)
419 (void)printf(" IFD does not support GET_DATA_RATES request: %s\n",
420 strerror(errno));
421 else
422 if (n % 4) /* not a multiple of 4 */
423 (void)printf(" wrong size for GET_DATA_RATES: %d\n", n);
424 else
425 {
426 int i;
427
428 /* we do not get the expected number of data rates */
429 if ((n != extra[27]*4) && extra[27])
430 {
431 (void)printf(" Got %d data rates but was expecting %d\n", n/4,
432 extra[27]);
433
434 /* we got more data than expected */
435 if (n > extra[27]*4)
436 n = extra[27]*4;
437 }
438
439 for (i=0; i<n; i+=4)
440 (void)printf(" Support %d bps\n", dw2i(ubuffer, i));
441 }
442 }
443 (void)printf(" dwMaxIFSD: %d\n", dw2i(extra, 28));
444 (void)printf(" dwSynchProtocols: 0x%08X\n", dw2i(extra, 32));
445 if (extra[32] & 0x01)
446 (void)printf(" 2-wire protocol\n");
447 if (extra[32] & 0x02)
448 (void)printf(" 3-wire protocol\n");
449 if (extra[32] & 0x04)
450 (void)printf(" I2C protocol\n");
451
452 (void)printf(" dwMechanical: 0x%08X\n", dw2i(extra, 36));
453 if (extra[36] == 0)
454 (void)printf(" No special characteristics\n");
455 if (extra[36] & 0x01)
456 (void)printf(" Card accept mechanism\n");
457 if (extra[36] & 0x02)
458 (void)printf(" Card ejection mechanism\n");
459 if (extra[36] & 0x04)
460 (void)printf(" Card capture mechanism\n");
461 if (extra[36] & 0x08)
462 (void)printf(" Card lock/unlock mechanism\n");
463
464 (void)printf(" dwFeatures: 0x%08X\n", dw2i(extra, 40));
465 if (dw2i(extra, 40) == 0)
466 (void)printf(" No special characteristics\n");
467 if (extra[40] & 0x02)
468 (void)printf(" ....02 Automatic parameter configuration based on ATR data\n");
469 if (extra[40] & 0x04)
470 (void)printf(" ....04 Automatic activation of ICC on inserting\n");
471 if (extra[40] & 0x08)
472 (void)printf(" ....08 Automatic ICC voltage selection\n");
473 if (extra[40] & 0x10)
474 (void)printf(" ....10 Automatic ICC clock frequency change according to parameters\n");
475 if (extra[40] & 0x20)
476 (void)printf(" ....20 Automatic baud rate change according to frequency and Fi, Di params\n");
477 if (extra[40] & 0x40)
478 (void)printf(" ....40 Automatic parameters negotiation made by the CCID\n");
479 if (extra[40] & 0x80)
480 (void)printf(" ....80 Automatic PPS made by the CCID\n");
481 if (extra[41] & 0x01)
482 (void)printf(" ..01.. CCID can set ICC in clock stop mode\n");
483 if (extra[41] & 0x02)
484 (void)printf(" ..02.. NAD value other than 00 accepted (T=1)\n");
485 if (extra[41] & 0x04)
486 (void)printf(" ..04.. Automatic IFSD exchange as first exchange (T=1)\n");
487 if (extra[41] & 0x08)
488 (void)printf(" ..08.. Unknown (ICCD?)\n");
489 switch (extra[42] & 0x07)
490 {
491 case 0x00:
492 (void)printf(" 00.... Character level exchange\n");
493 break;
494
495 case 0x01:
496 (void)printf(" 01.... TPDU level exchange\n");
497 break;
498
499 case 0x02:
500 (void)printf(" 02.... Short APDU level exchange\n");
501 break;
502
503 case 0x04:
504 (void)printf(" 04.... Short and Extended APDU level exchange\n");
505 break;
506 }
507
508 (void)printf(" dwMaxCCIDMessageLength: %d bytes\n", dw2i(extra, 44));
509 (void)printf(" bClassGetResponse: 0x%02X\n", extra[48]);
510 if (0xFF == extra[48])
511 (void)printf(" echoes the APDU class\n");
512 (void)printf(" bClassEnveloppe: 0x%02X\n", extra[49]);
513 if (0xFF == extra[49])
514 (void)printf(" echoes the APDU class\n");
515 (void)printf(" wLcdLayout: 0x%04X\n", (extra[51] << 8)+extra[50]);
516 if (extra[50])
517 (void)printf(" %d lines\n", extra[50]);
518 if (extra[51])
519 (void)printf(" %d characters per line\n", extra[51]);
520 (void)printf(" bPINSupport: 0x%02X\n", extra[52]);
521 if (extra[52] & 0x01)
522 (void)printf(" PIN Verification supported\n");
523 if (extra[52] & 0x02)
524 (void)printf(" PIN Modification supported\n");
525 (void)printf(" bMaxCCIDBusySlots: %d\n", extra[53]);
526
527 return FALSE;
528 } /* ccid_parse_interface_descriptor */
529

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.5