pcsc-lite  1.9.8
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  *
13 Redistribution and use in source and binary forms, with or without
14 modification, are permitted provided that the following conditions
15 are met:
16 
17 1. Redistributions of source code must retain the above copyright
18  notice, this list of conditions and the following disclaimer.
19 2. 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.
22 3. 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 
25 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34 THIS 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 
82 extern char Add_Interface_In_Name;
83 extern char Add_Serial_In_Name;
84 
85 /* we use the default libusb context */
86 #define ctx NULL
87 
88 pthread_mutex_t usbNotifierMutex;
89 
90 static pthread_t usbNotifyThread;
91 static int driverSize = -1;
92 static char AraKiriHotPlug = FALSE;
93 static int rescan_pipe[] = { -1, -1 };
94 extern int HPForceReaderPolling;
95 
96 /* values of ifdCapabilities bits */
97 #define IFD_GENERATE_HOTPLUG 1
98 
102 static 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 
118 static struct _readerTracker
119 {
120  char status;
121  char bus_device[BUS_DEVICE_STRSIZE];
122  char *fullName;
123 } readerTracker[PCSCLITE_MAX_READERS_CONTEXTS];
124 
125 static 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);
131 static LONG HPRemoveHotPluggable(int reader_index);
132 static void HPCleanupHotPluggable(int reader_index);
133 
134 static 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 
299 static 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 
337 static 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 
476 static 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 
556 LONG 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 
597 LONG 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 
609 static 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 
772 static 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 
788 static 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 
799 ULONG HPRegisterForHotplugEvents(void)
800 {
801  (void)pthread_mutex_init(&usbNotifierMutex, NULL);
802  return 0;
803 }
804 
805 void 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.