25 #if defined(__APPLE__) && !defined(HAVE_LIBUSB)
26 #include <CoreFoundation/CoreFoundation.h>
27 #include <IOKit/IOCFPlugIn.h>
28 #include <IOKit/IOKitLib.h>
29 #include <IOKit/usb/IOUSBLib.h>
46 typedef struct HPDriver
52 } HPDriver, *HPDriverVector;
57 typedef struct HPDevice
61 struct HPDevice *m_next;
62 } HPDevice, *HPDeviceList;
68 static HPDeviceList sDeviceList = NULL;
74 static void HPDeviceAppeared(
void *refCon, io_iterator_t iterator)
81 while ((obj = IOIteratorNext(iterator)))
82 kret = IOObjectRelease(obj);
84 HPSearchHotPluggables();
91 static void HPDeviceDisappeared(
void *refCon, io_iterator_t iterator)
98 while ((obj = IOIteratorNext(iterator)))
99 kret = IOObjectRelease(obj);
101 HPSearchHotPluggables();
113 static HPDriverVector HPDriversGetFromDirectory(
const char *driverBundlePath)
116 Log2(PCSC_LOG_DEBUG,
"Entering HPDriversGetFromDirectory: %s",
120 int readersNumber = 0;
121 HPDriverVector bundleVector = NULL;
122 CFArrayRef bundleArray;
123 CFStringRef driverBundlePathString =
124 CFStringCreateWithCString(kCFAllocatorDefault,
126 kCFStringEncodingMacRoman);
127 CFURLRef pluginUrl = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
128 driverBundlePathString,
129 kCFURLPOSIXPathStyle, TRUE);
131 CFRelease(driverBundlePathString);
134 Log1(PCSC_LOG_ERROR,
"error getting plugin directory URL");
137 bundleArray = CFBundleCreateBundlesFromDirectory(kCFAllocatorDefault,
141 Log1(PCSC_LOG_ERROR,
"error getting plugin directory bundles");
144 CFRelease(pluginUrl);
146 size_t bundleArraySize = CFArrayGetCount(bundleArray);
150 for (i = 0; i < bundleArraySize; i++)
152 CFBundleRef currBundle =
153 (CFBundleRef) CFArrayGetValueAtIndex(bundleArray, i);
154 CFDictionaryRef dict = CFBundleGetInfoDictionary(currBundle);
156 const void * blobValue = CFDictionaryGetValue(dict,
157 CFSTR(PCSCLITE_HP_MANUKEY_NAME));
161 Log1(PCSC_LOG_ERROR,
"error getting vendor ID from bundle");
165 if (CFGetTypeID(blobValue) == CFArrayGetTypeID())
168 CFArrayRef propertyArray = blobValue;
169 readersNumber += CFArrayGetCount(propertyArray);
176 Log2(PCSC_LOG_DEBUG,
"Total of %d readers supported", readersNumber);
184 bundleVector = calloc(readersNumber,
sizeof(HPDriver));
187 Log1(PCSC_LOG_ERROR,
"memory allocation failure");
191 HPDriver *driverBundle = bundleVector;
192 for (i = 0; i < bundleArraySize; i++)
194 CFBundleRef currBundle =
195 (CFBundleRef) CFArrayGetValueAtIndex(bundleArray, i);
196 CFDictionaryRef dict = CFBundleGetInfoDictionary(currBundle);
198 CFURLRef bundleUrl = CFBundleCopyBundleURL(currBundle);
199 CFStringRef bundlePath = CFURLCopyPath(bundleUrl);
201 driverBundle->m_libPath = strdup(CFStringGetCStringPtr(bundlePath,
202 CFStringGetSystemEncoding()));
204 const void * blobValue = CFDictionaryGetValue(dict,
205 CFSTR(PCSCLITE_HP_MANUKEY_NAME));
209 Log1(PCSC_LOG_ERROR,
"error getting vendor ID from bundle");
213 if (CFGetTypeID(blobValue) == CFArrayGetTypeID())
215 CFArrayRef vendorArray = blobValue;
216 CFArrayRef productArray;
217 CFArrayRef friendlyNameArray;
218 char *libPath = driverBundle->m_libPath;
221 Log2(PCSC_LOG_DEBUG,
"Driver with aliases: %s", libPath);
224 productArray = CFDictionaryGetValue(dict,
225 CFSTR(PCSCLITE_HP_PRODKEY_NAME));
228 Log1(PCSC_LOG_ERROR,
"error getting product ID from bundle");
233 friendlyNameArray = CFDictionaryGetValue(dict,
234 CFSTR(PCSCLITE_HP_NAMEKEY_NAME));
235 if (!friendlyNameArray)
237 Log1(PCSC_LOG_ERROR,
"error getting product ID from bundle");
241 int reader_nb = CFArrayGetCount(vendorArray);
243 if (reader_nb != CFArrayGetCount(productArray))
246 "Malformed Info.plist: %d vendors and %ld products",
247 reader_nb, CFArrayGetCount(productArray));
251 if (reader_nb != CFArrayGetCount(friendlyNameArray))
254 "Malformed Info.plist: %d vendors and %ld friendlynames",
255 reader_nb, CFArrayGetCount(friendlyNameArray));
260 for (j=0; j<reader_nb; j++)
262 CFStringRef strValue = CFArrayGetValueAtIndex(vendorArray, j);
264 driverBundle->m_vendorId = strtoul(CFStringGetCStringPtr(strValue,
265 CFStringGetSystemEncoding()), NULL, 16);
267 strValue = CFArrayGetValueAtIndex(productArray, j);
268 driverBundle->m_productId = strtoul(CFStringGetCStringPtr(strValue,
269 CFStringGetSystemEncoding()), NULL, 16);
271 strValue = CFArrayGetValueAtIndex(friendlyNameArray, j);
272 const char *cstr = CFStringGetCStringPtr(strValue,
273 CFStringGetSystemEncoding());
275 driverBundle->m_friendlyName = strdup(cstr);
276 if (!driverBundle->m_libPath)
277 driverBundle->m_libPath = strdup(libPath);
280 Log2(PCSC_LOG_DEBUG,
"VendorID: 0x%04X",
281 driverBundle->m_vendorId);
282 Log2(PCSC_LOG_DEBUG,
"ProductID: 0x%04X",
283 driverBundle->m_productId);
284 Log2(PCSC_LOG_DEBUG,
"Friendly name: %s",
285 driverBundle->m_friendlyName);
286 Log2(PCSC_LOG_DEBUG,
"Driver: %s", driverBundle->m_libPath);
295 CFStringRef strValue = blobValue;
298 Log3(PCSC_LOG_DEBUG,
"Driver without alias: %s %s",
299 driverBundle->m_friendlyName, driverBundle->m_libPath);
302 driverBundle->m_vendorId = strtoul(CFStringGetCStringPtr(strValue,
303 CFStringGetSystemEncoding()), NULL, 16);
305 strValue = (CFStringRef) CFDictionaryGetValue(dict,
306 CFSTR(PCSCLITE_HP_PRODKEY_NAME));
309 Log1(PCSC_LOG_ERROR,
"error getting product ID from bundle");
312 driverBundle->m_productId = strtoul(CFStringGetCStringPtr(strValue,
313 CFStringGetSystemEncoding()), NULL, 16);
315 strValue = (CFStringRef) CFDictionaryGetValue(dict,
316 CFSTR(PCSCLITE_HP_NAMEKEY_NAME));
319 Log1(PCSC_LOG_ERROR,
"error getting product friendly name from bundle");
320 driverBundle->m_friendlyName = strdup(
"unnamed device");
324 const char *cstr = CFStringGetCStringPtr(strValue,
325 CFStringGetSystemEncoding());
327 driverBundle->m_friendlyName = strdup(cstr);
330 Log2(PCSC_LOG_DEBUG,
"VendorID: 0x%04X", driverBundle->m_vendorId);
331 Log2(PCSC_LOG_DEBUG,
"ProductID: 0x%04X", driverBundle->m_productId);
332 Log2(PCSC_LOG_DEBUG,
"Friendly name: %s", driverBundle->m_friendlyName);
333 Log2(PCSC_LOG_DEBUG,
"Driver: %s", driverBundle->m_libPath);
340 CFRelease(bundleArray);
347 static HPDriver *HPDriverCopy(HPDriver * rhs)
352 HPDriver *newDriverBundle = calloc(1,
sizeof(HPDriver));
354 if (!newDriverBundle)
357 newDriverBundle->m_vendorId = rhs->m_vendorId;
358 newDriverBundle->m_productId = rhs->m_productId;
359 newDriverBundle->m_friendlyName = strdup(rhs->m_friendlyName);
360 newDriverBundle->m_libPath = strdup(rhs->m_libPath);
362 return newDriverBundle;
368 static void HPDriverRelease(HPDriver * driverBundle)
372 free(driverBundle->m_friendlyName);
373 free(driverBundle->m_libPath);
380 static void HPDriverVectorRelease(HPDriverVector driverBundleVector)
382 if (driverBundleVector)
386 for (b = driverBundleVector; b->m_vendorId; ++b)
389 free(driverBundleVector);
397 HPDeviceListInsert(HPDeviceList list, HPDriver * bundle, UInt32 address)
399 HPDevice *newReader = calloc(1,
sizeof(HPDevice));
403 Log1(PCSC_LOG_ERROR,
"memory allocation failure");
407 newReader->m_driver = HPDriverCopy(bundle);
408 newReader->m_address = address;
409 newReader->m_next = list;
417 static void HPDeviceListRelease(HPDeviceList list)
421 for (p = list; p; p = p->m_next)
422 HPDriverRelease(p->m_driver);
428 static int HPDeviceEquals(HPDevice * a, HPDevice * b)
430 return (a->m_driver->m_vendorId == b->m_driver->m_vendorId)
431 && (a->m_driver->m_productId == b->m_driver->m_productId)
432 && (a->m_address == b->m_address);
440 HPDriversMatchUSBDevices(HPDriverVector driverBundle,
441 HPDeviceList * readerList)
443 CFDictionaryRef usbMatch = IOServiceMatching(
"IOUSBDevice");
448 "error getting USB match from IOServiceMatching()");
452 io_iterator_t usbIter;
453 kern_return_t kret = IOServiceGetMatchingServices(kIOMasterPortDefault,
459 "error getting iterator from IOServiceGetMatchingServices()");
463 IOIteratorReset(usbIter);
464 io_object_t usbDevice = 0;
466 while ((usbDevice = IOIteratorNext(usbIter)))
470 kret = IORegistryEntryGetName(usbDevice, namebuf);
474 "error getting device name from IORegistryEntryGetName()");
478 IOCFPlugInInterface **iodev;
481 kret = IOCreatePlugInInterfaceForService(usbDevice,
482 kIOUSBDeviceUserClientTypeID,
483 kIOCFPlugInInterfaceID, &iodev, &score);
486 Log1(PCSC_LOG_ERROR,
"error getting plugin interface from IOCreatePlugInInterfaceForService()");
489 IOObjectRelease(usbDevice);
491 IOUSBDeviceInterface **usbdev;
492 HRESULT hres = (*iodev)->QueryInterface(iodev,
493 CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),
494 (LPVOID *) & usbdev);
496 (*iodev)->Release(iodev);
500 "error querying interface in QueryInterface()");
505 UInt16 productId = 0;
506 UInt32 usbAddress = 0;
508 kret = (*usbdev)->GetDeviceVendor(usbdev, &vendorId);
509 kret = (*usbdev)->GetDeviceProduct(usbdev, &productId);
510 kret = (*usbdev)->GetLocationID(usbdev, &usbAddress);
511 (*usbdev)->Release(usbdev);
514 Log4(PCSC_LOG_DEBUG,
"Found USB device 0x%04X:0x%04X at 0x%X",
515 vendorId, productId, usbAddress);
518 for (driver = driverBundle; driver->m_vendorId; ++driver)
520 if ((driver->m_vendorId == vendorId)
521 && (driver->m_productId == productId))
524 Log4(PCSC_LOG_DEBUG,
"Adding USB device %04X:%04X at 0x%X",
525 vendorId, productId, usbAddress);
528 HPDeviceListInsert(*readerList, driver, usbAddress);
533 IOObjectRelease(usbIter);
542 HPDriversMatchPCCardDevices(HPDriver * driverBundle,
543 HPDeviceList * readerList)
545 CFDictionaryRef pccMatch = IOServiceMatching(
"IOPCCard16Device");
547 if (pccMatch == NULL)
550 "error getting PCCard match from IOServiceMatching()");
554 io_iterator_t pccIter;
556 IOServiceGetMatchingServices(kIOMasterPortDefault, pccMatch,
561 "error getting iterator from IOServiceGetMatchingServices()");
565 IOIteratorReset(pccIter);
566 io_object_t pccDevice = 0;
568 while ((pccDevice = IOIteratorNext(pccIter)))
572 kret = IORegistryEntryGetName(pccDevice, namebuf);
575 Log1(PCSC_LOG_ERROR,
"error getting plugin interface from IOCreatePlugInInterfaceForService()");
579 UInt32 productId = 0;
580 UInt32 pccAddress = 0;
582 IORegistryEntryCreateCFProperty(pccDevice, CFSTR(
"VendorID"),
583 kCFAllocatorDefault, 0);
587 Log1(PCSC_LOG_ERROR,
"error getting vendor");
591 CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type,
595 IORegistryEntryCreateCFProperty(pccDevice, CFSTR(
"DeviceID"),
596 kCFAllocatorDefault, 0);
599 Log1(PCSC_LOG_ERROR,
"error getting device");
603 CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type,
607 IORegistryEntryCreateCFProperty(pccDevice, CFSTR(
"SocketNumber"),
608 kCFAllocatorDefault, 0);
611 Log1(PCSC_LOG_ERROR,
"error getting PC Card socket");
615 CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type,
618 HPDriver *driver = driverBundle;
620 for (; driver->m_vendorId; ++driver)
622 if ((driver->m_vendorId == vendorId)
623 && (driver->m_productId == productId))
626 HPDeviceListInsert(*readerList, driver, pccAddress);
630 IOObjectRelease(pccIter);
635 static void HPEstablishUSBNotification(
void)
637 io_iterator_t deviceAddedIterator;
638 io_iterator_t deviceRemovedIterator;
639 CFMutableDictionaryRef matchingDictionary;
640 IONotificationPortRef notificationPort;
643 notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
644 CFRunLoopAddSource(CFRunLoopGetCurrent(),
645 IONotificationPortGetRunLoopSource(notificationPort),
646 kCFRunLoopDefaultMode);
648 matchingDictionary = IOServiceMatching(
"IOUSBDevice");
649 if (!matchingDictionary)
651 Log1(PCSC_LOG_ERROR,
"IOServiceMatching() failed");
654 (CFMutableDictionaryRef) CFRetain(matchingDictionary);
656 kret = IOServiceAddMatchingNotification(notificationPort,
657 kIOMatchedNotification,
658 matchingDictionary, HPDeviceAppeared, NULL, &deviceAddedIterator);
662 "IOServiceAddMatchingNotification()-1 failed with code %d", kret);
664 HPDeviceAppeared(NULL, deviceAddedIterator);
666 kret = IOServiceAddMatchingNotification(notificationPort,
667 kIOTerminatedNotification,
669 HPDeviceDisappeared, NULL, &deviceRemovedIterator);
673 "IOServiceAddMatchingNotification()-2 failed with code %d", kret);
675 HPDeviceDisappeared(NULL, deviceRemovedIterator);
678 static void HPEstablishPCCardNotification(
void)
680 io_iterator_t deviceAddedIterator;
681 io_iterator_t deviceRemovedIterator;
682 CFMutableDictionaryRef matchingDictionary;
683 IONotificationPortRef notificationPort;
686 notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
687 CFRunLoopAddSource(CFRunLoopGetCurrent(),
688 IONotificationPortGetRunLoopSource(notificationPort),
689 kCFRunLoopDefaultMode);
691 matchingDictionary = IOServiceMatching(
"IOPCCard16Device");
692 if (!matchingDictionary)
694 Log1(PCSC_LOG_ERROR,
"IOServiceMatching() failed");
697 (CFMutableDictionaryRef) CFRetain(matchingDictionary);
699 kret = IOServiceAddMatchingNotification(notificationPort,
700 kIOMatchedNotification,
701 matchingDictionary, HPDeviceAppeared, NULL, &deviceAddedIterator);
705 "IOServiceAddMatchingNotification()-1 failed with code %d", kret);
707 HPDeviceAppeared(NULL, deviceAddedIterator);
709 kret = IOServiceAddMatchingNotification(notificationPort,
710 kIOTerminatedNotification,
712 HPDeviceDisappeared, NULL, &deviceRemovedIterator);
716 "IOServiceAddMatchingNotification()-2 failed with code %d", kret);
718 HPDeviceDisappeared(NULL, deviceRemovedIterator);
724 static void HPDeviceNotificationThread(
void)
726 HPEstablishUSBNotification();
727 HPEstablishPCCardNotification();
736 LONG HPSearchHotPluggables(
void)
738 HPDriver *drivers = HPDriversGetFromDirectory(PCSCLITE_HP_DROPDIR);
743 HPDeviceList devices = NULL;
745 if (HPDriversMatchUSBDevices(drivers, &devices))
748 if (HPDriversMatchPCCardDevices(drivers, &devices))
753 for (a = devices; a; a = a->m_next)
758 for (b = sDeviceList; b; b = b->m_next)
760 if (HPDeviceEquals(a, b))
768 char deviceName[MAX_DEVICENAME];
772 snprintf(deviceName,
sizeof(deviceName),
773 "%s", a->m_driver->m_friendlyName);
774 deviceName[
sizeof(deviceName)-1] =
'\0';
776 RFAddReader(a->m_driver->m_friendlyName,
777 PCSCLITE_HP_BASE_PORT + a->m_address, a->m_driver->m_libPath,
782 for (a = sDeviceList; a; a = a->m_next)
787 for (b = devices; b; b = b->m_next)
789 if (HPDeviceEquals(a, b))
797 RFRemoveReader(a->m_driver->m_friendlyName,
798 PCSCLITE_HP_BASE_PORT + a->m_address);
802 HPDeviceListRelease(sDeviceList);
803 sDeviceList = devices;
804 HPDriverVectorRelease(drivers);
810 pthread_t sHotplugWatcherThread;
815 ULONG HPRegisterForHotplugEvents(
void)
817 ThreadCreate(&sHotplugWatcherThread,
819 (PCSCLITE_THREAD_FUNCTION( )) HPDeviceNotificationThread, NULL);
824 LONG HPStopHotPluggables(
void)
829 void HPReCheckSerialReaders(
void)
Reads lexical config files and updates database.
This defines some structures and #defines to be used over the transport layer.
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.