pcsc-lite  1.9.5
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  libusb_free_config_descriptor(config_desc);
390  continue;
391  }
392 
393 #ifdef DEBUG_HOTPLUG
394  Log3(PCSC_LOG_DEBUG, "Found matching USB device: %d:%d",
395  bus_number, device_address);
396 #endif
397 
398  for (interface = 0; interface < config_desc->bNumInterfaces;
399  interface++)
400  {
401  int newreader;
402 
403  /* A known device has been found */
404  snprintf(bus_device, BUS_DEVICE_STRSIZE, "%d:%d:%d",
405  bus_number, device_address, interface);
406  bus_device[BUS_DEVICE_STRSIZE - 1] = '\0';
407  newreader = TRUE;
408 
409  /* Check if the reader is a new one */
410  for (j=0; j<PCSCLITE_MAX_READERS_CONTEXTS; j++)
411  {
412  if (strncmp(readerTracker[j].bus_device,
413  bus_device, BUS_DEVICE_STRSIZE) == 0)
414  {
415  /* The reader is already known */
416  readerTracker[j].status = READER_PRESENT;
417  newreader = FALSE;
418 #ifdef DEBUG_HOTPLUG
419  Log2(PCSC_LOG_DEBUG, "Refresh USB device: %s",
420  bus_device);
421 #endif
422  break;
423  }
424  }
425 
426  /* New reader found */
427  if (newreader)
428  HPAddHotPluggable(dev, desc, bus_device,
429  &config_desc->interface[interface], driver, classdriver);
430  }
431 
432  libusb_free_config_descriptor(config_desc);
433  }
434 
435  /*
436  * check if all the previously found readers are still present
437  */
438  for (i=0; i<PCSCLITE_MAX_READERS_CONTEXTS; i++)
439  {
440  if ((readerTracker[i].status == READER_ABSENT) &&
441  (readerTracker[i].fullName != NULL))
442  HPRemoveHotPluggable(i);
443  }
444 
445  if (AraKiriHotPlug)
446  {
447  int retval;
448 
449  for (i=0; i<driverSize; i++)
450  {
451  /* free strings allocated by strdup() */
452  free(driverTracker[i].bundleName);
453  free(driverTracker[i].libraryPath);
454  free(driverTracker[i].readerName);
455  free(driverTracker[i].CFBundleName);
456  }
457  free(driverTracker);
458 
459  Log1(PCSC_LOG_INFO, "Hotplug stopped");
460  pthread_exit(&retval);
461  }
462 
463  /* free the libusb allocated list & devices */
464  libusb_free_device_list(devs, 1);
465 }
466 
467 static void * HPEstablishUSBNotifications(int pipefd[2])
468 {
469  int i, do_polling;
470  int r;
471  char c = 42; /* magic value */
472 
473  r = libusb_init(ctx);
474  if (r < 0)
475  {
476  Log2(PCSC_LOG_CRITICAL, "libusb_init failed: %s", libusb_error_name(r));
477  /* emergency exit */
478  kill(getpid(), SIGTERM);
479  return NULL;
480  }
481 
482  /* scan the USB bus for devices at startup */
483  HPRescanUsbBus();
484 
485  /* signal that the initially connected readers are now visible */
486  if (write(pipefd[1], &c, 1) == -1)
487  {
488  Log2(PCSC_LOG_ERROR, "write: %s", strerror(errno));
489  return NULL;
490  }
491 
492  /* if at least one driver do not have IFD_GENERATE_HOTPLUG */
493  do_polling = FALSE;
494  for (i=0; i<driverSize; i++)
495  if (driverTracker[i].libraryPath)
496  if ((driverTracker[i].ifdCapabilities & IFD_GENERATE_HOTPLUG) == 0)
497  {
498  Log2(PCSC_LOG_INFO,
499  "Driver %s does not support IFD_GENERATE_HOTPLUG. Using active polling instead.",
500  driverTracker[i].bundleName);
501  if (HPForceReaderPolling < 1)
502  HPForceReaderPolling = 1;
503  break;
504  }
505 
506  if (HPForceReaderPolling)
507  {
508  Log2(PCSC_LOG_INFO,
509  "Polling forced every %d second(s)", HPForceReaderPolling);
510  do_polling = TRUE;
511  }
512 
513  if (do_polling)
514  {
515  while (!AraKiriHotPlug)
516  {
517  SYS_Sleep(HPForceReaderPolling);
518  HPRescanUsbBus();
519  }
520  libusb_exit(ctx);
521  }
522  else
523  {
524  char dummy;
525 
526  if (pipe(rescan_pipe) == -1)
527  {
528  Log2(PCSC_LOG_ERROR, "pipe: %s", strerror(errno));
529  return NULL;
530  }
531  while (read(rescan_pipe[0], &dummy, sizeof(dummy)) > 0)
532  {
533  Log1(PCSC_LOG_INFO, "Reload serial configuration");
534  HPRescanUsbBus();
535 #ifdef USE_SERIAL
536  RFReCheckReaderConf();
537 #endif
538  Log1(PCSC_LOG_INFO, "End reload serial configuration");
539  }
540  close(rescan_pipe[0]);
541  rescan_pipe[0] = -1;
542  }
543 
544  return NULL;
545 }
546 
547 LONG HPSearchHotPluggables(void)
548 {
549  int i;
550 
551  for (i=0; i<PCSCLITE_MAX_READERS_CONTEXTS; i++)
552  {
553  readerTracker[i].status = READER_ABSENT;
554  readerTracker[i].bus_device[0] = '\0';
555  readerTracker[i].fullName = NULL;
556  }
557 
558  if (HPReadBundleValues() > 0)
559  {
560  int pipefd[2];
561  char c;
562 
563  if (pipe(pipefd) == -1)
564  {
565  Log2(PCSC_LOG_ERROR, "pipe: %s", strerror(errno));
566  return -1;
567  }
568 
569  ThreadCreate(&usbNotifyThread, THREAD_ATTR_DETACHED,
570  (PCSCLITE_THREAD_FUNCTION( )) HPEstablishUSBNotifications, pipefd);
571 
572  /* Wait for initial readers to setup */
573  if (read(pipefd[0], &c, 1) == -1)
574  {
575  Log2(PCSC_LOG_ERROR, "read: %s", strerror(errno));
576  return -1;
577  };
578 
579  /* cleanup pipe fd */
580  close(pipefd[0]);
581  close(pipefd[1]);
582  }
583 
584  return 0;
585 }
586 
587 LONG HPStopHotPluggables(void)
588 {
589  AraKiriHotPlug = TRUE;
590  if (rescan_pipe[1] >= 0)
591  {
592  close(rescan_pipe[1]);
593  rescan_pipe[1] = -1;
594  }
595 
596  return 0;
597 }
598 
599 static LONG HPAddHotPluggable(struct libusb_device *dev,
600  struct libusb_device_descriptor desc,
601  const char bus_device[],
602  const struct libusb_interface *idesc,
603  struct _driverTracker *driver,
604  struct _driverTracker *classdriver)
605 {
606  int i;
607  uint8_t iInterface = 0;
608  uint8_t iSerialNumber = 0;
609  char deviceName[MAX_DEVICENAME];
610 
611  Log2(PCSC_LOG_INFO, "Adding USB device: %s", bus_device);
612 
613  snprintf(deviceName, sizeof(deviceName), "usb:%04x/%04x:libusb-1.0:%s",
614  desc.idVendor, desc.idProduct, bus_device);
615 
616  deviceName[sizeof(deviceName) -1] = '\0';
617 
618  pthread_mutex_lock(&usbNotifierMutex);
619 
620  /* find a free entry */
621  for (i=0; i<PCSCLITE_MAX_READERS_CONTEXTS; i++)
622  {
623  if (readerTracker[i].fullName == NULL)
624  break;
625  }
626 
628  {
629  Log2(PCSC_LOG_ERROR,
630  "Not enough reader entries. Already found %d readers", i);
631  pthread_mutex_unlock(&usbNotifierMutex);
632  return 0;
633  }
634 
635  strncpy(readerTracker[i].bus_device, bus_device,
636  sizeof(readerTracker[i].bus_device));
637  readerTracker[i].bus_device[sizeof(readerTracker[i].bus_device) - 1] = '\0';
638  readerTracker[i].fullName = NULL;
639 
640  if (Add_Interface_In_Name && idesc->num_altsetting > 0)
641  iInterface = idesc->altsetting[0].iInterface;
642 
643  if (Add_Serial_In_Name)
644  iSerialNumber = desc.iSerialNumber;
645 
646  if (iSerialNumber != 0 || iInterface != 0)
647  {
648  libusb_device_handle *device;
649  int ret;
650 
651  ret = libusb_open(dev, &device);
652  if (ret < 0)
653  {
654  Log2(PCSC_LOG_ERROR, "libusb_open failed: %s",
655  libusb_error_name(ret));
656  }
657  else
658  {
659  unsigned char interfaceName[MAX_READERNAME];
660  unsigned char serialNumber[MAX_READERNAME];
661  char fullname[MAX_READERNAME * 3];
662  fullname[0] = '\0';
663  int ret_interface = 0;
664  int ret_serial = 0;
665 
666  if (iInterface)
667  {
668  ret_interface = libusb_get_string_descriptor_ascii(device,
669  iInterface, interfaceName, sizeof interfaceName);
670  if (ret_interface < 0)
671  {
672  Log2(PCSC_LOG_ERROR,
673  "libusb_get_string_descriptor_ascii failed: %s",
674  libusb_error_name(ret_interface));
675  }
676  }
677 
678  if (iSerialNumber)
679  {
680  ret_serial = libusb_get_string_descriptor_ascii(device,
681  iSerialNumber, serialNumber, sizeof serialNumber);
682  if (ret_serial < 0)
683  {
684  Log2(PCSC_LOG_ERROR,
685  "libusb_get_string_descriptor_ascii failed: %s",
686  libusb_error_name(ret_serial));
687  }
688  }
689 
690  libusb_close(device);
691 
692  if (ret_interface > 0 && ret_serial > 0)
693  {
694  snprintf(fullname, sizeof(fullname), "%s [%s] (%s)",
695  driver->readerName, interfaceName, serialNumber);
696  }
697  else
698  {
699  if (ret_interface > 0)
700  {
701  snprintf(fullname, sizeof(fullname), "%s [%s]",
702  driver->readerName, interfaceName);
703  }
704  else
705  {
706  if (ret_serial > 0)
707  {
708  snprintf(fullname, sizeof(fullname), "%s (%s)",
709  driver->readerName, serialNumber);
710  }
711  }
712  }
713 
714  if (fullname[0] != '\0')
715  readerTracker[i].fullName = strdup(fullname);
716  }
717  }
718 
719  if (readerTracker[i].fullName == NULL)
720  readerTracker[i].fullName = strdup(driver->readerName);
721 
722  LONG ret;
723  ret = RFAddReader(readerTracker[i].fullName, PCSCLITE_HP_BASE_PORT + i,
724  driver->libraryPath, deviceName);
725  /* success by default */
726  readerTracker[i].status = READER_PRESENT;
727  if ((SCARD_S_SUCCESS != ret) && (SCARD_E_UNKNOWN_READER != ret))
728  {
729  Log2(PCSC_LOG_ERROR, "Failed adding USB device: %s",
730  driver->readerName);
731 
732  if (classdriver && driver != classdriver)
733  {
734  /* the reader can also be used by the a class driver */
735  ret = RFAddReader(readerTracker[i].fullName,
736  PCSCLITE_HP_BASE_PORT + i,
737  classdriver->libraryPath, deviceName);
738  if ((SCARD_S_SUCCESS != ret) && (SCARD_E_UNKNOWN_READER != ret))
739  {
740  Log2(PCSC_LOG_ERROR, "Failed adding USB device: %s",
741  driver->readerName);
742  readerTracker[i].status = READER_FAILED;
743  }
744  }
745  else
746  readerTracker[i].status = READER_FAILED;
747  }
748 
749  if (READER_FAILED == readerTracker[i].status)
750  (void)CheckForOpenCT();
751 
752  pthread_mutex_unlock(&usbNotifierMutex);
753 
754  return 1;
755 } /* End of function */
756 
757 static LONG HPRemoveHotPluggable(int reader_index)
758 {
759  pthread_mutex_lock(&usbNotifierMutex);
760 
761  Log3(PCSC_LOG_INFO, "Removing USB device[%d]: %s", reader_index,
762  readerTracker[reader_index].bus_device);
763 
764  RFRemoveReader(readerTracker[reader_index].fullName,
765  PCSCLITE_HP_BASE_PORT + reader_index, REMOVE_READER_FLAG_REMOVED);
766  free(readerTracker[reader_index].fullName);
767  readerTracker[reader_index].status = READER_ABSENT;
768  readerTracker[reader_index].bus_device[0] = '\0';
769  readerTracker[reader_index].fullName = NULL;
770 
771  pthread_mutex_unlock(&usbNotifierMutex);
772 
773  return 1;
774 } /* End of function */
775 
779 ULONG HPRegisterForHotplugEvents(void)
780 {
781  (void)pthread_mutex_init(&usbNotifierMutex, NULL);
782  return 0;
783 }
784 
785 void HPReCheckSerialReaders(void)
786 {
787  Log0(PCSC_LOG_INFO);
788  if (rescan_pipe[1] >= 0)
789  {
790  char dummy = 0;
791  if (write(rescan_pipe[1], &dummy, sizeof(dummy)) == -1)
792  Log2(PCSC_LOG_ERROR, "write: %s", strerror(errno));
793  }
794 }
795 
796 #endif
797 
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.