30 #include <boost/filesystem.hpp>
31 #include <boost/range/iterator_range.hpp>
32 #include <boost/algorithm/string.hpp>
41 #include <linux/serial.h>
42 #include <sys/ioctl.h>
60 boost::optional<USBSerialDevice>
61 make_USBSerialDevice(
const std::string &device) {
70 boost::filesystem::path uevent_file =
71 "/sys/class/tty/" + device +
"/device/uevent";
72 if (!boost::filesystem::exists(uevent_file)) {
76 std::ifstream uevent_input(uevent_file.generic_string());
78 while (std::getline(uevent_input, line)) {
79 if (!boost::starts_with(line,
"PRODUCT="))
83 const auto first = line.find(
"=");
84 const auto second = line.find(
"/", first);
85 const auto third = line.find(
"/", second + 1);
87 const std::string vendor_id_str =
88 line.substr(first + 1, second - first - 1);
89 const std::string product_id_str =
90 line.substr(second + 1, third - second - 1);
92 const uint16_t detected_vendor_id =
93 std::stoi(vendor_id_str.c_str(), 0, 16);
94 const uint16_t detected_product_id =
95 std::stoi(product_id_str.c_str(), 0, 16);
98 const std::string device_name =
99 (boost::filesystem::path(
"/dev") / device).generic_string();
100 USBSerialDevice usb_serial_device(detected_vendor_id,
102 device_name, device_name);
103 return usb_serial_device;
116 bool serial8250_device_connected(
const std::string &port) {
117 const int fd = open(port.c_str(), O_RDWR | O_NONBLOCK | O_NOCTTY);
122 struct serial_struct serial_info;
123 const int ret = ioctl(fd, TIOCGSERIAL, &serial_info);
129 if (PORT_UNKNOWN == serial_info.type) {
148 bool matches_ids(
const USBSerialDevice &device,
149 const boost::optional<uint16_t> &vendorID,
150 const boost::optional<uint16_t> &productID) {
151 const bool vendor_matches =
152 (!vendorID || *vendorID == device.getVID());
153 const bool product_matches =
154 (!productID || *productID == device.getPID());
156 return (vendor_matches && product_matches);
161 std::vector<USBSerialDevice>
162 getSerialDeviceList(boost::optional<uint16_t> vendorID,
163 boost::optional<uint16_t> productID) {
165 std::vector<USBSerialDevice> devices;
168 const boost::filesystem::path sys_class_tty =
"/sys/class/tty";
169 for (
const auto &path_name : boost::make_iterator_range(
170 boost::filesystem::directory_iterator(sys_class_tty),
171 boost::filesystem::directory_iterator())) {
173 const boost::filesystem::path device_candidate = path_name;
174 const boost::filesystem::path driver_file =
175 device_candidate /
"device" /
"driver";
176 if (!boost::filesystem::exists(driver_file)) {
181 const boost::filesystem::path basename =
182 boost::filesystem::basename(device_candidate);
184 auto usb_serial_device =
185 make_USBSerialDevice(basename.generic_string());
186 if (!usb_serial_device)
190 if (!matches_ids(*usb_serial_device, vendorID, productID))
195 if (boost::filesystem::exists(driver_file /
"serial8250")) {
196 const bool is_connected = serial8250_device_connected(
197 "/dev/" + basename.generic_string());
203 devices.push_back(*usb_serial_device);