The branch main has been updated by kevans:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=4c556a4e8d149169a7d8e029aee7f3d017fd4e7f

commit 4c556a4e8d149169a7d8e029aee7f3d017fd4e7f
Author:     Aymeric Wibo <obi...@gmail.com>
AuthorDate: 2025-06-12 16:54:13 +0000
Commit:     Kyle Evans <kev...@freebsd.org>
CommitDate: 2025-06-12 16:56:31 +0000

    libusb: implement `libusb_get_parent`
    
    Newer versions of drivers such as libwacom (graphics tablets) or
    libfprint (fingerprint scanners) call g_usb_device_get_parent.  This in
    turn calls libusb_get_parent on platforms which implement it, and
    returns NULL on platforms that don't.  This patch implements this
    function on FreeBSD.
    
    Reviewed by:    bapt, kevans
    Differential Revision:  https://reviews.freebsd.org/D46992
---
 lib/libusb/libusb.3   |  9 +++++++--
 lib/libusb/libusb.h   |  1 +
 lib/libusb/libusb10.c | 34 ++++++++++++++++++++++++++++++++--
 lib/libusb/libusb10.h |  1 +
 4 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/lib/libusb/libusb.3 b/lib/libusb/libusb.3
index 1ca0e677d96f..a9a99f307a86 100644
--- a/lib/libusb/libusb.3
+++ b/lib/libusb/libusb.3
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd May 16, 2025
+.Dd June 12, 2025
 .Dt LIBUSB 3
 .Os
 .Sh NAME
@@ -117,7 +117,7 @@ This function does not return NULL.
 .Fn libusb_set_debug "libusb_context *ctx" "int level"
 Set the debug level to
 .Fa level .
-.Pp
+.Sh DEVICE HANDLING AND ENUMERATION
 .Ft ssize_t
 .Fn libusb_get_device_list "libusb_context *ctx" "libusb_device ***list"
 Populate
@@ -220,6 +220,11 @@ Close a device handle.
 Get the device contained by devh.
 Returns NULL on error.
 .Pp
+.Ft libusb_device *
+.Fn libusb_get_parent "libusb_device *dev"
+Get dev's parent device.
+Returns NULL if the device has no parent (i.e. is a root device).
+.Pp
 .Ft int
 .Fn libusb_get_configuration "libusb_device_handle *devh" "int *config"
 Returns the value of the current configuration.
diff --git a/lib/libusb/libusb.h b/lib/libusb/libusb.h
index cdac94b17c64..0aad29aa4ecc 100644
--- a/lib/libusb/libusb.h
+++ b/lib/libusb/libusb.h
@@ -503,6 +503,7 @@ int libusb_open(libusb_device * dev, libusb_device_handle 
** devh);
 libusb_device_handle *libusb_open_device_with_vid_pid(libusb_context * ctx, 
uint16_t vendor_id, uint16_t product_id);
 void   libusb_close(libusb_device_handle * devh);
 libusb_device *libusb_get_device(libusb_device_handle * devh);
+libusb_device *libusb_get_parent(libusb_device * dev);
 int    libusb_get_configuration(libusb_device_handle * devh, int *config);
 int    libusb_set_configuration(libusb_device_handle * devh, int 
configuration);
 int    libusb_claim_interface(libusb_device_handle * devh, int 
interface_number);
diff --git a/lib/libusb/libusb10.c b/lib/libusb/libusb10.c
index b442a1f489a0..3e81f234a735 100644
--- a/lib/libusb/libusb10.c
+++ b/lib/libusb/libusb10.c
@@ -3,6 +3,7 @@
  *
  * Copyright (c) 2009 Sylvestre Gallon. All rights reserved.
  * Copyright (c) 2009-2023 Hans Petter Selasky
+ * Copyright (c) 2024 Aymeric Wibo
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -311,9 +312,9 @@ ssize_t
 libusb_get_device_list(libusb_context *ctx, libusb_device ***list)
 {
        struct libusb20_backend *usb_backend;
-       struct libusb20_device *pdev;
+       struct libusb20_device *pdev, *parent_dev;
        struct libusb_device *dev;
-       int i;
+       int i, j, k;
 
        ctx = GET_CONTEXT(ctx);
 
@@ -365,6 +366,9 @@ libusb_get_device_list(libusb_context *ctx, libusb_device 
***list)
                /* set context we belong to */
                dev->ctx = ctx;
 
+               /* assume we have no parent by default */
+               dev->parent_dev = NULL;
+
                /* link together the two structures */
                dev->os_priv = pdev;
                pdev->privLuData = dev;
@@ -374,6 +378,25 @@ libusb_get_device_list(libusb_context *ctx, libusb_device 
***list)
        }
        (*list)[i] = NULL;
 
+       /* for each device, find its parent */
+       for (j = 0; j < i; j++) {
+               pdev = (*list)[j]->os_priv;
+
+               for (k = 0; k < i; k++) {
+                       if (k == j)
+                               continue;
+
+                       parent_dev = (*list)[k]->os_priv;
+
+                       if (parent_dev->bus_number != pdev->bus_number)
+                               continue;
+                       if (parent_dev->device_address == pdev->parent_address) 
{
+                               (*list)[j]->parent_dev = 
libusb_ref_device((*list)[k]);
+                               break;
+                       }
+               }
+       }
+
        libusb20_be_free(usb_backend);
        return (i);
 }
@@ -540,6 +563,7 @@ libusb_unref_device(libusb_device *dev)
        CTX_UNLOCK(dev->ctx);
 
        if (dev->refcnt == 0) {
+               libusb_unref_device(dev->parent_dev);
                libusb20_dev_free(dev->os_priv);
                free(dev);
        }
@@ -816,6 +840,12 @@ libusb_set_interface_alt_setting(struct libusb20_device 
*pdev,
        return (err ? LIBUSB_ERROR_OTHER : 0);
 }
 
+libusb_device *
+libusb_get_parent(libusb_device *dev)
+{
+       return (dev->parent_dev);
+}
+
 static struct libusb20_transfer *
 libusb10_get_transfer(struct libusb20_device *pdev,
     uint8_t endpoint, uint8_t xfer_index)
diff --git a/lib/libusb/libusb10.h b/lib/libusb/libusb10.h
index f34ea25740d6..70b5525df537 100644
--- a/lib/libusb/libusb10.h
+++ b/lib/libusb/libusb10.h
@@ -142,6 +142,7 @@ struct libusb_device {
        struct libusb_super_pollfd dev_poll;
 
        struct libusb_context *ctx;
+       struct libusb_device *parent_dev;
 
        TAILQ_ENTRY(libusb_device) hotplug_entry;
 

Reply via email to