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__)