Te sugerimos que revises esta respuesta en un ambiente controlado antes de enviarlo a producción, saludos.
Solución:
los /sys
El sistema de archivos debe contener mucha información para su búsqueda. Mi sistema (2.6.32-40-generic # 87-Ubuntu) sugiere:
/sys/class/tty
Lo que le brinda descripciones de todos los dispositivos TTY conocidos por el sistema. Un ejemplo recortado:
# ll /sys/class/tty/ttyUSB*
lrwxrwxrwx 1 root root 0 2012-03-28 20:43 /sys/class/tty/ttyUSB0 -> ../../devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.4/2-1.4:1.0/ttyUSB0/tty/ttyUSB0/
lrwxrwxrwx 1 root root 0 2012-03-28 20:44 /sys/class/tty/ttyUSB1 -> ../../devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.3/2-1.3:1.0/ttyUSB1/tty/ttyUSB1/
Siguiendo uno de estos enlaces:
# ll /sys/class/tty/ttyUSB0/
insgesamt 0
drwxr-xr-x 3 root root 0 2012-03-28 20:43 ./
drwxr-xr-x 3 root root 0 2012-03-28 20:43 ../
-r--r--r-- 1 root root 4096 2012-03-28 20:49 dev
lrwxrwxrwx 1 root root 0 2012-03-28 20:43 device -> ../../../ttyUSB0/
drwxr-xr-x 2 root root 0 2012-03-28 20:49 power/
lrwxrwxrwx 1 root root 0 2012-03-28 20:43 subsystem -> ../../../../../../../../../../class/tty/
-rw-r--r-- 1 root root 4096 2012-03-28 20:43 uevent
Aquí el dev
archivo contiene esta información:
# cat /sys/class/tty/ttyUSB0/dev
188:0
Este es el nodo mayor / menor. Estos se pueden buscar en el /dev
directorio para obtener nombres fáciles de usar:
# ll -R /dev |grep "188, *0"
crw-rw---- 1 root dialout 188, 0 2012-03-28 20:44 ttyUSB0
los /sys/class/tty
dir contiene todos los dispositivos TTY, pero es posible que desee excluir esos molestos terminales virtuales y pseudo terminales. Le sugiero que examine solo aquellos que tienen un device/driver
entrada:
# ll /sys/class/tty/*/device/driver
lrwxrwxrwx 1 root root 0 2012-03-28 19:07 /sys/class/tty/ttyS0/device/driver -> ../../../bus/pnp/drivers/serial/
lrwxrwxrwx 1 root root 0 2012-03-28 19:07 /sys/class/tty/ttyS1/device/driver -> ../../../bus/pnp/drivers/serial/
lrwxrwxrwx 1 root root 0 2012-03-28 19:07 /sys/class/tty/ttyS2/device/driver -> ../../../bus/platform/drivers/serial8250/
lrwxrwxrwx 1 root root 0 2012-03-28 19:07 /sys/class/tty/ttyS3/device/driver -> ../../../bus/platform/drivers/serial8250/
lrwxrwxrwx 1 root root 0 2012-03-28 20:43 /sys/class/tty/ttyUSB0/device/driver -> ../../../../../../../../bus/usb-serial/drivers/ftdi_sio/
lrwxrwxrwx 1 root root 0 2012-03-28 21:15 /sys/class/tty/ttyUSB1/device/driver -> ../../../../../../../../bus/usb-serial/drivers/ftdi_sio/
En kernels recientes (no estoy seguro desde cuándo) puede enumerar el contenido de / dev / serial para obtener una lista de los puertos seriales de su sistema. En realidad, son enlaces simbólicos que apuntan al nodo / dev / correcto:
[email protected]:~$ ls /dev/serial/
total 0
drwxr-xr-x 2 root root 60 2011-07-20 17:12 by-id/
drwxr-xr-x 2 root root 60 2011-07-20 17:12 by-path/
[email protected]:~$ ls /dev/serial/by-id/
total 0
lrwxrwxrwx 1 root root 13 2011-07-20 17:12 usb-Prolific_Technology_Inc._USB-Serial_Controller-if00-port0 -> ../../ttyUSB0
[email protected]:~$ ls /dev/serial/by-path/
total 0
lrwxrwxrwx 1 root root 13 2011-07-20 17:12 pci-0000:00:0b.0-usb-0:3:1.0-port0 -> ../../ttyUSB0
Este es un adaptador USB-serial, como puede ver. Tenga en cuenta que cuando no hay puertos serie en el sistema, el directorio / dev / serial / no existe. Espero que esto ayude :).
Estoy haciendo algo como el siguiente código. Funciona para dispositivos USB y también para los estúpidos dispositivos serial8250 de los que todos tenemos 30, pero solo un par de ellos realmente funcionan.
Básicamente utilizo el concepto de respuestas anteriores. Primero enumere todos los dispositivos tty en / sys / class / tty /. Los dispositivos que no contienen un subdirectorio / device se filtran. / sys / class / tty / console es uno de estos dispositivos. Luego, los dispositivos que realmente contienen un dispositivo se aceptan como puerto serie válido según el destino del controlador-enlace simbólico 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
y para 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
Todos los controladores controlados por serial8250 deben ser sondas que utilicen el ioctl mencionado anteriormente.
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
Solo el puerto que informa un tipo de dispositivo válido es válido.
La fuente completa para enumerar los puertos de serie se ve así. Las adiciones son bienvenidas.
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
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& comList, list& 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& comList, list comList8250)
struct serial_struct serinfo;
list::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
list getComList()
int n;
struct dirent **namelist;
list comList;
list 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 l = getComList();
list::iterator it = l.begin();
while (it != l.end())
cout << *it << endl;
it++;
return 0;
Si estás de acuerdo, tienes el poder dejar un post acerca de qué te ha gustado de esta noticia.