pcsc-lite  1.9.4
hotplug_libudev.c
Go to the documentation of this file.
1 /*
2  * MUSCLE SmartCard Development ( https://pcsclite.apdu.fr/ )
3  *
4  * Copyright (C) 2011
5  * Ludovic Rousseau <ludovic.rousseau@free.fr>
6  * Copyright (C) 2014
7  * Stefani Seibold <stefani@seibold.net>
8  *
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions
11 are met:
12 
13 1. Redistributions of source code must retain the above copyright
14  notice, this list of conditions and the following disclaimer.
15 2. Redistributions in binary form must reproduce the above copyright
16  notice, this list of conditions and the following disclaimer in the
17  documentation and/or other materials provided with the distribution.
18 3. The name of the author may not be used to endorse or promote products
19  derived from this software without specific prior written permission.
20 
21 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
38 #include "config.h"
39 #if defined(HAVE_LIBUDEV) && defined(USE_USB)
40 
41 #define _GNU_SOURCE /* for asprintf(3) */
42 #include <string.h>
43 #include <stdio.h>
44 #include <dirent.h>
45 #include <stdlib.h>
46 #include <pthread.h>
47 #include <libudev.h>
48 #include <poll.h>
49 #include <ctype.h>
50 
51 #include "debuglog.h"
52 #include "parser.h"
53 #include "readerfactory.h"
54 #include "sys_generic.h"
55 #include "hotplug.h"
56 #include "utils.h"
57 
58 #ifndef TEMP_FAILURE_RETRY
59 #define TEMP_FAILURE_RETRY(expression) \
60  (__extension__ \
61  ({ long int __result; \
62  do __result = (long int) (expression); \
63  while (__result == -1L && errno == EINTR); \
64  __result; }))
65 #endif
66 
67 #undef DEBUG_HOTPLUG
68 
69 #define FALSE 0
70 #define TRUE 1
71 
72 extern char Add_Interface_In_Name;
73 extern char Add_Serial_In_Name;
74 
75 static pthread_t usbNotifyThread;
76 static int driverSize = -1;
77 static struct udev *Udev;
78 
79 
83 static struct _driverTracker
84 {
85  unsigned int manuID;
86  unsigned int productID;
87 
88  char *bundleName;
89  char *libraryPath;
90  char *readerName;
91  char *CFBundleName;
92 } *driverTracker = NULL;
93 #define DRIVER_TRACKER_SIZE_STEP 10
94 
95 /* The CCID driver already supports 176 readers.
96  * We start with a big array size to avoid reallocation. */
97 #define DRIVER_TRACKER_INITIAL_SIZE 200
98 
102 static struct _readerTracker
103 {
104  char *devpath;
105  char *fullName;
106  char *sysname;
107 } readerTracker[PCSCLITE_MAX_READERS_CONTEXTS];
108 
109 
110 static LONG HPReadBundleValues(void)
111 {
112  LONG rv;
113  DIR *hpDir;
114  struct dirent *currFP = NULL;
115  char fullPath[FILENAME_MAX];
116  char fullLibPath[FILENAME_MAX];
117  int listCount = 0;
118 
119  hpDir = opendir(PCSCLITE_HP_DROPDIR);
120 
121  if (NULL == hpDir)
122  {
123  Log1(PCSC_LOG_ERROR, "Cannot open PC/SC drivers directory: " PCSCLITE_HP_DROPDIR);
124  Log1(PCSC_LOG_ERROR, "Disabling USB support for pcscd.");
125  return -1;
126  }
127 
128  /* allocate a first array */
129  driverSize = DRIVER_TRACKER_INITIAL_SIZE;
130  driverTracker = calloc(driverSize, sizeof(*driverTracker));
131  if (NULL == driverTracker)
132  {
133  Log1(PCSC_LOG_CRITICAL, "Not enough memory");
134  (void)closedir(hpDir);
135  return -1;
136  }
137 
138 #define GET_KEY(key, values) \
139  rv = LTPBundleFindValueWithKey(&plist, key, values); \
140  if (rv) \
141  { \
142  Log2(PCSC_LOG_ERROR, "Value/Key not defined for " key " in %s", \
143  fullPath); \
144  continue; \
145  }
146 
147  while ((currFP = readdir(hpDir)) != 0)
148  {
149  if (strstr(currFP->d_name, ".bundle") != 0)
150  {
151  unsigned int alias;
152  list_t plist, *values;
153  list_t *manuIDs, *productIDs, *readerNames;
154  char *CFBundleName;
155  char *libraryPath;
156 
157  /*
158  * The bundle exists - let's form a full path name and get the
159  * vendor and product ID's for this particular bundle
160  */
161  (void)snprintf(fullPath, sizeof(fullPath), "%s/%s/Contents/Info.plist",
162  PCSCLITE_HP_DROPDIR, currFP->d_name);
163  fullPath[sizeof(fullPath) - 1] = '\0';
164 
165  rv = bundleParse(fullPath, &plist);
166  if (rv)
167  continue;
168 
169  /* get CFBundleExecutable */
170  GET_KEY(PCSCLITE_HP_LIBRKEY_NAME, &values)
171  libraryPath = list_get_at(values, 0);
172  (void)snprintf(fullLibPath, sizeof(fullLibPath),
173  "%s/%s/Contents/%s/%s",
174  PCSCLITE_HP_DROPDIR, currFP->d_name, PCSC_ARCH,
175  libraryPath);
176  fullLibPath[sizeof(fullLibPath) - 1] = '\0';
177 
178  GET_KEY(PCSCLITE_HP_MANUKEY_NAME, &manuIDs)
179  GET_KEY(PCSCLITE_HP_PRODKEY_NAME, &productIDs)
180  GET_KEY(PCSCLITE_HP_NAMEKEY_NAME, &readerNames)
181 
182  if ((list_size(manuIDs) != list_size(productIDs))
183  || (list_size(manuIDs) != list_size(readerNames)))
184  {
185  Log2(PCSC_LOG_CRITICAL, "Error parsing %s", fullPath);
186  (void)closedir(hpDir);
187  return -1;
188  }
189 
190  /* Get CFBundleName */
191  rv = LTPBundleFindValueWithKey(&plist, PCSCLITE_HP_CFBUNDLE_NAME,
192  &values);
193  if (rv)
194  CFBundleName = NULL;
195  else
196  CFBundleName = strdup(list_get_at(values, 0));
197 
198  /* while we find a nth ifdVendorID in Info.plist */
199  for (alias=0; alias<list_size(manuIDs); alias++)
200  {
201  char *value;
202 
203  /* variables entries */
204  value = list_get_at(manuIDs, alias);
205  driverTracker[listCount].manuID = strtol(value, NULL, 16);
206 
207  value = list_get_at(productIDs, alias);
208  driverTracker[listCount].productID = strtol(value, NULL, 16);
209 
210  driverTracker[listCount].readerName = strdup(list_get_at(readerNames, alias));
211 
212  /* constant entries for a same driver */
213  driverTracker[listCount].bundleName = strdup(currFP->d_name);
214  driverTracker[listCount].libraryPath = strdup(fullLibPath);
215  driverTracker[listCount].CFBundleName = CFBundleName;
216 
217 #ifdef DEBUG_HOTPLUG
218  Log2(PCSC_LOG_INFO, "Found driver for: %s",
219  driverTracker[listCount].readerName);
220 #endif
221  listCount++;
222  if (listCount >= driverSize)
223  {
224  int i;
225 
226  /* increase the array size */
227  driverSize += DRIVER_TRACKER_SIZE_STEP;
228 #ifdef DEBUG_HOTPLUG
229  Log2(PCSC_LOG_INFO,
230  "Increase driverTracker to %d entries", driverSize);
231 #endif
232 
233  void* tmp = realloc(driverTracker,
234  driverSize * sizeof(*driverTracker));
235 
236  if (NULL == tmp)
237  {
238  free(driverTracker);
239  Log1(PCSC_LOG_CRITICAL, "Not enough memory");
240  driverSize = -1;
241  (void)closedir(hpDir);
242  return -1;
243  }
244  driverTracker = tmp;
245 
246  /* clean the newly allocated entries */
247  for (i=driverSize-DRIVER_TRACKER_SIZE_STEP; i<driverSize; i++)
248  {
249  driverTracker[i].manuID = 0;
250  driverTracker[i].productID = 0;
251  driverTracker[i].bundleName = NULL;
252  driverTracker[i].libraryPath = NULL;
253  driverTracker[i].readerName = NULL;
254  driverTracker[i].CFBundleName = NULL;
255  }
256  }
257  }
258  bundleRelease(&plist);
259  }
260  }
261 
262  driverSize = listCount;
263  (void)closedir(hpDir);
264 
265 #ifdef DEBUG_HOTPLUG
266  Log2(PCSC_LOG_INFO, "Found drivers for %d readers", listCount);
267 #endif
268 
269  return 0;
270 } /* HPReadBundleValues */
271 
272 
273 /*@null@*/ static struct _driverTracker *get_driver(struct udev_device *dev,
274  const char *devpath, struct _driverTracker **classdriver)
275 {
276  int i;
277  unsigned int idVendor, idProduct;
278  static struct _driverTracker *driver;
279  const char *str;
280 
281  str = udev_device_get_sysattr_value(dev, "idVendor");
282  if (!str)
283  {
284  Log1(PCSC_LOG_ERROR, "udev_device_get_sysattr_value() failed");
285  return NULL;
286  }
287  idVendor = strtol(str, NULL, 16);
288 
289  str = udev_device_get_sysattr_value(dev, "idProduct");
290  if (!str)
291  {
292  Log1(PCSC_LOG_ERROR, "udev_device_get_sysattr_value() failed");
293  return NULL;
294  }
295  idProduct = strtol(str, NULL, 16);
296 
297 #ifdef NO_LOG
298  (void)devpath;
299 #endif
300  Log4(PCSC_LOG_DEBUG,
301  "Looking for a driver for VID: 0x%04X, PID: 0x%04X, path: %s",
302  idVendor, idProduct, devpath);
303 
304  *classdriver = NULL;
305  driver = NULL;
306  /* check if the device is supported by one driver */
307  for (i=0; i<driverSize; i++)
308  {
309  if (driverTracker[i].libraryPath != NULL &&
310  idVendor == driverTracker[i].manuID &&
311  idProduct == driverTracker[i].productID)
312  {
313  if ((driverTracker[i].CFBundleName != NULL)
314  && (0 == strcmp(driverTracker[i].CFBundleName, "CCIDCLASSDRIVER")))
315  *classdriver = &driverTracker[i];
316  else
317  /* it is not a CCID Class driver */
318  driver = &driverTracker[i];
319  }
320  }
321 
322  /* if we found a specific driver */
323  if (driver)
324  return driver;
325 
326  /* else return the Class driver (if any) */
327  return *classdriver;
328 }
329 
330 
331 static void HPRemoveDevice(struct udev_device *dev)
332 {
333  int i;
334  const char *devpath;
335  struct udev_device *parent;
336  const char *sysname;
337 
338  /* The device pointed to by dev contains information about
339  the interface. In order to get information about the USB
340  device, get the parent device with the subsystem/devtype pair
341  of "usb"/"usb_device". This will be several levels up the
342  tree, but the function will find it.*/
343  parent = udev_device_get_parent_with_subsystem_devtype(dev, "usb",
344  "usb_device");
345  if (!parent)
346  return;
347 
348  devpath = udev_device_get_devnode(parent);
349  if (!devpath)
350  {
351  /* the device disapeared? */
352  Log1(PCSC_LOG_ERROR, "udev_device_get_devnode() failed");
353  return;
354  }
355 
356  sysname = udev_device_get_sysname(dev);
357  if (!sysname)
358  {
359  Log1(PCSC_LOG_ERROR, "udev_device_get_sysname() failed");
360  return;
361  }
362 
363  for (i=0; i<PCSCLITE_MAX_READERS_CONTEXTS; i++)
364  {
365  if (readerTracker[i].fullName && !strcmp(sysname, readerTracker[i].sysname))
366  {
367  Log4(PCSC_LOG_INFO, "Removing USB device[%d]: %s at %s", i,
368  readerTracker[i].fullName, readerTracker[i].devpath);
369 
370  RFRemoveReader(readerTracker[i].fullName, PCSCLITE_HP_BASE_PORT + i);
371 
372  free(readerTracker[i].devpath);
373  readerTracker[i].devpath = NULL;
374  free(readerTracker[i].fullName);
375  readerTracker[i].fullName = NULL;
376  free(readerTracker[i].sysname);
377  readerTracker[i].sysname = NULL;
378  break;
379  }
380  }
381 }
382 
383 
384 static void HPAddDevice(struct udev_device *dev)
385 {
386  int index, a;
387  char *deviceName = NULL;
388  char *fullname = NULL;
389  struct _driverTracker *driver, *classdriver;
390  const char *sSerialNumber = NULL, *sInterfaceName = NULL;
391  const char *sInterfaceNumber;
392  LONG ret;
393  int bInterfaceNumber;
394  const char *devpath;
395  struct udev_device *parent;
396  const char *sysname;
397 
398  /* The device pointed to by dev contains information about
399  the interface. In order to get information about the USB
400  device, get the parent device with the subsystem/devtype pair
401  of "usb"/"usb_device". This will be several levels up the
402  tree, but the function will find it.*/
403  parent = udev_device_get_parent_with_subsystem_devtype(dev, "usb",
404  "usb_device");
405  if (!parent)
406  return;
407 
408  devpath = udev_device_get_devnode(parent);
409  if (!devpath)
410  {
411  /* the device disapeared? */
412  Log1(PCSC_LOG_ERROR, "udev_device_get_devnode() failed");
413  return;
414  }
415 
416  driver = get_driver(parent, devpath, &classdriver);
417  if (NULL == driver)
418  {
419  /* not a smart card reader */
420 #ifdef DEBUG_HOTPLUG
421  Log2(PCSC_LOG_DEBUG, "%s is not a supported smart card reader",
422  devpath);
423 #endif
424  return;
425  }
426 
427  sysname = udev_device_get_sysname(dev);
428  if (!sysname)
429  {
430  Log1(PCSC_LOG_ERROR, "udev_device_get_sysname() failed");
431  return;
432  }
433 
434  /* check for duplicated add */
435  for (index=0; index<PCSCLITE_MAX_READERS_CONTEXTS; index++)
436  {
437  if (readerTracker[index].fullName && !strcmp(sysname, readerTracker[index].sysname))
438  return;
439  }
440 
441  Log2(PCSC_LOG_INFO, "Adding USB device: %s", driver->readerName);
442 
443  sInterfaceNumber = udev_device_get_sysattr_value(dev, "bInterfaceNumber");
444  if (sInterfaceNumber)
445  bInterfaceNumber = atoi(sInterfaceNumber);
446  else
447  bInterfaceNumber = 0;
448 
449  a = asprintf(&deviceName, "usb:%04x/%04x:libudev:%d:%s",
450  driver->manuID, driver->productID, bInterfaceNumber, devpath);
451  if (-1 == a)
452  {
453  Log1(PCSC_LOG_ERROR, "asprintf() failed");
454  return;
455  }
456 
457  /* find a free entry */
458  for (index=0; index<PCSCLITE_MAX_READERS_CONTEXTS; index++)
459  {
460  if (NULL == readerTracker[index].fullName)
461  break;
462  }
463 
464  if (PCSCLITE_MAX_READERS_CONTEXTS == index)
465  {
466  Log2(PCSC_LOG_ERROR,
467  "Not enough reader entries. Already found %d readers", index);
468  return;
469  }
470 
471  if (Add_Interface_In_Name)
472  sInterfaceName = udev_device_get_sysattr_value(dev, "interface");
473 
474  if (Add_Serial_In_Name)
475  sSerialNumber = udev_device_get_sysattr_value(parent, "serial");
476 
477  /* name from the Info.plist file */
478  fullname = strdup(driver->readerName);
479 
480  /* interface name from the device (if any) */
481  if (sInterfaceName)
482  {
483  char *result;
484 
485  char *tmpInterfaceName = strdup(sInterfaceName);
486 
487  /* check the interface name contains only valid ASCII codes */
488  for (size_t i=0; i<strlen(tmpInterfaceName); i++)
489  {
490  if (! isascii(tmpInterfaceName[i]))
491  tmpInterfaceName[i] = '.';
492  }
493 
494  /* create a new name */
495  a = asprintf(&result, "%s [%s]", fullname, tmpInterfaceName);
496  if (-1 == a)
497  {
498  Log1(PCSC_LOG_ERROR, "asprintf() failed");
499  free(tmpInterfaceName);
500  goto exit;
501  }
502 
503  free(fullname);
504  free(tmpInterfaceName);
505  fullname = result;
506  }
507 
508  /* serial number from the device (if any) */
509  if (sSerialNumber)
510  {
511  /* only add the serial number if it is not already present in the
512  * interface name */
513  if (!sInterfaceName || NULL == strstr(sInterfaceName, sSerialNumber))
514  {
515  char *result;
516 
517  /* create a new name */
518  a = asprintf(&result, "%s (%s)", fullname, sSerialNumber);
519  if (-1 == a)
520  {
521  Log1(PCSC_LOG_ERROR, "asprintf() failed");
522  goto exit;
523  }
524 
525  free(fullname);
526  fullname = result;
527  }
528  }
529 
530  readerTracker[index].fullName = strdup(fullname);
531  readerTracker[index].devpath = strdup(devpath);
532  readerTracker[index].sysname = strdup(sysname);
533 
534  ret = RFAddReader(fullname, PCSCLITE_HP_BASE_PORT + index,
535  driver->libraryPath, deviceName);
536  if ((SCARD_S_SUCCESS != ret) && (SCARD_E_UNKNOWN_READER != ret))
537  {
538  Log2(PCSC_LOG_ERROR, "Failed adding USB device: %s",
539  driver->readerName);
540 
541  if (classdriver && driver != classdriver)
542  {
543  /* the reader can also be used by the a class driver */
544  ret = RFAddReader(fullname, PCSCLITE_HP_BASE_PORT + index,
545  classdriver->libraryPath, deviceName);
546  if ((SCARD_S_SUCCESS != ret) && (SCARD_E_UNKNOWN_READER != ret))
547  {
548  Log2(PCSC_LOG_ERROR, "Failed adding USB device: %s",
549  driver->readerName);
550  (void)CheckForOpenCT();
551  }
552  }
553  else
554  {
555  (void)CheckForOpenCT();
556  }
557  }
558 
559  if (SCARD_S_SUCCESS != ret)
560  {
561  /* adding the reader failed */
562  free(readerTracker[index].devpath);
563  readerTracker[index].devpath = NULL;
564  free(readerTracker[index].fullName);
565  readerTracker[index].fullName = NULL;
566  free(readerTracker[index].sysname);
567  readerTracker[index].sysname = NULL;
568  }
569 
570 exit:
571  free(fullname);
572  free(deviceName);
573 } /* HPAddDevice */
574 
575 
576 static void HPScanUSB(struct udev *udev)
577 {
578  struct udev_enumerate *enumerate;
579  struct udev_list_entry *devices, *dev_list_entry;
580 
581  /* Create a list of the devices in the 'usb' subsystem. */
582  enumerate = udev_enumerate_new(udev);
583  udev_enumerate_add_match_subsystem(enumerate, "usb");
584  udev_enumerate_scan_devices(enumerate);
585  devices = udev_enumerate_get_list_entry(enumerate);
586 
587  /* For each item enumerated */
588  udev_list_entry_foreach(dev_list_entry, devices)
589  {
590  struct udev_device *dev;
591  const char *devpath;
592 
593  /* Get the filename of the /sys entry for the device
594  and create a udev_device object (dev) representing it */
595  devpath = udev_list_entry_get_name(dev_list_entry);
596  dev = udev_device_new_from_syspath(udev, devpath);
597 
598 #ifdef DEBUG_HOTPLUG
599  Log2(PCSC_LOG_DEBUG, "Found matching USB device: %s", devpath);
600 #endif
601  HPAddDevice(dev);
602 
603  /* free device */
604  udev_device_unref(dev);
605  }
606 
607  /* Free the enumerator object */
608  udev_enumerate_unref(enumerate);
609 }
610 
611 
612 static void * HPEstablishUSBNotifications(void *arg)
613 {
614  struct udev_monitor *udev_monitor = arg;
615  int r;
616  int fd;
617  struct pollfd pfd;
618 
619  pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
620  pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
621 
622  /* udev monitor file descriptor */
623  fd = udev_monitor_get_fd(udev_monitor);
624  if (fd < 0)
625  {
626  Log2(PCSC_LOG_ERROR, "udev_monitor_get_fd() error: %d", fd);
627  pthread_exit(NULL);
628  }
629 
630  pfd.fd = fd;
631  pfd.events = POLLIN;
632 
633  for (;;)
634  {
635  struct udev_device *dev;
636 
637 #ifdef DEBUG_HOTPLUG
638  Log0(PCSC_LOG_INFO);
639 #endif
640  pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
641 
642  /* wait for a udev event */
643  r = TEMP_FAILURE_RETRY(poll(&pfd, 1, -1));
644  if (r < 0)
645  {
646  Log2(PCSC_LOG_ERROR, "select(): %s", strerror(errno));
647  pthread_exit(NULL);
648  }
649 
650  pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
651 
652  dev = udev_monitor_receive_device(udev_monitor);
653  if (dev)
654  {
655  const char *action = udev_device_get_action(dev);
656 
657  if (action)
658  {
659  if (!strcmp("remove", action))
660  {
661  Log1(PCSC_LOG_INFO, "USB Device removed");
662  HPRemoveDevice(dev);
663  }
664  else
665  if (!strcmp("add", action))
666  {
667  Log1(PCSC_LOG_INFO, "USB Device add");
668  HPAddDevice(dev);
669  }
670  }
671 
672  /* free device */
673  udev_device_unref(dev);
674  }
675  }
676 
677  pthread_exit(NULL);
678 } /* HPEstablishUSBNotifications */
679 
680 
681 /***
682  * Start a thread waiting for hotplug events
683  */
684 LONG HPSearchHotPluggables(void)
685 {
686  int i;
687 
688  for (i=0; i<PCSCLITE_MAX_READERS_CONTEXTS; i++)
689  {
690  readerTracker[i].devpath = NULL;
691  readerTracker[i].fullName = NULL;
692  readerTracker[i].sysname = NULL;
693  }
694 
695  return HPReadBundleValues();
696 } /* HPSearchHotPluggables */
697 
698 
702 LONG HPStopHotPluggables(void)
703 {
704  int i;
705 
706  if (driverSize <= 0)
707  return 0;
708 
709  if (!Udev)
710  return 0;
711 
712  pthread_cancel(usbNotifyThread);
713  pthread_join(usbNotifyThread, NULL);
714 
715  for (i=0; i<driverSize; i++)
716  {
717  /* free strings allocated by strdup() */
718  free(driverTracker[i].bundleName);
719  free(driverTracker[i].libraryPath);
720  free(driverTracker[i].readerName);
721  }
722  free(driverTracker);
723 
724  udev_unref(Udev);
725 
726  Udev = NULL;
727  driverSize = -1;
728 
729  Log1(PCSC_LOG_INFO, "Hotplug stopped");
730  return 0;
731 } /* HPStopHotPluggables */
732 
733 
737 ULONG HPRegisterForHotplugEvents(void)
738 {
739  struct udev_monitor *udev_monitor;
740  int r;
741 
742  if (driverSize <= 0)
743  {
744  Log1(PCSC_LOG_INFO, "No bundle files in pcsc drivers directory: "
745  PCSCLITE_HP_DROPDIR);
746  Log1(PCSC_LOG_INFO, "Disabling USB support for pcscd");
747  return 0;
748  }
749 
750  /* Create the udev object */
751  Udev = udev_new();
752  if (!Udev)
753  {
754  Log1(PCSC_LOG_ERROR, "udev_new() failed");
755  return SCARD_F_INTERNAL_ERROR;
756  }
757 
758  udev_monitor = udev_monitor_new_from_netlink(Udev, "udev");
759  if (NULL == udev_monitor)
760  {
761  Log1(PCSC_LOG_ERROR, "udev_monitor_new_from_netlink() error");
762  pthread_exit(NULL);
763  }
764 
765  /* filter only the interfaces */
766  r = udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "usb",
767  "usb_interface");
768  if (r)
769  {
770  Log2(PCSC_LOG_ERROR, "udev_monitor_filter_add_match_subsystem_devtype() error: %d\n", r);
771  pthread_exit(NULL);
772  }
773 
774  r = udev_monitor_enable_receiving(udev_monitor);
775  if (r)
776  {
777  Log2(PCSC_LOG_ERROR, "udev_monitor_enable_receiving() error: %d\n", r);
778  pthread_exit(NULL);
779  }
780 
781  /* scan the USB bus at least once before accepting client connections */
782  HPScanUSB(Udev);
783 
784  if (ThreadCreate(&usbNotifyThread, 0,
785  (PCSCLITE_THREAD_FUNCTION( )) HPEstablishUSBNotifications, udev_monitor))
786  {
787  Log1(PCSC_LOG_ERROR, "ThreadCreate() failed");
788  return SCARD_F_INTERNAL_ERROR;
789  }
790 
791  return 0;
792 } /* HPRegisterForHotplugEvents */
793 
794 
795 void HPReCheckSerialReaders(void)
796 {
797  /* nothing to do here */
798 #ifdef DEBUG_HOTPLUG
799  Log0(PCSC_LOG_ERROR);
800 #endif
801 } /* HPReCheckSerialReaders */
802 
803 #endif
804 
This handles debugging.
#define SCARD_F_INTERNAL_ERROR
An internal consistency check failed.
Definition: pcsclite.h:109
#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.
#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.