48 #if defined(__APPLE__) && !defined(HAVE_LIBUSB)
49 #include <CoreFoundation/CoreFoundation.h>
50 #include <IOKit/IOCFPlugIn.h>
51 #include <IOKit/IOKitLib.h>
52 #include <IOKit/usb/IOUSBLib.h>
69 typedef struct HPDriver
75 } HPDriver, *HPDriverVector;
80 typedef struct HPDevice
84 struct HPDevice *m_next;
85 } HPDevice, *HPDeviceList;
91 static HPDeviceList sDeviceList = NULL;
97 static void HPDeviceAppeared(
void *refCon, io_iterator_t iterator)
104 while ((obj = IOIteratorNext(iterator)))
105 kret = IOObjectRelease(obj);
107 HPSearchHotPluggables();
114 static void HPDeviceDisappeared(
void *refCon, io_iterator_t iterator)
121 while ((obj = IOIteratorNext(iterator)))
122 kret = IOObjectRelease(obj);
124 HPSearchHotPluggables();
136 static HPDriverVector HPDriversGetFromDirectory(
const char *driverBundlePath)
139 Log2(PCSC_LOG_DEBUG,
"Entering HPDriversGetFromDirectory: %s",
143 int readersNumber = 0;
144 HPDriverVector bundleVector = NULL;
145 CFArrayRef bundleArray;
146 CFStringRef driverBundlePathString =
147 CFStringCreateWithCString(kCFAllocatorDefault,
149 kCFStringEncodingMacRoman);
150 CFURLRef pluginUrl = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
151 driverBundlePathString,
152 kCFURLPOSIXPathStyle, TRUE);
154 CFRelease(driverBundlePathString);
157 Log1(PCSC_LOG_ERROR,
"error getting plugin directory URL");
160 bundleArray = CFBundleCreateBundlesFromDirectory(kCFAllocatorDefault,
164 Log1(PCSC_LOG_ERROR,
"error getting plugin directory bundles");
167 CFRelease(pluginUrl);
169 size_t bundleArraySize = CFArrayGetCount(bundleArray);
173 for (i = 0; i < bundleArraySize; i++)
175 CFBundleRef currBundle =
176 (CFBundleRef) CFArrayGetValueAtIndex(bundleArray, i);
177 CFDictionaryRef dict = CFBundleGetInfoDictionary(currBundle);
179 const void * blobValue = CFDictionaryGetValue(dict,
180 CFSTR(PCSCLITE_HP_MANUKEY_NAME));
184 Log1(PCSC_LOG_ERROR,
"error getting vendor ID from bundle");
188 if (CFGetTypeID(blobValue) == CFArrayGetTypeID())
191 CFArrayRef propertyArray = blobValue;
192 readersNumber += CFArrayGetCount(propertyArray);
199 Log2(PCSC_LOG_DEBUG,
"Total of %d readers supported", readersNumber);
207 bundleVector = calloc(readersNumber,
sizeof(HPDriver));
210 Log1(PCSC_LOG_ERROR,
"memory allocation failure");
214 HPDriver *driverBundle = bundleVector;
215 for (i = 0; i < bundleArraySize; i++)
217 CFBundleRef currBundle =
218 (CFBundleRef) CFArrayGetValueAtIndex(bundleArray, i);
219 CFDictionaryRef dict = CFBundleGetInfoDictionary(currBundle);
221 CFURLRef bundleUrl = CFBundleCopyBundleURL(currBundle);
222 CFStringRef bundlePath = CFURLCopyPath(bundleUrl);
224 driverBundle->m_libPath = strdup(CFStringGetCStringPtr(bundlePath,
225 CFStringGetSystemEncoding()));
227 const void * blobValue = CFDictionaryGetValue(dict,
228 CFSTR(PCSCLITE_HP_MANUKEY_NAME));
232 Log1(PCSC_LOG_ERROR,
"error getting vendor ID from bundle");
236 if (CFGetTypeID(blobValue) == CFArrayGetTypeID())
238 CFArrayRef vendorArray = blobValue;
239 CFArrayRef productArray;
240 CFArrayRef friendlyNameArray;
241 char *libPath = driverBundle->m_libPath;
244 Log2(PCSC_LOG_DEBUG,
"Driver with aliases: %s", libPath);
247 productArray = CFDictionaryGetValue(dict,
248 CFSTR(PCSCLITE_HP_PRODKEY_NAME));
251 Log1(PCSC_LOG_ERROR,
"error getting product ID from bundle");
256 friendlyNameArray = CFDictionaryGetValue(dict,
257 CFSTR(PCSCLITE_HP_NAMEKEY_NAME));
258 if (!friendlyNameArray)
260 Log1(PCSC_LOG_ERROR,
"error getting product ID from bundle");
264 int reader_nb = CFArrayGetCount(vendorArray);
266 if (reader_nb != CFArrayGetCount(productArray))
269 "Malformed Info.plist: %d vendors and %ld products",
270 reader_nb, CFArrayGetCount(productArray));
274 if (reader_nb != CFArrayGetCount(friendlyNameArray))
277 "Malformed Info.plist: %d vendors and %ld friendlynames",
278 reader_nb, CFArrayGetCount(friendlyNameArray));
283 for (j=0; j<reader_nb; j++)
285 CFStringRef strValue = CFArrayGetValueAtIndex(vendorArray, j);
287 driverBundle->m_vendorId = strtoul(CFStringGetCStringPtr(strValue,
288 CFStringGetSystemEncoding()), NULL, 16);
290 strValue = CFArrayGetValueAtIndex(productArray, j);
291 driverBundle->m_productId = strtoul(CFStringGetCStringPtr(strValue,
292 CFStringGetSystemEncoding()), NULL, 16);
294 strValue = CFArrayGetValueAtIndex(friendlyNameArray, j);
295 const char *cstr = CFStringGetCStringPtr(strValue,
296 CFStringGetSystemEncoding());
298 driverBundle->m_friendlyName = strdup(cstr);
299 if (!driverBundle->m_libPath)
300 driverBundle->m_libPath = strdup(libPath);
303 Log2(PCSC_LOG_DEBUG,
"VendorID: 0x%04X",
304 driverBundle->m_vendorId);
305 Log2(PCSC_LOG_DEBUG,
"ProductID: 0x%04X",
306 driverBundle->m_productId);
307 Log2(PCSC_LOG_DEBUG,
"Friendly name: %s",
308 driverBundle->m_friendlyName);
309 Log2(PCSC_LOG_DEBUG,
"Driver: %s", driverBundle->m_libPath);
318 CFStringRef strValue = blobValue;
321 Log3(PCSC_LOG_DEBUG,
"Driver without alias: %s %s",
322 driverBundle->m_friendlyName, driverBundle->m_libPath);
325 driverBundle->m_vendorId = strtoul(CFStringGetCStringPtr(strValue,
326 CFStringGetSystemEncoding()), NULL, 16);
328 strValue = (CFStringRef) CFDictionaryGetValue(dict,
329 CFSTR(PCSCLITE_HP_PRODKEY_NAME));
332 Log1(PCSC_LOG_ERROR,
"error getting product ID from bundle");
335 driverBundle->m_productId = strtoul(CFStringGetCStringPtr(strValue,
336 CFStringGetSystemEncoding()), NULL, 16);
338 strValue = (CFStringRef) CFDictionaryGetValue(dict,
339 CFSTR(PCSCLITE_HP_NAMEKEY_NAME));
342 Log1(PCSC_LOG_ERROR,
"error getting product friendly name from bundle");
343 driverBundle->m_friendlyName = strdup(
"unnamed device");
347 const char *cstr = CFStringGetCStringPtr(strValue,
348 CFStringGetSystemEncoding());
350 driverBundle->m_friendlyName = strdup(cstr);
353 Log2(PCSC_LOG_DEBUG,
"VendorID: 0x%04X", driverBundle->m_vendorId);
354 Log2(PCSC_LOG_DEBUG,
"ProductID: 0x%04X", driverBundle->m_productId);
355 Log2(PCSC_LOG_DEBUG,
"Friendly name: %s", driverBundle->m_friendlyName);
356 Log2(PCSC_LOG_DEBUG,
"Driver: %s", driverBundle->m_libPath);
363 CFRelease(bundleArray);
370 static HPDriver *HPDriverCopy(HPDriver * rhs)
375 HPDriver *newDriverBundle = calloc(1,
sizeof(HPDriver));
377 if (!newDriverBundle)
380 newDriverBundle->m_vendorId = rhs->m_vendorId;
381 newDriverBundle->m_productId = rhs->m_productId;
382 newDriverBundle->m_friendlyName = strdup(rhs->m_friendlyName);
383 newDriverBundle->m_libPath = strdup(rhs->m_libPath);
385 return newDriverBundle;
391 static void HPDriverRelease(HPDriver * driverBundle)
395 free(driverBundle->m_friendlyName);
396 free(driverBundle->m_libPath);
403 static void HPDriverVectorRelease(HPDriverVector driverBundleVector)
405 if (driverBundleVector)
409 for (b = driverBundleVector; b->m_vendorId; ++b)
412 free(driverBundleVector);
420 HPDeviceListInsert(HPDeviceList list, HPDriver * bundle, UInt32 address)
422 HPDevice *newReader = calloc(1,
sizeof(HPDevice));
426 Log1(PCSC_LOG_ERROR,
"memory allocation failure");
430 newReader->m_driver = HPDriverCopy(bundle);
431 newReader->m_address = address;
432 newReader->m_next = list;
440 static void HPDeviceListRelease(HPDeviceList list)
444 for (p = list; p; p = p->m_next)
445 HPDriverRelease(p->m_driver);
451 static int HPDeviceEquals(HPDevice * a, HPDevice * b)
453 return (a->m_driver->m_vendorId == b->m_driver->m_vendorId)
454 && (a->m_driver->m_productId == b->m_driver->m_productId)
455 && (a->m_address == b->m_address);
463 HPDriversMatchUSBDevices(HPDriverVector driverBundle,
464 HPDeviceList * readerList)
466 CFDictionaryRef usbMatch = IOServiceMatching(
"IOUSBDevice");
471 "error getting USB match from IOServiceMatching()");
475 io_iterator_t usbIter;
476 kern_return_t kret = IOServiceGetMatchingServices(kIOMasterPortDefault,
482 "error getting iterator from IOServiceGetMatchingServices()");
486 IOIteratorReset(usbIter);
487 io_object_t usbDevice = 0;
489 while ((usbDevice = IOIteratorNext(usbIter)))
493 kret = IORegistryEntryGetName(usbDevice, namebuf);
497 "error getting device name from IORegistryEntryGetName()");
501 IOCFPlugInInterface **iodev;
504 kret = IOCreatePlugInInterfaceForService(usbDevice,
505 kIOUSBDeviceUserClientTypeID,
506 kIOCFPlugInInterfaceID, &iodev, &score);
509 Log1(PCSC_LOG_ERROR,
"error getting plugin interface from IOCreatePlugInInterfaceForService()");
512 IOObjectRelease(usbDevice);
514 IOUSBDeviceInterface **usbdev;
515 HRESULT hres = (*iodev)->QueryInterface(iodev,
516 CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),
517 (LPVOID *) & usbdev);
519 (*iodev)->Release(iodev);
523 "error querying interface in QueryInterface()");
528 UInt16 productId = 0;
529 UInt32 usbAddress = 0;
531 kret = (*usbdev)->GetDeviceVendor(usbdev, &vendorId);
532 kret = (*usbdev)->GetDeviceProduct(usbdev, &productId);
533 kret = (*usbdev)->GetLocationID(usbdev, &usbAddress);
534 (*usbdev)->Release(usbdev);
537 Log4(PCSC_LOG_DEBUG,
"Found USB device 0x%04X:0x%04X at 0x%X",
538 vendorId, productId, usbAddress);
541 for (driver = driverBundle; driver->m_vendorId; ++driver)
543 if ((driver->m_vendorId == vendorId)
544 && (driver->m_productId == productId))
547 Log4(PCSC_LOG_DEBUG,
"Adding USB device %04X:%04X at 0x%X",
548 vendorId, productId, usbAddress);
551 HPDeviceListInsert(*readerList, driver, usbAddress);
556 IOObjectRelease(usbIter);
565 HPDriversMatchPCCardDevices(HPDriver * driverBundle,
566 HPDeviceList * readerList)
568 CFDictionaryRef pccMatch = IOServiceMatching(
"IOPCCard16Device");
570 if (pccMatch == NULL)
573 "error getting PCCard match from IOServiceMatching()");
577 io_iterator_t pccIter;
579 IOServiceGetMatchingServices(kIOMasterPortDefault, pccMatch,
584 "error getting iterator from IOServiceGetMatchingServices()");
588 IOIteratorReset(pccIter);
589 io_object_t pccDevice = 0;
591 while ((pccDevice = IOIteratorNext(pccIter)))
595 kret = IORegistryEntryGetName(pccDevice, namebuf);
598 Log1(PCSC_LOG_ERROR,
"error getting plugin interface from IOCreatePlugInInterfaceForService()");
602 UInt32 productId = 0;
603 UInt32 pccAddress = 0;
605 IORegistryEntryCreateCFProperty(pccDevice, CFSTR(
"VendorID"),
606 kCFAllocatorDefault, 0);
610 Log1(PCSC_LOG_ERROR,
"error getting vendor");
614 CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type,
618 IORegistryEntryCreateCFProperty(pccDevice, CFSTR(
"DeviceID"),
619 kCFAllocatorDefault, 0);
622 Log1(PCSC_LOG_ERROR,
"error getting device");
626 CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type,
630 IORegistryEntryCreateCFProperty(pccDevice, CFSTR(
"SocketNumber"),
631 kCFAllocatorDefault, 0);
634 Log1(PCSC_LOG_ERROR,
"error getting PC Card socket");
638 CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type,
641 HPDriver *driver = driverBundle;
643 for (; driver->m_vendorId; ++driver)
645 if ((driver->m_vendorId == vendorId)
646 && (driver->m_productId == productId))
649 HPDeviceListInsert(*readerList, driver, pccAddress);
653 IOObjectRelease(pccIter);
658 static void HPEstablishUSBNotification(
void)
660 io_iterator_t deviceAddedIterator;
661 io_iterator_t deviceRemovedIterator;
662 CFMutableDictionaryRef matchingDictionary;
663 IONotificationPortRef notificationPort;
666 notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
667 CFRunLoopAddSource(CFRunLoopGetCurrent(),
668 IONotificationPortGetRunLoopSource(notificationPort),
669 kCFRunLoopDefaultMode);
671 matchingDictionary = IOServiceMatching(
"IOUSBDevice");
672 if (!matchingDictionary)
674 Log1(PCSC_LOG_ERROR,
"IOServiceMatching() failed");
677 (CFMutableDictionaryRef) CFRetain(matchingDictionary);
679 kret = IOServiceAddMatchingNotification(notificationPort,
680 kIOMatchedNotification,
681 matchingDictionary, HPDeviceAppeared, NULL, &deviceAddedIterator);
685 "IOServiceAddMatchingNotification()-1 failed with code %d", kret);
687 HPDeviceAppeared(NULL, deviceAddedIterator);
689 kret = IOServiceAddMatchingNotification(notificationPort,
690 kIOTerminatedNotification,
692 HPDeviceDisappeared, NULL, &deviceRemovedIterator);
696 "IOServiceAddMatchingNotification()-2 failed with code %d", kret);
698 HPDeviceDisappeared(NULL, deviceRemovedIterator);
701 static void HPEstablishPCCardNotification(
void)
703 io_iterator_t deviceAddedIterator;
704 io_iterator_t deviceRemovedIterator;
705 CFMutableDictionaryRef matchingDictionary;
706 IONotificationPortRef notificationPort;
709 notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
710 CFRunLoopAddSource(CFRunLoopGetCurrent(),
711 IONotificationPortGetRunLoopSource(notificationPort),
712 kCFRunLoopDefaultMode);
714 matchingDictionary = IOServiceMatching(
"IOPCCard16Device");
715 if (!matchingDictionary)
717 Log1(PCSC_LOG_ERROR,
"IOServiceMatching() failed");
720 (CFMutableDictionaryRef) CFRetain(matchingDictionary);
722 kret = IOServiceAddMatchingNotification(notificationPort,
723 kIOMatchedNotification,
724 matchingDictionary, HPDeviceAppeared, NULL, &deviceAddedIterator);
728 "IOServiceAddMatchingNotification()-1 failed with code %d", kret);
730 HPDeviceAppeared(NULL, deviceAddedIterator);
732 kret = IOServiceAddMatchingNotification(notificationPort,
733 kIOTerminatedNotification,
735 HPDeviceDisappeared, NULL, &deviceRemovedIterator);
739 "IOServiceAddMatchingNotification()-2 failed with code %d", kret);
741 HPDeviceDisappeared(NULL, deviceRemovedIterator);
747 static void HPDeviceNotificationThread(
void)
749 HPEstablishUSBNotification();
750 HPEstablishPCCardNotification();
759 LONG HPSearchHotPluggables(
void)
761 HPDriver *drivers = HPDriversGetFromDirectory(PCSCLITE_HP_DROPDIR);
766 HPDeviceList devices = NULL;
768 if (HPDriversMatchUSBDevices(drivers, &devices))
771 if (HPDriversMatchPCCardDevices(drivers, &devices))
776 for (a = devices; a; a = a->m_next)
781 for (b = sDeviceList; b; b = b->m_next)
783 if (HPDeviceEquals(a, b))
791 char deviceName[MAX_DEVICENAME];
795 snprintf(deviceName,
sizeof(deviceName),
796 "%s", a->m_driver->m_friendlyName);
797 deviceName[
sizeof(deviceName)-1] =
'\0';
799 RFAddReader(a->m_driver->m_friendlyName,
800 PCSCLITE_HP_BASE_PORT + a->m_address, a->m_driver->m_libPath,
805 for (a = sDeviceList; a; a = a->m_next)
810 for (b = devices; b; b = b->m_next)
812 if (HPDeviceEquals(a, b))
820 RFRemoveReader(a->m_driver->m_friendlyName,
821 PCSCLITE_HP_BASE_PORT + a->m_address);
825 HPDeviceListRelease(sDeviceList);
826 sDeviceList = devices;
827 HPDriverVectorRelease(drivers);
833 pthread_t sHotplugWatcherThread;
838 ULONG HPRegisterForHotplugEvents(
void)
840 ThreadCreate(&sHotplugWatcherThread,
842 (PCSCLITE_THREAD_FUNCTION( )) HPDeviceNotificationThread, NULL);
847 LONG HPStopHotPluggables(
void)
852 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.