6 #include <CoreFoundation/CoreFoundation.h> 7 #include <IOKit/IOKitLib.h> 8 #include <IOKit/serial/IOSerialKeys.h> 9 #include <IOKit/IOBSD.h> 21 #define HARDWARE_ID_STRING_LENGTH 128 23 string cfstring_to_string(CFStringRef cfstring);
24 string get_device_path(io_object_t& serial_port);
25 string get_class_name(io_object_t& obj);
26 io_registry_entry_t get_parent_iousb_device(io_object_t& serial_port);
27 string get_string_property(io_object_t& device,
const char* property);
28 uint16_t get_int_property(io_object_t& device,
const char* property);
29 string rtrim(
const string& str);
32 cfstring_to_string(CFStringRef cfstring)
34 char cstring[MAXPATHLEN];
39 Boolean success = CFStringGetCString(cfstring,
42 kCFStringEncodingASCII);
52 get_device_path(io_object_t& serial_port)
54 CFTypeRef callout_path;
57 callout_path = IORegistryEntryCreateCFProperty(serial_port,
58 CFSTR(kIOCalloutDeviceKey),
64 if (CFGetTypeID(callout_path) == CFStringGetTypeID())
65 device_path = cfstring_to_string(static_cast<CFStringRef>(callout_path));
67 CFRelease(callout_path);
74 get_class_name(io_object_t& obj)
78 kern_return_t kern_result;
80 kern_result = IOObjectGetClass(obj, class_name);
82 if (kern_result == KERN_SUCCESS)
89 get_parent_iousb_device(io_object_t& serial_port)
91 io_object_t device = serial_port;
92 io_registry_entry_t parent = 0;
93 io_registry_entry_t result = 0;
94 kern_return_t kern_result = KERN_FAILURE;
95 string name = get_class_name(device);
98 while (name !=
"IOUSBDevice")
100 kern_result = IORegistryEntryGetParentEntry(device,
104 if (kern_result != KERN_SUCCESS)
112 name = get_class_name(device);
115 if (kern_result == KERN_SUCCESS)
122 get_string_property(io_object_t& device,
const char* property)
124 string property_name;
128 CFStringRef property_as_cfstring = CFStringCreateWithCString(
131 kCFStringEncodingASCII);
133 CFTypeRef name_as_cfstring = IORegistryEntryCreateCFProperty(
135 property_as_cfstring,
139 if (name_as_cfstring)
141 if (CFGetTypeID(name_as_cfstring) == CFStringGetTypeID())
142 property_name = cfstring_to_string(static_cast<CFStringRef>(name_as_cfstring));
144 CFRelease(name_as_cfstring);
147 if (property_as_cfstring)
148 CFRelease(property_as_cfstring);
151 return property_name;
155 get_int_property(io_object_t& device,
const char* property)
161 CFStringRef property_as_cfstring = CFStringCreateWithCString(
164 kCFStringEncodingASCII);
166 CFTypeRef number = IORegistryEntryCreateCFProperty(device,
167 property_as_cfstring,
171 if (property_as_cfstring)
172 CFRelease(property_as_cfstring);
176 if (CFGetTypeID(number) == CFNumberGetTypeID())
178 bool success = CFNumberGetValue(static_cast<CFNumberRef>(number),
194 string rtrim(
const string& str)
198 string whitespace =
" \t\f\v\n\r";
200 std::size_t found = result.find_last_not_of(whitespace);
202 if (found != std::string::npos)
203 result.erase(found + 1);
213 vector<PortInfo> devices_found;
214 CFMutableDictionaryRef classes_to_match;
215 io_iterator_t serial_port_iterator;
216 io_object_t serial_port;
217 mach_port_t master_port;
218 kern_return_t kern_result;
220 kern_result = IOMasterPort(MACH_PORT_NULL, &master_port);
222 if (kern_result != KERN_SUCCESS)
223 return devices_found;
225 classes_to_match = IOServiceMatching(kIOSerialBSDServiceValue);
227 if (classes_to_match == NULL)
228 return devices_found;
230 CFDictionarySetValue(classes_to_match,
231 CFSTR(kIOSerialBSDTypeKey),
232 CFSTR(kIOSerialBSDAllTypes));
234 kern_result = IOServiceGetMatchingServices(master_port, classes_to_match, &serial_port_iterator);
236 if (KERN_SUCCESS != kern_result)
237 return devices_found;
239 while ((serial_port = IOIteratorNext(serial_port_iterator)))
241 string device_path = get_device_path(serial_port);
242 io_registry_entry_t parent = get_parent_iousb_device(serial_port);
243 IOObjectRelease(serial_port);
245 if (device_path.empty())
249 port_info.port = device_path;
250 port_info.description =
"n/a";
251 port_info.hardware_id =
"n/a";
253 string device_name = rtrim(get_string_property(parent,
"USB Product Name"));
254 string vendor_name = rtrim(get_string_property(parent,
"USB Vendor Name"));
255 string description = rtrim(vendor_name +
" " + device_name);
256 if (!description.empty())
257 port_info.description = description;
259 string serial_number = rtrim(get_string_property(parent,
"USB Serial Number"));
260 uint16_t vendor_id = get_int_property(parent,
"idVendor");
261 uint16_t product_id = get_int_property(parent,
"idProduct");
263 if (vendor_id && product_id)
265 char cstring[HARDWARE_ID_STRING_LENGTH];
267 if (serial_number.empty())
268 serial_number =
"None";
270 int ret = snprintf(cstring, HARDWARE_ID_STRING_LENGTH,
"USB VID:PID=%04x:%04x SNR=%s",
273 serial_number.c_str());
275 if ((ret >= 0) && (ret < HARDWARE_ID_STRING_LENGTH))
276 port_info.hardware_id = cstring;
279 devices_found.push_back(port_info);
282 IOObjectRelease(serial_port_iterator);
283 return devices_found;
286 #endif // defined(__APPLE__) std::vector< PortInfo > list_ports()