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",
299 driverBundle, 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 for (driver = driverBundle; driver->m_vendorId; ++driver)
516 if ((driver->m_vendorId == vendorId)
517 && (driver->m_productId == productId))
520 HPDeviceListInsert(*readerList, driver, usbAddress);
525 IOObjectRelease(usbIter);
534 HPDriversMatchPCCardDevices(HPDriver * driverBundle,
535 HPDeviceList * readerList)
537 CFDictionaryRef pccMatch = IOServiceMatching(
"IOPCCard16Device");
539 if (pccMatch == NULL)
542 "error getting PCCard match from IOServiceMatching()");
546 io_iterator_t pccIter;
548 IOServiceGetMatchingServices(kIOMasterPortDefault, pccMatch,
553 "error getting iterator from IOServiceGetMatchingServices()");
557 IOIteratorReset(pccIter);
558 io_object_t pccDevice = 0;
560 while ((pccDevice = IOIteratorNext(pccIter)))
564 kret = IORegistryEntryGetName(pccDevice, namebuf);
567 Log1(PCSC_LOG_ERROR,
"error getting plugin interface from IOCreatePlugInInterfaceForService()");
571 UInt32 productId = 0;
572 UInt32 pccAddress = 0;
574 IORegistryEntryCreateCFProperty(pccDevice, CFSTR(
"VendorID"),
575 kCFAllocatorDefault, 0);
579 Log1(PCSC_LOG_ERROR,
"error getting vendor");
583 CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type,
587 IORegistryEntryCreateCFProperty(pccDevice, CFSTR(
"DeviceID"),
588 kCFAllocatorDefault, 0);
591 Log1(PCSC_LOG_ERROR,
"error getting device");
595 CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type,
599 IORegistryEntryCreateCFProperty(pccDevice, CFSTR(
"SocketNumber"),
600 kCFAllocatorDefault, 0);
603 Log1(PCSC_LOG_ERROR,
"error getting PC Card socket");
607 CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type,
610 HPDriver *driver = driverBundle;
612 for (; driver->m_vendorId; ++driver)
614 if ((driver->m_vendorId == vendorId)
615 && (driver->m_productId == productId))
618 HPDeviceListInsert(*readerList, driver, pccAddress);
622 IOObjectRelease(pccIter);
627 static void HPEstablishUSBNotification(
void)
629 io_iterator_t deviceAddedIterator;
630 io_iterator_t deviceRemovedIterator;
631 CFMutableDictionaryRef matchingDictionary;
632 IONotificationPortRef notificationPort;
635 notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
636 CFRunLoopAddSource(CFRunLoopGetCurrent(),
637 IONotificationPortGetRunLoopSource(notificationPort),
638 kCFRunLoopDefaultMode);
640 matchingDictionary = IOServiceMatching(
"IOUSBDevice");
641 if (!matchingDictionary)
643 Log1(PCSC_LOG_ERROR,
"IOServiceMatching() failed");
646 (CFMutableDictionaryRef) CFRetain(matchingDictionary);
648 kret = IOServiceAddMatchingNotification(notificationPort,
649 kIOMatchedNotification,
650 matchingDictionary, HPDeviceAppeared, NULL, &deviceAddedIterator);
654 "IOServiceAddMatchingNotification()-1 failed with code %d", kret);
656 HPDeviceAppeared(NULL, deviceAddedIterator);
658 kret = IOServiceAddMatchingNotification(notificationPort,
659 kIOTerminatedNotification,
661 HPDeviceDisappeared, NULL, &deviceRemovedIterator);
665 "IOServiceAddMatchingNotification()-2 failed with code %d", kret);
667 HPDeviceDisappeared(NULL, deviceRemovedIterator);
670 static void HPEstablishPCCardNotification(
void)
672 io_iterator_t deviceAddedIterator;
673 io_iterator_t deviceRemovedIterator;
674 CFMutableDictionaryRef matchingDictionary;
675 IONotificationPortRef notificationPort;
678 notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
679 CFRunLoopAddSource(CFRunLoopGetCurrent(),
680 IONotificationPortGetRunLoopSource(notificationPort),
681 kCFRunLoopDefaultMode);
683 matchingDictionary = IOServiceMatching(
"IOPCCard16Device");
684 if (!matchingDictionary)
686 Log1(PCSC_LOG_ERROR,
"IOServiceMatching() failed");
689 (CFMutableDictionaryRef) CFRetain(matchingDictionary);
691 kret = IOServiceAddMatchingNotification(notificationPort,
692 kIOMatchedNotification,
693 matchingDictionary, HPDeviceAppeared, NULL, &deviceAddedIterator);
697 "IOServiceAddMatchingNotification()-1 failed with code %d", kret);
699 HPDeviceAppeared(NULL, deviceAddedIterator);
701 kret = IOServiceAddMatchingNotification(notificationPort,
702 kIOTerminatedNotification,
704 HPDeviceDisappeared, NULL, &deviceRemovedIterator);
708 "IOServiceAddMatchingNotification()-2 failed with code %d", kret);
710 HPDeviceDisappeared(NULL, deviceRemovedIterator);
716 static void HPDeviceNotificationThread(
void)
718 HPEstablishUSBNotification();
719 HPEstablishPCCardNotification();
728 LONG HPSearchHotPluggables(
void)
730 HPDriver *drivers = HPDriversGetFromDirectory(PCSCLITE_HP_DROPDIR);
735 HPDeviceList devices = NULL;
737 if (HPDriversMatchUSBDevices(drivers, &devices))
740 if (HPDriversMatchPCCardDevices(drivers, &devices))
745 for (a = devices; a; a = a->m_next)
750 for (b = sDeviceList; b; b = b->m_next)
752 if (HPDeviceEquals(a, b))
760 char deviceName[MAX_DEVICENAME];
764 snprintf(deviceName,
sizeof(deviceName),
765 "%s", a->m_driver->m_friendlyName);
766 deviceName[
sizeof(deviceName)-1] =
'\0';
768 RFAddReader(a->m_driver->m_friendlyName,
769 PCSCLITE_HP_BASE_PORT + a->m_address, a->m_driver->m_libPath,
774 for (a = sDeviceList; a; a = a->m_next)
779 for (b = devices; b; b = b->m_next)
781 if (HPDeviceEquals(a, b))
789 RFRemoveReader(a->m_driver->m_friendlyName,
790 PCSCLITE_HP_BASE_PORT + a->m_address);
794 HPDeviceListRelease(sDeviceList);
795 sDeviceList = devices;
796 HPDriverVectorRelease(drivers);
802 pthread_t sHotplugWatcherThread;
807 ULONG HPRegisterForHotplugEvents(
void)
809 ThreadCreate(&sHotplugWatcherThread,
811 (PCSCLITE_THREAD_FUNCTION( )) HPDeviceNotificationThread, NULL);
816 LONG HPStopHotPluggables(
void)
821 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.