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