From 83e23f85da8dc4df1a94d865a509b7b2c85847ab Mon Sep 17 00:00:00 2001 From: Talha Can Havadar Date: Mon, 24 Mar 2025 22:08:29 +0100 Subject: [PATCH 1/2] add block dev column in list command and add option for debug log --- poetry.lock | 13 ++++++++++++- pyproject.toml | 1 + sdwire/backend/detect.py | 27 ++++++++++++++++++--------- sdwire/backend/device/sdwire.py | 14 +++++++++++++- sdwire/backend/device/sdwirec.py | 20 +++++++++++++++++--- sdwire/backend/device/usb_device.py | 3 +++ sdwire/main.py | 10 ++++++---- 7 files changed, 70 insertions(+), 18 deletions(-) diff --git a/poetry.lock b/poetry.lock index 2e8280a..7da04c9 100644 --- a/poetry.lock +++ b/poetry.lock @@ -161,6 +161,17 @@ files = [ [package.extras] cp2110 = ["hidapi"] +[[package]] +name = "pyudev" +version = "0.24.3" +description = "A libudev binding" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pyudev-0.24.3-py3-none-any.whl", hash = "sha256:e8246f0a014fe370119ba2bc781bfbe62c0298d0d6b39c94e83102a8a3f56960"}, + {file = "pyudev-0.24.3.tar.gz", hash = "sha256:2e945427a21674893bb97632401db62139d91cea1ee96137cc7b07ad22198fc7"}, +] + [[package]] name = "pyusb" version = "1.2.1" @@ -186,4 +197,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.12" -content-hash = "c61936c9ccf80594827f2143bbe271ba5f5cd18d167c6a04cf01301c86e08813" +content-hash = "c662532cb37834415d4ded9a9a93023f02c1853c215d5d48a6446b6930a28a9f" diff --git a/pyproject.toml b/pyproject.toml index 7ee5bb8..465bd44 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,6 +14,7 @@ adafruit-board-toolkit = "^1.1.1" semver = "^3.0.2" pyusb = "^1.2.1" pyftdi = "^0.55.4" +pyudev = "^0.24.3" [tool.poetry.group.dev.dependencies] diff --git a/sdwire/backend/detect.py b/sdwire/backend/detect.py index 898658d..3e6df01 100644 --- a/sdwire/backend/detect.py +++ b/sdwire/backend/detect.py @@ -8,6 +8,7 @@ from .device.sdwirec import SDWireC from .device.usb_device import PortInfo +import pyudev import usb.core import usb.util from usb.core import Device @@ -52,7 +53,11 @@ def get_sdwire_devices() -> List[SDWire]: # Badgerd SDWireC # VID = 0x04e8 PID = 0x6001 result = [] - devices: List[Device] = usb.core.find(find_all=True) + devices: List[Device] = pyudev.Context().list_devices( + subsystem="usb", + ID_VENDOR_ID=f"{constants.SDWIRE3_VID:04x}", + ID_MODEL_ID=f"{constants.SDWIRE3_PID:04x}", + ) if not devices: log.info("no usb devices found while searching for SDWire..") return [] @@ -62,14 +67,15 @@ def get_sdwire_devices() -> List[SDWire]: product = None serial = None manufacturer = None + bus = None + address = None try: - product = device.idProduct - vendor = device.idVendor - serial = ( - usb.util.get_string(device, device.iSerialNumber, None) - + f"{device.bus}{device.port_number}" - ) - manufacturer = device.manufacturer + product = int(f"0x{device.get("ID_MODEL_ID")}", 16) + vendor = int(f"0x{device.get("ID_VENDOR_ID")}", 16) + bus = int(device.get("BUSNUM")) + address = int(device.get("DEVNUM")) + serial = f"{device.get("ID_USB_SERIAL_SHORT")}:{bus}.{address}" + manufacturer = "" except Exception as e: log.debug( "not able to get usb product, serial_number and manufacturer information, err: %s", @@ -77,9 +83,12 @@ def get_sdwire_devices() -> List[SDWire]: ) if product == constants.SDWIRE3_PID and vendor == constants.SDWIRE3_VID: + usb_device: List[Device] = usb.core.find( + idVendor=vendor, idProduct=product, bus=bus, address=address + ) result.append( SDWire( - port_info=PortInfo(device, product, vendor, serial, device), + port_info=PortInfo(device, product, vendor, serial, usb_device), generation=SDWIRE_GENERATION_SDWIRE3, ) ) diff --git a/sdwire/backend/device/sdwire.py b/sdwire/backend/device/sdwire.py index c8990ff..10254bb 100644 --- a/sdwire/backend/device/sdwire.py +++ b/sdwire/backend/device/sdwire.py @@ -8,10 +8,18 @@ class SDWire(USBDevice): + __block_dev = None def __init__(self, port_info: PortInfo, generation: int): super().__init__(port_info) self.generation = generation + for sibling in self.dev_string.parent.children: + if ( + self.dev_string.device_path != sibling.device_path + and sibling.device_type == "disk" + ): + self.__block_dev = f"/dev/{sibling.device_path.split("/")[-1]}" + break def switch_ts(self): try: @@ -33,8 +41,12 @@ def switch_dut(self): e, ) + @property + def block_dev(self): + return self.__block_dev + def __str__(self): - return f"{self.serial_string}\t[{int(self.manufacturer_string):04x}::{int(self.product_string):04x}]" + return f"{self.serial_string}\t[{int(self.manufacturer_string):04x}::{int(self.product_string):04x}]\t\t{self.block_dev}" def __repr__(self): return self.__str__() diff --git a/sdwire/backend/device/sdwirec.py b/sdwire/backend/device/sdwirec.py index 3f48d72..1a1742f 100644 --- a/sdwire/backend/device/sdwirec.py +++ b/sdwire/backend/device/sdwirec.py @@ -7,18 +7,32 @@ class SDWireC(USBDevice): + __block_dev = None def __init__(self, port_info: PortInfo): super().__init__(port_info) + for d in self._pyudev_context.list_devices(ID_MODEL="sd-wire"): + d_serial = d.get("ID_USB_SERIAL_SHORT", None) + if d_serial is not None and d_serial == self.serial_string: + for sibling in d.parent.children: + if ( + d.device_path != sibling.device_path + and sibling.device_type == "disk" + ): + self.__block_dev = f"/dev/{sibling.device_path.split("/")[-1]}" + break + break def __str__(self): - return ( - f"{self.serial_string}\t[{self.product_string}::{self.manufacturer_string}]" - ) + return f"{self.serial_string}\t[{self.product_string}::{self.manufacturer_string}]\t{self.block_dev}" def __repr__(self): return self.__str__() + @property + def block_dev(self): + return self.__block_dev + def switch_ts(self): self._set_sdwire(1) diff --git a/sdwire/backend/device/usb_device.py b/sdwire/backend/device/usb_device.py index b984cd7..cf5ae97 100644 --- a/sdwire/backend/device/usb_device.py +++ b/sdwire/backend/device/usb_device.py @@ -1,4 +1,5 @@ from collections import namedtuple +import pyudev from serial.tools.list_ports_common import ListPortInfo PortInfo = namedtuple( @@ -8,9 +9,11 @@ class USBDevice: __port_info = None + _pyudev_context = None def __init__(self, port_info: PortInfo): self.__port_info = port_info + self._pyudev_context = pyudev.Context() @property def usb_device(self): diff --git a/sdwire/main.py b/sdwire/main.py index 251e3f1..9e99c10 100644 --- a/sdwire/main.py +++ b/sdwire/main.py @@ -1,4 +1,5 @@ #!/usr/bin/env python +import logging import click from .backend import utils from .backend import detect @@ -6,14 +7,15 @@ @click.group() -def main(): - pass +@click.option("--debug", required=False, is_flag=True, help="Enable debug output") +def main(debug=None): + if debug: + logging.basicConfig(level=logging.DEBUG) @main.command() def list(): - - print(f"Serial\t\t\tProduct Info") + print(f"Serial\t\t\tProduct Info\t\tBlock Dev") for sdwire in detect.get_sdwire_devices(): print(sdwire) From 3ccaa1b874ff191335a170a41cbb03a4b152d773 Mon Sep 17 00:00:00 2001 From: Talha Can Havadar Date: Mon, 24 Mar 2025 22:11:18 +0100 Subject: [PATCH 2/2] bump version to 0.2.3 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 465bd44..301fc1f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "sdwire" -version = "0.2.2" +version = "0.2.3" description = "CLI application to interact with Badgerd SDWire devices" authors = ["Talha Can Havadar "] license = "GPL-3"