51 #if defined(__APPLE__) && !defined(HAVE_LIBUSB) 52 #include <CoreFoundation/CoreFoundation.h> 53 #include <IOKit/IOCFPlugIn.h> 54 #include <IOKit/IOKitLib.h> 55 #include <IOKit/usb/IOUSBLib.h> 72 typedef struct HPDriver
78 } HPDriver, *HPDriverVector;
83 typedef struct HPDevice
87 struct HPDevice *m_next;
88 } HPDevice, *HPDeviceList;
94 static HPDeviceList sDeviceList = NULL;
100 static void HPDeviceAppeared(
void *refCon, io_iterator_t iterator)
107 while ((obj = IOIteratorNext(iterator)))
108 kret = IOObjectRelease(obj);
110 HPSearchHotPluggables();
117 static void HPDeviceDisappeared(
void *refCon, io_iterator_t iterator)
124 while ((obj = IOIteratorNext(iterator)))
125 kret = IOObjectRelease(obj);
127 HPSearchHotPluggables();
139 static HPDriverVector HPDriversGetFromDirectory(
const char *driverBundlePath)
142 Log2(PCSC_LOG_DEBUG,
"Entering HPDriversGetFromDirectory: %s",
146 int readersNumber = 0;
147 HPDriverVector bundleVector = NULL;
148 CFArrayRef bundleArray;
149 CFStringRef driverBundlePathString =
150 CFStringCreateWithCString(kCFAllocatorDefault,
152 kCFStringEncodingMacRoman);
153 CFURLRef pluginUrl = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
154 driverBundlePathString,
155 kCFURLPOSIXPathStyle, TRUE);
157 CFRelease(driverBundlePathString);
160 Log1(PCSC_LOG_ERROR,
"error getting plugin directory URL");
163 bundleArray = CFBundleCreateBundlesFromDirectory(kCFAllocatorDefault,
167 Log1(PCSC_LOG_ERROR,
"error getting plugin directory bundles");
170 CFRelease(pluginUrl);
172 size_t bundleArraySize = CFArrayGetCount(bundleArray);
176 for (i = 0; i < bundleArraySize; i++)
178 CFBundleRef currBundle =
179 (CFBundleRef) CFArrayGetValueAtIndex(bundleArray, i);
180 CFDictionaryRef dict = CFBundleGetInfoDictionary(currBundle);
182 const void * blobValue = CFDictionaryGetValue(dict,
183 CFSTR(PCSCLITE_HP_MANUKEY_NAME));
187 Log1(PCSC_LOG_ERROR,
"error getting vendor ID from bundle");
191 if (CFGetTypeID(blobValue) == CFArrayGetTypeID())
194 CFArrayRef propertyArray = blobValue;
195 readersNumber += CFArrayGetCount(propertyArray);
202 Log2(PCSC_LOG_DEBUG,
"Total of %d readers supported", readersNumber);
210 bundleVector = calloc(readersNumber,
sizeof(HPDriver));
213 Log1(PCSC_LOG_ERROR,
"memory allocation failure");
217 HPDriver *driverBundle = bundleVector;
218 for (i = 0; i < bundleArraySize; i++)
220 CFBundleRef currBundle =
221 (CFBundleRef) CFArrayGetValueAtIndex(bundleArray, i);
222 CFDictionaryRef dict = CFBundleGetInfoDictionary(currBundle);
224 CFURLRef bundleUrl = CFBundleCopyBundleURL(currBundle);
225 CFStringRef bundlePath = CFURLCopyPath(bundleUrl);
227 driverBundle->m_libPath = strdup(CFStringGetCStringPtr(bundlePath,
228 CFStringGetSystemEncoding()));
230 const void * blobValue = CFDictionaryGetValue(dict,
231 CFSTR(PCSCLITE_HP_MANUKEY_NAME));
235 Log1(PCSC_LOG_ERROR,
"error getting vendor ID from bundle");
239 if (CFGetTypeID(blobValue) == CFArrayGetTypeID())
241 CFArrayRef vendorArray = blobValue;
242 CFArrayRef productArray;
243 CFArrayRef friendlyNameArray;
244 char *libPath = driverBundle->m_libPath;
247 Log2(PCSC_LOG_DEBUG,
"Driver with aliases: %s", libPath);
250 productArray = CFDictionaryGetValue(dict,
251 CFSTR(PCSCLITE_HP_PRODKEY_NAME));
254 Log1(PCSC_LOG_ERROR,
"error getting product ID from bundle");
259 friendlyNameArray = CFDictionaryGetValue(dict,
260 CFSTR(PCSCLITE_HP_NAMEKEY_NAME));
261 if (!friendlyNameArray)
263 Log1(PCSC_LOG_ERROR,
"error getting product ID from bundle");
267 int reader_nb = CFArrayGetCount(vendorArray);
269 if (reader_nb != CFArrayGetCount(productArray))
272 "Malformed Info.plist: %d vendors and %ld products",
273 reader_nb, CFArrayGetCount(productArray));
277 if (reader_nb != CFArrayGetCount(friendlyNameArray))
280 "Malformed Info.plist: %d vendors and %ld friendlynames",
281 reader_nb, CFArrayGetCount(friendlyNameArray));
286 for (j=0; j<reader_nb; j++)
288 CFStringRef strValue = CFArrayGetValueAtIndex(vendorArray, j);
290 driverBundle->m_vendorId = strtoul(CFStringGetCStringPtr(strValue,
291 CFStringGetSystemEncoding()), NULL, 16);
293 strValue = CFArrayGetValueAtIndex(productArray, j);
294 driverBundle->m_productId = strtoul(CFStringGetCStringPtr(strValue,
295 CFStringGetSystemEncoding()), NULL, 16);
297 strValue = CFArrayGetValueAtIndex(friendlyNameArray, j);
298 const char *cstr = CFStringGetCStringPtr(strValue,
299 CFStringGetSystemEncoding());
301 driverBundle->m_friendlyName = strdup(cstr);
302 if (!driverBundle->m_libPath)
303 driverBundle->m_libPath = strdup(libPath);
306 Log2(PCSC_LOG_DEBUG,
"VendorID: 0x%04X",
307 driverBundle->m_vendorId);
308 Log2(PCSC_LOG_DEBUG,
"ProductID: 0x%04X",
309 driverBundle->m_productId);
310 Log2(PCSC_LOG_DEBUG,
"Friendly name: %s",
311 driverBundle->m_friendlyName);
312 Log2(PCSC_LOG_DEBUG,
"Driver: %s", driverBundle->m_libPath);
321 CFStringRef strValue = blobValue;
324 Log3(PCSC_LOG_DEBUG,
"Driver without alias: %s %s",
325 driverBundle->m_friendlyName, driverBundle->m_libPath);
328 driverBundle->m_vendorId = strtoul(CFStringGetCStringPtr(strValue,
329 CFStringGetSystemEncoding()), NULL, 16);
331 strValue = (CFStringRef) CFDictionaryGetValue(dict,
332 CFSTR(PCSCLITE_HP_PRODKEY_NAME));
335 Log1(PCSC_LOG_ERROR,
"error getting product ID from bundle");
338 driverBundle->m_productId = strtoul(CFStringGetCStringPtr(strValue,
339 CFStringGetSystemEncoding()), NULL, 16);
341 strValue = (CFStringRef) CFDictionaryGetValue(dict,
342 CFSTR(PCSCLITE_HP_NAMEKEY_NAME));
345 Log1(PCSC_LOG_ERROR,
"error getting product friendly name from bundle");
346 driverBundle->m_friendlyName = strdup(
"unnamed device");
350 const char *cstr = CFStringGetCStringPtr(strValue,
351 CFStringGetSystemEncoding());
353 driverBundle->m_friendlyName = strdup(cstr);
356 Log2(PCSC_LOG_DEBUG,
"VendorID: 0x%04X", driverBundle->m_vendorId);
357 Log2(PCSC_LOG_DEBUG,
"ProductID: 0x%04X", driverBundle->m_productId);
358 Log2(PCSC_LOG_DEBUG,
"Friendly name: %s", driverBundle->m_friendlyName);
359 Log2(PCSC_LOG_DEBUG,
"Driver: %s", driverBundle->m_libPath);
366 CFRelease(bundleArray);
373 static HPDriver *HPDriverCopy(HPDriver * rhs)
378 HPDriver *newDriverBundle = calloc(1,
sizeof(HPDriver));
380 if (!newDriverBundle)
383 newDriverBundle->m_vendorId = rhs->m_vendorId;
384 newDriverBundle->m_productId = rhs->m_productId;
385 newDriverBundle->m_friendlyName = strdup(rhs->m_friendlyName);
386 newDriverBundle->m_libPath = strdup(rhs->m_libPath);
388 return newDriverBundle;
394 static void HPDriverRelease(HPDriver * driverBundle)
398 free(driverBundle->m_friendlyName);
399 free(driverBundle->m_libPath);
406 static void HPDriverVectorRelease(HPDriverVector driverBundleVector)
408 if (driverBundleVector)
412 for (b = driverBundleVector; b->m_vendorId; ++b)
415 free(driverBundleVector);
423 HPDeviceListInsert(HPDeviceList list, HPDriver * bundle, UInt32 address)
425 HPDevice *newReader = calloc(1,
sizeof(HPDevice));
429 Log1(PCSC_LOG_ERROR,
"memory allocation failure");
433 newReader->m_driver = HPDriverCopy(bundle);
434 newReader->m_address = address;
435 newReader->m_next = list;
443 static void HPDeviceListRelease(HPDeviceList list)
447 for (p = list; p; p = p->m_next)
448 HPDriverRelease(p->m_driver);
454 static int HPDeviceEquals(HPDevice * a, HPDevice * b)
456 return (a->m_driver->m_vendorId == b->m_driver->m_vendorId)
457 && (a->m_driver->m_productId == b->m_driver->m_productId)
458 && (a->m_address == b->m_address);
466 HPDriversMatchUSBDevices(HPDriverVector driverBundle,
467 HPDeviceList * readerList)
469 CFDictionaryRef usbMatch = IOServiceMatching(
"IOUSBDevice");
474 "error getting USB match from IOServiceMatching()");
478 io_iterator_t usbIter;
479 kern_return_t kret = IOServiceGetMatchingServices(kIOMasterPortDefault,
485 "error getting iterator from IOServiceGetMatchingServices()");
489 IOIteratorReset(usbIter);
490 io_object_t usbDevice = 0;
492 while ((usbDevice = IOIteratorNext(usbIter)))
496 kret = IORegistryEntryGetName(usbDevice, namebuf);
500 "error getting device name from IORegistryEntryGetName()");
504 IOCFPlugInInterface **iodev;
507 kret = IOCreatePlugInInterfaceForService(usbDevice,
508 kIOUSBDeviceUserClientTypeID,
509 kIOCFPlugInInterfaceID, &iodev, &score);
512 Log1(PCSC_LOG_ERROR,
"error getting plugin interface from IOCreatePlugInInterfaceForService()");
515 IOObjectRelease(usbDevice);
517 IOUSBDeviceInterface **usbdev;
518 HRESULT hres = (*iodev)->QueryInterface(iodev,
519 CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),
520 (LPVOID *) & usbdev);
522 (*iodev)->Release(iodev);
526 "error querying interface in QueryInterface()");
531 UInt16 productId = 0;
532 UInt32 usbAddress = 0;
534 kret = (*usbdev)->GetDeviceVendor(usbdev, &vendorId);
535 kret = (*usbdev)->GetDeviceProduct(usbdev, &productId);
536 kret = (*usbdev)->GetLocationID(usbdev, &usbAddress);
537 (*usbdev)->Release(usbdev);
540 Log4(PCSC_LOG_DEBUG,
"Found USB device 0x%04X:0x%04X at 0x%X",
541 vendorId, productId, usbAddress);
544 for (driver = driverBundle; driver->m_vendorId; ++driver)
546 if ((driver->m_vendorId == vendorId)
547 && (driver->m_productId == productId))
550 Log4(PCSC_LOG_DEBUG,
"Adding USB device %04X:%04X at 0x%X",
551 vendorId, productId, usbAddress);
554 HPDeviceListInsert(*readerList, driver, usbAddress);
559 IOObjectRelease(usbIter);
568 HPDriversMatchPCCardDevices(HPDriver * driverBundle,
569 HPDeviceList * readerList)
571 CFDictionaryRef pccMatch = IOServiceMatching(
"IOPCCard16Device");
573 if (pccMatch == NULL)
576 "error getting PCCard match from IOServiceMatching()");
580 io_iterator_t pccIter;
582 IOServiceGetMatchingServices(kIOMasterPortDefault, pccMatch,
587 "error getting iterator from IOServiceGetMatchingServices()");
591 IOIteratorReset(pccIter);
592 io_object_t pccDevice = 0;
594 while ((pccDevice = IOIteratorNext(pccIter)))
598 kret = IORegistryEntryGetName(pccDevice, namebuf);
601 Log1(PCSC_LOG_ERROR,
"error getting plugin interface from IOCreatePlugInInterfaceForService()");
605 UInt32 productId = 0;
606 UInt32 pccAddress = 0;
608 IORegistryEntryCreateCFProperty(pccDevice, CFSTR(
"VendorID"),
609 kCFAllocatorDefault, 0);
613 Log1(PCSC_LOG_ERROR,
"error getting vendor");
617 CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type,
621 IORegistryEntryCreateCFProperty(pccDevice, CFSTR(
"DeviceID"),
622 kCFAllocatorDefault, 0);
625 Log1(PCSC_LOG_ERROR,
"error getting device");
629 CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type,
633 IORegistryEntryCreateCFProperty(pccDevice, CFSTR(
"SocketNumber"),
634 kCFAllocatorDefault, 0);
637 Log1(PCSC_LOG_ERROR,
"error getting PC Card socket");
641 CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type,
644 HPDriver *driver = driverBundle;
646 for (; driver->m_vendorId; ++driver)
648 if ((driver->m_vendorId == vendorId)
649 && (driver->m_productId == productId))
652 HPDeviceListInsert(*readerList, driver, pccAddress);
656 IOObjectRelease(pccIter);
661 static void HPEstablishUSBNotification(
void)
663 io_iterator_t deviceAddedIterator;
664 io_iterator_t deviceRemovedIterator;
665 CFMutableDictionaryRef matchingDictionary;
666 IONotificationPortRef notificationPort;
669 notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
670 CFRunLoopAddSource(CFRunLoopGetCurrent(),
671 IONotificationPortGetRunLoopSource(notificationPort),
672 kCFRunLoopDefaultMode);
674 matchingDictionary = IOServiceMatching(
"IOUSBDevice");
675 if (!matchingDictionary)
677 Log1(PCSC_LOG_ERROR,
"IOServiceMatching() failed");
680 (CFMutableDictionaryRef) CFRetain(matchingDictionary);
682 kret = IOServiceAddMatchingNotification(notificationPort,
683 kIOMatchedNotification,
684 matchingDictionary, HPDeviceAppeared, NULL, &deviceAddedIterator);
688 "IOServiceAddMatchingNotification()-1 failed with code %d", kret);
690 HPDeviceAppeared(NULL, deviceAddedIterator);
692 kret = IOServiceAddMatchingNotification(notificationPort,
693 kIOTerminatedNotification,
695 HPDeviceDisappeared, NULL, &deviceRemovedIterator);
699 "IOServiceAddMatchingNotification()-2 failed with code %d", kret);
701 HPDeviceDisappeared(NULL, deviceRemovedIterator);
704 static void HPEstablishPCCardNotification(
void)
706 io_iterator_t deviceAddedIterator;
707 io_iterator_t deviceRemovedIterator;
708 CFMutableDictionaryRef matchingDictionary;
709 IONotificationPortRef notificationPort;
712 notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
713 CFRunLoopAddSource(CFRunLoopGetCurrent(),
714 IONotificationPortGetRunLoopSource(notificationPort),
715 kCFRunLoopDefaultMode);
717 matchingDictionary = IOServiceMatching(
"IOPCCard16Device");
718 if (!matchingDictionary)
720 Log1(PCSC_LOG_ERROR,
"IOServiceMatching() failed");
723 (CFMutableDictionaryRef) CFRetain(matchingDictionary);
725 kret = IOServiceAddMatchingNotification(notificationPort,
726 kIOMatchedNotification,
727 matchingDictionary, HPDeviceAppeared, NULL, &deviceAddedIterator);
731 "IOServiceAddMatchingNotification()-1 failed with code %d", kret);
733 HPDeviceAppeared(NULL, deviceAddedIterator);
735 kret = IOServiceAddMatchingNotification(notificationPort,
736 kIOTerminatedNotification,
738 HPDeviceDisappeared, NULL, &deviceRemovedIterator);
742 "IOServiceAddMatchingNotification()-2 failed with code %d", kret);
744 HPDeviceDisappeared(NULL, deviceRemovedIterator);
750 static void HPDeviceNotificationThread(
void)
752 HPEstablishUSBNotification();
753 HPEstablishPCCardNotification();
762 LONG HPSearchHotPluggables(
void)
764 HPDriver *drivers = HPDriversGetFromDirectory(PCSCLITE_HP_DROPDIR);
769 HPDeviceList devices = NULL;
771 if (HPDriversMatchUSBDevices(drivers, &devices))
774 if (HPDriversMatchPCCardDevices(drivers, &devices))
779 for (a = devices; a; a = a->m_next)
784 for (b = sDeviceList; b; b = b->m_next)
786 if (HPDeviceEquals(a, b))
794 char deviceName[MAX_DEVICENAME];
798 snprintf(deviceName,
sizeof(deviceName),
799 "%s", a->m_driver->m_friendlyName);
800 deviceName[
sizeof(deviceName)-1] =
'\0';
802 RFAddReader(a->m_driver->m_friendlyName,
803 PCSCLITE_HP_BASE_PORT + a->m_address, a->m_driver->m_libPath,
808 for (a = sDeviceList; a; a = a->m_next)
813 for (b = devices; b; b = b->m_next)
815 if (HPDeviceEquals(a, b))
823 RFRemoveReader(a->m_driver->m_friendlyName,
824 PCSCLITE_HP_BASE_PORT + a->m_address);
828 HPDeviceListRelease(sDeviceList);
829 sDeviceList = devices;
830 HPDriverVectorRelease(drivers);
836 pthread_t sHotplugWatcherThread;
841 ULONG HPRegisterForHotplugEvents(
void)
843 ThreadCreate(&sHotplugWatcherThread,
845 (PCSCLITE_THREAD_FUNCTION( )) HPDeviceNotificationThread, NULL);
850 LONG HPStopHotPluggables(
void)
855 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.