I have a USB GSM modem that does not alwasys work property (Huawei E367u-2) Sometimes it gets reset (USB device disconnect/reconnect in logs) and when it comes back up, it's has different ttyUSB numbers. Sometimes on boot, usb_modswitch seems to just not get fired. The computer is a Raspberry Pi running Raspbian.
I have a simple solution to this, every minute CRON runs the following script:
If WVDIAL is not running:
Run WVDIAL
I want to change the script to be this:
If /dev/ttyUSB0 is not present:
If DevicePresent(12d1:1446):
ResetDevice(12d1:1446)
ElseIs DevicePresemt(12d1:1506)
ResetUSB(12d1:1506)
If WVDIAL is not running:
Run WVDIAL
Obviously this is pseudo code, but I have the following lines that I need to string together but I can't figure out how:
This loads wvdial if it is not running:
#! /bin/sh
# /etc/init.d/wvdial
### BEGIN INIT INFO
# Provides: TheInternet
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Simple script to start a program at boot
# Description: A simple script from www.stuffaboutcode.com which will start / stop a program a boot / shutdown.
### END INIT INFO
# If you want a command to always run, put it here
# Carry out specific functions when asked to by the system
case "1ドル" in
start)
echo "Starting GPRS Internet"
# run application you want to start
/sbin/start-stop-daemon --start --background --quiet --exec /usr/bin/wvdial internet
;;
stop)
echo "Stopping GPRS Internet"
# kill application you want to stop
/sbin/start-stop-daemon --stop --exec /usr/bin/wvdial
;;
*)
echo "Usage: /etc/init.d/noip {start|stop}"
exit 1
;;
esac
exit 0
This lets me find the /sys
path to a certain device:
for X in /sys/bus/usb/devices/*; do
echo "$X"
cat "$X/idVendor" 2>/dev/null
cat "$X/idProduct" 2>/dev/null
echo
done
And this resets a USB device if you know the correct /sys path:
echo 0 > /sys/bus/usb/devices/1-1.2.1.1/authorized
echo 1 > /sys/bus/usb/devices/1-1.2.1.1/authorized
So, I need to string the last 2 sections and a test to /dev/ttyUSB0
into a section that goes under the "If you want a command to always run. put it here" section
UPDATE 1
usbreset, although functioning, does not do the job.
Only echo 0 the 1 into authroized
correctly simulates a device disconnect/reconnect.
This is what does the trick of booting the device or usb_modeswitch back into life.
As such I've managed to cobble together this:
echo "Searching for 1ドル"
devPath=`lsusb | grep 1ドル | sed -r 's/Bus ([0-9]{3}) Device ([0-9]{3}).*/bus\/usb\/1円\/2円/g;'`
echo "Found 1ドル @ $devPath"
echo "Searching for sysPath"
for sysPath in /sys/bus/usb/devices/*; do
echo "$sysPath/uevent"
devName=`cat "$sysPath/uevent" | grep $devPath`
#echo devName=$devName
if [ ! -z $devName ]
then
break
fi
done
if [ ! -z $devName ]
then
echo "Found 1ドル @ $sysPath, Resetting"
echo "echo 0 > $sysPath/authorized"
echo 0 > $sysPath/authorized
echo "echo 1 > $sysPath/authorized"
echo 1 > $sysPath/authorized
else
echo "Could not find 1ドル"
fi
I think therefore all I have to do now is put this in the init.d script:
if ttyUSB0 not present
if 12d1:1446 present
/usr/sbin/resetdevicebyauthorized 12d1:1446
else if 12d1:1506 present
/usr/sbin/resetdevicebyauthorized 12d1:1506
fi
fi
5 Answers 5
i made a simple bash script for reset particular USB device.
#!/bin/bash
#type lsusb to find "vendor" and "product" ID in terminal
set -euo pipefail
IFS=$'\n\t'
#edit the below tow lines of vendor and product values using lsusb result
dev=$(lsusb -t | grep usbdevicename | grep 'If 1' | cut -d' ' -f13|cut -d"," -f1)
#VENDOR=05a3
#PRODUCT=9230
VENDOR=$(lsusb -s $dev | cut -d' ' -f6 | cut -d: -f1)
PRODUCT=$(lsusb -s $dev | cut -d' ' -f6 | cut -d: -f2)
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
You can reset USB bus via this C program. https://gist.github.com/x2q/5124616
Download C code from github
wget -c --no-check-certificate https://gist.githubusercontent.com/x2q/5124616/raw/3f6e5f144efab2bc8e9d02b95b8301e1e0eab669/usbreset.c -O usbreset.c
Compile C code as usbreset
cc usbreset.c -o usbreset
Give execute permission to program
chmod +x usbreset
List your USB devices via lsusb command
lsusb
You should see USB device entries in your output and check device you want to reset for.
Bus 002 Device 003: ID 0fe9:9010 DVICO
Run usbreset program with arguments
sudo ./usbreset /dev/bus/usb/002/003
-
Still need to put it together into a script. Something like:
x = lsusb | grep xxxx:yyyy
/usr/sbin/usbreset $x
. Sadly it appears we can't put line breaks in a commentRoboJ1M– RoboJ1M2013年08月27日 14:22:25 +00:00Commented Aug 27, 2013 at 14:22 -
I need it in my init.d script (
wvdialer
). Currently CRON runs it every minute, and it re-loads wvdial if it's not present (usingstart-stop-daemon
). But it won't start if ttyUSB0 isn't there. Now for various reasons the stick just sometimes needs kicking back to life. So in that script I needIf ttyUSB0 is not present reset the USB stick
RoboJ1M– RoboJ1M2013年08月27日 14:32:28 +00:00Commented Aug 27, 2013 at 14:32 -
1Use lsusb command to get more information? Example ; lsusb -d xxxx:yyyy then check if your USB modem there, if it doesn't call usbreset.gurcanozturk– gurcanozturk2013年08月28日 06:41:39 +00:00Commented Aug 28, 2013 at 6:41
-
Thanks!, I use it to reset a webcam and works great. I will add this function inside my code.Deulis– Deulis2021年04月09日 02:35:53 +00:00Commented Apr 9, 2021 at 2:35
You can use pyusb to reset a device:
First install pyusb:
sudo pip install pyusb
Then create this script and run it:
#!/usr/bin/python
from usb.core import find as finddev
dev = finddev(idVendor=0x1234, idProduct=0x5678)
dev.reset()
Adapt the idVendor
and idProduct
to the device you want to reset (you can find the id via lsusb
)
Thank you so much! This C-Code works just great. This is the simple shell script I did to identify the USB device
#!/bin/bash
USBNAME=webcam
LSUSB=$(lsusb | grep --ignore-case $USBNAME)
FOLD="/dev/bus/usb/"$(echo $LSUSB | cut --delimiter=' ' --fields='2')"/"$(echo $LSUSB | cut --delimiter=' ' --fields='4' | tr --delete ":")
echo $LSUSB
echo $FOLD
sudo ./usbreset $FOLD
Resetting my Huawei modem does not always work. Since I'm dialing in with a systemd service anyways, I added some lines that fully unpower all USB devices and reboots the raspberry after 5 minutes :-)
[Unit]
Description=GSM Internet
Requires=network.target
# If unable to start within 12hrs, unpower all USB and reboot
StartLimitIntervalSec=43200
StartLimitBurst=300
OnFailure=unpower-usb-reboot.service
[Service]
Type=forking
User=root
ExecStartPre=/bin/ls /dev/serial/by-id/usb-HUAWEI_Technology_HUAWEI_Mobile-if00-port0
ExecStart=/usr/bin/pon
RemainAfterExit=yes
ExecStop=/usr/bin/poff
Restart=always
RestartSec=120
[Install]
WantedBy=multi-user.target
[Unit]
Description=Unpowers all USB and reboots
[Service]
User=root
ExecStart=/bin/sh -c 'echo 0 > /sys/devices/platform/soc/20980000.usb/buspower; sleep 5m; shutdown -r now'
usbreset
fails with Huawei modems, the modem is not able to recover and freezes at the reboot. I'm currently solving the same problem, and might have a fully working solution soon.