Murasaki LinkStation's USB hot-plugging system

'' This article Based on work by Harry, frontalot, and nix. Originally by nix. at Linkstationwiki.org ''

Overview
The original LinkStation firmware (at least for the LS1 and LS2) and the OpenLink firmware use a software called Murasaki for handling the USB hot-plugging of printers and hard disks. [Murasaki] is not some special Buffalo software, but a free alternative hot-plugging framework for Linux. It replaces Linux's normal hot-plugging framework HotPlug. It is unknown why Buffalo / MontaVista went for Murasaki instead of the standard hot-plugging framework. But anyhow, Murasaki is suitable for the desired task.

The Murasaki version 0.6.12 that comes with the mipsel-hdhlan LinkStation 2.05 firmware is rather old. That version also is incomplete. The components which are not used for USB hot-plugging are not included. However, the missing components, e.g. FireWire support, don't make much sense on the LinkStation and the old version is nevertheless functional.

Adding Support for Other Devices
Before you start to mess around with Murasaki, please be aware that you should possess some understanding of Murasaki, Linux, and shell scripting. In short, you should know what you are doing.

Drivers & Kernel Modules
Murasaki is not limited to handling only printers and hard disks. It can handle other types of USB devices too. However, the necessary drivers (kernel modules) must first be built and installed on the LinkStation. See Loadable kernel modules for information about loadable kernel modules - some of which are for USB devices.

Murasaki Configuration
Then the Murasaki configuration files need to be adapted. The Murasaki files which need to be touched are:


 * /etc/murasaki/murasaki.usbmap:To map devices with unknown ids to a driver.
 * To find out the values for an entry you should plug in the unknown USB device and then fetch the data from the syslog log file /var/log/linkstation.log. Some entries can also be found in [].

device-name script ...
 * /etc/murasaki/murasaki.call:To map device types or module names to corresponding start-stop scripts which are called when a device of a certain type is plugged-in or a certain module is loaded. Also, the scripts are called after a device or module is removed. :The format is


 * for devices, or

module-name script ...


 * for modules. The first argument to the scripts is either start or stop to identify the actual event.


 * /etc/murasaki/bin/...:Start-stop scripts should be placed in /etc/murasaki/bin. The existing mount_sd.sh script in that directory can serve as an example. mount_sd.sh is the script which is supposed to mount USB disks, once they are plugged in.


 * /etc/murasaki/murasaki.precall:(not used by by the stock LinkStation firmware) The file has a very similar function to murasaki.call. The difference is when the scripts are called. murasaki.precall scripts are called before a device is loaded and before a device is unloaded. Scripts specified in murasaki.call</tt> are called after a device is loaded and after a device is unloaded.


 * /etc/murasaki/murasaki.depend: Module dependencies.
 * This file specifies kernel module dependencies related to USB. Typically, a USB device driver at least depends on the usbcore</tt> module. The format of an entry is

dependent: depends ...


 * typically an entry looks like

dependent: usbcore


 * /etc/murasaki/murasaki.sticky:(not used by by the stock LinkStation firmware) A list of modules which are not unloaded, even if a hot-plug remove event happens. This is useful for devices which are regularly plugged-in and out at a high frequency.

Trouble Shooting
If things don't work out, you can start debugging at the following places:


 * Check /var/log/linkstation.log</tt> for any Murasaki messages. If Murasaki doesn't know the USB ID it will print out information on how to add it here.


 * Check /proc/bus/usb/devices</tt> after inserting the USB device. There should be an entry for your device. Note, each entry for a device starts with a T line. To get a slightly better readable printout, you could run

awk '/^T/ { print ""} {print}' /proc/bus/usb/devices | more


 * instead of a simple cat</tt> or more</tt>.
 * The output for a device should, for example, look like:

T: Bus=02 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12  MxCh= 0 D: Ver= x.xx Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1 P: Vendor=xxxx ProdID=xxxx Rev= x.x S:  Product=USB Storage Device C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr= 96mA I: If#= 0 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage E: Ad=81(I) Atr=02(Bulk) MxPS=  64 Ivl=0ms E: Ad=02(O) Atr=02(Bulk) MxPS=  64 Ivl=0ms


 * Note the I (for Interface) line. A USB device can have multiple interfaces. The one is the above example has been associated with a device driver (usb-storage). This is what you want. If no interface gets associated wit a driver, it doesn't exist for the kernel.
 * FYI, the letters in the output stand for:
 * T:Topology
 * B:Bandwidth
 * D:Device description
 * P:Product Id
 * S:Text description
 * C:Configuration info. * indicates the active configuration.
 * I:Interface description
 * E:Endpoint descripton

usbdevfs hub 0- 15: usblp usb-storage usb-storage
 * One can check all USB drivers currently known (loaded) by the kernel with
 * 1) cat /proc/bus/usb/drivers

cat /proc/scsi/usb-storage-*/*
 * If a USB storage device has been found, and the USB storage driver been loaded, then the SCSI disk driver emulation device driver should have been automatically loaded on top of it.
 * shows all such devices. E.g. the output should be similar to

Host scsi0: usb-storage Vendor: xxxxx xxxx xxxxxxxxx Product: USB Storage Device Serial Number: None Protocol: Transparent SCSI Transport: Bulk GUID: 0xxxxxxx0000000000000000 Attached: Yes


 * Note the Attached: Yes line. If this doesn't say Yes, then the device has been found, but for some reason is not attached (no media in the device). However, this can also happen when an external USB hub is in use between the storage device and the LinkStation. The only known way to fix this problem with a hub is to remove the hub and connect the storage device directly.

... ... /dev/sda1 on /mnt/usbdisk1 type vfat (rw)
 * If everything went fine until now, then Murasaki should have mounted the device:
 * 1) mount

Supporting USB Memory Sticks and Other USB Storage Devices
mount_sd.sh</tt> on stock mipsel-hdhlan firmware refuses to mount USB memory sticks or any other USB storage device which doesn't identify itself as a hard disk or optical disk. The culprit (bug or feature?) seems to be the program /usr/bin/parse_usbscsi</tt> which is used by mount_sd.sh</tt> to identify USB disks. A potential workaround is to add the following lines to mount_sd.sh</tt>, right after the call to /usr/bin/parse_usbscsi</tt>:

# # awk '$1 ~ /Host/ && $3 ~ /usb-storage/ { printf "/dev/sd%c\n", substr($2, 5, length($2) - 5) + 97 }' /proc/scsi/usb-storage-*/* >>/mnt/usbinfo/list
 * 1) HACK for mounting USB memory sticks.
 * 2) The above /usr/bin/parse_usbscsi doesn't identify
 * 3) them as usable storage device.

Please note that this hack ignores many finer details of identifying a disk. Also, the remaining unchanged parts of the mount_sd.sh</tt> script will not only mount the found memory stick but also share it via SAMBA, AppleTalk, and provide access to the data on the stick via ftp (if any of these services is configured). This may not be desirable - depending on the data on the stick. You will also see that SAMBA and AppleTalk are restarted.

Allowing More than one USB disk
mount_sd.sh</tt>, as-delivered, just mounts the first USB disk found. This is in line with Buffalo's product description. If one feels adventurous this can be changed in mount_sd.sh</tt>. The code was originally in mount_sd.sh</tt> and has just been commented out. The commented-out sections need some minor changes to get them to work again.