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.*");
309 vector<string> devices_found = glob(search_globs);
311 vector<string>::iterator iter = devices_found.begin();
313 while (iter != devices_found.end())
315 string device = *iter++;
317 vector<string> sysfs_info = get_sysfs_info(device);
319 string friendly_name = sysfs_info[0];
321 string hardware_id = sysfs_info[1];
323 PortInfo device_entry;
324 device_entry.port = device;
325 device_entry.description = friendly_name;
326 device_entry.hardware_id = hardware_id;
328 results.push_back(device_entry);
335 #endif // defined(__linux__) std::vector< PortInfo > list_ports()