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