30 #include <CoreFoundation/CoreFoundation.h>
31 #include <IOKit/IOKitLib.h>
32 #include <IOKit/IOKitKeys.h>
33 #include <IOKit/serial/IOSerialKeys.h>
47 int findSerialPorts(io_iterator_t *matchingServices) {
49 CFMutableDictionaryRef classesToMatch =
50 IOServiceMatching(kIOSerialBSDServiceValue);
51 if (classesToMatch == NULL) {
55 CFDictionarySetValue(classesToMatch, CFSTR(kIOSerialBSDTypeKey),
56 CFSTR(kIOSerialBSDAllTypes));
58 kern_return_t kernResult = IOServiceGetMatchingServices(
59 kIOMasterPortDefault, classesToMatch, matchingServices);
60 if (KERN_SUCCESS != kernResult) {
77 bool matches_ids(
const USBSerialDevice &device,
78 const boost::optional<uint16_t> &vendorID,
79 const boost::optional<uint16_t> &productID) {
80 const bool vendor_matches =
81 (!vendorID || *vendorID == device.getVID());
82 const bool product_matches =
83 (!productID || *productID == device.getPID());
85 return (vendor_matches && product_matches);
89 std::vector<USBSerialDevice>
90 getSerialDeviceList(boost::optional<uint16_t> vendorID,
91 boost::optional<uint16_t> productID) {
93 std::vector<USBSerialDevice> devices;
95 io_iterator_t serialPortIterator;
96 io_object_t serialPortService;
98 if (findSerialPorts(&serialPortIterator) ==
true) {
100 while ((serialPortService = IOIteratorNext(serialPortIterator)) !=
102 const CFNumberRef vidObj =
103 static_cast<CFNumberRef
>(IORegistryEntrySearchCFProperty(
104 serialPortService, kIOServicePlane, CFSTR(
"idVendor"),
105 NULL, kIORegistryIterateRecursively |
106 kIORegistryIterateParents));
107 const CFNumberRef pidObj =
108 static_cast<CFNumberRef
>(IORegistryEntrySearchCFProperty(
109 serialPortService, kIOServicePlane, CFSTR(
"idProduct"),
110 NULL, kIORegistryIterateRecursively |
111 kIORegistryIterateParents));
112 const CFStringRef bsdPathObj =
113 static_cast<CFStringRef
>(IORegistryEntryCreateCFProperty(
114 serialPortService, CFSTR(kIOCalloutDeviceKey),
115 kCFAllocatorDefault, 0));
117 if (!vidObj || !pidObj || !bsdPathObj) {
122 CFNumberGetValue(vidObj, kCFNumberSInt16Type, &vid);
123 CFNumberGetValue(pidObj, kCFNumberSInt16Type, &pid);
126 CFIndex bufferSize = CFStringGetMaximumSizeForEncoding(
127 CFStringGetLength(bsdPathObj),
128 kCFStringEncodingMacRoman) +
130 std::vector<char> bsdPathBuf(bufferSize);
131 CFStringGetCString(bsdPathObj, bsdPathBuf.data(), bufferSize,
132 kCFStringEncodingMacRoman);
134 USBSerialDevice usb_serial_device(vid, pid, bsdPathBuf.data(),
137 if (matches_ids(usb_serial_device, vendorID, productID)) {
138 devices.push_back(usb_serial_device);