pcsc-lite 1.9.7
hotplug_libusb.c
Go to the documentation of this file.
1/*
2 * MUSCLE SmartCard Development ( https://pcsclite.apdu.fr/ )
3 *
4 * Copyright (C) 2001-2004
5 * David Corcoran <corcoran@musclecard.com>
6 * Copyright (C) 2003-2011
7 * Ludovic Rousseau <ludovic.rousseau@free.fr>
8 * Copyright (C) 2003
9 * Toni Andjelkovic <toni@soth.at>
10 * Copyright (C) 2003-2004
11 * Damien Sauveron <damien.sauveron@labri.fr>
12 *
13Redistribution and use in source and binary forms, with or without
14modification, are permitted provided that the following conditions
15are met:
16
171. Redistributions of source code must retain the above copyright
18 notice, this list of conditions and the following disclaimer.
192. Redistributions in binary form must reproduce the above copyright
20 notice, this list of conditions and the following disclaimer in the
21 documentation and/or other materials provided with the distribution.
223. The name of the author may not be used to endorse or promote products
23 derived from this software without specific prior written permission.
24
25THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 */
36
42#include "config.h"
43#ifdef HAVE_LIBUSB
44
45#define _GNU_SOURCE /* for asprintf(3) */
46#include <string.h>
47#include <sys/types.h>
48#include <stdio.h>
49#include <dirent.h>
50#include <fcntl.h>
51#include <time.h>
52#include <stdlib.h>
53#include <unistd.h>
54#include <errno.h>
55#include <libusb.h>
56#include <pthread.h>
57#include <signal.h>
58
59#include "misc.h"
60#include "wintypes.h"
61#include "pcscd.h"
62#include "debuglog.h"
63#include "parser.h"
64#include "readerfactory.h"
65#include "winscard_msg.h"
66#include "sys_generic.h"
67#include "hotplug.h"
68#include "utils.h"
69
70#undef DEBUG_HOTPLUG
71
72/* format is "%d:%d:%d", bus_number, device_address, interface */
73#define BUS_DEVICE_STRSIZE 10+1+10+1+10+1
74
75#define READER_ABSENT 0
76#define READER_PRESENT 1
77#define READER_FAILED 2
78
79#define FALSE 0
80#define TRUE 1
81
82extern char Add_Interface_In_Name;
83extern char Add_Serial_In_Name;
84
85/* we use the default libusb context */
86#define ctx NULL
87
88pthread_mutex_t usbNotifierMutex;
89
90static pthread_t usbNotifyThread;
91static int driverSize = -1;
92static char AraKiriHotPlug = FALSE;
93static int rescan_pipe[] = { -1, -1 };
94extern int HPForceReaderPolling;
95
96/* values of ifdCapabilities bits */
97#define IFD_GENERATE_HOTPLUG 1
98
102static struct _driverTracker
103{
104 unsigned int manuID;
105 unsigned int productID;
106
107 char *bundleName;
108 char *libraryPath;
109 char *readerName;
110 int ifdCapabilities;
111 char *CFBundleName;
112} *driverTracker = NULL;
113#define DRIVER_TRACKER_SIZE_STEP 8
114
118static struct _readerTracker
119{
120 char status;
121 char bus_device[BUS_DEVICE_STRSIZE];
122 char *fullName;
123} readerTracker[PCSCLITE_MAX_READERS_CONTEXTS];
124
125static LONG HPAddHotPluggable(struct libusb_device *dev,
126 struct libusb_device_descriptor desc,
127 const char bus_device[],
128 const struct libusb_interface *idesc,
129 struct _driverTracker *driver,
130 struct _driverTracker *classdriver);
131static LONG HPRemoveHotPluggable(int reader_index);
132
133static LONG HPReadBundleValues(void)
134{
135 LONG rv;
136 DIR *hpDir;
137 struct dirent *currFP = NULL;
138 char fullPath[FILENAME_MAX];
139 char fullLibPath[FILENAME_MAX];
140 int listCount = 0;
141
142 hpDir = opendir(PCSCLITE_HP_DROPDIR);
143
144 if (hpDir == NULL)
145 {
146 Log1(PCSC_LOG_ERROR, "Cannot open PC/SC drivers directory: " PCSCLITE_HP_DROPDIR);
147 Log1(PCSC_LOG_ERROR, "Disabling USB support for pcscd.");
148 return -1;
149 }
150
151 /* allocate a first array */
152 driverTracker = calloc(DRIVER_TRACKER_SIZE_STEP, sizeof(*driverTracker));
153 if (NULL == driverTracker)
154 {
155 Log1(PCSC_LOG_CRITICAL, "Not enough memory");
156 return -1;
157 }
158 driverSize = DRIVER_TRACKER_SIZE_STEP;
159
160#define GET_KEY(key, values) \
161 rv = LTPBundleFindValueWithKey(&plist, key, values); \
162 if (rv) \
163 { \
164 Log2(PCSC_LOG_ERROR, "Value/Key not defined for " key " in %s", \
165 fullPath); \
166 continue; \
167 }
168
169 while ((currFP = readdir(hpDir)) != 0)
170 {
171 if (strstr(currFP->d_name, ".bundle") != 0)
172 {
173 unsigned int alias;
174 list_t plist, *values;
175 list_t *manuIDs, *productIDs, *readerNames;
176 char *libraryPath;
177 int ifdCapabilities;
178 char *CFBundleName;
179
180 /*
181 * The bundle exists - let's form a full path name and get the
182 * vendor and product ID's for this particular bundle
183 */
184 snprintf(fullPath, sizeof(fullPath), "%s/%s/Contents/Info.plist",
185 PCSCLITE_HP_DROPDIR, currFP->d_name);
186 fullPath[sizeof(fullPath) - 1] = '\0';
187
188 rv = bundleParse(fullPath, &plist);
189 if (rv)
190 continue;
191
192 /* get CFBundleExecutable */
193 GET_KEY(PCSCLITE_HP_LIBRKEY_NAME, &values)
194 libraryPath = list_get_at(values, 0);
195 (void)snprintf(fullLibPath, sizeof(fullLibPath),
196 "%s/%s/Contents/%s/%s",
197 PCSCLITE_HP_DROPDIR, currFP->d_name, PCSC_ARCH,
198 libraryPath);
199 fullLibPath[sizeof(fullLibPath) - 1] = '\0';
200
201 /* Get ifdCapabilities */
202 GET_KEY(PCSCLITE_HP_CPCTKEY_NAME, &values)
203 ifdCapabilities = strtol(list_get_at(values, 0), NULL, 16);
204
205 GET_KEY(PCSCLITE_HP_MANUKEY_NAME, &manuIDs)
206 GET_KEY(PCSCLITE_HP_PRODKEY_NAME, &productIDs)
207 GET_KEY(PCSCLITE_HP_NAMEKEY_NAME, &readerNames)
208
209 /* Get CFBundleName */
210 rv = LTPBundleFindValueWithKey(&plist, PCSCLITE_HP_CFBUNDLE_NAME,
211 &values);
212 if (rv)
213 CFBundleName = NULL;
214 else
215 CFBundleName = strdup(list_get_at(values, 0));
216
217 /* while we find a nth ifdVendorID in Info.plist */
218 for (alias=0; alias<list_size(manuIDs); alias++)
219 {
220 char *value;
221
222 /* variables entries */
223 value = list_get_at(manuIDs, alias);
224 driverTracker[listCount].manuID = strtol(value, NULL, 16);
225
226 value = list_get_at(productIDs, alias);
227 driverTracker[listCount].productID = strtol(value, NULL, 16);
228
229 driverTracker[listCount].readerName = strdup(list_get_at(readerNames, alias));
230
231 /* constant entries for a same driver */
232 driverTracker[listCount].bundleName = strdup(currFP->d_name);
233 driverTracker[listCount].libraryPath = strdup(fullLibPath);
234 driverTracker[listCount].ifdCapabilities = ifdCapabilities;
235 driverTracker[listCount].CFBundleName = CFBundleName;
236
237#ifdef DEBUG_HOTPLUG
238 Log2(PCSC_LOG_INFO, "Found driver for: %s",
239 driverTracker[listCount].readerName);
240#endif
241 listCount++;
242 if (listCount >= driverSize)
243 {
244 int i;
245
246 /* increase the array size */
247 driverSize += DRIVER_TRACKER_SIZE_STEP;
248#ifdef DEBUG_HOTPLUG
249 Log2(PCSC_LOG_INFO,
250 "Increase driverTracker to %d entries", driverSize);
251#endif
252 void* tmp = realloc(driverTracker,
253 driverSize * sizeof(*driverTracker));
254 if (NULL == tmp)
255 {
256 free(driverTracker);
257 Log1(PCSC_LOG_CRITICAL, "Not enough memory");
258 driverSize = -1;
259 closedir(hpDir);
260 return -1;
261 }
262 driverTracker = tmp;
263
264 /* clean the newly allocated entries */
265 for (i=driverSize-DRIVER_TRACKER_SIZE_STEP; i<driverSize; i++)
266 {
267 driverTracker[i].manuID = 0;
268 driverTracker[i].productID = 0;
269 driverTracker[i].bundleName = NULL;
270 driverTracker[i].libraryPath = NULL;
271 driverTracker[i].readerName = NULL;
272 driverTracker[i].ifdCapabilities = 0;
273 driverTracker[i].CFBundleName = NULL;
274 }
275 }
276 }
277 bundleRelease(&plist);
278 }
279 }
280
281 driverSize = listCount;
282 closedir(hpDir);
283
284 if (driverSize == 0)
285 {
286 Log1(PCSC_LOG_INFO, "No bundle files in pcsc drivers directory: " PCSCLITE_HP_DROPDIR);
287 Log1(PCSC_LOG_INFO, "Disabling USB support for pcscd");
288 }
289#ifdef DEBUG_HOTPLUG
290 else
291 Log2(PCSC_LOG_INFO, "Found drivers for %d readers", listCount);
292#endif
293
294 return driverSize;
295}
296
297static struct _driverTracker *get_driver(unsigned int idVendor,
298 unsigned int idProduct, struct _driverTracker **classdriver)
299{
300 int i;
301 static struct _driverTracker *driver;
302
303#ifdef DEBUG_HOTPLUG
304 Log3(PCSC_LOG_DEBUG,
305 "Looking for a driver for VID: 0x%04X, PID: 0x%04X",
306 idVendor, idProduct);
307#endif
308
309 *classdriver = NULL;
310 driver = NULL;
311 /* check if the device is supported by one driver */
312 for (i=0; i<driverSize; i++)
313 {
314 if (driverTracker[i].libraryPath != NULL &&
315 idVendor == driverTracker[i].manuID &&
316 idProduct == driverTracker[i].productID)
317 {
318 if ((driverTracker[i].CFBundleName != NULL)
319 && (0 == strcmp(driverTracker[i].CFBundleName, "CCIDCLASSDRIVER")))
320 *classdriver = &driverTracker[i];
321 else
322 /* it is not a CCID Class driver */
323 driver = &driverTracker[i];
324 }
325 }
326
327 /* if we found a specific driver */
328 if (driver)
329 return driver;
330
331 /* else return the Class driver (if any) */
332 return *classdriver;
333}
334
335static void HPRescanUsbBus(void)
336{
337 int i, j;
338 char bus_device[BUS_DEVICE_STRSIZE];
339 libusb_device **devs, *dev;
340 ssize_t cnt;
341
342 for (i=0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
343 /* clear rollcall */
344 readerTracker[i].status = READER_ABSENT;
345
346 cnt = libusb_get_device_list(ctx, &devs);
347 if (cnt < 0)
348 {
349 Log2(PCSC_LOG_CRITICAL, "libusb_get_device_list() failed: %s",
350 libusb_error_name(cnt));
351 return;
352 }
353
354 /* For each USB device */
355 cnt = 0;
356 while ((dev = devs[cnt++]) != NULL)
357 {
358 struct libusb_device_descriptor desc;
359 struct libusb_config_descriptor *config_desc;
360 uint8_t bus_number = libusb_get_bus_number(dev);
361 uint8_t device_address = libusb_get_device_address(dev);
362 struct _driverTracker *driver, *classdriver;
363 int interface;
364
365 int r = libusb_get_device_descriptor(dev, &desc);
366 if (r < 0)
367 {
368 Log4(PCSC_LOG_ERROR,
369 "failed to get device descriptor for %d/%d: %s",
370 bus_number, device_address, libusb_error_name(r));
371 continue;
372 }
373
374 r = libusb_get_active_config_descriptor(dev, &config_desc);
375 if (r < 0)
376 {
377 Log4(PCSC_LOG_ERROR, "failed to get device config for %d/%d: %s",
378 bus_number, device_address, libusb_error_name(r));
379 continue;
380 }
381
382 driver = get_driver(desc.idVendor, desc.idProduct, &classdriver);
383 if (NULL == driver)
384 {
385 /* not a smart card reader */
386#ifdef DEBUG_HOTPLUG
387 Log3(PCSC_LOG_DEBUG, "%d/%d is not a supported smart card reader",
388 bus_number, device_address);
389#endif
390 libusb_free_config_descriptor(config_desc);
391 continue;
392 }
393
394#ifdef DEBUG_HOTPLUG
395 Log3(PCSC_LOG_DEBUG, "Found matching USB device: %d:%d",
396 bus_number, device_address);
397#endif
398
399 for (interface = 0; interface < config_desc->bNumInterfaces;
400 interface++)
401 {
402 int newreader;
403
404 /* A known device has been found */
405 snprintf(bus_device, BUS_DEVICE_STRSIZE, "%d:%d:%d",
406 bus_number, device_address, interface);
407 bus_device[BUS_DEVICE_STRSIZE - 1] = '\0';
408 newreader = TRUE;
409
410 /* Check if the reader is a new one */
411 for (j=0; j<PCSCLITE_MAX_READERS_CONTEXTS; j++)
412 {
413 if (strncmp(readerTracker[j].bus_device,
414 bus_device, BUS_DEVICE_STRSIZE) == 0)
415 {
416 /* The reader is already known */
417 readerTracker[j].status = READER_PRESENT;
418 newreader = FALSE;
419#ifdef DEBUG_HOTPLUG
420 Log2(PCSC_LOG_DEBUG, "Refresh USB device: %s",
421 bus_device);
422#endif
423 break;
424 }
425 }
426
427 /* New reader found */
428 if (newreader)
429 HPAddHotPluggable(dev, desc, bus_device,
430 &config_desc->interface[interface], driver, classdriver);
431 }
432
433 libusb_free_config_descriptor(config_desc);
434 }
435
436 /*
437 * check if all the previously found readers are still present
438 */
439 for (i=0; i<PCSCLITE_MAX_READERS_CONTEXTS; i++)
440 {
441 if ((readerTracker[i].status == READER_ABSENT) &&
442 (readerTracker[i].fullName != NULL))
443 HPRemoveHotPluggable(i);
444 }
445
446 if (AraKiriHotPlug)
447 {
448 int retval;
449
450 for (i=0; i<driverSize; i++)
451 {
452 /* free strings allocated by strdup() */
453 free(driverTracker[i].bundleName);
454 free(driverTracker[i].libraryPath);
455 free(driverTracker[i].readerName);
456 free(driverTracker[i].CFBundleName);
457 }
458 free(driverTracker);
459
460 Log1(PCSC_LOG_INFO, "Hotplug stopped");
461 pthread_exit(&retval);
462 }
463
464 /* free the libusb allocated list & devices */
465 libusb_free_device_list(devs, 1);
466}
467
468static void * HPEstablishUSBNotifications(int pipefd[2])
469{
470 int i, do_polling;
471 int r;
472 char c = 42; /* magic value */
473
474 r = libusb_init(ctx);
475 if (r < 0)
476 {
477 Log2(PCSC_LOG_CRITICAL, "libusb_init failed: %s", libusb_error_name(r));
478 /* emergency exit */
479 kill(getpid(), SIGTERM);
480 return NULL;
481 }
482
483 /* scan the USB bus for devices at startup */
484 HPRescanUsbBus();
485
486 /* signal that the initially connected readers are now visible */
487 if (write(pipefd[1], &c, 1) == -1)
488 {
489 Log2(PCSC_LOG_ERROR, "write: %s", strerror(errno));
490 return NULL;
491 }
492
493 /* if at least one driver do not have IFD_GENERATE_HOTPLUG */
494 do_polling = FALSE;
495 for (i=0; i<driverSize; i++)
496 if (driverTracker[i].libraryPath)
497 if ((driverTracker[i].ifdCapabilities & IFD_GENERATE_HOTPLUG) == 0)
498 {
499 Log2(PCSC_LOG_INFO,
500 "Driver %s does not support IFD_GENERATE_HOTPLUG. Using active polling instead.",
501 driverTracker[i].bundleName);
502 if (HPForceReaderPolling < 1)
503 HPForceReaderPolling = 1;
504 break;
505 }
506
507 if (HPForceReaderPolling)
508 {
509 Log2(PCSC_LOG_INFO,
510 "Polling forced every %d second(s)", HPForceReaderPolling);
511 do_polling = TRUE;
512 }
513
514 if (do_polling)
515 {
516 while (!AraKiriHotPlug)
517 {
518 SYS_Sleep(HPForceReaderPolling);
519 HPRescanUsbBus();
520 }
521 libusb_exit(ctx);
522 }
523 else
524 {
525 char dummy;
526
527 if (pipe(rescan_pipe) == -1)
528 {
529 Log2(PCSC_LOG_ERROR, "pipe: %s", strerror(errno));
530 return NULL;
531 }
532 while (read(rescan_pipe[0], &dummy, sizeof(dummy)) > 0)
533 {
534 Log1(PCSC_LOG_INFO, "Reload serial configuration");
535 HPRescanUsbBus();
536#ifdef USE_SERIAL
537 RFReCheckReaderConf();
538#endif
539 Log1(PCSC_LOG_INFO, "End reload serial configuration");
540 }
541 close(rescan_pipe[0]);
542 rescan_pipe[0] = -1;
543 }
544
545 return NULL;
546}
547
548LONG HPSearchHotPluggables(void)
549{
550 int i;
551
552 for (i=0; i<PCSCLITE_MAX_READERS_CONTEXTS; i++)
553 {
554 readerTracker[i].status = READER_ABSENT;
555 readerTracker[i].bus_device[0] = '\0';
556 readerTracker[i].fullName = NULL;
557 }
558
559 if (HPReadBundleValues() > 0)
560 {
561 int pipefd[2];
562 char c;
563
564 if (pipe(pipefd) == -1)
565 {
566 Log2(PCSC_LOG_ERROR, "pipe: %s", strerror(errno));
567 return -1;
568 }
569
570 ThreadCreate(&usbNotifyThread, THREAD_ATTR_DETACHED,
571 (PCSCLITE_THREAD_FUNCTION( )) HPEstablishUSBNotifications, pipefd);
572
573 /* Wait for initial readers to setup */
574 if (read(pipefd[0], &c, 1) == -1)
575 {
576 Log2(PCSC_LOG_ERROR, "read: %s", strerror(errno));
577 return -1;
578 };
579
580 /* cleanup pipe fd */
581 close(pipefd[0]);
582 close(pipefd[1]);
583 }
584
585 return 0;
586}
587
588LONG HPStopHotPluggables(void)
589{
590 AraKiriHotPlug = TRUE;
591 if (rescan_pipe[1] >= 0)
592 {
593 close(rescan_pipe[1]);
594 rescan_pipe[1] = -1;
595 }
596
597 return 0;
598}
599
600static LONG HPAddHotPluggable(struct libusb_device *dev,
601 struct libusb_device_descriptor desc,
602 const char bus_device[],
603 const struct libusb_interface *idesc,
604 struct _driverTracker *driver,
605 struct _driverTracker *classdriver)
606{
607 int i;
608 uint8_t iInterface = 0;
609 uint8_t iSerialNumber = 0;
610 char *deviceName;
611
612 Log2(PCSC_LOG_INFO, "Adding USB device: %s", bus_device);
613
614 i = asprintf(&deviceName, "usb:%04x/%04x:libusb-1.0:%s",
615 desc.idVendor, desc.idProduct, bus_device);
616 if (-1 == i)
617 {
618 Log1(PCSC_LOG_ERROR, "asprintf() failed");
619 return 0;
620 }
621
622 pthread_mutex_lock(&usbNotifierMutex);
623
624 /* find a free entry */
625 for (i=0; i<PCSCLITE_MAX_READERS_CONTEXTS; i++)
626 {
627 if (readerTracker[i].fullName == NULL)
628 break;
629 }
630
632 {
633 Log2(PCSC_LOG_ERROR,
634 "Not enough reader entries. Already found %d readers", i);
635 pthread_mutex_unlock(&usbNotifierMutex);
636 return 0;
637 }
638
639 strncpy(readerTracker[i].bus_device, bus_device,
640 sizeof(readerTracker[i].bus_device));
641 readerTracker[i].bus_device[sizeof(readerTracker[i].bus_device) - 1] = '\0';
642 readerTracker[i].fullName = NULL;
643
644 if (Add_Interface_In_Name && idesc->num_altsetting > 0)
645 iInterface = idesc->altsetting[0].iInterface;
646
647 if (Add_Serial_In_Name)
648 iSerialNumber = desc.iSerialNumber;
649
650 if (iSerialNumber != 0 || iInterface != 0)
651 {
652 libusb_device_handle *device;
653 int ret;
654
655 ret = libusb_open(dev, &device);
656 if (ret < 0)
657 {
658 Log2(PCSC_LOG_ERROR, "libusb_open failed: %s",
659 libusb_error_name(ret));
660 }
661 else
662 {
663 unsigned char interfaceName[MAX_READERNAME];
664 unsigned char serialNumber[MAX_READERNAME];
665 char fullname[MAX_READERNAME * 3];
666 fullname[0] = '\0';
667 int ret_interface = 0;
668 int ret_serial = 0;
669
670 if (iInterface)
671 {
672 ret_interface = libusb_get_string_descriptor_ascii(device,
673 iInterface, interfaceName, sizeof interfaceName);
674 if (ret_interface < 0)
675 {
676 Log2(PCSC_LOG_ERROR,
677 "libusb_get_string_descriptor_ascii failed: %s",
678 libusb_error_name(ret_interface));
679 }
680 }
681
682 if (iSerialNumber)
683 {
684 ret_serial = libusb_get_string_descriptor_ascii(device,
685 iSerialNumber, serialNumber, sizeof serialNumber);
686 if (ret_serial < 0)
687 {
688 Log2(PCSC_LOG_ERROR,
689 "libusb_get_string_descriptor_ascii failed: %s",
690 libusb_error_name(ret_serial));
691 }
692 }
693
694 libusb_close(device);
695
696 if (ret_interface > 0 && ret_serial > 0)
697 {
698 snprintf(fullname, sizeof(fullname), "%s [%s] (%s)",
699 driver->readerName, interfaceName, serialNumber);
700 }
701 else
702 {
703 if (ret_interface > 0)
704 {
705 snprintf(fullname, sizeof(fullname), "%s [%s]",
706 driver->readerName, interfaceName);
707 }
708 else
709 {
710 if (ret_serial > 0)
711 {
712 snprintf(fullname, sizeof(fullname), "%s (%s)",
713 driver->readerName, serialNumber);
714 }
715 }
716 }
717
718 if (fullname[0] != '\0')
719 readerTracker[i].fullName = strdup(fullname);
720 }
721 }
722
723 if (readerTracker[i].fullName == NULL)
724 readerTracker[i].fullName = strdup(driver->readerName);
725
726 LONG ret;
727 ret = RFAddReader(readerTracker[i].fullName, PCSCLITE_HP_BASE_PORT + i,
728 driver->libraryPath, deviceName);
729 /* success by default */
730 readerTracker[i].status = READER_PRESENT;
731 if ((SCARD_S_SUCCESS != ret) && (SCARD_E_UNKNOWN_READER != ret))
732 {
733 Log2(PCSC_LOG_ERROR, "Failed adding USB device: %s",
734 driver->readerName);
735
736 if (classdriver && driver != classdriver)
737 {
738 /* the reader can also be used by the a class driver */
739 ret = RFAddReader(readerTracker[i].fullName,
740 PCSCLITE_HP_BASE_PORT + i,
741 classdriver->libraryPath, deviceName);
742 if ((SCARD_S_SUCCESS != ret) && (SCARD_E_UNKNOWN_READER != ret))
743 {
744 Log2(PCSC_LOG_ERROR, "Failed adding USB device: %s",
745 driver->readerName);
746 readerTracker[i].status = READER_FAILED;
747 }
748 }
749 else
750 readerTracker[i].status = READER_FAILED;
751 }
752
753 if (READER_FAILED == readerTracker[i].status)
754 (void)CheckForOpenCT();
755
756 pthread_mutex_unlock(&usbNotifierMutex);
757
758 free(deviceName);
759
760 return 1;
761} /* End of function */
762
763static LONG HPRemoveHotPluggable(int reader_index)
764{
765 pthread_mutex_lock(&usbNotifierMutex);
766
767 Log3(PCSC_LOG_INFO, "Removing USB device[%d]: %s", reader_index,
768 readerTracker[reader_index].bus_device);
769
770 RFRemoveReader(readerTracker[reader_index].fullName,
771 PCSCLITE_HP_BASE_PORT + reader_index, REMOVE_READER_FLAG_REMOVED);
772 free(readerTracker[reader_index].fullName);
773 readerTracker[reader_index].status = READER_ABSENT;
774 readerTracker[reader_index].bus_device[0] = '\0';
775 readerTracker[reader_index].fullName = NULL;
776
777 pthread_mutex_unlock(&usbNotifierMutex);
778
779 return 1;
780} /* End of function */
781
785ULONG HPRegisterForHotplugEvents(void)
786{
787 (void)pthread_mutex_init(&usbNotifierMutex, NULL);
788 return 0;
789}
790
791void HPReCheckSerialReaders(void)
792{
793 Log0(PCSC_LOG_INFO);
794 if (rescan_pipe[1] >= 0)
795 {
796 char dummy = 0;
797 if (write(rescan_pipe[1], &dummy, sizeof(dummy)) == -1)
798 Log2(PCSC_LOG_ERROR, "write: %s", strerror(errno));
799 }
800}
801
802#endif
803
This handles debugging.
#define SCARD_E_UNKNOWN_READER
The specified reader name is not recognized.
Definition: pcsclite.h:125
#define SCARD_S_SUCCESS
No error was encountered.
Definition: pcsclite.h:107
This provides a search API for hot pluggble devices.
Reads lexical config files and updates database.
This keeps a list of defines for pcsc-lite.
#define PCSCLITE_MAX_READERS_CONTEXTS
Maximum readers context (a slot is count as a reader)
Definition: pcsclite.h:284
This keeps track of a list of currently available reader structures.
list object
Definition: simclist.h:181
This handles abstract system level calls.
int SYS_Sleep(int)
Makes the current process sleep for some seconds.
Definition: sys_unix.c:53
This defines some structures and #defines to be used over the transport layer.
This keeps a list of Windows(R) types.