pcsc-lite  2.2.3
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-2024
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 #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 
80 extern bool Add_Interface_In_Name;
81 extern bool Add_Serial_In_Name;
82 
83 /* we use the default libusb context */
84 #define ctx NULL
85 
86 pthread_mutex_t usbNotifierMutex;
87 
88 static pthread_t usbNotifyThread;
89 static int driverSize = -1;
90 static bool AraKiriHotPlug = false;
91 static int rescan_pipe[] = { -1, -1 };
92 extern int HPForceReaderPolling;
93 
94 /* values of ifdCapabilities bits */
95 #define IFD_GENERATE_HOTPLUG 1
96 
100 static 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 
116 static struct _readerTracker
117 {
118  char status;
119  char bus_device[BUS_DEVICE_STRSIZE];
120  char *fullName;
121 } readerTracker[PCSCLITE_MAX_READERS_CONTEXTS];
122 
123 static LONG HPAddHotPluggable(struct libusb_device *dev,
124  struct libusb_device_descriptor desc,
125  const char bus_device[],
126  const struct libusb_interface *idesc,
127  struct _driverTracker *driver,
128  struct _driverTracker *classdriver);
129 static LONG HPRemoveHotPluggable(int reader_index);
130 static void HPCleanupHotPluggable(int reader_index);
131 
132 static LONG HPReadBundleValues(const char * hpDirPath)
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(hpDirPath);
142 
143  if (hpDir == NULL)
144  {
145  Log2(PCSC_LOG_ERROR, "Cannot open PC/SC drivers directory: %s",
146  hpDirPath);
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  hpDirPath, 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  hpDirPath, 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 = 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 =
236  CFBundleName ? strdup(CFBundleName) : NULL;
237 
238 #ifdef DEBUG_HOTPLUG
239  Log2(PCSC_LOG_INFO, "Found driver for: %s",
240  driverTracker[listCount].readerName);
241 #endif
242  listCount++;
243  if (listCount >= driverSize)
244  {
245  int i;
246 
247  /* increase the array size */
248  driverSize += DRIVER_TRACKER_SIZE_STEP;
249 #ifdef DEBUG_HOTPLUG
250  Log2(PCSC_LOG_INFO,
251  "Increase driverTracker to %d entries", driverSize);
252 #endif
253  void* tmp = realloc(driverTracker,
254  driverSize * sizeof(*driverTracker));
255  if (NULL == tmp)
256  {
257  free(driverTracker);
258  Log1(PCSC_LOG_CRITICAL, "Not enough memory");
259  driverSize = -1;
260  closedir(hpDir);
261  return -1;
262  }
263  driverTracker = tmp;
264 
265  /* clean the newly allocated entries */
266  for (i=driverSize-DRIVER_TRACKER_SIZE_STEP; i<driverSize; i++)
267  {
268  driverTracker[i].manuID = 0;
269  driverTracker[i].productID = 0;
270  driverTracker[i].bundleName = NULL;
271  driverTracker[i].libraryPath = NULL;
272  driverTracker[i].readerName = NULL;
273  driverTracker[i].ifdCapabilities = 0;
274  driverTracker[i].CFBundleName = NULL;
275  }
276  }
277  }
278  bundleRelease(&plist);
279  }
280  }
281 
282  driverSize = listCount;
283  closedir(hpDir);
284 
285  if (driverSize == 0)
286  {
287  Log2(PCSC_LOG_INFO, "No bundle files in pcsc drivers directory: %s",
288  hpDirPath);
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 roll call */
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  bool 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 
452 static void * HPEstablishUSBNotifications(int pipefd[2])
453 {
454  bool do_polling;
455  int r;
456  char c = 42; /* magic value */
457 
458  r = libusb_init(ctx);
459  if (r < 0)
460  {
461  Log2(PCSC_LOG_CRITICAL, "libusb_init failed: %s", libusb_error_name(r));
462  /* emergency exit */
463  kill(getpid(), SIGTERM);
464  return NULL;
465  }
466 
467  /* scan the USB bus for devices at startup */
468  HPRescanUsbBus();
469 
470  /* signal that the initially connected readers are now visible */
471  if (write(pipefd[1], &c, 1) == -1)
472  {
473  Log2(PCSC_LOG_ERROR, "write: %s", strerror(errno));
474  return NULL;
475  }
476 
477  /* if at least one driver do not have IFD_GENERATE_HOTPLUG */
478  do_polling = false;
479  for (int i=0; i<driverSize; i++)
480  if (driverTracker[i].libraryPath)
481  if ((driverTracker[i].ifdCapabilities & IFD_GENERATE_HOTPLUG) == 0)
482  {
483  Log2(PCSC_LOG_INFO,
484  "Driver %s does not support IFD_GENERATE_HOTPLUG. Using active polling instead.",
485  driverTracker[i].bundleName);
486  if (HPForceReaderPolling < 1)
487  HPForceReaderPolling = 1;
488  break;
489  }
490 
491  if (HPForceReaderPolling)
492  {
493  Log2(PCSC_LOG_INFO,
494  "Polling forced every %d second(s)", HPForceReaderPolling);
495  do_polling = true;
496  }
497 
498  if (do_polling)
499  {
500  while (!AraKiriHotPlug)
501  {
502  SYS_Sleep(HPForceReaderPolling);
503  HPRescanUsbBus();
504  }
505  }
506  else
507  {
508  char dummy;
509  while (read(rescan_pipe[0], &dummy, sizeof(dummy)) > 0)
510  {
511  if (AraKiriHotPlug)
512  break;
513  Log1(PCSC_LOG_INFO, "Reload serial configuration");
514  HPRescanUsbBus();
515 #ifdef USE_SERIAL
516  RFReCheckReaderConf();
517 #endif
518  Log1(PCSC_LOG_INFO, "End reload serial configuration");
519  }
520  }
521 
522  libusb_exit(ctx);
523 
524  for (int i=0; i<PCSCLITE_MAX_READERS_CONTEXTS; i++)
525  {
526  if (readerTracker[i].fullName != NULL)
527  HPCleanupHotPluggable(i);
528  }
529 
530  for (int i=0; i<driverSize; i++)
531  {
532  /* free strings allocated by strdup() */
533  free(driverTracker[i].bundleName);
534  free(driverTracker[i].libraryPath);
535  free(driverTracker[i].readerName);
536  free(driverTracker[i].CFBundleName);
537  }
538  free(driverTracker);
539 
540  close(rescan_pipe[0]);
541  rescan_pipe[0] = -1;
542 
543  Log1(PCSC_LOG_INFO, "Hotplug stopped");
544 
545  return NULL;
546 }
547 
548 LONG HPSearchHotPluggables(const char * hpDirPath)
549 {
550  int i;
551 
552  AraKiriHotPlug = false;
553  for (i=0; i<PCSCLITE_MAX_READERS_CONTEXTS; i++)
554  {
555  readerTracker[i].status = READER_ABSENT;
556  readerTracker[i].bus_device[0] = '\0';
557  readerTracker[i].fullName = NULL;
558  }
559 
560  if (HPReadBundleValues(hpDirPath) > 0)
561  {
562  /* used for waiting for the initialization completion */
563  int pipefd[2];
564  char c;
565 
566  if (pipe(pipefd) == -1)
567  {
568  Log2(PCSC_LOG_ERROR, "pipe: %s", strerror(errno));
569  return -1;
570  }
571 
572  /* used for rescan events */
573  if (pipe(rescan_pipe) == -1)
574  {
575  Log2(PCSC_LOG_ERROR, "pipe: %s", strerror(errno));
576  return -1;
577  }
578 
579  ThreadCreate(&usbNotifyThread, 0,
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  /* tell the rescan thread to shut down; it checks the ara kiri flag, but it
600  * might also need to be awaken from reading the rescan pipe */
601  AraKiriHotPlug = true;
602  HPReCheckSerialReaders();
603 
604  if (rescan_pipe[1] >= 0)
605  {
606  close(rescan_pipe[1]);
607  rescan_pipe[1] = -1;
608  }
609  /* wait for the rescan thread to complete its cleanup */
610  pthread_join(usbNotifyThread, NULL);
611 
612  return 0;
613 }
614 
615 static LONG HPAddHotPluggable(struct libusb_device *dev,
616  struct libusb_device_descriptor desc,
617  const char bus_device[],
618  const struct libusb_interface *idesc,
619  struct _driverTracker *driver,
620  struct _driverTracker *classdriver)
621 {
622  int i;
623  uint8_t iInterface = 0;
624  uint8_t iSerialNumber = 0;
625  char *deviceName;
626 
627  Log2(PCSC_LOG_INFO, "Adding USB device: %s", bus_device);
628 
629  i = asprintf(&deviceName, "usb:%04x/%04x:libusb-1.0:%s",
630  desc.idVendor, desc.idProduct, bus_device);
631  if (-1 == i)
632  {
633  Log1(PCSC_LOG_ERROR, "asprintf() failed");
634  return 0;
635  }
636 
637  pthread_mutex_lock(&usbNotifierMutex);
638 
639  /* find a free entry */
640  for (i=0; i<PCSCLITE_MAX_READERS_CONTEXTS; i++)
641  {
642  if (readerTracker[i].fullName == NULL)
643  break;
644  }
645 
647  {
648  Log2(PCSC_LOG_ERROR,
649  "Not enough reader entries. Already found %d readers", i);
650  pthread_mutex_unlock(&usbNotifierMutex);
651  return 0;
652  }
653 
654  strncpy(readerTracker[i].bus_device, bus_device,
655  sizeof(readerTracker[i].bus_device));
656  readerTracker[i].bus_device[sizeof(readerTracker[i].bus_device) - 1] = '\0';
657  readerTracker[i].fullName = NULL;
658 
659  if (Add_Interface_In_Name && idesc->num_altsetting > 0)
660  iInterface = idesc->altsetting[0].iInterface;
661 
662  if (Add_Serial_In_Name)
663  iSerialNumber = desc.iSerialNumber;
664 
665  if (iSerialNumber != 0 || iInterface != 0)
666  {
667  libusb_device_handle *device;
668  int ret;
669 
670  ret = libusb_open(dev, &device);
671  if (ret < 0)
672  {
673  Log2(PCSC_LOG_ERROR, "libusb_open failed: %s",
674  libusb_error_name(ret));
675  }
676  else
677  {
678  unsigned char interfaceName[MAX_READERNAME];
679  unsigned char serialNumber[MAX_READERNAME];
680  char fullname[MAX_READERNAME * 3];
681  fullname[0] = '\0';
682  int ret_interface = 0;
683  int ret_serial = 0;
684 
685  if (iInterface)
686  {
687  ret_interface = libusb_get_string_descriptor_ascii(device,
688  iInterface, interfaceName, sizeof interfaceName);
689  if (ret_interface < 0)
690  {
691  Log2(PCSC_LOG_ERROR,
692  "libusb_get_string_descriptor_ascii failed: %s",
693  libusb_error_name(ret_interface));
694  }
695  }
696 
697  if (iSerialNumber)
698  {
699  ret_serial = libusb_get_string_descriptor_ascii(device,
700  iSerialNumber, serialNumber, sizeof serialNumber);
701  if (ret_serial < 0)
702  {
703  Log2(PCSC_LOG_ERROR,
704  "libusb_get_string_descriptor_ascii failed: %s",
705  libusb_error_name(ret_serial));
706  }
707  }
708 
709  libusb_close(device);
710 
711  if (ret_interface > 0 && ret_serial > 0)
712  {
713  snprintf(fullname, sizeof(fullname), "%s [%s] (%s)",
714  driver->readerName, interfaceName, serialNumber);
715  }
716  else
717  {
718  if (ret_interface > 0)
719  {
720  snprintf(fullname, sizeof(fullname), "%s [%s]",
721  driver->readerName, interfaceName);
722  }
723  else
724  {
725  if (ret_serial > 0)
726  {
727  snprintf(fullname, sizeof(fullname), "%s (%s)",
728  driver->readerName, serialNumber);
729  }
730  }
731  }
732 
733  if (fullname[0] != '\0')
734  readerTracker[i].fullName = strdup(fullname);
735  }
736  }
737 
738  if (readerTracker[i].fullName == NULL)
739  readerTracker[i].fullName = strdup(driver->readerName);
740 
741  LONG ret;
742  ret = RFAddReader(readerTracker[i].fullName, PCSCLITE_HP_BASE_PORT + i,
743  driver->libraryPath, deviceName);
744  /* success by default */
745  readerTracker[i].status = READER_PRESENT;
746  if ((SCARD_S_SUCCESS != ret) && (SCARD_E_UNKNOWN_READER != ret))
747  {
748  Log2(PCSC_LOG_ERROR, "Failed adding USB device: %s",
749  driver->readerName);
750 
751  if (classdriver && driver != classdriver)
752  {
753  /* the reader can also be used by the a class driver */
754  ret = RFAddReader(readerTracker[i].fullName,
755  PCSCLITE_HP_BASE_PORT + i,
756  classdriver->libraryPath, deviceName);
757  if ((SCARD_S_SUCCESS != ret) && (SCARD_E_UNKNOWN_READER != ret))
758  {
759  Log2(PCSC_LOG_ERROR, "Failed adding USB device: %s",
760  driver->readerName);
761  readerTracker[i].status = READER_FAILED;
762  }
763  }
764  else
765  readerTracker[i].status = READER_FAILED;
766  }
767 
768  if (READER_FAILED == readerTracker[i].status)
769  (void)CheckForOpenCT();
770 
771  pthread_mutex_unlock(&usbNotifierMutex);
772 
773  free(deviceName);
774 
775  return 1;
776 } /* End of function */
777 
778 static LONG HPRemoveHotPluggable(int reader_index)
779 {
780  pthread_mutex_lock(&usbNotifierMutex);
781 
782  Log3(PCSC_LOG_INFO, "Removing USB device[%d]: %s", reader_index,
783  readerTracker[reader_index].bus_device);
784 
785  RFRemoveReader(readerTracker[reader_index].fullName,
786  PCSCLITE_HP_BASE_PORT + reader_index, REMOVE_READER_FLAG_REMOVED);
787  HPCleanupHotPluggable(reader_index);
788 
789  pthread_mutex_unlock(&usbNotifierMutex);
790 
791  return 1;
792 } /* End of function */
793 
794 static void HPCleanupHotPluggable(int reader_index)
795 {
796  free(readerTracker[reader_index].fullName);
797  readerTracker[reader_index].status = READER_ABSENT;
798  readerTracker[reader_index].bus_device[0] = '\0';
799  readerTracker[reader_index].fullName = NULL;
800 } /* End of function */
801 
805 ULONG HPRegisterForHotplugEvents(const char * hpDirPath)
806 {
807  (void)hpDirPath;
808 
809  (void)pthread_mutex_init(&usbNotifierMutex, NULL);
810  return 0;
811 }
812 
813 void HPReCheckSerialReaders(void)
814 {
815  Log0(PCSC_LOG_INFO);
816  if (rescan_pipe[1] >= 0)
817  {
818  char dummy = 0;
819  if (write(rescan_pipe[1], &dummy, sizeof(dummy)) == -1)
820  Log2(PCSC_LOG_ERROR, "write: %s", strerror(errno));
821  }
822 }
823 
824 #endif
825 
debuglog.h
This handles debugging.
SCARD_S_SUCCESS
#define SCARD_S_SUCCESS
No error was encountered.
Definition: pcsclite.h:107
sys_generic.h
This handles abstract system level calls.
readerfactory.h
This keeps track of a list of currently available reader structures.
SYS_Sleep
int SYS_Sleep(int)
Makes the current process sleep for some seconds.
Definition: sys_unix.c:62
list_t
list object
Definition: simclist.h:181
winscard_msg.h
This defines some structures and #defines to be used over the transport layer.
PCSCLITE_MAX_READERS_CONTEXTS
#define PCSCLITE_MAX_READERS_CONTEXTS
Maximum readers context (a slot is count as a reader)
Definition: pcsclite.h:285
parser.h
Reads lexical config files and updates database.
wintypes.h
This keeps a list of Windows(R) types.
SCARD_E_UNKNOWN_READER
#define SCARD_E_UNKNOWN_READER
The specified reader name is not recognized.
Definition: pcsclite.h:125
hotplug.h
This provides a search API for hot pluggble devices.