-
Notifications
You must be signed in to change notification settings - Fork 79
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add usb_probe tool and improve compatibility (#33)
* add usb_probe tool and improve compatibility with older/non-compliant devices * fix logic test * add doc
- Loading branch information
1 parent
996a9e2
commit 84d70ad
Showing
8 changed files
with
336 additions
and
64 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
# Copyright 2021-2022 Google LLC | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# https://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
# ----------------------------------------------------------------------------- | ||
# This tool lists all the USB devices, with details about each device. | ||
# For each device, the different possible Bumble transport strings that can | ||
# refer to it are listed. If the device is known to be a Bluetooth HCI device, | ||
# its identifier is printed in reverse colors, and the transport names in cyan color. | ||
# For other devices, regardless of their type, the transport names are printed | ||
# in red. Whether that device is actually a Bluetooth device or not depends on | ||
# whether it is a Bluetooth device that uses a non-standard Class, or some other | ||
# type of device (there's no way to tell). | ||
# ----------------------------------------------------------------------------- | ||
|
||
# ----------------------------------------------------------------------------- | ||
# Imports | ||
# ----------------------------------------------------------------------------- | ||
import os | ||
import logging | ||
import usb1 | ||
from colors import color | ||
|
||
|
||
# ----------------------------------------------------------------------------- | ||
# Constants | ||
# ----------------------------------------------------------------------------- | ||
USB_DEVICE_CLASS_WIRELESS_CONTROLLER = 0xE0 | ||
USB_DEVICE_SUBCLASS_RF_CONTROLLER = 0x01 | ||
USB_DEVICE_PROTOCOL_BLUETOOTH_PRIMARY_CONTROLLER = 0x01 | ||
|
||
USB_DEVICE_CLASSES = { | ||
0x00: 'Device', | ||
0x01: 'Audio', | ||
0x02: 'Communications and CDC Control', | ||
0x03: 'Human Interface Device', | ||
0x05: 'Physical', | ||
0x06: 'Still Imaging', | ||
0x07: 'Printer', | ||
0x08: 'Mass Storage', | ||
0x09: 'Hub', | ||
0x0A: 'CDC Data', | ||
0x0B: 'Smart Card', | ||
0x0D: 'Content Security', | ||
0x0E: 'Video', | ||
0x0F: 'Personal Healthcare', | ||
0x10: 'Audio/Video', | ||
0x11: 'Billboard', | ||
0x12: 'USB Type-C Bridge', | ||
0x3C: 'I3C', | ||
0xDC: 'Diagnostic', | ||
USB_DEVICE_CLASS_WIRELESS_CONTROLLER: ( | ||
'Wireless Controller', | ||
{ | ||
0x01: { | ||
0x01: 'Bluetooth', | ||
0x02: 'UWB', | ||
0x03: 'Remote NDIS', | ||
0x04: 'Bluetooth AMP' | ||
} | ||
} | ||
), | ||
0xEF: 'Miscellaneous', | ||
0xFE: 'Application Specific', | ||
0xFF: 'Vendor Specific' | ||
} | ||
|
||
|
||
# ----------------------------------------------------------------------------- | ||
def main(): | ||
logging.basicConfig(level = os.environ.get('BUMBLE_LOGLEVEL', 'WARNING').upper()) | ||
|
||
with usb1.USBContext() as context: | ||
bluetooth_device_count = 0 | ||
devices = {} | ||
|
||
for device in context.getDeviceIterator(skip_on_error=True): | ||
device_class = device.getDeviceClass() | ||
device_subclass = device.getDeviceSubClass() | ||
device_protocol = device.getDeviceProtocol() | ||
|
||
device_id = (device.getVendorID(), device.getProductID()) | ||
|
||
device_is_bluetooth_hci = ( | ||
device_class == USB_DEVICE_CLASS_WIRELESS_CONTROLLER and | ||
device_subclass == USB_DEVICE_SUBCLASS_RF_CONTROLLER and | ||
device_protocol == USB_DEVICE_PROTOCOL_BLUETOOTH_PRIMARY_CONTROLLER | ||
) | ||
|
||
device_class_details = '' | ||
device_class_info = USB_DEVICE_CLASSES.get(device_class) | ||
if device_class_info is not None: | ||
if type(device_class_info) is tuple: | ||
device_class = device_class_info[0] | ||
device_subclass_info = device_class_info[1].get(device_subclass) | ||
if device_subclass_info: | ||
device_class_details = f' [{device_subclass_info.get(device_protocol)}]' | ||
else: | ||
device_class = device_class_info | ||
|
||
if device_is_bluetooth_hci: | ||
bluetooth_device_count += 1 | ||
fg_color = 'black' | ||
bg_color = 'yellow' | ||
else: | ||
fg_color = 'yellow' | ||
bg_color = 'black' | ||
|
||
# Compute the different ways this can be referenced as a Bumble transport | ||
bumble_transport_names = [] | ||
basic_transport_name = f'usb:{device.getVendorID():04X}:{device.getProductID():04X}' | ||
|
||
if device_is_bluetooth_hci: | ||
bumble_transport_names.append(f'usb:{bluetooth_device_count - 1}') | ||
|
||
serial_number_collision = False | ||
if device_id in devices: | ||
for device_serial in devices[device_id]: | ||
if device_serial == device.getSerialNumber(): | ||
serial_number_collision = True | ||
|
||
if device_id not in devices: | ||
bumble_transport_names.append(basic_transport_name) | ||
else: | ||
bumble_transport_names.append(f'{basic_transport_name}#{len(devices[device_id])}') | ||
|
||
if device.getSerialNumber() and not serial_number_collision: | ||
bumble_transport_names.append(f'{basic_transport_name}/{device.getSerialNumber()}') | ||
|
||
print(color(f'ID {device.getVendorID():04X}:{device.getProductID():04X}', fg=fg_color, bg=bg_color)) | ||
if bumble_transport_names: | ||
print(color(' Bumble Transport Names:', 'blue'), ' or '.join(color(x, 'cyan' if device_is_bluetooth_hci else 'red') for x in bumble_transport_names)) | ||
print(color(' Bus/Device: ', 'green'), f'{device.getBusNumber():03}/{device.getDeviceAddress():03}') | ||
if device.getSerialNumber(): | ||
print(color(' Serial: ', 'green'), device.getSerialNumber()) | ||
print(color(' Class: ', 'green'), device_class) | ||
print(color(' Subclass/Protocol: ', 'green'), f'{device_subclass}/{device_protocol}{device_class_details}') | ||
print(color(' Manufacturer: ', 'green'), device.getManufacturer()) | ||
print(color(' Product: ', 'green'), device.getProduct()) | ||
print() | ||
|
||
devices.setdefault(device_id, []).append(device.getSerialNumber()) | ||
|
||
|
||
# ----------------------------------------------------------------------------- | ||
if __name__ == '__main__': | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.