1
0
mirror of git://sigrok.org/libserialport synced 2023-08-10 21:13:24 +03:00

Remove the udev dependency and parse the /sys hierarchy instead.

This commit is contained in:
Aurelien Jacobs 2014-05-31 00:48:54 +02:00
parent 073c86bd07
commit 98cac5d63e
3 changed files with 27 additions and 57 deletions

6
README
View File

@ -40,11 +40,7 @@ port, e.g. for USB devices the USB VID and PID of the underlying device.
Dependencies Dependencies
============ ============
On Linux, libudev is required. On other systems no other libraries are required. No other libraries are required.
The libudev dependency could be eliminated in favour of direct sysfs queries at
the cost of some brevity. This is not currently a priority but if you feel like
doing this feel free to submit a patch.
Building Building
======== ========

View File

@ -80,15 +80,6 @@ SP_PKGLIBS=""
case $target_os in case $target_os in
*linux*) *linux*)
AM_CONDITIONAL([LINUX], true) AM_CONDITIONAL([LINUX], true)
# On Linux libudev is currently required for enumeration.
AC_ARG_WITH([libudev],
[AS_HELP_STRING([--with-libudev],
[use libudev for serial port enumeration @<:@default=check@:>@])],
[], [with_libudev=check])
AS_IF([test "x$with_libudev" != xno], [
PKG_CHECK_MODULES([libudev], [libudev >= 0],
[CFLAGS="$CFLAGS $libudev_CFLAGS"; LIBS="$LIBS $libudev_LIBS";
SP_PKGLIBS="$SP_PKGLIBS libudev"; AC_DEFINE(HAVE_LIBUDEV)])], [])
;; ;;
*darwin*) *darwin*)
AM_CONDITIONAL([LINUX], false) AM_CONDITIONAL([LINUX], false)

View File

@ -47,9 +47,7 @@
#include <sys/syslimits.h> #include <sys/syslimits.h>
#endif #endif
#ifdef __linux__ #ifdef __linux__
#ifdef HAVE_LIBUDEV #include <dirent.h>
#include "libudev.h"
#endif
#ifndef __ANDROID__ #ifndef __ANDROID__
#include "linux/serial.h" #include "linux/serial.h"
#endif #endif
@ -463,72 +461,57 @@ out:
IOObjectRelease(iter); IOObjectRelease(iter);
out_done: out_done:
#endif #endif
#if defined(__linux__) && defined(HAVE_LIBUDEV) #ifdef __linux__
struct udev *ud; char name[PATH_MAX], target[PATH_MAX];
struct udev_enumerate *ud_enumerate; struct dirent entry, *result;
struct udev_list_entry *ud_list;
struct udev_list_entry *ud_entry;
const char *path;
struct udev_device *ud_dev, *ud_parent;
const char *name;
const char *driver;
int fd, ioctl_result;
struct serial_struct serial_info; struct serial_struct serial_info;
int len, fd, ioctl_result;
DIR *dir;
ret = SP_OK; ret = SP_OK;
DEBUG("Enumerating tty devices"); DEBUG("Enumerating tty devices");
ud = udev_new(); if (!(dir = opendir("/sys/class/tty")))
ud_enumerate = udev_enumerate_new(ud); RETURN_FAIL("could not open /sys/class/tty");
udev_enumerate_add_match_subsystem(ud_enumerate, "tty");
udev_enumerate_scan_devices(ud_enumerate);
ud_list = udev_enumerate_get_list_entry(ud_enumerate);
DEBUG("Iterating over results"); DEBUG("Iterating over results");
udev_list_entry_foreach(ud_entry, ud_list) { while (!readdir_r(dir, &entry, &result) && result) {
path = udev_list_entry_get_name(ud_entry); len = readlinkat(dirfd(dir), entry.d_name, target, sizeof(target));
DEBUG("Found device %s", path); if (len <= 0 || len >= (int) sizeof(target)-1)
ud_dev = udev_device_new_from_syspath(ud, path);
/* If there is no parent device, this is a virtual tty. */
ud_parent = udev_device_get_parent(ud_dev);
if (ud_parent == NULL) {
DEBUG("No parent device, assuming virtual tty");
udev_device_unref(ud_dev);
continue; continue;
} target[len] = 0;
name = udev_device_get_devnode(ud_dev); if (strstr(target, "virtual"))
/* The serial8250 driver has a hardcoded number of ports. continue;
* The only way to tell which actually exist on a given system snprintf(name, sizeof(name), "/dev/%s", entry.d_name);
* is to try to open them and make an ioctl call. */ DEBUG("Found device %s", name);
driver = udev_device_get_driver(ud_parent); if (strstr(target, "serial8250")) {
if (driver && !strcmp(driver, "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"); DEBUG("serial8250 device, attempting to open");
if ((fd = open(name, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0) { if ((fd = open(name, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0) {
DEBUG("open failed, skipping"); DEBUG("open failed, skipping");
goto skip; continue;
} }
ioctl_result = ioctl(fd, TIOCGSERIAL, &serial_info); ioctl_result = ioctl(fd, TIOCGSERIAL, &serial_info);
close(fd); close(fd);
if (ioctl_result != 0) { if (ioctl_result != 0) {
DEBUG("ioctl failed, skipping"); DEBUG("ioctl failed, skipping");
goto skip; continue;
} }
if (serial_info.type == PORT_UNKNOWN) { if (serial_info.type == PORT_UNKNOWN) {
DEBUG("port type is unknown, skipping"); DEBUG("port type is unknown, skipping");
goto skip; continue;
} }
} }
DEBUG("Found port %s", name); DEBUG("Found port %s", name);
list = list_append(list, name); list = list_append(list, name);
skip:
udev_device_unref(ud_dev);
if (!list) { if (!list) {
SET_ERROR(ret, SP_ERR_MEM, "list append failed"); SET_ERROR(ret, SP_ERR_MEM, "list append failed");
goto out; break;
} }
} }
out: closedir(dir);
udev_enumerate_unref(ud_enumerate);
udev_unref(ud);
#endif #endif
switch (ret) { switch (ret) {