X-Git-Url: http://sigrok.org/gitweb/?a=blobdiff_plain;f=linux.c;h=61446a4171ae863034b2cf75b3ff81efc2dff0e8;hb=da8730199a215c9ccd938202fb55ac9e3f58a0b2;hp=23258514534d21e4a9f4e631373b324340aba10b;hpb=e33dcf90a0b0e510eb990c657eab88243d0ac5fd;p=libserialport.git diff --git a/linux.c b/linux.c index 2325851..61446a4 100644 --- a/linux.c +++ b/linux.c @@ -20,12 +20,13 @@ #include "libserialport.h" #include "libserialport_internal.h" -enum sp_return get_port_details(struct sp_port *port) +SP_PRIV enum sp_return get_port_details(struct sp_port *port) { /* Description limited to 127 char, anything longer would not be user friendly anyway */ char description[128]; - int bus, address, vid, pid = -1; + int bus, address; + unsigned int vid, pid; char manufacturer[128], product[128], serial[128]; char baddr[32]; const char dir_name[] = "/sys/class/tty/%s/device/%s%s"; @@ -35,12 +36,12 @@ enum sp_return get_port_details(struct sp_port *port) int i, count; if (strncmp(port->name, "/dev/", 5)) - RETURN_ERROR(SP_ERR_ARG, "Device name not recognized (%s)", port->name); + RETURN_ERROR(SP_ERR_ARG, "Device name not recognized."); snprintf(file_name, sizeof(file_name), "/sys/class/tty/%s", dev); count = readlink(file_name, file_name, sizeof(file_name)); if (count <= 0 || count >= (int) sizeof(file_name)-1) - RETURN_ERROR(SP_ERR_ARG, "Device not found (%s)", port->name); + RETURN_ERROR(SP_ERR_ARG, "Device not found."); file_name[count] = 0; if (strstr(file_name, "bluetooth")) port->transport = SP_TRANSPORT_BLUETOOTH; @@ -155,3 +156,67 @@ enum sp_return get_port_details(struct sp_port *port) RETURN_OK(); } + +SP_PRIV enum sp_return list_ports(struct sp_port ***list) +{ + char name[PATH_MAX], target[PATH_MAX]; + struct dirent entry, *result; +#ifdef HAVE_SERIAL_STRUCT + struct serial_struct serial_info; + int ioctl_result; +#endif + char buf[sizeof(entry.d_name) + 16]; + int len, fd; + DIR *dir; + int ret = SP_OK; + + DEBUG("Enumerating tty devices"); + if (!(dir = opendir("/sys/class/tty"))) + RETURN_FAIL("could not open /sys/class/tty"); + + DEBUG("Iterating over results"); + while (!readdir_r(dir, &entry, &result) && result) { + snprintf(buf, sizeof(buf), "/sys/class/tty/%s", entry.d_name); + len = readlink(buf, target, sizeof(target)); + if (len <= 0 || len >= (int) sizeof(target)-1) + continue; + target[len] = 0; + if (strstr(target, "virtual")) + continue; + snprintf(name, sizeof(name), "/dev/%s", entry.d_name); + DEBUG_FMT("Found device %s", name); + if (strstr(target, "serial8250")) { + /* The serial8250 driver has a hardcoded number of ports. + * The only way to tell which actually exist on a given system + * is to try to open them and make an ioctl call. */ + DEBUG("serial8250 device, attempting to open"); + if ((fd = open(name, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0) { + DEBUG("open failed, skipping"); + continue; + } +#ifdef HAVE_SERIAL_STRUCT + ioctl_result = ioctl(fd, TIOCGSERIAL, &serial_info); +#endif + close(fd); +#ifdef HAVE_SERIAL_STRUCT + if (ioctl_result != 0) { + DEBUG("ioctl failed, skipping"); + continue; + } + if (serial_info.type == PORT_UNKNOWN) { + DEBUG("port type is unknown, skipping"); + continue; + } +#endif + } + DEBUG_FMT("Found port %s", name); + *list = list_append(*list, name); + if (!list) { + SET_ERROR(ret, SP_ERR_MEM, "list append failed"); + break; + } + } + closedir(dir); + + return ret; +}