Adventures in not actually frying my USB bus

Well, that was exciting. I had an unplanned adventure in technical troubleshooting today.

The symptom: USB isn’t working properly. Low-speed 1.1 devices work, but USB 2.0 appears busted. Rebooting doesn’t fix the problem. Trying other kernels doesn’t fix the problem. The problem also exists in Windows. All googling indicates possible hardware failure. Shit.

I really didn’t want to call tech support, so I actually ran the Dell Diagnostic help tree that comes with their installation of windows. Some of the questions are obvious, like, are the ports physically damaged, but as you drill down it makes a very helpful suggestion: Try running the diagnostics program that came with your computer!

In my case, Dell has a program that will burn a bootable CD. That CD will test the entire system, including the USB subsystem. Interestingly, the diagnostic came back clean. How can USB be busted if the tests are ok?

Ultimately, I have no idea, because when I rebooted into Windows the problem was gone. Booting back into linux, the problem was fixed there too. And here I thought I would have to replace the motherboard because of a burnt-out usb system.

The first moral of the story: It is possible for linux to fuck up USB so bad, a reboot and power-cycle won’t fix it.

The second moral of the story: It’s really nice to have windows around when you want to see if a problem is linux-specific, or hardware-specific. (The same goes the other way. If you have windows installed, it’s nice to have a linux installation, or at least a boot disc, so you can try stuff out.)

The third moral of the story: Even if you think you are technically able, don’t jump to the conclusion that a problem is fucked hardware. Go through the motions of troubleshooting the problem, and who knows, it might actually be fixable without mailing your part in for service. I was this close to calling Dell, and there would have been no need.

Edit:
Hrm. Well, the usb died again. This time the dell diagnostic didn’t bring it back. Time to call tech support

Edit 2:
Double hrm. Spent an hour on the phone and screen sharing with Dell tech support, who proved completely immune to my evidence that this was a hardware issue, not a software issue. They installed some driver and the problem went away, but I think it’s just like last time — it randomly fixed itself and the problem still remains. The best part was when the tech support person suddenly decided to become a sales rep and asked me why I hadn’t bought dell’s extra Accidental Protection Plan or some shitty tuneup software. Way to put progressbar time to good use, assholes.

More Audio 4 DJ tricks

In my DJ setup, I use the JACK sound server to link my mixing program to a bunch of fun effects. It is possible to get JACK to perform at extremely low latencies (~6ms and less) but it’s hard to get all the options just right. For the benefit of others who don’t want to go through the same trial and error I did, here is the command line I’m using to launch jack:

jackd -R -P 99 -p128 --timeout 4500 -d alsa -d AUDIO4DJ -p $size -n $periods -i 4 -o 4 -r 44100

Here’s what all that means:

  • -R: Realtime mode
  • -P 99: Realtime Priority value (maxed out)
  • -p 128: max jack ports
  • –timeout 4500: client timeout in ms. This is very important, because Mixxx might hang for longer than the default 500ms when it’s loading tracks. If that happens, JACK kicks out Mixxx and playback stops
  • -d alsa: Use ALSA backend

(Note, after this argument, the rest of the arguments are ALSA-specific

  • -d AUDIO4DJ: use the AUDIO4DJ alsa device (see my previous post)
  • -p $size -n $periods: These two options are what determines the size of the sound buffer. The first number is the frame size, in bytes (I think). The second is the number of frames. Multiply the two together to get the total size. With a special realtime kernel, I can set this to 64 and 4 (total: 256, or about 6ms). With a standard kernel, it has to be 128 and 3 (total: 384, 9ms). The idea is you want to get the total multiplied number as small as possible without inducing the dreaded XRUN, which happens when your computer can’t feed audio to the sound card fast enough.
  • -i 4 -o 4: 4 inputs, 4 outputs
  • -r 44100: CD-rate audio

Yeah, I know, if I just bought a mac and Traktor or Serato I wouldn’t have to deal with this shit, but I’m cheap and can’t resist a challenge.

Native Instruments Audio 4 DJ on linux

The Native Instruments Audio4DJ is a professional-quality USB soundcard for DJing that is also supported under linux. Like mode devices that are “supported” under linux, however, it can be tricky to set up correctly. In my case, I need the device to work with the JACK sound server, and I needed to do a little extra work.

The first trick is setting up ALSA so that JACK works happily with the card. The problem is that the drivers don’t supply any regular mixer controls for the Audio4DJ, which makes jackd unhappy. So when creating a .asoundrc, it’s necessary to substitute the internal soundcard as the mixer elements for that device. Putting this text in ~/.asoundrc does the trick:

pcm.AUDIO4DJ {
    type multi;
    # bind hardware devices
    slaves.a.pcm "hw:1,0,0";
    slaves.a.channels 2;
    slaves.b.pcm "hw:1,0,1";
    slaves.b.channels 2;
    # bind channels to virtual device;
    bindings.0.slave a;
    bindings.0.channel 0;
    bindings.1.slave a;
    bindings.1.channel 1;
    bindings.2.slave b;
    bindings.2.channel 0;
    bindings.3.slave b;
    bindings.3.channel 1;
}

# JACK will be unhappy if there is no mixer to talk to, so we set
# this to card 0. This could be any device but 0 is easy. 
#note that audio4dj is actually card 1 -- we are faking mixer elements so JACK is happy:

ctl.AUDIO4DJ {
        type hw;
        card 0;
}

The second question is how to change the input mode of the Audio4DJ from phono to line and back. Normally this type of setting would be found in the alsamixer program, but for some reason it’s hidden away. This script makes it easy:

#!/bin/bash

if [ "$1"x == "x" ] ; then
	echo "$0 [phono|line|timecode]"
	exit 1
fi

dev=`aplay -l  | grep Audio4DJ | grep "device 0" | cut -d\  -f 2 | cut -d: -f 1`
if [ "$dev"x == "x" ] ; then
	echo "Audio 4 DJ not connected"
	exit 1
fi

result=0
if [ "$1" == "phono" ] ; then
	amixer -c $dev cset numid=1 2 > /dev/null
	result=$?
elif [ "$1" == "line" ] ; then
	amixer -c $dev cset numid=1 1 > /dev/null
	result=$?
elif [ "$1" == "timecode" ] ; then
	amixer -c $dev cset numid=1 0 > /dev/null
	result=$?
else
	echo "$0 [phono|line|timecode]"
	exit 1
fi

if [ $result -ne 0 ] ; then
	echo "Error setting Audio 4 DJ input"
	exit $result
fi