From 9942940e9f125fd12e279596c51e03dd3afa2733 Mon Sep 17 00:00:00 2001 From: kyufie Date: Tue, 1 Oct 2024 19:33:57 +0700 Subject: [PATCH] enhance(main/libusb): Add integration with `termux-usb -E` This commit adds the ability for `libusb` to access connected USB device through file descriptor given by `termux-usb -E` --- packages/libusb/build.sh | 1 + packages/libusb/termux-usb-support.patch | 163 +++++++++++++++++++++++ 2 files changed, 164 insertions(+) create mode 100644 packages/libusb/termux-usb-support.patch diff --git a/packages/libusb/build.sh b/packages/libusb/build.sh index 0bcb5a01017ed0..fd63242ebead1d 100644 --- a/packages/libusb/build.sh +++ b/packages/libusb/build.sh @@ -3,6 +3,7 @@ TERMUX_PKG_DESCRIPTION="A C library that provides generic access to USB devices" TERMUX_PKG_LICENSE="LGPL-2.1" TERMUX_PKG_MAINTAINER="@termux" TERMUX_PKG_VERSION="1.0.27" +TERMUX_PKG_REVISION=1 TERMUX_PKG_SRCURL=https://github.com/libusb/libusb/releases/download/v${TERMUX_PKG_VERSION}/libusb-${TERMUX_PKG_VERSION}.tar.bz2 TERMUX_PKG_SHA256=ffaa41d741a8a3bee244ac8e54a72ea05bf2879663c098c82fc5757853441575 TERMUX_PKG_AUTO_UPDATE=true diff --git a/packages/libusb/termux-usb-support.patch b/packages/libusb/termux-usb-support.patch new file mode 100644 index 00000000000000..ace26217b43751 --- /dev/null +++ b/packages/libusb/termux-usb-support.patch @@ -0,0 +1,163 @@ +--- libusb-1.0.27/libusb/os/linux_usbfs.c ++++ libusb-1.0.27.mod/libusb/os/linux_usbfs.c +@@ -26,6 +26,7 @@ + #include "linux_usbfs.h" + + #include ++#include + #include + #include + #include +@@ -74,6 +75,7 @@ + + #define USBDEV_PATH "/dev" + #define USB_DEVTMPFS_PATH "/dev/bus/usb" ++#define TERMUX_USB_ENV "TERMUX_USB_FD" + + /* use usbdev*.* device names in /dev instead of the usbfs bus directories */ + static int usbdev_names = 0; +@@ -105,6 +107,8 @@ + static int linux_default_scan_devices(struct libusb_context *ctx); + #endif + ++static int linux_termux_scan_devices(struct libusb_context *ctx); ++ + struct kernel_version { + int major; + int minor; +@@ -127,6 +131,7 @@ + size_t descriptors_len; + struct config_descriptor *config_descriptors; + int active_config; /* cache val for !sysfs_available */ ++ int termux_fd; + }; + + struct linux_device_handle_priv { +@@ -188,6 +193,24 @@ + char path[24]; + int fd; + ++ struct linux_device_priv *priv = usbi_get_device_priv(dev); ++ ++ if ((fd = priv->termux_fd) != -1) { ++ /* The returned fd (from this function) might gets closed at some ++ * point in the future when the user close the handle ++ * Avoid touching the fd given by Android since we might want to close ++ * and reopen the device again */ ++ if ((fd = dup(priv->termux_fd)) == -1) { ++ usbi_err(ctx, "unable to duplicate termux usb fd: %s", strerror(errno)); ++ return LIBUSB_ERROR_IO; ++ } ++ /* Android gives fd with O_RDWR by default, and changing the mode ++ * of an fd is not possible at the moment */ ++ usbi_info(ctx, "setting fd mode for termux supplied usb device is unsupported, the fd will have mode O_RDWR instead"); ++ ++ return fd; ++ } ++ + if (usbdev_names) + snprintf(path, sizeof(path), USBDEV_PATH "/usbdev%u.%u", + dev->bus_number, dev->device_address); +@@ -458,12 +481,18 @@ + + usbi_mutex_static_lock(&linux_hotplug_lock); + ++ if (getenv(TERMUX_USB_ENV)) { ++ ret = linux_termux_scan_devices(ctx); ++ goto out; ++ } ++ + #if defined(HAVE_LIBUDEV) + ret = linux_udev_scan_devices(ctx); + #else + ret = linux_default_scan_devices(ctx); + #endif + ++out: + usbi_mutex_static_unlock(&linux_hotplug_lock); + + return ret; +@@ -916,6 +945,8 @@ + int fd, speed, r; + ssize_t nb; + ++ priv->termux_fd = -1; ++ + dev->bus_number = busnum; + dev->device_address = devaddr; + +@@ -1328,6 +1359,74 @@ + } + #endif + ++static int linux_termux_get_devinfo(int fd, uint8_t *busnum, uint8_t *devaddr) ++{ ++ char proc_path[PATH_MAX], usbfs_path[PATH_MAX]; ++ ++ snprintf(proc_path, PATH_MAX, "/proc/self/fd/%u", fd); ++ if (readlink(proc_path, usbfs_path, PATH_MAX) < 0 || ++ strncmp("/dev/bus/usb/", usbfs_path, 12)) { ++ return LIBUSB_ERROR_IO; ++ } ++ ++ if (sscanf(usbfs_path, "/dev/bus/usb/%hhu/%hhu", busnum, devaddr) != 2) ++ return LIBUSB_ERROR_IO; ++ ++ return LIBUSB_SUCCESS; ++} ++ ++static int linux_termux_scan_devices(struct libusb_context *ctx) ++{ ++ struct libusb_device *dev; ++ struct linux_device_priv *priv; ++ uint8_t busnum, devaddr; ++ unsigned long session_id; ++ char *envval, *envval_end; ++ int fd, r; ++ ++ envval = getenv(TERMUX_USB_ENV); ++ ++ assert(envval); ++ ++ errno = 0; ++ fd = strtol(envval, &envval_end, 10); ++ if (*envval == '\0' || *envval_end != '\0' || errno || fd < 0) { ++ usbi_err(ctx, "invalid usb fd in TERMUX_USB_FD"); ++ return LIBUSB_ERROR_NO_DEVICE; ++ } ++ ++ r = linux_termux_get_devinfo(fd, &busnum, &devaddr); ++ if (r < 0) { ++ usbi_err(ctx, "unable to get device info from fd %d", fd); ++ return r; ++ } ++ ++ session_id = busnum << 8 | devaddr; ++ usbi_dbg(ctx, "allocating new device for %u/%u (session %lu)", ++ busnum, devaddr, session_id); ++ dev = usbi_alloc_device(ctx, session_id); ++ if (!dev) ++ return LIBUSB_ERROR_NO_MEM; ++ ++ r = initialize_device(dev, busnum, devaddr, NULL, fd); ++ if (r < 0) ++ goto out; ++ r = usbi_sanitize_device(dev); ++ if (r < 0) ++ goto out; ++ ++ priv = usbi_get_device_priv(dev); ++ priv->termux_fd = fd; ++ ++out: ++ if (r < 0) ++ libusb_unref_device(dev); ++ else ++ usbi_connect_device(dev); ++ ++ return r; ++} ++ + static int initialize_handle(struct libusb_device_handle *handle, int fd) + { + struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle);