Saltar al contenido

¿Cómo encontrar todos los dispositivos serie (ttyS, ttyUSB, ..) en Linux sin abrirlos?

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.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *