Как надежно различать два одинаковых USB-устройства в Window
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 08.01.25 18:55
Оценка:
Как известно, два одинаковых USB-устройства, не имеющих внутренних состояний, которые можно было бы использовать в качестве идентификаторов, из любой системы выглядят одинаково, и система не имеет возможности определить, какое из устройств куда подключено. Для адресации таких устройств обычно генерируются внутренние уникальные идентификаторы на основе физического адреса (контроллер/хаб/порт).

У меня сейчас нет задачи различать именно сами устройства — достаточно было бы адресовать их по подключению. Я наивно полагал, что свойство Location information (SPDRP_LOCATION_INFORMATION) как раз и является уникальным и постоянным идентификатором устройства. У меня на ноутбуке один внутренний хаб, и для всех устройств всегда Hub_#0001.

Но отправил программу пользователю, а у него между перезагрузками Location Information меняется: Port_#0001.Hub_#0003, Port_#0001.Hub_#0007, Port_#0001.Hub_#0004, Port_#0001.Hub_#0005. Судя по всему, у контроллера несколько хабов, и они определяются в случайном порядке.

Какие из доступных свойств устройства можно надежно и предсказуемо (чтоб не менялись между перезагрузками) использовать для адресации?

P.S. Уточню: требуется не способ адресации заранее неизвестного устройства в заранее неизвестной системе, а постоянный адрес уже известного устройства. То есть, в первый раз устройство будет найдено любым из доступных в системе способов (по имени или другим свойствам), а уже затем нужно определить его "физический адрес", чтобы при следующем запуске (в том числе после выключения/перезагрузки) уверенно и предсказуемо найти его уже по адресу — разумеется, при условии, что оно подключено к тому же самому разъему.
Отредактировано 08.01.2025 19:06 Евгений Музыченко . Предыдущая версия .
Re: Как надежно различать два одинаковых USB-устройства в Window
От: velkin Удмуртия https://kisa.biz
Дата: 08.01.25 20:32
Оценка: 14 (1)
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>P.S. Уточню: требуется не способ адресации заранее неизвестного устройства в заранее неизвестной системе, а постоянный адрес уже известного устройства. То есть, в первый раз устройство будет найдено любым из доступных в системе способов (по имени или другим свойствам), а уже затем нужно определить его "физический адрес", чтобы при следующем запуске (в том числе после выключения/перезагрузки) уверенно и предсказуемо найти его уже по адресу — разумеется, при условии, что оно подключено к тому же самому разъему.


У меня к примеру была задача поставить на Raspberry Pi 2 проброс портов в интернет. Я скомпилировал драйвера для USB устройств CH34X. И началось, каждый раз при перезагрузке компьютера получались разные ttyUSB или в терминологии виндузятников COM порты.

Я считал командной информацию для каждого из USB портов. Сами устройства CH34X как клоны.

  udev_info_port1.txt
Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.

looking at device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2:1.0/ttyUSB0/tty/ttyUSB0':
KERNEL=="ttyUSB0"
SUBSYSTEM=="tty"
DRIVER==""
ATTR{power/control}=="auto"
ATTR{power/runtime_active_time}=="0"
ATTR{power/runtime_status}=="unsupported"
ATTR{power/runtime_suspended_time}=="0"

looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2:1.0/ttyUSB0':
KERNELS=="ttyUSB0"
SUBSYSTEMS=="usb-serial"
DRIVERS=="ch341-uart"
ATTRS{port_number}=="0"
ATTRS{power/control}=="auto"
ATTRS{power/runtime_active_time}=="0"
ATTRS{power/runtime_status}=="unsupported"
ATTRS{power/runtime_suspended_time}=="0"

looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2:1.0':
KERNELS=="1-1.2:1.0"
SUBSYSTEMS=="usb"
DRIVERS=="ch341"
ATTRS{authorized}=="1"
ATTRS{bAlternateSetting}==" 0"
ATTRS{bInterfaceClass}=="ff"
ATTRS{bInterfaceNumber}=="00"
ATTRS{bInterfaceProtocol}=="02"
ATTRS{bInterfaceSubClass}=="01"
ATTRS{bNumEndpoints}=="03"
ATTRS{supports_autosuspend}=="1"

looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2':
KERNELS=="1-1.2"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{authorized}=="1"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{bConfigurationValue}=="1"
ATTRS{bDeviceClass}=="ff"
ATTRS{bDeviceProtocol}=="00"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bMaxPacketSize0}=="8"
ATTRS{bMaxPower}=="96mA"
ATTRS{bNumConfigurations}=="1"
ATTRS{bNumInterfaces}==" 1"
ATTRS{bcdDevice}=="0254"
ATTRS{bmAttributes}=="80"
ATTRS{busnum}=="1"
ATTRS{configuration}==""
ATTRS{devnum}=="10"
ATTRS{devpath}=="1.2"
ATTRS{devspec}=="(null)"
ATTRS{idProduct}=="7523"
ATTRS{idVendor}=="1a86"
ATTRS{ltm_capable}=="no"
ATTRS{maxchild}=="0"
ATTRS{power/active_duration}=="3100"
ATTRS{power/autosuspend}=="2"
ATTRS{power/autosuspend_delay_ms}=="2000"
ATTRS{power/connected_duration}=="3100"
ATTRS{power/control}=="on"
ATTRS{power/level}=="on"
ATTRS{power/persist}=="1"
ATTRS{power/runtime_active_time}=="2870"
ATTRS{power/runtime_status}=="active"
ATTRS{power/runtime_suspended_time}=="0"
ATTRS{product}=="USB2.0-Ser!"
ATTRS{quirks}=="0x0"
ATTRS{removable}=="removable"
ATTRS{remove}=="(not readable)"
ATTRS{rx_lanes}=="1"
ATTRS{speed}=="12"
ATTRS{tx_lanes}=="1"
ATTRS{urbnum}=="16"
ATTRS{version}==" 1.10"

looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1':
KERNELS=="1-1"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{authorized}=="1"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{bConfigurationValue}=="1"
ATTRS{bDeviceClass}=="09"
ATTRS{bDeviceProtocol}=="02"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bMaxPacketSize0}=="64"
ATTRS{bMaxPower}=="2mA"
ATTRS{bNumConfigurations}=="1"
ATTRS{bNumInterfaces}==" 1"
ATTRS{bcdDevice}=="0200"
ATTRS{bmAttributes}=="e0"
ATTRS{busnum}=="1"
ATTRS{configuration}==""
ATTRS{devnum}=="2"
ATTRS{devpath}=="1"
ATTRS{idProduct}=="9514"
ATTRS{idVendor}=="0424"
ATTRS{ltm_capable}=="no"
ATTRS{maxchild}=="5"
ATTRS{power/active_duration}=="256670"
ATTRS{power/autosuspend}=="0"
ATTRS{power/autosuspend_delay_ms}=="0"
ATTRS{power/connected_duration}=="256670"
ATTRS{power/control}=="auto"
ATTRS{power/level}=="auto"
ATTRS{power/runtime_active_time}=="256219"
ATTRS{power/runtime_status}=="active"
ATTRS{power/runtime_suspended_time}=="0"
ATTRS{quirks}=="0x0"
ATTRS{removable}=="unknown"
ATTRS{remove}=="(not readable)"
ATTRS{rx_lanes}=="1"
ATTRS{speed}=="480"
ATTRS{tx_lanes}=="1"
ATTRS{urbnum}=="161"
ATTRS{version}==" 2.00"

looking at parent device '/devices/platform/soc/3f980000.usb/usb1':
KERNELS=="usb1"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{authorized}=="1"
ATTRS{authorized_default}=="1"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{bConfigurationValue}=="1"
ATTRS{bDeviceClass}=="09"
ATTRS{bDeviceProtocol}=="01"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bMaxPacketSize0}=="64"
ATTRS{bMaxPower}=="0mA"
ATTRS{bNumConfigurations}=="1"
ATTRS{bNumInterfaces}==" 1"
ATTRS{bcdDevice}=="0606"
ATTRS{bmAttributes}=="e0"
ATTRS{busnum}=="1"
ATTRS{configuration}==""
ATTRS{devnum}=="1"
ATTRS{devpath}=="0"
ATTRS{idProduct}=="0002"
ATTRS{idVendor}=="1d6b"
ATTRS{interface_authorized_default}=="1"
ATTRS{ltm_capable}=="no"
ATTRS{manufacturer}=="Linux 6.6.51+rpt-rpi-v7 dwc_otg_hcd"
ATTRS{maxchild}=="1"
ATTRS{power/active_duration}=="256800"
ATTRS{power/autosuspend}=="0"
ATTRS{power/autosuspend_delay_ms}=="0"
ATTRS{power/connected_duration}=="256810"
ATTRS{power/control}=="auto"
ATTRS{power/level}=="auto"
ATTRS{power/runtime_active_time}=="256813"
ATTRS{power/runtime_status}=="active"
ATTRS{power/runtime_suspended_time}=="0"
ATTRS{product}=="DWC OTG Controller"
ATTRS{quirks}=="0x0"
ATTRS{removable}=="unknown"
ATTRS{remove}=="(not readable)"
ATTRS{rx_lanes}=="1"
ATTRS{serial}=="3f980000.usb"
ATTRS{speed}=="480"
ATTRS{tx_lanes}=="1"
ATTRS{urbnum}=="26"
ATTRS{version}==" 2.00"

looking at parent device '/devices/platform/soc/3f980000.usb':
KERNELS=="3f980000.usb"
SUBSYSTEMS=="platform"
DRIVERS=="dwc_otg"
ATTRS{busconnected}=="Bus Connected = 0x1"
ATTRS{buspower}=="Bus Power = 0x1"
ATTRS{bussuspend}=="Bus Suspend = 0x0"
ATTRS{devspeed}=="Device Speed = 0x0"
ATTRS{disconnect_us}=="(not readable)"
ATTRS{driver_override}=="(null)"
ATTRS{enumspeed}=="Device Enumeration Speed = 0x1"
ATTRS{fr_interval}=="Frame Interval = 0x1d4b"
ATTRS{ggpio}=="GGPIO = 0x00000000"
ATTRS{gnptxfsiz}=="GNPTXFSIZ = 0x01000306"
ATTRS{gotgctl}=="GOTGCTL = 0x001c0001"
ATTRS{gpvndctl}=="GPVNDCTL = 0x00000000"
ATTRS{grxfsiz}=="GRXFSIZ = 0x00000306"
ATTRS{gsnpsid}=="GSNPSID = 0x4f54280a"
ATTRS{guid}=="GUID = 0x2708a000"
ATTRS{gusbcfg}=="GUSBCFG = 0x20001700"
ATTRS{hcd_frrem}=="HCD Dump Frame Remaining"
ATTRS{hcddump}=="HCD Dump"
ATTRS{hnp}=="HstNegScs = 0x0"
ATTRS{hnpcapable}=="HNPCapable = 0x1"
ATTRS{hprt0}=="HPRT0 = 0x00001005"
ATTRS{hptxfsiz}=="HPTXFSIZ = 0x02000406"
ATTRS{hsic_connect}=="HSIC Connect = 0x1"
ATTRS{inv_sel_hsic}=="Invert Select HSIC = 0x0"
ATTRS{mode}=="Mode = 0x1"
ATTRS{mode_ch_tim_en}=="Mode Change Ready Timer Enable = 0x0"
ATTRS{power/control}=="auto"
ATTRS{power/runtime_active_time}=="0"
ATTRS{power/runtime_status}=="unsupported"
ATTRS{power/runtime_suspended_time}=="0"
ATTRS{rd_reg_test}=="Time to read GNPTXFSIZ reg 10000000 times: 1480 msecs (148 jiffies)"
ATTRS{regdump}=="Register Dump"
ATTRS{regoffset}=="0xffffffff"
ATTRS{regvalue}=="invalid offset"
ATTRS{rem_wakeup_pwrdn}==""
ATTRS{remote_wakeup}=="Remote Wakeup Sig = 0 Enabled = 0 LPM Remote Wakeup = 0"
ATTRS{spramdump}=="SPRAM Dump"
ATTRS{srp}=="SesReqScs = 0x1"
ATTRS{srpcapable}=="SRPCapable = 0x1"
ATTRS{wr_reg_test}=="Time to write GNPTXFSIZ reg 10000000 times: 370 msecs (37 jiffies)"

looking at parent device '/devices/platform/soc':
KERNELS=="soc"
SUBSYSTEMS=="platform"
DRIVERS=="simple-pm-bus"
ATTRS{driver_override}=="(null)"
ATTRS{power/control}=="auto"
ATTRS{power/runtime_active_time}=="0"
ATTRS{power/runtime_status}=="unsupported"
ATTRS{power/runtime_suspended_time}=="0"

looking at parent device '/devices/platform':
KERNELS=="platform"
SUBSYSTEMS==""
DRIVERS==""
ATTRS{power/control}=="auto"
ATTRS{power/runtime_active_time}=="0"
ATTRS{power/runtime_status}=="unsupported"
ATTRS{power/runtime_suspended_time}=="0"

  udev_info_port2.txt
Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.

looking at device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.4/1-1.4:1.0/ttyUSB0/tty/ttyUSB0':
KERNEL=="ttyUSB0"
SUBSYSTEM=="tty"
DRIVER==""
ATTR{power/control}=="auto"
ATTR{power/runtime_active_time}=="0"
ATTR{power/runtime_status}=="unsupported"
ATTR{power/runtime_suspended_time}=="0"

looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.4/1-1.4:1.0/ttyUSB0':
KERNELS=="ttyUSB0"
SUBSYSTEMS=="usb-serial"
DRIVERS=="ch341-uart"
ATTRS{port_number}=="0"
ATTRS{power/control}=="auto"
ATTRS{power/runtime_active_time}=="0"
ATTRS{power/runtime_status}=="unsupported"
ATTRS{power/runtime_suspended_time}=="0"

looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.4/1-1.4:1.0':
KERNELS=="1-1.4:1.0"
SUBSYSTEMS=="usb"
DRIVERS=="ch341"
ATTRS{authorized}=="1"
ATTRS{bAlternateSetting}==" 0"
ATTRS{bInterfaceClass}=="ff"
ATTRS{bInterfaceNumber}=="00"
ATTRS{bInterfaceProtocol}=="02"
ATTRS{bInterfaceSubClass}=="01"
ATTRS{bNumEndpoints}=="03"
ATTRS{supports_autosuspend}=="1"

looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.4':
KERNELS=="1-1.4"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{authorized}=="1"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{bConfigurationValue}=="1"
ATTRS{bDeviceClass}=="ff"
ATTRS{bDeviceProtocol}=="00"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bMaxPacketSize0}=="8"
ATTRS{bMaxPower}=="96mA"
ATTRS{bNumConfigurations}=="1"
ATTRS{bNumInterfaces}==" 1"
ATTRS{bcdDevice}=="0254"
ATTRS{bmAttributes}=="80"
ATTRS{busnum}=="1"
ATTRS{configuration}==""
ATTRS{devnum}=="9"
ATTRS{devpath}=="1.4"
ATTRS{devspec}=="(null)"
ATTRS{idProduct}=="7523"
ATTRS{idVendor}=="1a86"
ATTRS{ltm_capable}=="no"
ATTRS{maxchild}=="0"
ATTRS{power/active_duration}=="15960"
ATTRS{power/autosuspend}=="2"
ATTRS{power/autosuspend_delay_ms}=="2000"
ATTRS{power/connected_duration}=="15960"
ATTRS{power/control}=="on"
ATTRS{power/level}=="on"
ATTRS{power/persist}=="1"
ATTRS{power/runtime_active_time}=="15735"
ATTRS{power/runtime_status}=="active"
ATTRS{power/runtime_suspended_time}=="0"
ATTRS{product}=="USB2.0-Ser!"
ATTRS{quirks}=="0x0"
ATTRS{removable}=="removable"
ATTRS{remove}=="(not readable)"
ATTRS{rx_lanes}=="1"
ATTRS{speed}=="12"
ATTRS{tx_lanes}=="1"
ATTRS{urbnum}=="16"
ATTRS{version}==" 1.10"

looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1':
KERNELS=="1-1"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{authorized}=="1"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{bConfigurationValue}=="1"
ATTRS{bDeviceClass}=="09"
ATTRS{bDeviceProtocol}=="02"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bMaxPacketSize0}=="64"
ATTRS{bMaxPower}=="2mA"
ATTRS{bNumConfigurations}=="1"
ATTRS{bNumInterfaces}==" 1"
ATTRS{bcdDevice}=="0200"
ATTRS{bmAttributes}=="e0"
ATTRS{busnum}=="1"
ATTRS{configuration}==""
ATTRS{devnum}=="2"
ATTRS{devpath}=="1"
ATTRS{idProduct}=="9514"
ATTRS{idVendor}=="0424"
ATTRS{ltm_capable}=="no"
ATTRS{maxchild}=="5"
ATTRS{power/active_duration}=="248790"
ATTRS{power/autosuspend}=="0"
ATTRS{power/autosuspend_delay_ms}=="0"
ATTRS{power/connected_duration}=="248790"
ATTRS{power/control}=="auto"
ATTRS{power/level}=="auto"
ATTRS{power/runtime_active_time}=="248343"
ATTRS{power/runtime_status}=="active"
ATTRS{power/runtime_suspended_time}=="0"
ATTRS{quirks}=="0x0"
ATTRS{removable}=="unknown"
ATTRS{remove}=="(not readable)"
ATTRS{rx_lanes}=="1"
ATTRS{speed}=="480"
ATTRS{tx_lanes}=="1"
ATTRS{urbnum}=="139"
ATTRS{version}==" 2.00"

looking at parent device '/devices/platform/soc/3f980000.usb/usb1':
KERNELS=="usb1"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{authorized}=="1"
ATTRS{authorized_default}=="1"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{bConfigurationValue}=="1"
ATTRS{bDeviceClass}=="09"
ATTRS{bDeviceProtocol}=="01"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bMaxPacketSize0}=="64"
ATTRS{bMaxPower}=="0mA"
ATTRS{bNumConfigurations}=="1"
ATTRS{bNumInterfaces}==" 1"
ATTRS{bcdDevice}=="0606"
ATTRS{bmAttributes}=="e0"
ATTRS{busnum}=="1"
ATTRS{configuration}==""
ATTRS{devnum}=="1"
ATTRS{devpath}=="0"
ATTRS{idProduct}=="0002"
ATTRS{idVendor}=="1d6b"
ATTRS{interface_authorized_default}=="1"
ATTRS{ltm_capable}=="no"
ATTRS{manufacturer}=="Linux 6.6.51+rpt-rpi-v7 dwc_otg_hcd"
ATTRS{maxchild}=="1"
ATTRS{power/active_duration}=="248930"
ATTRS{power/autosuspend}=="0"
ATTRS{power/autosuspend_delay_ms}=="0"
ATTRS{power/connected_duration}=="248930"
ATTRS{power/control}=="auto"
ATTRS{power/level}=="auto"
ATTRS{power/runtime_active_time}=="248934"
ATTRS{power/runtime_status}=="active"
ATTRS{power/runtime_suspended_time}=="0"
ATTRS{product}=="DWC OTG Controller"
ATTRS{quirks}=="0x0"
ATTRS{removable}=="unknown"
ATTRS{remove}=="(not readable)"
ATTRS{rx_lanes}=="1"
ATTRS{serial}=="3f980000.usb"
ATTRS{speed}=="480"
ATTRS{tx_lanes}=="1"
ATTRS{urbnum}=="26"
ATTRS{version}==" 2.00"

looking at parent device '/devices/platform/soc/3f980000.usb':
KERNELS=="3f980000.usb"
SUBSYSTEMS=="platform"
DRIVERS=="dwc_otg"
ATTRS{busconnected}=="Bus Connected = 0x1"
ATTRS{buspower}=="Bus Power = 0x1"
ATTRS{bussuspend}=="Bus Suspend = 0x0"
ATTRS{devspeed}=="Device Speed = 0x0"
ATTRS{disconnect_us}=="(not readable)"
ATTRS{driver_override}=="(null)"
ATTRS{enumspeed}=="Device Enumeration Speed = 0x1"
ATTRS{fr_interval}=="Frame Interval = 0x1d4b"
ATTRS{ggpio}=="GGPIO = 0x00000000"
ATTRS{gnptxfsiz}=="GNPTXFSIZ = 0x01000306"
ATTRS{gotgctl}=="GOTGCTL = 0x001c0001"
ATTRS{gpvndctl}=="GPVNDCTL = 0x00000000"
ATTRS{grxfsiz}=="GRXFSIZ = 0x00000306"
ATTRS{gsnpsid}=="GSNPSID = 0x4f54280a"
ATTRS{guid}=="GUID = 0x2708a000"
ATTRS{gusbcfg}=="GUSBCFG = 0x20001700"
ATTRS{hcd_frrem}=="HCD Dump Frame Remaining"
ATTRS{hcddump}=="HCD Dump"
ATTRS{hnp}=="HstNegScs = 0x0"
ATTRS{hnpcapable}=="HNPCapable = 0x1"
ATTRS{hprt0}=="HPRT0 = 0x00001005"
ATTRS{hptxfsiz}=="HPTXFSIZ = 0x02000406"
ATTRS{hsic_connect}=="HSIC Connect = 0x1"
ATTRS{inv_sel_hsic}=="Invert Select HSIC = 0x0"
ATTRS{mode}=="Mode = 0x1"
ATTRS{mode_ch_tim_en}=="Mode Change Ready Timer Enable = 0x0"
ATTRS{power/control}=="auto"
ATTRS{power/runtime_active_time}=="0"
ATTRS{power/runtime_status}=="unsupported"
ATTRS{power/runtime_suspended_time}=="0"
ATTRS{rd_reg_test}=="Time to read GNPTXFSIZ reg 10000000 times: 1210 msecs (121 jiffies)"
ATTRS{regdump}=="Register Dump"
ATTRS{regoffset}=="0xffffffff"
ATTRS{regvalue}=="invalid offset"
ATTRS{rem_wakeup_pwrdn}==""
ATTRS{remote_wakeup}=="Remote Wakeup Sig = 0 Enabled = 0 LPM Remote Wakeup = 0"
ATTRS{spramdump}=="SPRAM Dump"
ATTRS{srp}=="SesReqScs = 0x1"
ATTRS{srpcapable}=="SRPCapable = 0x1"
ATTRS{wr_reg_test}=="Time to write GNPTXFSIZ reg 10000000 times: 370 msecs (37 jiffies)"

looking at parent device '/devices/platform/soc':
KERNELS=="soc"
SUBSYSTEMS=="platform"
DRIVERS=="simple-pm-bus"
ATTRS{driver_override}=="(null)"
ATTRS{power/control}=="auto"
ATTRS{power/runtime_active_time}=="0"
ATTRS{power/runtime_status}=="unsupported"
ATTRS{power/runtime_suspended_time}=="0"

looking at parent device '/devices/platform':
KERNELS=="platform"
SUBSYSTEMS==""
DRIVERS==""
ATTRS{power/control}=="auto"
ATTRS{power/runtime_active_time}=="0"
ATTRS{power/runtime_status}=="unsupported"
ATTRS{power/runtime_suspended_time}=="0"

После сравнения kdiff3 я обнаружил, что у них различается devpath или ещё devnum.

ATTRS{devpath}=="1.2"
ATTRS{devpath}=="1.4"

И так далее. Путь скорее всего является срезом от полного пути.

looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2':
looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2:1.0':
looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2:1.0/ttyUSB0':
looking at _____ device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2:1.0/ttyUSB0/tty/ttyUSB0':


Я взял devpath и создал ссылку на конкретный физический USB порт.
/etc/udev/rules.d/10-local.rules

SUBSYSTEM=="tty", ATTRS{devpath}=="1.2", SYMLINK+="ttyUSB_1_2", OWNER="velkin", GROUP="dialout", MODE="0666"
SUBSYSTEM=="tty", ATTRS{devpath}=="1.4", SYMLINK+="ttyUSB_1_4", OWNER="velkin", GROUP="dialout", MODE="0666"
SUBSYSTEM=="tty", ATTRS{devpath}=="1.3", SYMLINK+="ttyUSB_1_3", OWNER="velkin", GROUP="dialout", MODE="0666"
SUBSYSTEM=="tty", ATTRS{devpath}=="1.5", SYMLINK+="ttyUSB_1_5", OWNER="velkin", GROUP="dialout", MODE="0666"

И потом сделал примерно так.

ser2net.yaml

connection: &object_30
accepter: tcp,7001
enable: on
options:
banner: *banner
kickolduser: true
telnet-brk-on-sync: true
connector: serialdev,
/dev/ttyUSB_1_2,
9600n81,local

А до этого была попытка определить устройство по его параметрам, а не путь к нему, то есть не по разъёму USB на материнке.

SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", ATTRS{product}=="USB2.0-Ser!", SYMLINK+="usb2com_ch340"

Я могу вырезать ещё раз часть кода, ту что под катом.

looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2':
KERNELS=="1-1.2"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{authorized}=="1"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{bConfigurationValue}=="1"
ATTRS{bDeviceClass}=="ff"
ATTRS{bDeviceProtocol}=="00"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bMaxPacketSize0}=="8"
ATTRS{bMaxPower}=="96mA"
ATTRS{bNumConfigurations}=="1"
ATTRS{bNumInterfaces}==" 1"
ATTRS{bcdDevice}=="0254"
ATTRS{bmAttributes}=="80"
ATTRS{busnum}=="1"
ATTRS{configuration}==""
ATTRS{devnum}=="10"
ATTRS{devpath}=="1.2"
ATTRS{devspec}=="(null)"
ATTRS{idProduct}=="7523"
ATTRS{idVendor}=="1a86"
ATTRS{ltm_capable}=="no"
ATTRS{maxchild}=="0"
ATTRS{power/active_duration}=="3100"
ATTRS{power/autosuspend}=="2"
ATTRS{power/autosuspend_delay_ms}=="2000"
ATTRS{power/connected_duration}=="3100"
ATTRS{power/control}=="on"
ATTRS{power/level}=="on"
ATTRS{power/persist}=="1"
ATTRS{power/runtime_active_time}=="2870"
ATTRS{power/runtime_status}=="active"
ATTRS{power/runtime_suspended_time}=="0"
ATTRS{product}=="USB2.0-Ser!"
ATTRS{quirks}=="0x0"
ATTRS{removable}=="removable"
ATTRS{remove}=="(not readable)"
ATTRS{rx_lanes}=="1"
ATTRS{speed}=="12"
ATTRS{tx_lanes}=="1"
ATTRS{urbnum}=="16"
ATTRS{version}==" 1.10"

Если отбросить параметры power, то kdiff3 показывает различие только.

ATTRS{devnum}=="9" ATTRS{devnum}=="10"
ATTRS{devpath}=="1.4" ATTRS{devpath}=="1.2"

То есть команды udevadm info --name=/dev/ttyUSB0 и прочие больше ничего не покажут.

Может тебе это никак и не поможет, но я, например, не нашёл решение своей проблемы в лоб в веб-поиске, но косвенно догадался как решить. А это в свою очередь даёт мне возможность направлять более точные запросы в веб-поиск по тому же devpath. Здесь скорее вопрос можешь ли ты считывать параметры USB устройств в Windows.

Ну то есть, когда устройство втыкается в порт.
1. Можно определить куда воткнули новое устройство, то есть в какой разъём.
devpath (под вопросом devnum)
2. Определить какое устройство было воткнуто.
idVendor, idProduct (под вопросом product) и так далее

А устройство так же может быть USB хабом. И вопрос опять в том, что те же два USB хаба могут ничем и не отличаться. Если бы у меня были конкретные устройства, особенно одинаковые, я бы их воткнул и посмотрел, что будет, если взять два одинаковых хаба, воткнуть их в два USB разъёма на материнке, и потом попытаться отличить один от другого. А если их переткнуть между разъёмами на материнке наоборот.

Вот почему я просто прибил устройство к разъёму USB на материнке, а не к параметрам самого устройства. У меня есть скачанная книжка по программированию USB портов, но я её не читал. Так что я всё это понимаю на примитивном уровне команд утилит в гнулинуксе. Но по сути вызов библиотек включая системные не слишком от них отличается. Что они могут, то и ты сможешь, главное знать, что вызывать.

Опять если набрать в веб-поиске то, что ты сам написал SPDRP_LOCATION_INFORMATION.
https://learn.microsoft.com/ru-ru/windows-hardware/drivers/install/accessing-device-instance-spdrp-xxx-properties
https://www.cyberforum.ru/win-api/thread1176871.html
И так далее. Читаешь, разбираешься, может пишешь код, чтобы посмотреть, что выдаёт система. Или давай дождёмся экспертов.
Re: Как надежно различать два одинаковых USB-устройства в Wi
От: vsb Казахстан  
Дата: 08.01.25 21:43
Оценка: -1
У USB есть дескрипторы. Они должны быть доступны через какое-то API. В device descriptor есть поля idVendor, idProduct, bcdDevice, iManufacturer, iProduct, iSerialNumber. Не все из них обязательны и не все устройства их реализуют как положено, но в теории iSerialNumber должен быть уникальным для устройства, ну а остальные поля идентифицируют модель устройства. В общем полагаться на это на 100% нельзя, но для каких-то конкретных случаев с известными устройствами с нормально написанной прошивкой — можно.
Отредактировано 08.01.2025 21:43 vsb . Предыдущая версия .
Re[2]: Как надежно различать два одинаковых USB-устройства в Wi
От: Pzz Россия https://github.com/alexpevzner
Дата: 08.01.25 22:30
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>У USB есть дескрипторы. Они должны быть доступны через какое-то API. В device descriptor есть поля idVendor, idProduct, bcdDevice, iManufacturer, iProduct, iSerialNumber. Не все из них обязательны и не все устройства их реализуют как положено, но в теории iSerialNumber должен быть уникальным для устройства, ну а остальные поля идентифицируют модель устройства. В общем полагаться на это на 100% нельзя, но для каких-то конкретных случаев с известными устройствами с нормально написанной прошивкой — можно.


У некоторык классов устройств (например, у принтеров), iSerialNumber надёжен. У других классов (например, у мышей-клавиатур) он прописывается от балды и может повторяться.

У сетевых карт есть еще MAC address, он тоже надёжен.

В общем, ответ зависит от класса.
Re[3]: Как надежно различать два одинаковых USB-устройства в Wi
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 08.01.25 22:36
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>У сетевых карт есть еще MAC address, он тоже надёжен.


Вот это сейчас смешно было
Маньяк Робокряк колесит по городу
Re[4]: Как надежно различать два одинаковых USB-устройства в Wi
От: Pzz Россия https://github.com/alexpevzner
Дата: 08.01.25 22:56
Оценка:
Здравствуйте, Marty, Вы писали:

Pzz>>У сетевых карт есть еще MAC address, он тоже надёжен.


M>Вот это сейчас смешно было


Почему?
Re[5]: Как надежно различать два одинаковых USB-устройства в Wi
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 09.01.25 04:37
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>>>У сетевых карт есть еще MAC address, он тоже надёжен.


M>>Вот это сейчас смешно было


Pzz>Почему?


Китайцы по этому поводу не парятся
Маньяк Робокряк колесит по городу
Re[6]: Как надежно различать два одинаковых USB-устройства в Wi
От: Pzz Россия https://github.com/alexpevzner
Дата: 09.01.25 07:01
Оценка:
Здравствуйте, Marty, Вы писали:

Pzz>>Почему?


M>Китайцы по этому поводу не парятся


Не парятся, но коллизии редко случаются.
Re[2]: Как надежно различать два одинаковых USB-устройства в Window
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 09.01.25 09:42
Оценка:
Здравствуйте, velkin, Вы писали:

V>Может тебе это никак и не поможет


Да — слишком много кода, слишком мало пояснений, а вдумчиво разбираться в коде не вижу смысла. Пальцем показать можете?

V>можешь ли ты считывать параметры USB устройств в Windows.


Могу, конечно. Мне нужно лишь определить, какие из них однозначно и повторяемо (между перезагрузками/переподключениями) определяют физические координаты подключенного устройства.

V>1. Можно определить куда воткнули новое устройство, то есть в какой разъём.


Мне нужно именно это. У Вас в Linux получилось? После перезагрузки координаты сохраняются?

V>2. Определить какое устройство было воткнуто.


Этого на данный момент не требуется.

V>А устройство так же может быть USB хабом. И вопрос опять в том, что те же два USB хаба могут ничем и не отличаться.


Это тоже не проблема, если есть возможность однозначно определить физические координаты.

V>я просто прибил устройство к разъёму USB на материнке


То есть, у Вас таки получилось надежно адресовать устройство по расположению разъема? А сколько в системе встроенных USB-хабов? У меня под рукой только ноутбуки, в каждом по одному хабу, поэтому у себя я тоже не вижу изменений при перезагрузке. А у юзера десктоп, хабов несколько, и они, судя по всему, при перечислении определяются в случайном порядке.

V>Читаешь, разбираешься, может пишешь код, чтобы посмотреть, что выдаёт система.


Все найденное уже прочитано и опробовано.
Re[2]: Как надежно различать два одинаковых USB-устройства в Wi
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 09.01.25 09:43
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>У USB есть дескрипторы. Они должны быть доступны через какое-то API. В device descriptor есть поля idVendor, idProduct, bcdDevice, iManufacturer, iProduct, iSerialNumber.


Я ж вроде достаточно явно написал, и в конце еще раз пояснил, что сами устройства совершенно неразличимы, и задачи различать, какое где, у меня не стоит.
Re[5]: Как надежно различать два одинаковых USB-устройства в Wi
От: mike_rs Россия  
Дата: 09.01.25 12:41
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>>>У сетевых карт есть еще MAC address, он тоже надёжен.

M>>Вот это сейчас смешно было
Pzz>Почему?

может рандомно назначаться для всяких wifi адаптеров, в телефонах сейчас это популярно
Re[3]: Как надежно различать два одинаковых USB-устройства в Window
От: velkin Удмуртия https://kisa.biz
Дата: 09.01.25 16:44
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>То есть, у Вас таки получилось надежно адресовать устройство по расположению разъема?


Да, именно по расположению разъёма, но не на USB хабе, а на материнской плате.

ЕМ>А сколько в системе встроенных USB-хабов?


Давай определимся с терминологией.

USB разъёмы на материнской плате.



USB Hub (концентратор, разветвитель)




Преобразователь USB на RS-232 (ttyUSB, COM-port)



ЕМ>У меня под рукой только ноутбуки, в каждом по одному хабу, поэтому у себя я тоже не вижу изменений при перезагрузке. А у юзера десктоп, хабов несколько, и они, судя по всему, при перечислении определяются в случайном порядке.


У меня путь ttyUSB#, то есть ttyUSB0, ttyUSB1, ttyUSB2, ttyUSB3 и так далее всё время скакал от устройства к устройству. Это как в Windows был бы COM1, а после перезагрузки стал COM2, а после перевтыкания разъёма опять COM1 или COM3 и так далее. Да, все аналогии с Windows очень условны.

Потому я вместо ttyUSB#, то есть ttyUSB0, ttyUSB1, ttyUSB2, ttyUSB3 создал псевдонимы прибитые к разъёмам USB на материнке и использую для обращения именно псевдонимы ttyUSB_1_2, ttyUSB_1_4, ttyUSB_1_3, ttyUSB_1_5. Причём я мог бы назвать псевдонимы как угодно. И даже мог бы сделать проверку пути вместе с проверкой идентификатора вендора и продукта, просто мне это не нужно.
/etc/udev/rules.d/10-local.rules

SUBSYSTEM=="tty", ATTRS{devpath}=="1.2", SYMLINK+="ttyUSB_1_2", OWNER="velkin", GROUP="dialout", MODE="0666"
SUBSYSTEM=="tty", ATTRS{devpath}=="1.4", SYMLINK+="ttyUSB_1_4", OWNER="velkin", GROUP="dialout", MODE="0666"
SUBSYSTEM=="tty", ATTRS{devpath}=="1.3", SYMLINK+="ttyUSB_1_3", OWNER="velkin", GROUP="dialout", MODE="0666"
SUBSYSTEM=="tty", ATTRS{devpath}=="1.5", SYMLINK+="ttyUSB_1_5", OWNER="velkin", GROUP="dialout", MODE="0666"

Фактически я исключил ту часть пути, которая идёт после выделенного

looking at device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2:1.0/ttyUSB0/tty/ttyUSB0'

Там может быть случайно назначаемый ttyUSB0, ttyUSB1, ttyUSB2, ttyUSB3, ttyUSB4, ttyUSB5, ttyUSB6 и так далее, но мне нужен псевдоним только на.

looking at device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2


У меня была идея использовать ещё и USB Hub, но в принципе хватило и разъёмов на материнской плате. Метод которым я действовал тоже изложил. Создаёшь листинги по известным параметрам, потом сравниваешь kdiff3, которая так же есть в Windows.

Смысл в том, что ttyUSB# воткнутого устройства всё время меняется, но путь разъёма на материнской плате не меняется, это ATTRS{devpath}. А вот с путём USB Hub надо ещё провести опыты.

В мире программирования очень много абстракций. Это надо конкретно сесть за твой код и твои устройства. И даже не только твои, нужно ещё симулировать ситуацию как у твоего пользователя. А дальше по науке логике, анализ (разбор), синтез (сбор) и сравнение.

И повторюсь, всё это чисто для размышления. Потому что сразу готового программного решения как на stackoverflow у меня конкретно для Windows и его библиотек нет. А людей, которые уже решили эту задачу в комментариях можно ждать очень долго.

Ещё есть такое обстоятельство, что если программист решает, что что-то сделать невозможно, он это и не делает. Иногда нужна мотивация, что хотя бы чисто теоретически такое возможно. Я, конечно, за это не поручусь, но тем не менее.
Re[4]: Как надежно различать два одинаковых USB-устройства в Window
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 09.01.25 21:31
Оценка:
Здравствуйте, velkin, Вы писали:

V>по расположению разъёма, но не на USB хабе, а на материнской плате.


Я имел в виду внутренний хаб платы. Устройства никогда не подключаются непосредственно к контроллеру/хосту — под ним всегда есть хотя бы один хаб. В ноутбуках он, как правило, один, а на десктопных платах их обычно несколько.

ЕМ>>А сколько в системе встроенных USB-хабов?


V>Давай определимся с терминологией.


Если все эти иллюстрации предназначены для меня, то у меня есть подозрение, что в структуре и работе USB я разбираюсь несколько лучше Вас. Или они просто для того, чтобы попутно оформить реплику в виде очередной статьи?

V>У меня путь ttyUSB#, то есть ttyUSB0, ttyUSB1, ttyUSB2, ttyUSB3 и так далее всё время скакал от устройства к устройству. Это как в Windows был бы COM1, а после перезагрузки стал COM2, а после перевтыкания разъёма опять COM1 или COM3 и так далее.


В Windows так не бывает. Если она однажды присвоила имя устройству, подключенному в конкретный разъем, то после перезагрузки это имя сохранится. А имена эти связаны с так называемыми interface paths, по которым можно обратиться к устройству. В составе interface path всегда есть hardware path, который формируется из идентификаторов шины и самого устройства, и эти пути при перезагрузке меняться не должны. Поэтому я и удивился, когда юзер пожаловался, что у него каждый раз получается другой путь. Правда, я сильно подозреваю, что он что-то напутал — например, перетыкал устройства, перепутал пути и т.п.

V>Смысл в том, что ttyUSB# воткнутого устройства всё время меняется, но путь разъёма на материнской плате не меняется, это ATTRS{devpath}.


А вот мой юзер утверждает, что у него наоборот: имена устройств сохраняются, а location information, состоящая из номеров хаба и разъема, меняется при каждой перезагрузке.

V>надо конкретно сесть за твой код и твои устройства.


При чем здесь мои код и устройства? Надо понять, какие атрибуты физического адреса устройства, определяемые виндой, воспроизводятся при ее перезагрузке.
Re: Как надежно различать два одинаковых USB-устройства в Window
От: Vzhyk2  
Дата: 10.01.25 17:35
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Как известно, два одинаковых USB-устройства, не имеющих внутренних состояний,

Это всё, что у тебя есть https://the-sz.com/products/usbid/index.php.
Re[5]: Как надежно различать два одинаковых USB-устройства в Wi
От: Vzhyk2  
Дата: 10.01.25 17:36
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>>>У сетевых карт есть еще MAC address, он тоже надёжен.

Pzz>Почему?
Потому что он случайный и запросто меняется.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.