14

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
  • 1
    +1 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.
    – yo'
    Commented Mar 19, 2014 at 22:26
  • I know it's not what you want to hear, but the after the stick I was using that caused this problem fried itself, I picked up a Huawei E3131 for from Tesco (£10). It's a router in a stick, you just plug it in and you get eth1 with a NAT'd IP and you're done. It even has a web interface for config. And it can be flipped to normal PPP mode if you need to. @tohecz
    – RoboJ1M
    Commented Mar 20, 2014 at 9:51
  • Well, tell me if there's a 4G one so cheap, and you're my hero! :) (I'm currently with 4G tariff and 3G modem, yeah, and with a 4G modem that has no ARM drivers.)
    – yo'
    Commented Mar 20, 2014 at 10:20
  • Possible duplicate of Resetting usb device from terminal Commented Dec 26, 2016 at 1:19
  • Check out this related question on Unix&Linux SE. Commented Nov 18, 2019 at 13:17

5 Answers 5

3

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
13

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
4
  • 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 comment
    – RoboJ1M
    Commented 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 (using start-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 need If ttyUSB0 is not present reset the USB stick
    – RoboJ1M
    Commented Aug 27, 2013 at 14:32
  • 1
    Use lsusb command to get more information? Example ; lsusb -d xxxx:yyyy then check if your USB modem there, if it doesn't call usbreset. Commented 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
    Commented Apr 9, 2021 at 2:35
4

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)

1

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
0

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'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.