NSLU2-Linux
view · edit · print · history

The internal USB hub

10 ports instead of 2 usb slots

Inside the NSLU2 we have a usb-hub, which has not 2 ports but 5 ports. Only two of these ports are normally used, because they have a usb slot on the outside of the slug where you can plug in some usb device (a disk, memory stick, usb-hub, keyboard, camera, whatever you want).

Since a usb hub can operate on two speeds (usb 1.x or 2.0), each port is really two ports, one for fast speed and one for slow speed. So there are really 10 ports all together: 5 ports on a fast hub (bus 1), 3 ports on a slow hub (bus 2) and 2 ports on another slow hub (bus 3). Yes, the internal hub is really 3 hub-buses, linked together in one device.

So you thought you'd learn something about the two usb slots of the NSLU2, and now I tell you we have 10 usb ports? Yes. Sorry.

From ports to disk slots

So which usb slot is related to which port? The hole labeled "Disk 1" is port 0 of the fast hub (bus 1) and port 0 of the first slow hub (bus 2). The hole labeled "Disk 2" port 1 of the fast hub (bus 1) and port 0 of the second slow hub (bus 3)

                bus  port 
  Disk 1  fast   1    0   
          slow   2    0   
  Disk 2  fast   1    1   
          slow   3    0   

Finding more info about what is connected

The file /proc/bus/usb/devices gives information about what is on what bus. To understand this file, you have to remember that usb devices can be linked together in hubs (up to 5 hubs downstream), which makes a tree of devices. So you can add a usb hub to the slug, which contains some devices, and some more hubs, which in turn can contain devices. The internal hub is on level 0, the hubs and devices connected directly to it, are on level 1, devices connected to hubs on level 1 are on level 2, and so on.

Each device that gets connected will get a device number, which also shows up in /proc/bus/usb/devices.

Now lets read /proc/bus/usb/devices, or rather let's focus on the lines starting with "T:"

  T:  Bus=01 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=480 MxCh= 5

This is on level 00, so it is part of the internal hub. It is bus 1 of the internal hub, with no parent and port 0 of the non-existent parent. It got device number 1, operates on high speed and has 5 channels, which is 5 ports. So this is the fast hub (bus 1) with 5 ports.

  T:  Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12  MxCh= 3

This is the second bus of the internal hub (same dev#, also level 00), bus 2, speed is slow and it has 3 ports.

  T:  Bus=03 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12  MxCh= 2

The third bus of the internal hub (level 00 again), just as slow, with 2 channels (2 ports).

  T:  Bus=03 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12  MxCh= 0

Ah, here we have a device connected to bus 3, the second slow bus, so this must be something in the usb slot labeled "Disk-2"

  T:  Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=480 MxCh= 0

And yet another device, now connected to bus 1, port 0. This is a fast device, something in usb slot labeled "Disk-1"

Now, if we want to know if we have something in slot 1, or slot 2, we can search for certain strings in /proc/bus/usb/devices. If we find either

	Bus=01 Lev=01 Prnt=01 Port=00

or

	Bus=02 Lev=01 Prnt=01 Port=00

there is something in slot 1.

If we find

	Bus=01 Lev=01 Prnt=01 Port=01

or

	Bus=03 Lev=01 Prnt=01 Port=00 

we have something in slot 2.

Play with the leds

I made a little cron script that does the checking for me, and turns the disk leds on for me in OpenSlug, since OpenSlug has no disk-led support yet. Nothing special, and no lights flashing on disk access, but the lights go on if there is something in the slot, and they turn off if there isn't. I use the command leds to turn them on. Right now the leds disk-1 controls the disk-2 led and vice versa, but that will be better in the future.

For example:


    d1_fast="Bus=01 Lev=01 Prnt=01 Port=00"
    d1_slow="Bus=02 Lev=01 Prnt=01 Port=00"
    d2_fast="Bus=01 Lev=01 Prnt=01 Port=01"
    d2_slow="Bus=03 Lev=01 Prnt=01 Port=00"

    devinfofile="/proc/bus/usb/devices"

    d1_results=`grep "$d1_fast\|$d1_slow" $devinfofile`
    if [ "$d1_results" != "" ] ; then
            echo "  disk 1 present"
    fi

A better way is to use /etc/udev/rules.d/udev.rules, which has rules to follow whenever a change in devices occurs. I added one line:

    BUS=="usb", RUN+="/local/bin/usbleds %b"

This will run the script /local/bin/usbleds, which looks like this:

#!/bin/sh


d1_fast="Bus=01 Lev=01 Prnt=01 Port=00"
d1_slow="Bus=02 Lev=01 Prnt=01 Port=00"
d2_fast="Bus=01 Lev=01 Prnt=01 Port=01"
d2_slow="Bus=03 Lev=01 Prnt=01 Port=00"

BEEP="/bin/beep"
beepup="$BEEP -f 262 -n -f 294"
beepdown="$BEEP -f 294 -n -f 262"

LEDS="/sbin/leds"
led1on="$LEDS disk-2 on"
led1off="$LEDS disk-2 off"
led2on="$LEDS disk-1 on"
led2off="$LEDS disk-1 off"

devinfofile="/proc/bus/usb/devices"

d1_stat_file="/tmp/whatisinusb1"
d2_stat_file="/tmp/whatisinusb2"

d1_results=`grep "$d1_fast\|$d1_slow" $devinfofile`
d2_results=`grep "$d2_fast\|$d2_slow" $devinfofile`

d1_prev=`cat $d1_stat_file`
d2_prev=`cat $d2_stat_file`


if [ "$d1_results" != "" ] ; then                                               
        $led1on                                                                 
        if [ "$d1_prev" = "" ] ; then
                $beepup
        fi
else             
        $led1off
        if [ "$d1_prev" != "" ] ; then
                $beepdown 
        fi
fi



if [ "$d2_results" != "" ] ; then                                               
        $led2on                                                                 
        if [ "$d2_prev" = ""  ] ; then
                $beepup
        fi
else             
        $led2off
        if [ "$d2_prev" != ""  ] ; then
                $beepdown
        fi
fi


if [ "$d1_results" != "$d1_prev" ] ; then
        echo "$d1_results" > $d1_stat_file
fi

if [ "$d2_results" != "$d2_prev" ] ; then
        echo "$d2_results" > $d2_stat_file
fi

Nothing fancy, it does the job.

See also HowTo EnableExtraUSBPorts

view · edit · print · history · Last edited by Kees Moerman.
Based on work by Jelle Alten, kilgore, and rwhitby.
Originally by Jelle Alten.
Page last modified on May 10, 2010, at 12:51 PM