@TOC
是否可以重置USB设备的连接,而无需从计算机断开连接/连接?
具体来说我的设备是数码相机。 我正在使用 gphoto2
,但最近我得到了"设备读取错误",所以我想尝试执行连接的软件重置。
我可以看出,摄像头没有加载内核模块。 唯一看上去相关的是 usbhid
。
将以下内容保存为 usbreset.c
/* usbreset – send a USB port reset to a USB device /
#include
#include
#include
#include
#include
#include
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
命令时,对
和
id进行必要的替换:
$ sudo./usbreset/dev/bus/usb/002/003
上程序来源:http://marc.info/?l=linux-usb&m=121459435621262&w=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 " c a t " X" cat" X"cat"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#̲#*/}"{i%/}/unbind"
echo"KaTeX parse error: Expected '}', got '#' at position 3: {i#̲#*/}"{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) )
我需要在 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 。
我正在用一种锤子重新加载模块。 这是我的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
重置的最快方式是重置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 。 你也可以在自动脚本中加入。
问题的特殊情况是gphoto2在USB上的通信问题,在gphoto2中有一个选项可以重置它的USB连接:
gphoto2 –reset
可能这里选项在询问问题时不存在于 2010中。
我制作了一个 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 nThe device number can be obtained from lsusb command result’ )
return
reset_device(args.devnum)
if name’main’:
main()
下面的脚本将只重置匹配的产品/供应商 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
有人订购了sledgehammer? 这是由不同的答案拼凑在一起的。
#!/bin/bash
# Root required
if (( UID )); then
exec sudo"
0
"
"
0""
0""@"
fi
cd/sys/bus/pci/drivers
function reinit {(
local d=“
1
"
<
/
s
p
a
n
>
<
s
p
a
n
c
l
a
s
s
=
"
p
l
n
"
>
t
e
s
t
<
/
s
p
a
n
>
<
s
p
a
n
c
l
a
s
s
=
"
p
u
n
"
>
−
<
/
s
p
a
n
>
<
s
p
a
n
c
l
a
s
s
=
"
p
l
n
"
>
e
<
/
s
p
a
n
>
<
s
p
a
n
c
l
a
s
s
=
"
s
t
r
"
>
"
1"</span><span class="pln"> test </span><span class="pun">-</span><span class="pln">e</span><span class="str">"
1"</span><spanclass="pln">test</span><spanclass="pun">−</span><spanclass="pln">e</span><spanclass="str">"d” || return
rmmod"
d
"
<
/
s
p
a
n
>
<
s
p
a
n
c
l
a
s
s
=
"
p
l
n
"
>
c
d
<
/
s
p
a
n
>
<
s
p
a
n
c
l
a
s
s
=
"
s
t
r
"
>
"
d"</span><span class="pln"> cd</span><span class="str">"
d"</span><spanclass="pln">cd</span><spanclass="str">"d"
for i in
<
/
s
p
a
n
>
<
s
p
a
n
c
l
a
s
s
=
"
p
u
n
"
>
(
<
/
s
p
a
n
>
<
s
p
a
n
c
l
a
s
s
=
"
p
l
n
"
>
l
s
<
/
s
p
a
n
>
<
s
p
a
n
c
l
a
s
s
=
"
p
u
n
"
>
∣
<
/
s
p
a
n
>
<
s
p
a
n
c
l
a
s
s
=
"
p
l
n
"
>
g
r
e
p
<
/
s
p
a
n
>
<
s
p
a
n
c
l
a
s
s
=
"
p
u
n
"
>
:
)
;
<
/
s
p
a
n
>
<
s
p
a
n
c
l
a
s
s
=
"
p
l
n
"
>
<
/
s
p
a
n
>
<
s
p
a
n
c
l
a
s
s
=
"
k
w
d
"
>
d
o
<
/
s
p
a
n
>
<
s
p
a
n
c
l
a
s
s
=
"
p
l
n
"
>
e
c
h
o
<
/
s
p
a
n
>
<
s
p
a
n
c
l
a
s
s
=
"
s
t
r
"
>
"
</span><span class="pun">(</span><span class="pln">ls </span><span class="pun">|</span><span class="pln"> grep </span><span class="pun">:);</span><span class="pln"> </span><span class="kwd">do</span><span class="pln"> echo</span><span class="str">"
</span><spanclass="pun">(</span><spanclass="pln">ls</span><spanclass="pun">∣</span><spanclass="pln">grep</span><spanclass="pun">:);</span><spanclass="pln"></span><spanclass="kwd">do</span><spanclass="pln">echo</span><spanclass="str">"i"> unbind
done
sleep 1
for i in
<
/
s
p
a
n
>
<
s
p
a
n
c
l
a
s
s
=
"
p
u
n
"
>
(
<
/
s
p
a
n
>
<
s
p
a
n
c
l
a
s
s
=
"
p
l
n
"
>
l
s
<
/
s
p
a
n
>
<
s
p
a
n
c
l
a
s
s
=
"
p
u
n
"
>
∣
<
/
s
p
a
n
>
<
s
p
a
n
c
l
a
s
s
=
"
p
l
n
"
>
g
r
e
p
<
/
s
p
a
n
>
<
s
p
a
n
c
l
a
s
s
=
"
p
u
n
"
>
:
)
;
<
/
s
p
a
n
>
<
s
p
a
n
c
l
a
s
s
=
"
p
l
n
"
>
<
/
s
p
a
n
>
<
s
p
a
n
c
l
a
s
s
=
"
k
w
d
"
>
d
o
<
/
s
p
a
n
>
<
s
p
a
n
c
l
a
s
s
=
"
p
l
n
"
>
e
c
h
o
<
/
s
p
a
n
>
<
s
p
a
n
c
l
a
s
s
=
"
s
t
r
"
>
"
</span><span class="pun">(</span><span class="pln">ls </span><span class="pun">|</span><span class="pln"> grep </span><span class="pun">:);</span><span class="pln"> </span><span class="kwd">do</span><span class="pln"> echo</span><span class="str">"
</span><spanclass="pun">(</span><spanclass="pln">ls</span><spanclass="pun">∣</span><spanclass="pln">grep</span><spanclass="pun">:);</span><spanclass="pln"></span><spanclass="kwd">do</span><spanclass="pln">echo</span><spanclass="str">"i"> bind
done
modprobe"$d"
)}
for d in?hci???; do
echo" -
d
"
<
/
s
p
a
n
>
<
s
p
a
n
c
l
a
s
s
=
"
p
l
n
"
>
r
e
i
n
i
t
<
/
s
p
a
n
>
<
s
p
a
n
c
l
a
s
s
=
"
s
t
r
"
>
"
d"</span><span class="pln"> reinit</span><span class="str">"
d"</span><spanclass="pln">reinit</span><spanclass="str">"d"
done