ฉันกำลังทำโค้ดต่อไปนี้ ใช้งานได้กับอุปกรณ์ USB และ serial8250-devuices โง่ ๆ ที่เรามีทั้งหมด 30 ตัว แต่มีเพียงไม่กี่ตัวเท่านั้นที่ใช้งานได้จริง
โดยทั่วไปฉันใช้แนวคิดจากคำตอบก่อนหน้านี้ ก่อนอื่นให้ระบุอุปกรณ์ tty ทั้งหมดใน / sys / class / tty / อุปกรณ์ที่ไม่มี a / device subdir จะถูกกรองออกไป / sys / class / tty / console เป็นอุปกรณ์ดังกล่าว จากนั้นอุปกรณ์ที่มีอุปกรณ์จริง ๆ แล้วจึงได้รับการยอมรับว่าเป็นพอร์ตอนุกรมที่ถูกต้องขึ้นอยู่กับเป้าหมายของไดรเวอร์ symlink fx
$ ls -al /sys/class/tty/ttyUSB0//device/driver
lrwxrwxrwx 1 root root 0 sep 6 21:28 /sys/class/tty/ttyUSB0//device/driver -> ../../../bus/platform/drivers/usbserial
และสำหรับ ttyS0
$ ls -al /sys/class/tty/ttyS0//device/driver
lrwxrwxrwx 1 root root 0 sep 6 21:28 /sys/class/tty/ttyS0//device/driver -> ../../../bus/platform/drivers/serial8250
ไดรเวอร์ทั้งหมดที่ขับเคลื่อนด้วย serial8250 ต้องเป็นโพรบที่ใช้ ioctl ที่กล่าวถึงก่อนหน้านี้
if (ioctl(fd, TIOCGSERIAL, &serinfo)==0) {
// If device type is no PORT_UNKNOWN we accept the port
if (serinfo.type != PORT_UNKNOWN)
the_port_is_valid
เฉพาะพอร์ตที่รายงานประเภทอุปกรณ์ที่ถูกต้องเท่านั้นที่ถูกต้อง
แหล่งที่มาที่สมบูรณ์สำหรับการแจกแจง serialports มีลักษณะดังนี้ เพิ่มเติมยินดีต้อนรับ
#include <stdlib.h>
#include <dirent.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <linux/serial.h>
#include <iostream>
#include <list>
using namespace std;
static string get_driver(const string& tty) {
struct stat st;
string devicedir = tty;
// Append '/device' to the tty-path
devicedir += "/device";
// Stat the devicedir and handle it if it is a symlink
if (lstat(devicedir.c_str(), &st)==0 && S_ISLNK(st.st_mode)) {
char buffer[1024];
memset(buffer, 0, sizeof(buffer));
// Append '/driver' and return basename of the target
devicedir += "/driver";
if (readlink(devicedir.c_str(), buffer, sizeof(buffer)) > 0)
return basename(buffer);
}
return "";
}
static void register_comport( list<string>& comList, list<string>& comList8250, const string& dir) {
// Get the driver the device is using
string driver = get_driver(dir);
// Skip devices without a driver
if (driver.size() > 0) {
string devfile = string("/dev/") + basename(dir.c_str());
// Put serial8250-devices in a seperate list
if (driver == "serial8250") {
comList8250.push_back(devfile);
} else
comList.push_back(devfile);
}
}
static void probe_serial8250_comports(list<string>& comList, list<string> comList8250) {
struct serial_struct serinfo;
list<string>::iterator it = comList8250.begin();
// Iterate over all serial8250-devices
while (it != comList8250.end()) {
// Try to open the device
int fd = open((*it).c_str(), O_RDWR | O_NONBLOCK | O_NOCTTY);
if (fd >= 0) {
// Get serial_info
if (ioctl(fd, TIOCGSERIAL, &serinfo)==0) {
// If device type is no PORT_UNKNOWN we accept the port
if (serinfo.type != PORT_UNKNOWN)
comList.push_back(*it);
}
close(fd);
}
it ++;
}
}
list<string> getComList() {
int n;
struct dirent **namelist;
list<string> comList;
list<string> comList8250;
const char* sysdir = "/sys/class/tty/";
// Scan through /sys/class/tty - it contains all tty-devices in the system
n = scandir(sysdir, &namelist, NULL, NULL);
if (n < 0)
perror("scandir");
else {
while (n--) {
if (strcmp(namelist[n]->d_name,"..") && strcmp(namelist[n]->d_name,".")) {
// Construct full absolute file path
string devicedir = sysdir;
devicedir += namelist[n]->d_name;
// Register the device
register_comport(comList, comList8250, devicedir);
}
free(namelist[n]);
}
free(namelist);
}
// Only non-serial8250 has been added to comList without any further testing
// serial8250-devices must be probe to check for validity
probe_serial8250_comports(comList, comList8250);
// Return the lsit of detected comports
return comList;
}
int main() {
list<string> l = getComList();
list<string>::iterator it = l.begin();
while (it != l.end()) {
cout << *it << endl;
it++;
}
return 0;
}