44 #if defined(__linux__) && !defined(HAVE_LIBUSB) && !defined(HAVE_LIBUDEV) 45 #include <sys/types.h> 66 #define PCSCLITE_USB_PATH "/proc/bus/usb" 71 pthread_mutex_t usbNotifierMutex;
73 struct usb_device_descriptor
76 u_int8_t bDescriptorType;
78 u_int8_t bDeviceClass;
79 u_int8_t bDeviceSubClass;
80 u_int8_t bDeviceProtocol;
81 u_int8_t bMaxPacketSize0;
85 u_int8_t iManufacturer;
87 u_int8_t iSerialNumber;
88 u_int8_t bNumConfigurations;
90 __attribute__ ((packed));
92 static LONG HPAddHotPluggable(
int,
unsigned long);
93 static LONG HPRemoveHotPluggable(
int,
unsigned long);
94 static LONG HPReadBundleValues(
void);
95 static void HPEstablishUSBNotifications(
void);
97 static pthread_t usbNotifyThread;
98 static int AraKiriHotPlug = FALSE;
99 static int bundleSize = 0;
104 static struct _bundleTracker
109 struct _deviceNumber {
120 static LONG HPReadBundleValues(
void)
124 struct dirent *currFP = 0;
125 char fullPath[FILENAME_MAX];
126 char fullLibPath[FILENAME_MAX];
127 unsigned int listCount = 0;
129 hpDir = opendir(PCSCLITE_HP_DROPDIR);
134 "Cannot open PC/SC drivers directory: " PCSCLITE_HP_DROPDIR);
135 Log1(PCSC_LOG_INFO,
"Disabling USB support for pcscd.");
139 #define GET_KEY(key, values) \ 140 rv = LTPBundleFindValueWithKey(&plist, key, values); \ 143 Log2(PCSC_LOG_ERROR, "Value/Key not defined for " key " in %s", \ 148 while ((currFP = readdir(hpDir)) != 0)
150 if (strstr(currFP->d_name,
".bundle") != 0)
154 list_t *manuIDs, *productIDs, *readerNames;
161 snprintf(fullPath, FILENAME_MAX,
"%s/%s/Contents/Info.plist",
162 PCSCLITE_HP_DROPDIR, currFP->d_name);
163 fullPath[FILENAME_MAX - 1] =
'\0';
165 rv = bundleParse(fullPath, &plist);
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,
176 fullLibPath[
sizeof(fullLibPath) - 1] =
'\0';
178 GET_KEY(PCSCLITE_HP_CPCTKEY_NAME, &values)
179 GET_KEY(PCSCLITE_HP_MANUKEY_NAME, &manuIDs)
180 GET_KEY(PCSCLITE_HP_PRODKEY_NAME, &productIDs)
181 GET_KEY(PCSCLITE_HP_NAMEKEY_NAME, &readerNames)
184 for (alias=0; alias<list_size(manuIDs); alias++)
189 value = list_get_at(manuIDs, alias);
190 bundleTracker[listCount].manuID = strtol(value, NULL, 16);
192 value = list_get_at(productIDs, alias);
193 bundleTracker[listCount].productID = strtol(value, NULL, 16);
195 bundleTracker[listCount].readerName = strdup(list_get_at(readerNames, alias));
198 bundleTracker[listCount].bundleName = strdup(currFP->d_name);
199 bundleTracker[listCount].libraryPath = strdup(fullLibPath);
202 Log2(PCSC_LOG_INFO,
"Found driver for: %s",
203 bundleTracker[listCount].readerName);
207 if (listCount >= COUNT_OF(bundleTracker))
209 Log2(PCSC_LOG_CRITICAL,
"Too many readers declared. Maximum is %zd", COUNT_OF(bundleTracker));
213 bundleRelease(&plist);
218 bundleSize = listCount;
223 "No bundle files in pcsc drivers directory: " PCSCLITE_HP_DROPDIR);
224 Log1(PCSC_LOG_INFO,
"Disabling USB support for pcscd");
231 static void HPEstablishUSBNotifications(
void)
234 int i, j, usbDeviceStatus;
236 struct dirent *entry, *entryB;
238 int suspectDeviceNumber;
239 char dirpath[FILENAME_MAX];
240 char filename[FILENAME_MAX];
242 struct usb_device_descriptor usbDescriptor;
245 suspectDeviceNumber = 0;
249 for (i = 0; i < bundleSize; i++)
252 suspectDeviceNumber = 0;
256 bundleTracker[i].deviceNumber[j].status = 0;
259 dir = opendir(PCSCLITE_USB_PATH);
263 "Cannot open USB path directory: " PCSCLITE_USB_PATH);
268 while ((entry = readdir(dir)) != 0)
274 if (entry->d_name[0] ==
'.')
276 if (!strchr(
"0123456789",
277 entry->d_name[strlen(entry->d_name) - 1]))
282 snprintf(dirpath,
sizeof dirpath,
"%s/%s",
283 PCSCLITE_USB_PATH, entry->d_name);
285 dirB = opendir(dirpath);
290 "USB path seems to have disappeared %s", dirpath);
295 while ((entryB = readdir(dirB)) != NULL)
300 if (entryB->d_name[0] ==
'.')
305 snprintf(filename,
sizeof filename,
"%s/%s",
306 dirpath, entryB->d_name);
307 deviceNumber = atoi(entryB->d_name);
309 fd = open(filename, O_RDONLY);
313 ret = read(fd, (
void *) &usbDescriptor,
314 sizeof(usbDescriptor));
325 if (usbDescriptor.idVendor == bundleTracker[i].manuID &&
326 usbDescriptor.idProduct == bundleTracker[i].productID &&
327 usbDescriptor.idVendor !=0 &&
328 usbDescriptor.idProduct != 0)
332 if (bundleTracker[i].deviceNumber[j].
id == deviceNumber &&
333 bundleTracker[i].deviceNumber[j].
id != 0)
335 bundleTracker[i].deviceNumber[j].status = 1;
343 suspectDeviceNumber = deviceNumber;
354 if (usbDeviceStatus == 1)
356 pthread_mutex_lock(&usbNotifierMutex);
360 if (bundleTracker[i].deviceNumber[j].
id == 0)
366 "Too many identical readers plugged in");
369 HPAddHotPluggable(i, j+1);
370 bundleTracker[i].deviceNumber[j].id = suspectDeviceNumber;
373 pthread_mutex_unlock(&usbNotifierMutex);
376 if (usbDeviceStatus == 0)
381 if (bundleTracker[i].deviceNumber[j].
id != 0 &&
382 bundleTracker[i].deviceNumber[j].status == 0)
384 pthread_mutex_lock(&usbNotifierMutex);
385 HPRemoveHotPluggable(i, j+1);
386 bundleTracker[i].deviceNumber[j].id = 0;
387 pthread_mutex_unlock(&usbNotifierMutex);
408 Log1(PCSC_LOG_INFO,
"Hotplug stopped");
409 pthread_exit(&retval);
415 LONG HPSearchHotPluggables(
void)
421 bundleTracker[i].productID = 0;
422 bundleTracker[i].manuID = 0;
425 bundleTracker[i].deviceNumber[j].
id = 0;
428 if (HPReadBundleValues() > 0)
429 ThreadCreate(&usbNotifyThread, THREAD_ATTR_DETACHED,
430 (PCSCLITE_THREAD_FUNCTION( )) HPEstablishUSBNotifications, 0);
435 LONG HPStopHotPluggables(
void)
437 AraKiriHotPlug = TRUE;
442 static LONG HPAddHotPluggable(
int i,
unsigned long usbAddr)
446 RFAddReader(bundleTracker[i].readerName, PCSCLITE_HP_BASE_PORT + usbAddr,
447 bundleTracker[i].libraryPath,
"");
452 static LONG HPRemoveHotPluggable(
int i,
unsigned long usbAddr)
454 RFRemoveReader(bundleTracker[i].readerName, PCSCLITE_HP_BASE_PORT + usbAddr);
462 ULONG HPRegisterForHotplugEvents(
void)
464 (void)pthread_mutex_init(&usbNotifierMutex, NULL);
468 void HPReCheckSerialReaders(
void)
This handles abstract system level calls.
int SYS_Sleep(int)
Makes the current process sleep for some seconds.
Reads lexical config files and updates database.
#define PCSCLITE_MAX_READERS_CONTEXTS
Maximum readers context (a slot is count as a reader)
This defines some structures and #defines to be used over the transport layer.
This keeps a list of defines for pcsc-lite.
This keeps a list of defines for pcsc-lite.
This keeps track of a list of currently available reader structures.
This provides a search API for hot pluggble devices.