my tech blog
Popular Posts
Latest Posts
Archives
Avoiding reboot: Resetting USB on a Linux machine
Every now and then, some USB device misbehaves badly enough to knock out the entire interface, to the extent that the system doesn’t detect any new USB devices. Or work so well with the existing ones, for that matter. The solution for me until now was to reboot the computer. But hey, I don’t like rebooting Linux!
So this script (I call it usbreset) performs a reset to the USB drivers as necessary to bring them back to life. As a side effect, an equivalent to unplugging and replugging all USB devices takes place. If possible, unmount any connected USB storage device (e.g. disk on key) before doing this. Also, if you’re in the middle of printing through a USB device, or some other operation, this will not be graceful.
An interesting thing I noted, was that if there’s a really problematic device on the bus (for example, a device that fails to enumerate), this script doesn’t return. It probably gets stuck on one of the writes to “bind” (hasn’t checked that all the way through).
Use at your own risk. You are root, you should know what you’re doing (or gamble like myself). Script follows.
If it doesn’t work for you, check the comments below. The names of the /sys files vary slightly among different distributions.
A word about how this script works, so it goes like this: The USB controllers are PCI / PCIe / fake PCI devices. So the script goes to the /sys directory that is related to the PCI devices’ driver, and unbinds them from the device, and then bind them back. So it’s like saying, nah, this device doesn’t belong to the driver, and then say, well, it is. And in the latter stage, the driver initializes the device, which does the job. On a good day.
Those file names like 0000:00:14.0 that appear in /sys/bus/pci/drivers/xhci_hcd/ are the PCI bus addresses of the USB controllers that are handled by the xhci_hcd driver. These will vanish from the directory after writing to “unbind” and return after writing to “bind”. The names can be found in /sys/bus/pci/devices/. Use “lspci” to tell which device is which.
The script above is in fact a newer version of the script, which I updated to in June 2014, after upgrading my kernel to 3.12. The older one, to which some of the comments relate, is this one:
The problem with the old script is that the EHCI subdirectory doesn’t appear on my system, because xHCI is a catch-all for all USB versions, hence when a USB port is 3.0 capable, it’s driven by the xhci_hcd driver only. The new script catches all possibilities. Hopefully.
Reader Comments
Hi I tried your script yesterday, and it worked perfectly. Then I updated to Ubuntu 13.04, and now I get the ehci_hcd error, do you have any idea why?
No idea. I’ll be glad if you found out and posted another comment saying how you solved this…
Thanks for the info Eli, the problem that Jesper might be having is that the bus names might be slightly different. I put an updated script at https://enc.com.au/2014/02/14/resetting-usb-devices/ with a link back here because its largely your script with that change and some minor cleanups.
sudo ./reset_usb
./reset_usb: line 17: echo: write error: No such device
./reset_usb: line 18: echo: write error: No such device
./reset_usb: line 21: cd: /sys/bus/pci/drivers/ehci_hcd: No such file or directory
Weird error. Failed to change directory to /sys/bus/pci/drivers/ehci_hcd
For what it’s worth. VMware loves to kill my USB for some reason.
Hmmm… Why did you use the old version?
But yes, VMware has a thing about stealing USB devices under my nose, but I didn’t know that it eliminated them too. 🙂
Источник
Resetting the USB Subsystem
Jarret W. Buse
Guest
Resetting the USB Subsystem
The Universal Serial Bus (USB) is a major improvement for all computer systems to allow a universal connection type for numerous device types. The Bus system is a little more complicated than most can imagine. Sometimes, it is possible that the USB devices fail and require to be restarted. Usually, this is a simple procedure of restarting the system, but this can be a major hassle at times. There is a better way.
Before we get to restarting the Universal Serial Bus, we need a little more understanding about it.
The main points about USB which makes it universally accepted are:
- Connector type – a universal connector which is unlike other types. Before, the serial, parallel, video, etc. were all different connector types.
- Expandable – ability to support 127 devices on a single bus.
- Hot swappable – supports attach/removal of device while system is on.
- Performance – four speeds exist depending on USB type
- Low Speed – 1.5 Mb/sec for USB 1.0
- Full Speed – 12 Mb/sec for USB 1.1
- High Speed – 480 Mb/sec for USB 2.0
- Super Speed – 5 Gb/sec for USB 3.0
- Plug and Play – supported Operating Systems can detect device type and configure the device as needed.
- Power – supplied by bus, if needed.
- Power Saving – ability to suspend/resume devices when not in use.
- Simplicity – easy for users to manage hardware.
As noted, there are four basic USB standards. Each standard has a specific Interface type as follows:
- 1.x – Open Host Controller Interface (OHCI)
- 1.x – Universal Host Controller Interface (UHCI)
- 2.0 – Enhanced Host Controller Interface (EHCI)
- 3.0 – eXtensible Host Controller Interface (xHCI)
To determine your USB type in Linux, go to a Terminal and use the ‘lsusb -t’ command. The following shows three different systems.
Looking at Figure 1, you can see there are four USB buses. These are labeled Bus 1 to Bus 4. All of these main devices are listed as “root_hubs” on Port 1. Root hubs are always Port 1 and devices attached are listed on the following ports, starting at 2, as they are attached. The driver specifies the Linux driver and designates the USB Standard (OHCI, UHCI, EHCI or xHCI). The number following the “/” designates how many ports are located on the device. Be aware that the number of ports may not be external ports. For example, Bus 1 in Figure 1 shows it has six ports. Bus 1 is definitely USB 2.0 since it is listed with the driver EHCI and lists the bus speed as 480M. Buses 2 to 4 are all USB 1.1 at a speed of 12M.
NOTE: Be aware that a port can be connected to a USB 1.x and 2.0 Root Hub. If the USB 2.0 Root Hub fails, then the port to which it is connected can still function as a USB 1.x port. We can explore this ability later.
Figure 2 shows a system with seven USB Buses. Three of the buses are USB 2.0 and four are USB 1.1. Some internal devices, which may be part of the ports, can include:
- Audio
- Video
- Network
- Chipsets
- Card readers
- Optical devices
- Internally mounted Mass Storage Device
- Bluetooth
Some systems use the bus on the motherboard and some motherboards literally have a USB port on it. An internal USB port can be used to add external ports or add an internal device. USB mass storage devices can be mounted internally and attached to the port.
Figure 3 shows a system with three USB hubs. Bus 1 and 2 are USB 2.0 while Bus 3 is a USB 3.0 root hub. Remember that the Root Hubs are listed as Device 1. Here, you can see there is a Device 2 on Bus 1 which is listed as “Intel” and is an Intel Webcam. Bus 2 has two devices connected to it as Device 2 and Device 3. Device 2 is listed as “Syntek” which is a mouse. Device 3 is a Multi Flash reader.
You may be looking at Figure 3 and thinking about the ID. Each USB device has a built-in Device ID which is in two parts separated by a colon ). The first part is the manufacturer (Vendor ID) and the second part is the device (Product ID). For example, 8087 is the manufacturer ID for Intel.
NOTE: Vendors may have more than one ID. A list of Vendor IDs can be found on the Internet or at https://usb-ids.gowdy.us/read/UD/.
If you have multiple external USB ports, you can place a device in a port and run ‘lsusb’ at a prompt in a terminal. From the output, you can determine which port belongs to which bus. By doing this, you can tell which port is which USB Standard and speed.
To see the USB devices in a tree view, you can use the “lsusb -t” command as shown in Figure 4 which is the output from the system in Figure 3.
So, let’s look back at Figure 2. Here, we can see there are seven Root Hubs listed as Bus 1 through 7. To be able to disable the Bus, we need to have a number for it which is made up as follows:
We have to find the addresses for each Root Hub to turn it off and back on. To get the addresses, we use the following command:
lspci | grep USB
NOTE: The command is case-sensitive, especially the ‘USB’ portion.
The ‘grep’ portion of the command is looking for lines with ‘USB’ in it. The system from Figure 2 will produce an output as shown in Figure 5.
Figure 5 shows the seven Root Hubs with the address. It is only missing the Domain portion which is: 0000. So, now we have the following addresses with a USB Type:
00:12.0 OHCI – USB 1.1
00:12.2 EHCI – USB 2.0
00:13.0 OHCI – USB 1.1
00:13:2 EHCI – USB 2.0
00:14.5 OHCI – USB 1.1
00:16.0 OHCI – USB 1.1
00:16.2 EHCI – USB 2.0
There is a minor problem yet. We do not know which address is for which Bus. If you managed some testing with the ‘lsusb’ command and moved a device from port to port, you should have an idea which ports are for which bus.
If a port quits working and you wish to turn off that specific Root Hub, then you need to know which port is which. If a Hub fails, you can use ‘lsusb -t’ to see if it is still ‘on’. For example, if your USB mouse stops functioning and you know it is Bus 5, run ‘lsusb -t’ to determine if Bus 5 is still listed. If Bus 5 does not appear in the output, then Bus 5 has failed.
To enable/disable a Root Hub, you need to know the address. Open a Terminal and log in as root. Once in as root, you can use the following command to match up the Bus evice to an address:
lsusb -v -s bus:device | grep iSerial
For example, if I wanted the address for the Root Hub on Bus 1, I would enter the following command:
lsusb -v -s 1:1 | grep iSerial
Figure 6 shows the results that the Root Hub, always Device 1, on Bus 1 is at the address 0000:00:12.2.
The same option would need to be run for all Root Hubs on all buses. My system gives the following:
00:12.0 – Bus 4
00:12.2 – Bus 1
00:13.0 – Bus 5
00:13.2 – Bus 2
00:14.5 – Bus 6
00:16.0 – Bus 7
00:16.2 – Bus 3
Let us assume my mouse quit working, which is connected to Bus 5. I run the ‘lsusb’ command see that Bus 5 is missing as shown in Figure 7.
I will need to perform a command to cause Bus 5 to be reactivated. I have already determined that Bus 5’s address is 0000:00:13.2, and from the ‘lsusb -t’ command, the driver is ‘ohci_hcd’. The command is as follows:
echo -n «0000:00:13.0» | tee /sys/bus/pci/drivers/ohci_hcd/bind
The address is the address of the device. The ‘ohci_hcd’ is from the ‘lsusb -t’ command. There are two terms to use at the end of the statement:
- bind – enable the Root Hub
- unbind – disable the Root Hub
The same Root Hub could be disabled with the following command:
echo -n «0000:00:13.0» | tee /sys/bus/pci/drivers/ohci_hcd/unbind
NOTE: The commands can be carried out in a terminal as the root user.
Be careful when disabling a specific Bus. If you disable a keyboard or mouse by accident, move the device to a different USB Port.
To enable my Bus 1 Root Hub, I would use the following command:
echo -n «0000:00:12.2» | tee /sys/bus/pci/drivers/ehci-pci/unbind
NOTE: Watch that the USB 1.1 devices are ‘ohci_hcd’ and the USB 2.0 devices are ‘ehci-pci’.
Источник
Как перезагрузить USB-устройство из командной строки?
Можно ли сбросить подключение USB-устройства без физического отключения / подключения от ПК?
В частности, мое устройство представляет собой цифровую камеру. Я использую gphoto2 , но в последнее время я получаю «ошибки чтения устройства», поэтому я хотел бы попытаться выполнить программный сброс соединения.
Из того, что я могу сказать, нет никаких модулей ядра, загружаемых для камеры. Единственный, который выглядит связанным, это usbhid .
Сохранить следующее как usbreset.c
Выполните следующие команды в терминале:
Получите идентификатор шины и устройства USB-устройства, которое вы хотите сбросить:
Сделайте нашу скомпилированную программу исполняемой:
Запустите программу с привилегией sudo; сделать необходимые замены и идентификаторы, найденные с помощью lsusb команды:
Я раньше не сталкивался с вашими конкретными обстоятельствами, поэтому я не уверен, что этого будет достаточно, но я нашел самый простой способ перезагрузить USB-устройство с помощью этой команды: (Внешние приложения не нужны)
Это именно то, что я использую для сброса моего Kinect, поскольку у libfreenect, похоже, нет API для возврата его в спящий режим. Он у меня на Gentoo box, но ядро должно быть достаточно новым, чтобы использовать ту же структуру пути для sysfs.
Ваш, очевидно, не будет, 1-4.6 но вы можете либо извлечь этот путь устройства из журнала ядра ( dmesg ), либо использовать что-то вроде lsusb получения идентификатора производителя и продукта, а затем использовать быструю команду, подобную этой, чтобы увидеть, как эти пути связаны с другим поставщиком. / пары идентификаторов продукта:
Это сбросит все подключенные порты USB1 / 2/3 [1]:
Я верю, что это решит вашу проблему. Если вы не хотите сбрасывать все конечные точки USB, вы можете использовать соответствующий идентификатор устройства из /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) )
Мне нужно было автоматизировать это в скрипте Python, поэтому я адаптировал чрезвычайно полезный ответ LiLo к следующему:
В моем случае это был драйвер cp210x (о котором я мог сказать lsmod | grep usbserial ), так что вы можете сохранить приведенный фрагмент как reset_usb.py, а затем сделать это:
Это также может быть полезно, если у вас еще нет настройки компилятора переменного тока в вашей системе, но у вас есть Python.
Я создал скрипт Python, который упрощает весь процесс на основе ответов здесь.
Сохраните приведенный ниже скрипт как reset_usb.py или клонируйте этот репозиторий .
Поскольку частный случай вопроса — это проблема связи gphoto2 с камерой по USB, в gphoto2 есть возможность сбросить USB-соединение:
Возможно, этот вариант не существовал в 2010 году, когда был задан вопрос.
Самым быстрым способом сброса будет сброс самого контроллера USB. Это заставит udev отменить регистрацию устройства при отключении, и регистрация вернется после того, как вы его включите.
Это должно работать для большинства компьютерных сред. Однако, если вы используете какое-то нестандартное оборудование, вы можете просто перебирать имена устройств. С помощью этого метода вам не нужно узнавать имя устройства по lsusb. Вы также можете включить в автоматизированный скрипт.
Я использую кувалду, перезагружая модули. Это мой скрипт usb_reset.sh:
И это мой файл службы systemd /usr/lib/systemd/system/usbreset.service, который запускает usb_reset.sh после запуска моего менеджера diplay:
Я сделал скрипт Python, который будет сбрасывать определенное устройство USB на основе номера устройства. Вы можете узнать номер устройства из команды lsusb.
В этой строке 004 номер устройства
Вот скрипт, который будет сбрасывать только соответствующий идентификатор продукта / поставщика.
Кто-нибудь заказывал кувалду? Это воедино из различных других ответов здесь.
Иногда я хочу выполнить эту операцию на определенном устройстве, как указано VID (идентификатор поставщика) и PID (идентификатор продукта). Это скрипт, который я нашел полезным для этой цели, который использует изящную библиотеку libusb.
Затем этот c ++ файл resetDeviceConnection должен выполнить эту задачу сброса подключения устройства, как указано в vid и pid.
Я сделал простой скрипт для перезагрузки определенного USB-устройства.
Возможно, это работает и для камеры:
После я восстановил голодный USB 3.0 HDD на 3.4.42 (kernel.org) Linux на моей стороне. dmesg сказал, что это было время ожидания команд после 360 секунд (извините, я не могу скопировать системный журнал здесь, не подключенные сети), и диск завис полностью. Процессы доступа к устройству были заблокированы в ядре и не могут быть уничтожены. NFS висел, ZFS висел, dd висел.
После этого все снова заработало. dmesg рассказал только одну строчку о USB найденном устройстве.
Я действительно понятия не имею, что делает следующее подробно. Но это сработало.
Следующий пример выводится из Debian Squeeze с 2.6.32-5-686 ядром, поэтому я думаю, что он работает для 2.6 и выше:
Если это не работает, возможно, кто-то еще может выяснить, как отправить реальный сброс на устройство.
Попробуйте, это отключение программного обеспечения (Eject).
Иногда не работает просто отсоединить устройство для некоторых устройств.
Я хочу удалить или извлечь мой «Genius NetScroll 120».
Тогда я сначала проверь мое подключенное USB-устройство
Хорошо, я нашел свою мышь, она имеет шину 002, устройство 009, idVendor 0458 и idProduct 003a, так что это справочная информация об устройстве мыши.
Это важно, номер шины — это начальный путь к устройству, и я проверю идентификатор продукта и поставщика, чтобы убедиться, что устройство удаляется.
Обратите внимание на папки, проверьте начало с папкой номер 2, я проверю эту, потому что мой Bus — 002, и одну за другой я проверяю каждую папку, содержащую правильные idVendor и idProduct, о моей информации о мыши.
В этом случае я получу информацию с помощью этой команды:
Хорошо, путь /sys/bus/usb/drivers/usb/2-1.3/ совпадает с моей информационной мышью! XDDD.
Пришло время удалить устройство!
Подключите снова USB-устройство, и оно снова работает!
Источник