@TOC
是否可以重置USB设备的连接,而无需从计算机断开连接/连接?
具体来说我的设备是数码相机。 我正在使用 gphoto2
,但最近我得到了"设备读取错误",所以我想尝试执行连接的软件重置。
我可以看出,摄像头没有加载内核模块。 唯一看上去相关的是 usbhid
。
回答 1:
将以下内容保存为 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-filenamen”);
return 1;
}
filename = argv[1];
fd = open(filename, O_WRONLY);
if (fd <0) {
perror(“Error opening output file”);
return 1;
}
printf(“Resetting USB device %sn”, filename);
rc = ioctl(fd, USBDEVFS_RESET, 0);
if (rc <0) {
perror(“Error in ioctl”);
return 1;
}
printf(“Reset successfuln”);
close(fd);
return 0;
}
在终端中运行以下命令:
编译程序:
复制代码$ cc usbreset.c -o usbreset
获取要重置的USB设备的总线和设备 ID:
复制代码$ lsusb
Bus 002 Device 003: ID 0fe9:9010 DVICO使编译后的程序成为可执行文件:
复制代码$ chmod +x usbreset
使用sudo特权执行程序,在运行
lsusb
命令时,对<Bus>
和<Device>
id进行必要的替换:复制代码$ sudo./usbreset/dev/bus/usb/002/003
回答 2:
我没有在你的特定情况下找到自己,所以我不确定它是否能够做到,但是我找到了 ( 无需外部应用)
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"
这是我用来重置我的for的实际方法,因为libfreenect似乎没有将它放回睡眠的API 。 它在我的foaf框中,但内核应该足够新,以使用相同的路径结构。
当然,我们可以使用 1-4.6
来获取供应商和产品 ID,然后使用像这样的快速命令来列出供应商和产品 ID,以列出路径与不同厂商/产品ID对的关系:
for X in/sys/bus/usb/devices/; do
echo"
X/idVendor" 2>/dev/null
cat"KaTeX parse error: Expected 'EOF', got '&' at position 15: X/idProduct" 2&̲gt;/dev/null
e…i" ] || continue
echo"KaTeX parse error: Expected '}', got '#' at position 3: {i#̲#*/}"</span><sp…{i%/}/unbind"
echo"KaTeX parse error: Expected '}', got '#' at position 3: {i#̲#*/}"</span><sp…{i%/*}/bind"
done
我相信这会解决你的问题。 如果不想重置所有的USB端点,可以从 /sys/bus/pci/drivers/ehci_hcd
中使用适当的设备 ID
注:[1]: *hci_hcd
内核驱动程序通常控制USB端口。 ohci_hcd
和 uhci_hcd
用于 USB1.1 端口,ehci_hcd
用于USB2端口,xhci_hcd
用于usb端口。 ( 请参阅 https://en.wikipedia.org/wiki/Host_controller_interface_(USB,Firewire) )
回答 4:
我需要在 python 脚本中自动化这个问题,因这里我适合于以下方面的基本应答:
#!/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
在我的例子中,它是cp210x驱动( 我可以从 lsmod | grep usbserial
),因此可以将上面的代码段保存为 reset_usb.py,然后执行以下操作:
sudo python reset_usb.py cp210x
如果你的系统上没有c 编译器设置,这也可以能会有帮助,但是你有 python 。
回答 5:
我正在用一种锤子重新加载模块。 这是我的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
这是我的systemd服务文件/usr/lib/systemd/system/usbreset. 服务,它在我的diplay管理器启动后运行 usb_reset.sh:
[Unit]
Description=usbreset Service
After=gdm.service
Wants=gdm.service
[Service]
Type=oneshot
ExecStart=/path/to/usb_reset.sh
回答 6:
重置的最快方式是重置USB控制器本身。 这样做将强制udev在断开连接时注销设备,并且 register 在你启用它后返回。
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
这对于大多数电脑环境都适用。 但是,如果你使用的是一些定制硬件,你可以简单地迭代设备名称。 使用这里方法,你不需要通过lsusb查找设备 NAME 。 你也可以在自动脚本中加入。
回答 7:
问题的特殊情况是gphoto2在USB上的通信问题,在gphoto2中有一个选项可以重置它的USB连接:
gphoto2 –reset
可能这里选项在询问问题时不存在于 2010中。
回答 8:
我制作了一个 python 脚本,它将根据设备号重置特定的USB设备。 你可以从命令lsusb中找到设备号。
例如:
$ lsusb
Bus 002 Device 004: ID 046d:c312 Logitech, Inc. DeLuxe 250 Keyboard
在这里字符串 004中是设备号
import os
import argparse
import subprocess
path=’/sys/bus/usb/devices/’
def runbash(cmd):
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
out = p.stdout.read().strip()
return out
def reset_device(dev_num):
sub_dirs = []
for root, dirs, files in os.walk(path):
for name in dirs:
sub_dirs.append(os.path.join(root, name))
dev_found = 0
for sub_dir in sub_dirs:
if True os.path.isfile(sub_dir+’/devnum’):
fd = open(sub_dir+’/devnum’,‘r’)
line = fd.readline()
if int(dev_num) int(line):
print ('Your device is at: ‘+sub_dir)
dev_found = 1
break
fd.close()
if dev_found 1:
reset_file = sub_dir+’/authorized’
runbash('echo 0> '+reset_file)
runbash(‘echo 1> ‘+reset_file)
print (‘Device reset successful’)
else:
print (“No such device”)
def main():
parser = argparse.ArgumentParser()
parser.add_argument(’-d’, ‘–devnum’, dest=‘devnum’)
args = parser.parse_args()
if args.devnum is None:
print(‘Usage:usb_reset.py -d <device_number> nThe device number can be obtained from lsusb command result’)
return
reset_device(args.devnum)
if name’main’:
main()
回答 9:
下面的脚本将只重置匹配的产品/供应商 ID 。
#!/bin/bash
set -euo pipefail
IFS=$‘nt’
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
回答 10:
有人订购了sledgehammer? 这是由不同的答案拼凑在一起的。
#!/bin/bash
# Root required
if (( UID )); then
exec sudo"
@"
fi
cd/sys/bus/pci/drivers
function reinit {(
local d=“
d” || return
rmmod"
d"
for i in
i"> unbind
done
sleep 1
for i in
i"> bind
done
modprobe"$d"
)}
for d in?hci???; do
echo" -
d"
done