Linux eMagic driver update
Dec. 10th, 2013 06:53 pm
Every now and then I'm reminded I'm not the last emi2|6 or 6|2m user left in the world-- apparently Debian just recently made some of the changes that broke the eMagic drivers on other distros years ago and I've been getting mail about it again.
Background: The eMagic emi2|6 and 6|2m firmware loaders shipped with the Linux kernel have been broken for many years. Different distros have had them on life support with an inconsistent array of minor patches, but they've got a couple problems across the lot: races in the loader, an incorrect memory target, deadlocking all of USB with synchronous firmware requests in probe(), and the fact that the bitstream.fw file being shipped for the 6|2m is the wrong file. Apparently, someone accidentally substituted the 2|6 version of the file in a code cleanup years ago, and so even if you get the 6|2m loader to work, it crashes the device because it uploads the wrong thing.
Oh, and Linux is apparently shipping a buggy, early version of the firmware without 96kHz support. Even if you don't care about 96kHz for audio production, and you probably shouldn't, the extra frequency range makes these guys a lot more useful as software oscilloscopes.
I've maintained a working version of the driver with updated firmware for the past several years, but getting it into the official kernel always stalled on 'wait, do you have permission from eMagic to use this firmware?' Unfortunately a) Apple bought eMagic and discontinued all their hardware products more than a decade ago, b) to my knowledge, no one ever had explicit permission to use the firmware currently being shipped either. I have no real interest in having a battle over firmware licensing, so my fixes continue to be my own. If Apple turns out to care, I'll pull them down, but I doubt that will happen. I don't think Apple remembers this device even exists. Seriously, they're Bondi Blue. That's soooo late-90's.
Anyway, here's my latest, updated, out-of-kernel firmware loader with the last firmware release form eMagic. It works properly on 2.6.x and 3.x.x kernels for both the emi2|6 and emi6|2m. It replaces the old firmware and two kernel modules with new firmware and a single unified firmware loader module name emi.ko. All new! Such shiny. Wow.
If you have kernel module build dependencies installed, it should be as easy as untarring as root, make, and make install. I also included a 'make remove-old' target to clean out the old driver and avoid any conflicts. It just removes the old modules and firmware files; obviously that might make a packaging system a little pissy (and you'd probably have to re-run it on each kernel update).
tl;dr, get the driver here: http://people.xiph.org/~xiphmont/emagic/
How did we break this?
Date: 2013-12-11 03:59 am (UTC)We're not patching the driver and it doesn't appear to have changed in any significant way upstream since 2.6.33 (where there was a single bug fix, backported to 2.6.32.y). So if it's regressed since Debian 6.0 'squeeze' this is probably due to changes in the USB stack.
There was a regression in udev last year that would cause drivers that do this to hang for something like 30 seconds. I'm not sure whether that's what you're referring to. It has been fixed in udev (and worked around in the kernel).
The conversions to use external firmware evidently weren't tested but there were subsequent fixes labelled as having been tested. But you're quite right, emi26/bitstream.fw and emi62/bitstream.fw are identical! I'll see if I can fix this.
Re: How did we break this?
Date: 2013-12-11 04:01 am (UTC)Never mind, I can see this was a different bug you fixed way back in 2006.
Re: How did we break this?
Date: 2013-12-11 04:14 am (UTC)The loaders were always a bit dodgy as the 'proper' way to do firmware requests shifted over the course of 2.6. The incorrect firmware file for the 6|2m showed up in 2.6.27. Then some other cleanup broke both loaders hard, and plugging in an eMagic box would actually panic the kernel.
Anyway, a few bugs in the loaders [like the panic] got fixed piecemeal at the end of 2.6 without ever actually getting reliably working loaders. Some patches made it, some just evaporated, I got frustrated with submitting patches, and so I just rewrote the whole thing and kept it out of tree. All I cared about was keeping my boxes running.
>There was a regression in udev last year that would cause drivers that do this to hang for something like 30 seconds.
If it's what I expect, this wasn't strictly udev's fault, and systemd still does the same thing, repeatedly triggering 30s of USB hang before giving up.
The simple fact is that drivers should not [now] be making synchronous firmware requests in probe(). Whatever changes got made to udev to mitigate the problem, systemd still triggers the deadlocks that are technically the old loaders' faults.
Note that the default firmware [in addition to shipping the completely wrong bitstream.fw file for the 6|2m] is also buggy-- 6|2m recording, which is sort of the whole point of the device, does not work properly in this early version. Every time you start recording, you have to toggle the switches on the front of the unit before the ADC will actually start running from the correct input source. And the 96kHz support is completely missing. The newer firmware fixes both.
Re: How did we break this?
Date: 2013-12-11 05:24 am (UTC)I've confirmed that your emi62_bitstream.fw is identical to what used to be in the driver, so this should get fixed shortly.
This is what Kay Sievers said, but it is a rule he invented to make his life easier.
Well, the udev and systemd projects were merged and I think the relevant code is now in libudev which is loaded by one or the other daemon. The kernel will now try to load firmware files directly before sending a uevent, but if a file isn't installed it can still hit this bug.
Unfortunately I don't think I can do anything about this due to the unclear licence status.
Re: How did we break this?
Date: 2013-12-15 05:30 am (UTC)Actually, firmware loading has been removed from udev. So it's fixed in some sense...