2023年8月4日 星期五

USB conception

/sys/bus/usb/devices
1-0:1.0  3-0:1.0  3-10:1.0  3-11      3-11:1.1  3-4      3-4.2      3-4.4      3-4.4:1.1  3-4.4:1.3  3-4.4:1.5  3-4.4:1.7  3-4.4:1.9  3-8:1.0  3-9:1.0  4-0:1.0  usb2  usb4
2-0:1.0  3-10     3-10:1.1  3-11:1.0  3-11:1.2  3-4:1.0  3-4.2:1.0  3-4.4:1.0  3-4.4:1.2  3-4.4:1.4  3-4.4:1.6  3-4.4:1.8  3-8        3-9      3-9:1.1  usb1     usb3

解析:
<bus>-<port[.port[.port]]>:<config>.<interface>
For more info:
1. 【USB笔记】接口描述符Interface Descriptor
2. Understand USB (in Linux)
3. superuser.com/

dmesg
[13363.344895] cdc_acm 3-4.4:1.0: ttyACM0: USB ACM device
[13363.345308] cdc_acm 3-4.4:1.2: ttyACM1: USB ACM device
[13363.346187] cdc_acm 3-4.4:1.4: ttyACM2: USB ACM device
[13363.346989] cdc_acm 3-4.4:1.6: ttyACM3: USB ACM device
4G/5G 模組會有數個 multi interface (MI)
Windows:
    裝罝管理員裡, com port(右鍵,內容)
    詳細資料,屬性,硬體識別碼
    USB\VID_1E2D&PID_0069&REV_0000&MI_02

Linux:
    $ cat /sys/devices/pci0000:00/0000:00:14.0/usb3/3-4/3-4.4/3-4.4:1.6/bInterfaceNumber
    $ ls /sys/devices/pci0000:00/0000:00:14.0/usb3/3-4/3-4.4/3-4.4:1.6/tty





好用tool: lsusb.py
lsusb.py
Output:
$ ./lsusb.py -i
 WARNING: Failure to read usb.ids
usb1              1d6b:0002 09 1IF  [USB 2.00,   480 Mbps,   0mA] (xhci-hcd 0000:00:0d.0) hub
usb2              1d6b:0003 09 1IF  [USB 3.10, 10000 Mbps,   0mA] (xhci-hcd 0000:00:0d.0) hub
usb3              1d6b:0002 09 1IF  [USB 2.00,   480 Mbps,   0mA] (xhci-hcd 0000:00:14.0) hub
  3-4               1a40:0101 09 1IF  [USB 2.00,   480 Mbps, 100mA] () hub
    3-4.2             047d:2048 00 1IF  [USB 2.00,   1.5 Mbps, 100mA] (Primax Kensington Eagle Trackball)
      3-4.2:1.0         (IF) 03:01:02 1EP  () usbhid hidraw0 (hid-generic) input15 (hid-generic)
    3-4.4             1e2d:0069 ef 10IFs [USB 2.00,   480 Mbps, 500mA] (Cinterion Wireless Modules PLSx3 f7b292b4)
      3-4.4:1.0         (IF) 02:02:01 1EP  () cdc_acm tty/ttyACM0
      3-4.4:1.1         (IF) 0a:00:00 2EPs () cdc_acm
      3-4.4:1.2         (IF) 02:02:01 1EP  () cdc_acm tty/ttyACM1
      3-4.4:1.3         (IF) 0a:00:00 2EPs () cdc_acm
      3-4.4:1.4         (IF) 02:02:01 1EP  () cdc_acm tty/ttyACM2
      3-4.4:1.5         (IF) 0a:00:00 2EPs () cdc_acm
      3-4.4:1.6         (IF) 02:02:01 1EP  () cdc_acm tty/ttyACM3
      3-4.4:1.7         (IF) 0a:00:00 2EPs () cdc_acm
      3-4.4:1.8         (IF) 02:06:00 1EP  () cdc_ether net/wwx00a0c6292b40
      3-4.4:1.9         (IF) 0a:00:00 2EPs () cdc_ether
  3-8               04f3:0c11 00 1IF  [USB 2.00,    12 Mbps, 100mA] (ELAN ELAN:Fingerprint)
    3-8:1.0           (IF) ff:00:00 5EPs ()
  3-9               13d3:56a2 ef 2IFs [USB 2.00,   480 Mbps, 500mA] (Azurewave USB2.0 HD UVC WebCam 0x0001)
    3-9:1.0           (IF) 0e:01:00 1EP  () uvcvideo video4linux/video1 video4linux/video0 input/input19
    3-9:1.1           (IF) 0e:02:00 0EPs () uvcvideo
  3-10              8087:0029 e0 2IFs [USB 2.01,    12 Mbps, 100mA] ()
    3-10:1.0          (IF) e0:01:01 3EPs () btusb bluetooth/hci0
    3-10:1.1          (IF) e0:01:01 2EPs () btusb
  3-11              1044:7a3c 00 3IFs [USB 2.00,    12 Mbps, 500mA] (GIGABYTE Fusion RGB KB)
    3-11:1.0          (IF) 03:01:01 1EP  () usbhid hidraw1 (hid-generic) input16 (hid-generic)
    3-11:1.1          (IF) 03:01:01 1EP  () usbhid hidraw2 (hid-generic) input32 (hid-generic)
    3-11:1.2          (IF) 03:01:00 1EP  () usbhid hidraw3 (hid-generic) input34 input39 input35 input33 input36 (hid-generic)
usb4              1d6b:0003 09 1IF  [USB 3.10, 20000 Mbps,   0mA] (xhci-hcd 0000:00:14.0) hub



#!/bin/bash

# Function to check if the VID and PID match
function check_vid_pid {
    local vid_pid_dir="$1"
    local vid="$2"
    local pid="$3"

    local device_vid=$(cat "$vid_pid_dir/idVendor" 2>/dev/null)
    local device_pid=$(cat "$vid_pid_dir/idProduct" 2>/dev/null)

    if [[ "$device_vid" == "$vid" && "$device_pid" == "$pid" ]]; then
        echo "$vid_pid_dir"
        return 0 # Indicate a match was found
    else
        return 1 # Indicate no match was found
    fi
}

# Search for USB devices with matching VID and PID
function search_usb_devices {
    local vid="$1"
    local pid="$2"
    local -a paths=()

    for device in /sys/bus/usb/devices/*; do
        if [[ -d "$device" ]]; then
            if check_vid_pid "$device" "$vid" "$pid"; then
                paths+=("$device")
            fi
        fi
    done
}

function find_ttyUSB_ACM {
    local path="$1"
    local bInterface="04"
    local tty_devices=()

    cd $path
    # Find directories that contain bInterfaceNumber files, limiting depth to 2
    find ./ -maxdepth 2 -type f -name "bInterfaceNumber" -print0 | while IFS= read -r -d $'\0' bInterface_file; do
        # Extract the directory containing the bInterfaceNumber file
        interface_dir=$(dirname "$bInterface_file")

        # Read the bInterfaceNumber
        interface_number=$(cat "$bInterface_file")

        # Check if the interface number matches the desired value
        if [[ "$interface_number" == "$bInterface" ]]; then
            #echo "Found matching bInterface in: $interface_dir"

            # Search for ttyUSB* device nodes within the interface directory
            find "$interface_dir" -maxdepth 1 -type d -name "ttyUSB*" -print0 | while IFS= read -r -d $'\0' ttyname; do
                echo "/dev/$(basename "$ttyname")"
                #tty_devices+=("/dev/$(basename "$ttyname")")
            done
        fi
    done

    #echo "${tty_devices[*]}"
}

# Usage: ./find_usb_device.sh VID PID
if [[ $# -ne 2 ]]; then
    echo "Usage: $0 VID PID"
    exit 1
fi

if systemctl is-enabled ModemManager.service; then
    echo "ModemManager is enabled."

    systemctl stop ModemManager.service
    sleep 3
    systemctl disable ModemManager.service
    sleep 3
    echo "ModemManager has been stopped and disabled."
else
    echo "ModemManager is not enabled."
fi

paths=$(search_usb_devices "$1" "$2")

# Iterate over the paths and find ttyUSB/ACM devices
for path in $paths; do
    echo "Searching for ttyUSB/ACM devices in: $path"
    # Capture the tty devices returned by find_ttyUSB_ACM
    tty_devices=$(find_ttyUSB_ACM "$path")

    #echo "bbb-$tty_devices"
done

output:
./find_usb_device.sh 1e2d 0069
/sys/bus/usb/devices/3-2/, 480Mbits, 500mA, USB 2.00
/sys/bus/usb/devices/3-2/3-2:1.6/tty/ttyACM3
/sys/bus/usb/devices/3-2/3-2:1.4/tty/ttyACM2
/sys/bus/usb/devices/3-2/3-2:1.2/tty/ttyACM1
/sys/bus/usb/devices/3-2/3-2:1.0/tty/ttyACM0

ludev library
#include <libudev.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[]) {
  if (argc != 4) {
    fprintf(stderr, "Usage: %s <VID> <PID> <bInterfaceNumber>\n", argv[0]);
    return 1;
  }

  const char *target_vid = argv[1];
  const char *target_pid = argv[2];
  const char *target_bInterfaceNumber = argv[3];

  struct udev *udev = udev_new();
  if (!udev) {
    fprintf(stderr, "Failed to create udev object\n");
    return 1;
  }

  struct udev_enumerate *enumerate = udev_enumerate_new(udev);
  udev_enumerate_add_match_subsystem(enumerate, "tty");
  udev_enumerate_add_match_property(enumerate, "ID_VENDOR_ID", target_vid);
  udev_enumerate_add_match_property(enumerate, "ID_MODEL_ID", target_pid);

  udev_enumerate_scan_devices(enumerate);

  struct udev_list_entry *devices = udev_enumerate_get_list_entry(enumerate);
  struct udev_list_entry *entry;

  udev_list_entry_foreach(entry, devices) {
    const char *path = udev_list_entry_get_name(entry);
    struct udev_device *dev = udev_device_new_from_syspath(udev, path);

    const char *devnode = udev_device_get_devnode(dev);
    const char *bInterface =
        udev_device_get_property_value(dev, "ID_USB_INTERFACE_NUM");

    // printf("devnode=%s, bInterface=%s\n", devnode, bInterface);

    if (devnode && bInterface &&
        strcmp(bInterface, target_bInterfaceNumber) == 0) {
      printf("Found device: %s\n", devnode);
    }

    udev_device_unref(dev);
  }

  udev_enumerate_unref(enumerate);
  udev_unref(udev);

  return 0;
}

output:
$ gcc find_usb_device.c -o find_usb_device -ludev

./find_usb_device 1bc7 1060 04
Found device: /dev/ttyUSB2
Found device: /dev/ttyUSB7
Found device: /dev/ttyUSB12

./find_usb_device 1e2d 0069 04
Found device: /dev/ttyACM2

udevadm
$ udevadm info --query=all --name=/dev/ttyUSB2
P: /devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.2/ttyUSB2/tty/ttyUSB2
N: ttyUSB2
L: 0
S: serial/by-id/usb-Telit_LE910C1-WWX_6db09e-if02-port0
S: serial/by-path/pci-0000:00:14.0-usb-0:2:1.2-port0
E: DEVPATH=/devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.2/ttyUSB2/tty/ttyUSB2
E: DEVNAME=/dev/ttyUSB2
E: MAJOR=188
E: MINOR=2
E: SUBSYSTEM=tty
E: ID_VENDOR_ID=1bc7
E: ID_MODEL_ID=1031
...
...
E: ID_USB_INTERFACE_NUM=02
E: ID_USB_DRIVER=option
E: ID_PATH=pci-0000:00:14.0-usb-0:2:1.2
E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_2_1_2

沒有留言:

張貼留言