cmc*_*nty 202 command-line usb
是否可以在不从 PC 物理断开/连接的情况下重置 USB 设备的连接?
具体来说,我的设备是数码相机。我正在使用gphoto2,但最近我收到“设备读取错误”,因此我想尝试对连接进行软件重置。
据我所知,没有为相机加载内核模块。唯一看起来相关的是usbhid.
Li *_* Lo 142
将以下内容另存为 usbreset.c
/* usbreset -- send a USB port reset to a USB device */
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <linux/usbdevice_fs.h>
int main(int argc, char **argv)
{
const char *filename;
int fd;
int rc;
if (argc != 2) {
fprintf(stderr, "Usage: usbreset device-filename\n");
return 1;
}
filename = argv[1];
fd = open(filename, O_WRONLY);
if (fd < 0) {
perror("Error opening output file");
return 1;
}
printf("Resetting USB device %s\n", filename);
rc = ioctl(fd, USBDEVFS_RESET, 0);
if (rc < 0) {
perror("Error in ioctl");
return 1;
}
printf("Reset successful\n");
close(fd);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在终端中运行以下命令:
编译程序:
$ cc usbreset.c -o usbreset
Run Code Online (Sandbox Code Playgroud)获取要重置的 USB 设备的总线和设备 ID:
$ lsusb
Bus 002 Device 003: ID 0fe9:9010 DVICO
Run Code Online (Sandbox Code Playgroud)使我们编译的程序可执行:
$ chmod +x usbreset
Run Code Online (Sandbox Code Playgroud)以sudo权限执行程序;通过运行以下命令对找到的<Bus>和<Device>id进行必要的替换lsusb:
$ sudo ./usbreset /dev/bus/usb/002/003
Run Code Online (Sandbox Code Playgroud)以上程序来源:http : //marc.info/?l=linux-usb&m=121459435621262&w=2
sso*_*low 81
我以前没有遇到过您的具体情况,所以我不确定它是否足够,但我发现重置 USB 设备的最简单方法是以下命令:(不需要外部应用程序)
sudo sh -c "echo 0 > /sys/bus/usb/devices/1-4.6/authorized"
sudo sh -c "echo 1 > /sys/bus/usb/devices/1-4.6/authorized"
Run Code Online (Sandbox Code Playgroud)
这是我用来重置 Kinect 的实际方法,因为 libfreenect 似乎没有让它重新进入睡眠状态的 API。它在我的 Gentoo 机器上,但内核应该足够新,以便为 sysfs 使用相同的路径结构。
您的显然不会,1-4.6但您可以从内核日志 ( dmesg) 中提取该设备路径,或者您可以使用类似的lsusb方法获取供应商和产品 ID,然后使用这样的快速命令来列出路径与不同供应商的关系/产品 ID 对:
for X in /sys/bus/usb/devices/*; do
echo "$X"
cat "$X/idVendor" 2>/dev/null
cat "$X/idProduct" 2>/dev/null
echo
done
Run Code Online (Sandbox Code Playgroud)
小智 65
这将重置所有 USB1/2/3 连接端口[1]:
for i in /sys/bus/pci/drivers/[uoex]hci_hcd/*:*; do
[ -e "$i" ] || continue
echo "${i##*/}" > "${i%/*}/unbind"
echo "${i##*/}" > "${i%/*}/bind"
done
Run Code Online (Sandbox Code Playgroud)
我相信这会解决你的问题。如果您不想重置所有 USB 端点,您可以使用适当的设备 ID/sys/bus/pci/drivers/ehci_hcd
注意: [1]:*hci_hcd内核驱动程序通常控制 USB 端口。ohci_hcd和uhci_hcd用于 USB1.1 端口,ehci_hcd用于 USB2 端口和xhci_hcd用于 USB3 端口。(见https://en.wikipedia.org/wiki/Host_controller_interface_(USB,_Firewire))
pan*_*.de 31
由于 APT 包 usbutils 提供了 usbreset 二进制文件,您只需通过以下方式重置 USB 设备:
usbreset ${USB_ID}
e.g.
usbreset 0d8c:0102
Run Code Online (Sandbox Code Playgroud)
mca*_*ans 13
我创建了一个 Python 脚本,它根据此处的答案简化了整个过程。
将下面的脚本保存为 reset_usb.py 或克隆这个 repo。
用法:
python reset_usb.py help # Show this help
sudo python reset_usb.py list # List all USB devices
sudo python reset_usb.py path /dev/bus/usb/XXX/YYY # Reset USB device using path /dev/bus/usb/XXX/YYY
sudo python reset_usb.py search "search terms" # Search for USB device using the search terms within the search string returned by list and reset matching device
sudo python reset_usb.py listpci # List all PCI USB devices
sudo python reset_usb.py pathpci /sys/bus/pci/drivers/.../XXXX:XX:XX.X # Reset PCI USB device using path /sys/bus/pci/drivers/.../XXXX:XX:XX.X
sudo python reset_usb.py searchpci "search terms" # Search for PCI USB device using the search terms within the search string returned by listpci and reset matching device
Run Code Online (Sandbox Code Playgroud)
脚本:
python reset_usb.py help # Show this help
sudo python reset_usb.py list # List all USB devices
sudo python reset_usb.py path /dev/bus/usb/XXX/YYY # Reset USB device using path /dev/bus/usb/XXX/YYY
sudo python reset_usb.py search "search terms" # Search for USB device using the search terms within the search string returned by list and reset matching device
sudo python reset_usb.py listpci # List all PCI USB devices
sudo python reset_usb.py pathpci /sys/bus/pci/drivers/.../XXXX:XX:XX.X # Reset PCI USB device using path /sys/bus/pci/drivers/.../XXXX:XX:XX.X
sudo python reset_usb.py searchpci "search terms" # Search for PCI USB device using the search terms within the search string returned by listpci and reset matching device
Run Code Online (Sandbox Code Playgroud)
Pet*_*ter 11
我需要在 python 脚本中自动执行此操作,因此我将 LiLo 非常有用的答案改编为以下内容:
#!/usr/bin/env python
import os
import sys
from subprocess import Popen, PIPE
import fcntl
driver = sys.argv[-1]
print "resetting driver:", driver
USBDEVFS_RESET= 21780
try:
lsusb_out = Popen("lsusb | grep -i %s"%driver, shell=True, bufsize=64, stdin=PIPE, stdout=PIPE, close_fds=True).stdout.read().strip().split()
bus = lsusb_out[1]
device = lsusb_out[3][:-1]
f = open("/dev/bus/usb/%s/%s"%(bus, device), 'w', os.O_WRONLY)
fcntl.ioctl(f, USBDEVFS_RESET, 0)
except Exception, msg:
print "failed to reset device:", msg
Run Code Online (Sandbox Code Playgroud)
就我而言,它是 cp210x 驱动程序(我可以从中看出lsmod | grep usbserial),因此您可以将上述代码段保存为 reset_usb.py,然后执行以下操作:
sudo python reset_usb.py cp210x
Run Code Online (Sandbox Code Playgroud)
如果您的系统上还没有 ac 编译器设置,但您有 python,这也可能会有所帮助。
小智 6
最快的重置方法是重置 USB 控制器本身。这样做将强制 udev 在断开连接时取消注册设备,一旦启用它,注册就会返回。
echo -n "0000:00:1a.0" | tee /sys/bus/pci/drivers/ehci_hcd/unbind
echo -n "0000:00:1d.0" | tee /sys/bus/pci/drivers/ehci_hcd/unbind
echo -n "0000:00:1a.0" | tee /sys/bus/pci/drivers/ehci_hcd/bind
echo -n "0000:00:1d.0" | tee /sys/bus/pci/drivers/ehci_hcd/bind
Run Code Online (Sandbox Code Playgroud)
这应该适用于大多数 PC 环境。但是,如果您使用的是某些自定义硬件,则可以简单地遍历设备名称。使用此方法,您无需通过 lsusb 找出设备名称。您也可以合并到自动化脚本中。
我通过重新加载模块来使用一种大锤。这是我的 usb_reset.sh 脚本:
#!/bin/bash
# USB drivers
rmmod xhci_pci
rmmod ehci_pci
# uncomment if you have firewire
#rmmod ohci_pci
modprobe xhci_pci
modprobe ehci_pci
# uncomment if you have firewire
#modprobe ohci_pci
Run Code Online (Sandbox Code Playgroud)
这是我的 systemd 服务文件 /usr/lib/systemd/system/usbreset.service,它在我的 diplay 管理器启动后运行 usb_reset.sh:
[Unit]
Description=usbreset Service
After=gdm.service
Wants=gdm.service
[Service]
Type=oneshot
ExecStart=/path/to/usb_reset.sh
Run Code Online (Sandbox Code Playgroud)
由于问题的特殊情况是 gphoto2 与 USB 上的相机的通信问题,因此 gphoto2 中有一个选项可以重置其 USB 连接:
gphoto2 --reset
Run Code Online (Sandbox Code Playgroud)
也许这个选项在 2010 年被问到时并不存在。
小智 5
我制作了一个 python 脚本,它将根据设备编号重置特定的 USB 设备。您可以通过命令 lsusb 找到设备号。
例如:
$ lsusb
Bus 002 Device 004: ID 046d:c312 Logitech, Inc. DeLuxe 250 Keyboard
Run Code Online (Sandbox Code Playgroud)
在此字符串中 004 是设备编号
$ lsusb
Bus 002 Device 004: ID 046d:c312 Logitech, Inc. DeLuxe 250 Keyboard
Run Code Online (Sandbox Code Playgroud)
这是只会重置匹配的产品/供应商 ID 的脚本。
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'
VENDOR="045e"
PRODUCT="0719"
for DIR in $(find /sys/bus/usb/devices/ -maxdepth 1 -type l); do
if [[ -f $DIR/idVendor && -f $DIR/idProduct &&
$(cat $DIR/idVendor) == $VENDOR && $(cat $DIR/idProduct) == $PRODUCT ]]; then
echo 0 > $DIR/authorized
sleep 0.5
echo 1 > $DIR/authorized
fi
done
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
509242 次 |
| 最近记录: |