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