aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Duarte <licorne@google.com>2024-03-14 20:34:53 +0000
committerDavid Duarte <git@delta.sh>2024-03-15 09:17:39 -0700
commit16d5cf67702a3e068dc4b64866090541e61bd1c4 (patch)
tree9f285c0ae50e2306ebf85018152647c9f4778bad
parenta2caf1deb2e5d88f53228829b3478571995e304c (diff)
downloadbumble-16d5cf67702a3e068dc4b64866090541e61bd1c4.tar.gz
usb: Add usb path moniker
Add a new moniker for usb and pyusb driver allowing to select the usb device using its bus id and port path like `usb:3-3.4.1`.
-rw-r--r--bumble/transport/pyusb.py9
-rw-r--r--bumble/transport/usb.py10
-rw-r--r--docs/mkdocs/src/transports/usb.md6
3 files changed, 25 insertions, 0 deletions
diff --git a/bumble/transport/pyusb.py b/bumble/transport/pyusb.py
index 5e686d1..2426b75 100644
--- a/bumble/transport/pyusb.py
+++ b/bumble/transport/pyusb.py
@@ -216,6 +216,15 @@ async def open_pyusb_transport(spec: str) -> Transport:
if ':' in spec:
vendor_id, product_id = spec.split(':')
device = usb_find(idVendor=int(vendor_id, 16), idProduct=int(product_id, 16))
+ elif '-' in spec:
+
+ def device_path(device):
+ if device.port_numbers:
+ return f'{device.bus}-{".".join(map(str, device.port_numbers))}'
+ else:
+ return str(device.bus)
+
+ device = usb_find(custom_match=lambda device: device_path(device) == spec)
else:
device_index = int(spec)
devices = list(
diff --git a/bumble/transport/usb.py b/bumble/transport/usb.py
index 1257260..6479016 100644
--- a/bumble/transport/usb.py
+++ b/bumble/transport/usb.py
@@ -396,6 +396,16 @@ async def open_usb_transport(spec: str) -> Transport:
break
device_index -= 1
device.close()
+ elif '-' in spec:
+
+ def device_path(device):
+ return f'{device.getBusNumber()}-{".".join(map(str, device.getPortNumberList()))}'
+
+ for device in context.getDeviceIterator(skip_on_error=True):
+ if device_path(device) == spec:
+ found = device
+ break
+ device.close()
else:
# Look for a compatible device by index
def device_is_bluetooth_hci(device):
diff --git a/docs/mkdocs/src/transports/usb.md b/docs/mkdocs/src/transports/usb.md
index e400630..08949f0 100644
--- a/docs/mkdocs/src/transports/usb.md
+++ b/docs/mkdocs/src/transports/usb.md
@@ -10,6 +10,7 @@ The moniker for a USB transport is either:
* `usb:<vendor>:<product>`
* `usb:<vendor>:<product>/<serial-number>`
* `usb:<vendor>:<product>#<index>`
+ * `usb:<bus>-<port_numbers>`
with `<index>` as a 0-based index (0 being the first one) to select amongst all the matching devices when there are more than one.
In the `usb:<index>` form, matching devices are the ones supporting Bluetooth HCI, as declared by their Class, Subclass and Protocol.
@@ -17,6 +18,8 @@ In the `usb:<vendor>:<product>#<index>` form, matching devices are the ones with
`<vendor>` and `<product>` are a vendor ID and product ID in hexadecimal.
+with `<port_numbers>` as a list of all port numbers from root separated with dots `.`
+
In addition, if the moniker ends with the symbol "!", the device will be used in "forced" mode:
the first USB interface of the device will be used, regardless of the interface class/subclass.
This may be useful for some devices that use a custom class/subclass but may nonetheless work as-is.
@@ -37,6 +40,9 @@ This may be useful for some devices that use a custom class/subclass but may non
`usb:0B05:17CB!`
The BT USB dongle vendor=0B05 and product=17CB, in "forced" mode.
+ `usb:3-3.4.1`
+ The BT USB dongle on bus 3 on port path 3, 4, 1.
+
## Alternative
The library includes two different implementations of the USB transport, implemented using different python bindings for `libusb`.