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
RoboJ1M
  • 325
  • 3
  • 4
  • 11
  • 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' Mar 19 '14 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 Mar 20 '14 at 09: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' Mar 20 '14 at 10:20

5 Answers5

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
gurcanozturk
  • 3,748
  • 1
  • 19
  • 17
  • 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 Aug 27 '13 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 Aug 27 '13 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. – gurcanozturk Aug 28 '13 at 06:41
  • Thanks!, I use it to reset a webcam and works great. I will add this function inside my code. – Deulis Apr 09 '21 at 02: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)

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

Thoht
  • 356
  • 4
  • 12
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
McPeppr
  • 121
  • 4
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'
ree2k
  • 1
  • 1