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