21 #include <sys/types.h>
28 using std::istringstream;
36 static vector<string> glob(
const vector<string>& patterns);
37 static string basename(
const string& path);
38 static string dirname(
const string& path);
39 static bool path_exists(
const string& path);
40 static string realpath(
const string& path);
41 static string usb_sysfs_friendly_name(
const string& sys_usb_path);
42 static vector<string> get_sysfs_info(
const string& device_path);
43 static string read_line(
const string& file);
44 static string usb_sysfs_hw_string(
const string& sysfs_path);
45 static string format(
const char* format, ...);
48 glob(
const vector<string>& patterns)
50 vector<string> paths_found;
52 if(patterns.size() == 0)
57 int glob_retval = glob(patterns[0].c_str(), 0, NULL, &glob_results);
59 vector<string>::const_iterator iter = patterns.begin();
61 while(++iter != patterns.end())
63 glob_retval = glob(iter->c_str(), GLOB_APPEND, NULL, &glob_results);
66 for(
int path_index = 0; path_index < glob_results.gl_pathc; path_index++)
68 paths_found.push_back(glob_results.gl_pathv[path_index]);
71 globfree(&glob_results);
77 basename(
const string& path)
79 size_t pos = path.rfind(
"/");
81 if(pos == std::string::npos)
84 return string(path, pos+1, string::npos);
88 dirname(
const string& path)
90 size_t pos = path.rfind(
"/");
92 if(pos == std::string::npos)
97 return string(path, 0, pos);
101 path_exists(
const string& path)
105 if( stat(path.c_str(), &sb ) == 0 )
112 realpath(
const string& path)
114 char* real_path = realpath(path.c_str(), NULL);
118 if(real_path != NULL)
129 usb_sysfs_friendly_name(
const string& sys_usb_path)
131 unsigned int device_number = 0;
133 istringstream( read_line(sys_usb_path +
"/devnum") ) >> device_number;
135 string manufacturer = read_line( sys_usb_path +
"/manufacturer" );
137 string product = read_line( sys_usb_path +
"/product" );
139 string serial = read_line( sys_usb_path +
"/serial" );
141 if( manufacturer.empty() && product.empty() &&
serial.empty() )
144 return format(
"%s %s %s", manufacturer.c_str(), product.c_str(),
serial.c_str() );
148 get_sysfs_info(
const string& device_path)
150 string device_name = basename( device_path );
152 string friendly_name;
156 string sys_device_path = format(
"/sys/class/tty/%s/device", device_name.c_str() );
158 if( device_name.compare(0,6,
"ttyUSB") == 0 )
160 sys_device_path = dirname( dirname( realpath( sys_device_path ) ) );
162 if( path_exists( sys_device_path ) )
164 friendly_name = usb_sysfs_friendly_name( sys_device_path );
166 hardware_id = usb_sysfs_hw_string( sys_device_path );
169 else if( device_name.compare(0,6,
"ttyACM") == 0 )
171 sys_device_path = dirname( realpath( sys_device_path ) );
173 if( path_exists( sys_device_path ) )
175 friendly_name = usb_sysfs_friendly_name( sys_device_path );
177 hardware_id = usb_sysfs_hw_string( sys_device_path );
184 string sys_id_path = sys_device_path +
"/id";
186 if( path_exists( sys_id_path ) )
187 hardware_id = read_line( sys_id_path );
190 if( friendly_name.empty() )
191 friendly_name = device_name;
193 if( hardware_id.empty() )
196 vector<string> result;
197 result.push_back(friendly_name);
198 result.push_back(hardware_id);
204 read_line(
const string& file)
206 ifstream ifs(file.c_str(), ifstream::in);
219 format(
const char* format, ...)
223 size_t buffer_size_bytes = 256;
227 char* buffer = (
char*)malloc(buffer_size_bytes);
234 unsigned int loop_count = 0;
238 va_start(ap, format);
240 int return_value = vsnprintf(buffer, buffer_size_bytes, format, ap);
242 if( return_value < 0 )
246 else if( return_value >= buffer_size_bytes )
250 buffer_size_bytes = return_value + 1;
252 char* new_buffer_ptr = (
char*)realloc(buffer, buffer_size_bytes);
254 if( new_buffer_ptr == NULL )
260 buffer = new_buffer_ptr;
271 if( ++loop_count > 5 )
281 usb_sysfs_hw_string(
const string& sysfs_path)
283 string serial_number = read_line( sysfs_path +
"/serial" );
285 if( serial_number.length() > 0 )
287 serial_number = format(
"SNR=%s", serial_number.c_str() );
290 string vid = read_line( sysfs_path +
"/idVendor" );
292 string pid = read_line( sysfs_path +
"/idProduct" );
294 return format(
"USB VID:PID=%s:%s %s", vid.c_str(), pid.c_str(), serial_number.c_str() );
300 vector<PortInfo> results;
302 vector<string> search_globs;
303 search_globs.push_back(
"/dev/ttyACM*");
304 search_globs.push_back(
"/dev/ttyS*");
305 search_globs.push_back(
"/dev/ttyUSB*");
306 search_globs.push_back(
"/dev/tty.*");
307 search_globs.push_back(
"/dev/cu.*");
308 search_globs.push_back(
"/dev/rfcomm*");
310 vector<string> devices_found = glob( search_globs );
312 vector<string>::iterator iter = devices_found.begin();
314 while( iter != devices_found.end() )
316 string device = *iter++;
318 vector<string> sysfs_info = get_sysfs_info( device );
320 string friendly_name = sysfs_info[0];
322 string hardware_id = sysfs_info[1];
324 PortInfo device_entry;
325 device_entry.port = device;
326 device_entry.description = friendly_name;
327 device_entry.hardware_id = hardware_id;
329 results.push_back( device_entry );
336 #endif // defined(__linux__)