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