Author: Michael Minn (see michaelminn.com for contact info)
June 22, 2007
Describes installation and operation of MMUSBAUDIO, a Linux kernel module device driver for a number of Roland / Edirol desktop audio devices, and MMFAKEALSA, a compatibility library that permits ALSA-only applications to use older OSS-only devices/drivers.
MMUSBAUDIO (formerly known as USBUA100) is a Linux kernel module device driver permitting access to the following Roland / Edirol desktop audio devices through the Open Sound System (OSS) interface (/dev/dsp, /dev/midi, etc.)
MMFAKEALSA is an optional library included with MMUSBAUDIO that allows ALSA-only applications to use MMUSBAUDIO and other OSS drivers without having to install ALSA. The Advanced Linux Sound Architecture (ALSA) supports many USB audio devices. It is provided with most major distributions of Linux and is recommended in most cases. However, there are some serious disadvantages to ALSA and MMUSBAUDIO is provided as an alternative:
MMJACKPLAY is another simple optional application included with MMUSBAUDIO that permits playback of .wav files through the JACK interface. The JACK Audio Connection Kit (JACK) provides the ability to route audio signals between various JACK-enabled audio software packages and sound cards/modules (clients) through a central daemon process (server). While JACK is not necessary for simple playback of audio or video files, it is helpful when working with complex audio applications where audio streams need to be routed from multiple sources through audio recording and/or processing software (plugins). MMJACKPLAY permits a .wav file to be treated as a JACK client.
MMUSBPLAY and MMUSBRECORD, are simple command line utilities included with MMUSBAUDIO for playing and recording .wav files. Both programs can handle a variety of sample rates and bit resolutions (including 96Khz/24-bit). While the standard play and record commands can be used with MMUSBAUDIO, as well as many GUI OSS players (such as XMMS), MMUSBPLAY and MMUSBRECORD permit playback/recording of 96Khz/24-bit file formats that OSS-Free does not support.
UA100MIX is an optional Motif-based X-Windows mixer console for controlling the UA-100's internal mixer and extensive array of effects. There are some quirks to the order of SYSEX messages that the UA-100 needs and you may need to click on selection boxes more than once to get the commands to work. The UA-100 has an extensive collection of audio effects and while capability for turning them on has been provided, only a handful of the dialogs needed to adjust the parameters for each effect have been written. Because the UA-100 is obsolete, no further upgrades are planned for UA100MIX
The Roland UA-5 is a USB audio convertor providing 24-bit audio at 44.1 / 48 / 96 KHz sampling rates through balanced or unbalanced connectors. Roland UA-100 is a USB desktop music production tool providing MIDI input/output and 16-bit / 44.1KHz digital audio. The Roland UA-1EX is a small USB device that provides 16- and 24-bit audio at 32/44.1/48/96 KHz with unbalanced RCA or Toslink optical connectors.
MMUSBAUDIO provides access to the MIDI ports of the Roland UA-100, UM-1 and SC-8850 through the /dev/midixx device files. The exact file names (i.e. /dev/midi00, /dev/midi01) are assigned dynamically and therefore system dependent. Despite an extraordinary effort, I was unable to get MMUSBAUDIO to work with /dev/sequencer due to the arcane complexity of the OSS interface. Therefore, MMUSBAUDIO MIDI devices will not be visible under /dev/sequencer and any program (such as playmidi or kmid) that uses /dev/sequencer will not work with MMUSBAUDIO.
MMUSBAUDIO provides output conversion for 8, 16, and 24 bit PCM (Little Endian) audio. The UA-100 supposedly has the capability for 20-bit audio, but I couldn't figure out how to access it and it's obsolete in this 24-bit world anyway. Although the UA-100 has two stereo audio output channels (i.e. two stereo D/A convertors or four channels), the USB protocol requires sending data for both channels simultaneously. To simplify implementation, only one audio device file (i.e. /dev/dsp or /dev/dsp1) is provided. While it writes stereo output only to the first output channel, it supports quadraphonic (4-channel) writes which write to both but is useless because the UA-100 has only two analog output connectors.
The UA-5 and UA-1EX provide full-duplex playback/recording at 44.1Khz and 48Khz, but will allow you to only play OR record at 96Khz. Sample rate on the UA-5 is selected by a knob on the front of the device and the device must be powered off/on to change the rate - simply turning the knob without rebooting the device will change nothing. MMUSBAUDIO automatically detects the selected rate. MMUSBAUDIO's sample rate conversion algorithm is very rudamentary and you will get significant audio artifacts when playing at a different rate from the device. MMUSBAUDIO provides no record rate conversion.
All of the supported devices use protocols similar to the USB-Audio and USB-MIDI standards. Therefore, MMUSBAUDIO should be relatively easy to upgrade for other devices.
The Makefile may require tweaking on some distributions. Audio input and output is relatively clean on my 600Mhz and 2.4Ghz laptops. There are occasional timing glitches that result in sporadic tics and dropouts, but this seems to be related to the fact that unmodified Linux is not a real-time OS.
MMUSBAUDIO provides no /dev/mixer support for either the UA-100 or UA-5.
Edirol, Roland's desktop music hardware distributor in the United States, has declined either to develop Linux drivers or provide specs so the open source community could develop a driver. Therefore, MMUSBAUDIO was developed based on work done by other Linux devlopers as well as USB traces on Windoze and extensive experimentation. As such, I cannot guarantee full-featured and problem-free operation and this product is offered to the open-source community without a warranty of any kind.
MMUSBAUDIO is available as source code only and compilation is not slow or difficult. MMUSBAUDIO should compile with no problem on Red Hat/Fedora installations that use 2.4 or 2.6 kernels. The Makefile may require some tweaking on other installations. Kernels before 2.2 do not have USB support and hence, MMUSBAUDIO will not compile or work on distros older than RH 7.0.
This will decompress the source and precompiled module into a "mmusbaudio" directory:
$ tar -zxvf mmusbaudio-*.tar.gz $ cd mmusbaudio
Make: AS SUPERUSER, perform a simple make and make install. The makefile should detect whether to use the 2.4 or 2.6 version.
$ make $ make install /sbin/modprobe mmusbaudio
Configure to load on boot: You may need to manually edit the /etc/modules.conf file (/etc/modprobe.conf.local on some distros like SuSE) if you want MMUSBAUDIO to be your primary sound device. OSS assigns audio devices (i.e. /dev/dsp, /dev/dsp1, etc.) on a first-come, first-serve basis. If you have an existing audio card, it is probably configured in /etc/modules.conf (or /etc/modprobe.conf on 2.6 kernel systems) and the device driver module will be loaded ahead of MMUSBAUDIO, thus causing MMUSBAUDIO to take /dev/dsp1. You should comment out any lines that begin with "alias sound". An example from my Toshiba 1905 (with a i810 audio chip) is given below:
#alias sound-slot-0 audio #alias sound-slot-0 i810_audio alias sound-slot-0 mmusbaudio alias sound-service-0-0 off
Note the "sound-service" line. Because MMUSBAUDIO does not support /dev/mixer, applications that use /dev/mixer (such as xmms) will work with MMUSBAUDIO but write a huge number of error messages to /var/log/messages. Turning sound service 0 (the mixer) to slot 0 (the primary sound device)
MMUSBAUDIO does not use ALSA and has no relationship to it. However, many new applications (such as Flash (tm), mplayer and xmms) either require ALSA or use it as the default option over the older OSS. And some applications that do not use ALSA directly (such as Firefox and Thunderbird) may link to libraries that have ALSA function calls and will crash if the ALSA libraries are removed.
This package contains mmfakealsa.c, which compiles to a library that can be used in place of libasound to translate ALSA function calls into OSS device operations.
MMFAKEALSA is not compiled as part of the default make or make install. To install as SUPERUSER:
make fake
This creates /lib/mmfakealsa.so and links /lib/libasound.so.2 to it, effectively replacing any existing /lib/libasound.so.2.x.x. If you are on a distro that places dynamically loadable libraries in some other location, you should modify FAKEALSA_LIB and FAKEALSA_LINK in the Makefile accordingly.
If ALSA compatibility is not an issue, MMUSBAUDIO should be able to run alongside ALSA provided the ALSA snd-usb-audio.o module does not load. You may want to look for it somewhere under /lib/modules, remove it and then run /sbin/depmod. If you want your USB device to be your primary sound device (i.e. /dev/dsp), and you run a distro that uses udev (dynamic device node creation at boot time), you will want to move the /etc/udev/rules.d/alsa.rules file to /etc/udev so it does not start ALSA at boot time, before the USB device is detected.
MMJACKPLAY is an optional command line program for playing/recording .wav files through the The JACK Audio Connection Kit (JACK). JACK must be installed in order for MMJACKPLAY to compile. It can be compiled and installed AS SUPERUSER with one command:
make mmjackplay
JACK operates as a server to which multiple clients can connect. A client can be an ALSA or OSS soundcard or a JACK-enabled program (such as Ardour or Jamin). The JACK daemon will detect any soundcards using the hardware interface specified on invocation. The following starts the JACK daemon to use MMUSBAUDIO (i.e. OSS interface) at 44,100 Hz sampling rate. The -b option overrides the MMUSBAUDIO default buffer size and uses a 1024 frame buffer that is necessary for audio software that uses a FFT:
jackd -d oss -r 44100 -b
Invocation with "-d oss" will create at least one input/output client named "oss". Similarly, invocation with "-d alsa" will create at least one client named generically named "alsa". The "jack_lsp" command can be used to list available soundcard clients.
MMJACKPLAY takes a list of files and/or clients and daisy-chains them so the output of one is connected to the input of the next client. For example, to play the .wav file to an OSS soundcard:
mmjackplay temp.wav oss
If you have a signal processing client (such as Jamin) that you want to process and audio file through, the client can be specified between the input and output files. Most
mmjackplay temp.wav jamin processed.wav
Most standalone clients (such as Jamin) automatically connect their output to the default audio device. Therefore, it does not need to be specified as a client then mmjackplay is invoked.
MMJACKPLAY supports the transport interconnection mechanism of JACK, so that clients that allow pausing and seeking will be able to change locations in the input and/or output files specified when MMJACKPLAY is started.
MMJACKPLAY can be closed with CTRL-C or "killall mmjackplay".
MMUSBAUDIO comes with mmusbplay and mmusbrecord, two simple command line utilities for playing and recording to .wav files:
mmusbplay wav_file [dsp_device] mmusbrecord [ -d dsp_device ] [ -r sample_rate] [ -b bit_resolution ] output_file
They are provided primarily for testing MMUSBAUDIO. They both play/record 24-bit/96Khz audio with the UA-5. 24/96 audio is not supported by other OSS devices. They do not support any file format other than .wav (i.e. RIFF).
Device Files:
Initial Test: You should initially test mmusbaudio with mmusbplay, a simple program included in the mmusbaudio tarball for playing .wav sound files. You will need an .wav audio file, which is called audio.wav below but can be named anything you want:
$ mmusbplay audio.wav
Ripping a .wav file: If you do not have a .wav file on your Linux or Windoze partitions, you can "rip" one from a CD using the cdda2wav program that ships with most Linux distributions. Insert a CD in your computer's CD-ROM drive and type the following. If you want to use something other than track #1, change the number after the -t option. You can also change "audio" to any file name you want.
$ cdda2wav -D /dev/cdrom -t 1 audio.wav
Audio Players: If you are getting audio output with mmusbplay, you should be able to use any audio program that can be configured to use OSS (i.e. /dev/dsp). Personally, I use XMMS (the X multimedia system), a player similar to winamp that comes with many standard Linux distributions.
ALSA Library Problems: Because of the ubiquity of ALSA, many audio programs are initially configured to use the ALSA sound libraries, which will not work with MMUSBAUDIO. For example, if the "play" script (which uses usually uses SOX) is setup to use ALSA, you may get messages like this:
# play -d /dev/dsp audio.wav ALSA lib pcm.c:2146:(snd_pcm_open_noupdate) Unknown PCM /dev/dsp sox: Failed writing /dev/dsp: cannot open audio device
Error Messages: The MMUSBAUDIO kernel module lists it's operational and error messages to the /var/log/messages system file, which can be viewed with the "dmesg" command. You can also open the file directly with "vi" as superuser. If MMUSBAUDIO is loading successfully, there should be messages somewhere near the end of the listing indicating which device files are being used, which should look something like this:
Jun 23 16:43:10: MMUSBAUDIO: Linux USB Driver for Roland MIDI interfaces v2008.03.21 Jun 23 16:43:10: MMUSBAUDIO: Registered UA-100 as /dev/dsp - interface 1/0, endpoint 1 Jun 23 16:43:10: MMUSBAUDIO: Registered UA-100 A as /dev/midi00 Jun 23 16:43:10: MMUSBAUDIO: Registered UA-100 B as /dev/midi01 Jun 23 16:43:10: MMUSBAUDIO: Registered UA-100 CTRL as /dev/midi02
This indicates that the audio device is /dev/dsp and the three MIDI ports (two in/out ports and one port for UA-100 control messages) are /dev/midi00, /dev/midi01 and /dev/midi02.
USB Device Listing: If you can't find these messages, perhaps MMUSBAUDIO was not loaded. You can verify that the USB subsystem has successfully recognized both MMUSBAUDIO and your hardware by typing:
$ cat /proc/bus/usb/devices
You will get some rather cryptic output giving information about the USB devices connected to your computer. At the end of the list should be something that looks like this
C:* #Ifs= 3 Cfg#= 1 Atr=40 MxPwr= 0mA I: If#= 0 Alt= 0 #EPs= 1 Cls=ff(vend.) Sub=ff Prot=00 Driver=mmusbaudio E: Ad=01(O) Atr=01(Isoc) MxPS= 0 Ivl= 1ms I: If#= 0 Alt= 1 #EPs= 1 Cls=ff(vend.) Sub=ff Prot=00 Driver=mmusbaudio E: Ad=01(O) Atr=01(Isoc) MxPS= 360 Ivl= 1ms I: If#= 1 Alt= 0 #EPs= 1 Cls=ff(vend.) Sub=ff Prot=00 Driver=mmusbaudio E: Ad=81(I) Atr=01(Isoc) MxPS= 0 Ivl= 1ms I: If#= 1 Alt= 1 #EPs= 1 Cls=ff(vend.) Sub=ff Prot=00 Driver=mmusbaudio E: Ad=81(I) Atr=01(Isoc) MxPS= 184 Ivl= 1ms I: If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=00 Driver=mmusbaudio E: Ad=02(O) Atr=02(Bulk) MxPS= 32 Ivl= 1ms E: Ad=82(I) Atr=02(Bulk) MxPS= 32 Ivl= 1ms I: If#= 2 Alt= 1 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=00 Driver=mmusbaudio E: Ad=02(O) Atr=02(Bulk) MxPS= 32 Ivl= 1ms E: Ad=82(I) Atr=03(Int.) MxPS= 32 Ivl= 2ms
The UA-5 will give a listing similar to the one below. The exact listing depends on the sampling frequency.
T: Bus=01 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 6 Spd=12 MxCh= 0 D: Ver= 1.10 Cls=ff(vend.) Sub=00 Prot=ff MxPS= 8 #Cfgs= 1 P: Vendor=0582 ProdID=0010 Rev= 1.00 S: Manufacturer=Roland S: Product=EDIROL UA-5 C:* #Ifs= 4 Cfg#= 1 Atr=c0 MxPwr= 0mA I: If#= 0 Alt= 0 #EPs= 0 Cls=ff(vend.) Sub=ff Prot=00 Driver=(none) I: If#= 1 Alt= 0 #EPs= 0 Cls=ff(vend.) Sub=ff Prot=00 Driver=mmusbaudio I: If#= 1 Alt= 1 #EPs= 1 Cls=ff(vend.) Sub=ff Prot=00 Driver=mmusbaudio E: Ad=01(O) Atr=09(Isoc) MxPS= 288 Ivl=1ms I: If#= 2 Alt= 0 #EPs= 0 Cls=ff(vend.) Sub=ff Prot=00 Driver=(none) I: If#= 2 Alt= 1 #EPs= 1 Cls=ff(vend.) Sub=ff Prot=00 Driver=(none) E: Ad=82(I) Atr=05(Isoc) MxPS= 288 Ivl=1ms I: If#= 3 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=00 Driver=(none) E: Ad=03(O) Atr=02(Bulk) MxPS= 8 Ivl=0ms E: Ad=84(I) Atr=02(Bulk) MxPS= 8 Ivl=0ms
This is a listing of the "endpoints" used for reading and writing to the MMUSBAUDIO. The important part is "Driver=mmusbaudio". If it reads "Driver=(none)", the USB subsystem has not recognized MMUSBAUDIO. If it reads "Driver=midi", that is fine because it is connected to the USB-MIDI class driver. Some endpoints are not used by MMUSBAUDIO, but at least one interface should indicate Driver=mmusbaudio. If you can't find anything like these lines in the listing, the USB subsystem has not detected your hardware and you should verify that your cable is connected correctly and the device is on.
Manual Load / Unload: You can manually load MMUSBAUDIO with the modprobe command AS SUPERUSER:
/sbin/modprobe mmusbaudio
You can also load modules with the insmod command AS SUPERUSER:
/sbin/insmod soundcore /sbin/insmod mmusbaudio
The modules can be unloaded with rmmod:
/sbin/rmmod mmusbaudio
The OSS mixer mechanism is inadequate for dealing with internal signal paths are as complex as the UA-100s. Therefore, I implemented UA100MIX, a MOTIF/LESSTIF graphical mixer interface for controlling the internal mixer and effects of the UA-100. This will not, of course, work with other USB MIDI devices like the UM-1.
Compilation of UA100MIX will require some MOTIF library (such as LessTif or OpenMotif) which is usually included in most distributions. Because the UA-100 is obsolete, UA100MIX does not compile by default and must be explicitly made and copied to the binary directory of your choice.
make ua100mix mv ua100mix /usr/local/bin
If you get compile errors when making ua100mix that indicate there is no "Xm.h" file, you probably do not have a MOTIF library installed on your system. You can easily download one from the LESSTIF web site.
The executable is called "ua100mix" and can be started by typing that on an X-Windows console.
The mixer assumes some familiarity with the audio paths of the UA-100. There are five channels:
Note that there is no recording level control. I have found that in practice, recording level should be set by the analog controls to maximize digital headroom on recorded tracks.
For each channel:
The UA-100 has the capability for either ONE very complex effect (FULL EFFECT) that can be applied to any input or assigned to one of the two system effects busses, OR THREE "compact" effects: an insertion effect that can be applied to one input and two system effects (a chorus and a reverb or delay) that are applied to the system effects busses. These are selected with the four buttons on the right of the UA100MIX dialog. Note that if a FULL effect is selected, the INSERTION and SYSTEM effects are turned off...and vice-versa.
The type of effect is selected in a combo box at the top of the appropriate dialog. THE PARAMETERS FOR MOST EFFECTS HAVE NOT BEEN IMPLEMENTED YET. When you select an effect, the default settings are applied for now. For the few effects with parameters, the meaning of a slider can be discerned by holding the mouse pointer over a slider...a tooltip bubble will pop up describing the purpose of the slider. This was chosen over short cryptic names to preserve space.
FULL effects can be applied to any input or to one of the two system effects busses. INSERTION effects can be applied to any input. The selection of where the effect is placed is a combo box next to the effect type combo box.
UA100MIX has the capability to save and load settings to/from the same .uax files that the MS-Windows version of the the mixer uses. This capability has not been tested extensively and is probably buggy.
UA100MIX works by sending system exclusive (SYSEX) messages to the UA-100 control port. The code (around line 302) contains a hard-coded string that defines this device as /dev/midi02 - which will be the device name if MMUSBAUDIO is used on a system where the UA-100 is the only MIDI device. You can change the MIDI device in the File->Midi Port dropdown menu when the program is running, although this change does not persist between invocations of the program. For a permanent change, you must alter the line in the source code
The UA-100 ships with a CD containing some awkwardly written HTML reference materials that are installed with the MS-Windows software in "/Program Files/Roland". If you have the UA-100 software installed on your Windows partition, you may want to consult this material for further details. You can also copy it off of the CD-ROM into a Linux directory.
Although the device descriptor for the UA-100 indicates that it is vendor specific, the MIDI implementation appears to comply with the official MIDI Device Class Definition. The MIDI endpoints of the UA-100 as well as the UM-1 and SC-8850 can also be accessed with USB-MIDI, the semi-official Linux USB MIDI class driver. However, I am not sure if you can use the class driver (yet) to access more than one of the MIDI ports (called Cable ID in the class driver), thus making it impossible to use both a MIDI output port and the UA-100 system control port for mixer control sysex MIDI messages. For that reason (and for convenience) MIDI endpoint handling is provided in MMUSBAUDIO.
The audio implementation is a bit more complex and non-standard. The module source code provides further documentation if you're interested.
I did make a request to the people at Edirol (the American distributor of Roland's desktop music products) for specs. Their response was that no Linux drivers were currently planned and that it would be difficult for them to provide me with enough complete information to develop a driver.
On a side note, I had problems with depmod issuing errors for unresolved symbols from usbcore.o and even some kernel symbols (like kmalloc). The solution is to include the linux/modversions.h file in the module source.
MIDI data is sent and received to/from the bulk transfer endpoints (interface #2, alternate 0, endpoints 0x02 and 0x82) in 4-byte chunks with a preceeding "burst" byte that indicates the destination/source port for following 3 bytes of data. All MIDI messages under status 0xf0 (SYSEX) are two or three bytes long and fit in a single 4-byte chunk. Messages over status byte 0xf0 are split into multiple consecutive chunks with the appropriate burst bytes specified below.
For MIDI sends, the upper 4 bits of the "burst" byte are the source/destination port (described below). The lower 4 bits are either the upper 4 bits of the MIDI message status byte, 4 for the beginning or middle of a SYSEX message, 6 if there are two bytes in the last SYSEX chunk, and 5 if there is one byte in the last chunk of a SYSEX message. For MIDI receives the protocol is basically the same with the upper four bits representing the input port.
Example: 19 90 30 70 is a note on message sent to port 2.
For UA-100 sends, the "burst byte" is 0x00 for MIDI OUT 1, 0x10 for MIDI OUT 2 and 0x20 for the UA-100 control port which receives SYSEX messages to change the internal mixer and effect settings. MIDI receives are basically the same: 0x00 for MIDI IN 1 and 0x00 for MIDI IN 2.
For the UM-1, there is only one input and output port, so the upper 4 bits of the "burst byte" are always 0x00.
For the SC-8850, the "burst byte" indicates which of the four "parts" (i.e. 16-channel banks) should receive the MIDI output: 0x00 for Part A, 0x10 for Part B, 0x20 for Part C and 0x30 for Part D. However, unlike the other devices, for MIDI input: 0x40 for MIDI IN 1 and 0x50 for MIDI IN 2
Chunks smaller than 4 bytes (such as two-byte program change messages) are padded with trailing NULLs to a 4-byte length.
I desperately attempted to find a way to provide a way of registering the MIDI ports so they could be used by /dev/sequencer, but there are apparently some interrupts used by /dev/sequencer that caused the USB subsystem to issue some cryptic interrupt messages.
On the UA-100 Audio data is written using a isosynchronous transfers to interface #0, address #1, alternate #1 for output and interface #1, address #81, alternate #1 for input. URBs are sent isosynchronously (e.g. urb->transfer_flags = USB_ISO_ASAP). While the 2.4 kernel versions of MMUSBAUDIO submitted URBs on demand from the write() function, the current versions use an internal ring buffer and recycles URBs from the completion callbacks. This technique is also used by the ALSA drivers.
To time isosynchronous writes correctly and provide minimal latency, each URB contains 1ms of data. Since 1ms at 44.1Khz equals 44.1 samples, URBs are sent with 44 samples but every 10th URB contains 45 samples.
With the UA-5, 48Khz and 96Khz rates divide evenly on 1ms boundaries so this variable length protocol is unnecessary at those rates.
For Reads, however, each frame must be sent at full length (184 bytes) or you will get a nasty kernel message in /var/log/messages: "usb-uhci.c: interrupt, status 2, frame# xxx" The "actual_length" field of each packets indicates the (variable) number of bytes returned in each packet.
Previous versions of MMUSBAUDIO used write URBs contain 10 isosynchronous packets totaling 441 samples apiece, i.e. 10ms per URB at 44.1Khz sample rate. This works out to 3528 bytes for write URBs with 8 byte samples (two 16-bit stereo channels) as nine packets of 352 bytes and one packet of 360 bytes. However, this scheme increased latency so the variable length URB scheme is used instead.
UA-100 interleaves 16-bit/44Khz PCM samples for the two output devices: L1, R1, L2, R2. If input is stereo, MMUSBAUDIO sends the data only to output device WAVE 1. If input is mono, MMUSBAUDIO sends the data to both channels of WAVE 1. Since MMUSBAUDIO sends URBs on demand, rather than continuously with a circular buffer as in the Linux audio class driver, it was not possible to create two separate Linux devices for wave 1 and wave 2. The UA-5 always sends/receives two channels of 24-bit audio (i.e. 6 bytes per sample)
Upgrade of MMUSBAUDIO for the 2.6 kernel was a massive pain since I chose to also move to a ring-buffer instead of URB submission on-demand.
The biggest problem was that when calling usb_unlink_urb() with the outbound URBs when closing the write() stream, some URBs would not unlink, even though their completion handler has been called. The usb_unlink_urb() function will return -ENODEV because the urb-"dev pointer is NULL and the URB structure seems to be filled with spurious data.
Calling usb_free_urb() with the mystery URB will result in a kjournald system crash. Because this affects writes to journaled file systems like EXT3 or REISERFS, this error is not logged and the system will simply freeze. I was only able to find this by testing from the console (without X Windows) and watching the error messages on the terminal.
This seemed to be related to my memset(0) to clear newly allocated URBs. usb_alloc_urb() apparently does more than just kmalloc() and this was causing problems. However, I am leaving in my old kludge to simply leave any errant URBs unfreed. This means that some URBs probably get stuck somewhere in kernel memory and will probably result in the exhaustion of kernel memory and some kind of kernel destabilization if the module is used frequently on a system that stays on for long durations. Be forewarned and if you have a solution, write me.
Note that any unfreed URBs are logged in /var/log/messages and you can observe for yourself how often this problem is occurring.
The other changes between 2.4 and 2.6 primarily involve the USB structures and function call parameters. One oddity - although the urb->interval field was always set to zero with isochronous transfers in the 2.4 kernel, it has to be set to non-zero for or usb_submit_urb() returns -EINVAL.
References:
Audio Device Class Definition
Audio Data Formats Definition
MIDI Device Class Definition
Intel USB Documentation Page
A listing of the UA-100 SYSEX messages (derived from Roland's documentation) is given below:
Data Transmission F0: Start SysEx 41: Manufacturer (Roland) 10: Device ID 00: Model ID 1 11: Model ID 2 12: Command (Transmit data) aa: Address aa aa: aa: dd: Data dd: ck: checksum = 128 - ((sum of address & data bytes) & 0x3f); f7: end of SysEx Examples: F0 41 10 00 11 12 00 40 02 00 01 00 3D F7 (select Stereo-EQ as Mic2 insertion effect) f0 41 10 00 11 12 00 40 50 03 64 09 f7 (master level of 64) In URB buffer, the message is split into 3 byte chunks with a 24h is placed before every chunk except for a 25h before the final chunk. 24 f0 41 10 24 00 11 12 24 00 40 02 24 00 01 00 25 f7 Note that for messages with multiple data bytes (length > 1), the first data byte (usually the significant one) comes first. ------------------------------------------------------------------------ 00 40 00 00 01 PC Mode (VT Effect Mode) - sent by UA-100? 00 40 00 00 03 PC Mode (Compact Effect Mode) 00 40 00 00 04 PC Mode (Full Effect Mode) 00 40 00 00 05 VT Mode 00 40 00 00 06 Vocal Mode 00 40 00 00 07 Guitar Mode 00 40 00 00 08 GAME Mode 00 40 00 00 09 BYPASS Mode 00 40 00 01 0x Copyright (0 off, 1 on) n = 1 (line, mic1, mic1+2), 2 (mic2), 3 (wave1), 4 (wave2), 5 (sys effect 1), 6 (sys effect 2) 00 40 0n 00 xx 00 Effect type (listed below) 00 40 0n 03 xx Effect parameter 1 00 40 0n 04 xx Effect parameter 2 00 40 0n 05 xx Effect parameter 3 00 40 0n 06 xx Effect parameter 4 00 40 0n 07 xx Effect parameter 5 00 40 0n 08 xx Effect parameter 6 00 40 0n 09 xx Effect parameter 7 00 40 0n 0A xx Effect parameter 8 00 40 0n 0B xx Effect parameter 9 00 40 0n 0C xx Effect parameter 10 00 40 0n 0D xx Effect parameter 11 00 40 0n 0E xx Effect parameter 12 00 40 0n 0F xx Effect parameter 13 00 40 0n 10 xx Effect parameter 14 00 40 0n 11 xx Effect parameter 15 00 40 0n 12 xx Effect parameter 16 00 40 0n 13 xx Effect parameter 17 00 40 0n 14 xx Effect parameter 18 00 40 0n 15 xx Effect parameter 19 00 40 0n 16 xx Effect parameter 20 00 40 0n 17 xx Effect parameter 21 00 40 0n 18 xx Effect parameter 22 00 40 0n 19 xx Effect parameter 23 00 40 0n 1A xx Effect parameter 24 00 40 0n 1B xx Effect parameter 25 00 40 0n 1C xx Effect parameter 26 00 40 0n 1D xx Effect parameter 27 00 40 0n 1E xx Effect parameter 28 00 40 0n 1F xx Effect parameter 29 00 40 0n 20 xx Effect parameter 30 00 40 0n 21 xx Effect parameter 31 00 40 0n 22 xx Effect parameter 32 00 40 0n 23 xx Effect parameter 33 00 40 0n 24 xx Effect parameter 34 00 40 0n 25 xx Effect parameter 35 00 40 0n 26 xx Effect parameter 36 00 40 0n 27 xx Effect parameter 37 00 40 0n 28 xx Effect parameter 38 00 40 0n 29 xx Effect parameter 39 00 40 0n 2A xx Effect parameter 40 00 40 10 00 00 Mic input mode 00 40 10 00 01 Line input mode 00 40 10 00 02 MIC1+MIC2 Mode (not in VT mode) 00 40 10 01 xx Input pan 1 (0 - 40 - 7f) 00 40 10 02 xx Input pan 2 (0 - 40 - 7f) 00 40 10 03 0x Monitor (0 off, 1 on) n = 1 (line, mic1, mic1+2), 2 (mic2), 3 (wave1), 4 (wave2), 5 (sys effect 1), 6 (sys effect 2) 00 40 1n 00 xx Effect 1 send level (full/compact effect mode) 00 40 1n 02 xx Effect 2 send level (full/compact effect mode) 00 40 1n 04 xx Submaster send level (not in VT mode) 00 40 1n 05 xx Fader level (not in VT mode) 00 40 1n 06 0x Mute (0 off, 1 on) 00 40 1n 07 0x Solo (0 off, 1 on) 00 40 40 00 01 VT effect mode 00 40 40 00 03 Compact effect mode (1 insertion + 2 system effects) 00 40 40 00 04 Full effect mode (1 effect) 00 40 40 01 0x Line/Mic1/Mic1+2 insertion effect on/off (0 off, 1 on) 00 40 40 02 0x Mic2 insertion effect on/off (0 off, 1 on) 00 40 40 03 0x Wave1 insertion effect on/off (0 off, 1 on) 00 40 40 04 0x Wave2 insertion effect on/off (0 off, 1 on) 00 40 40 05 0x System effect 1 on/off (0 off, 1 on) 00 40 40 06 0x System effect 2 on/off (0 off, 1 on) 00 40 40 07 xx Effect 1 master return 00 40 40 08 xx Effect 1 submaster return 00 40 40 09 xx Effect 2 master return 00 40 40 0A xx Effect 2 submaster return 00 40 40 0B 0x Vocal Transform 1 receive channel (0 - F) 00 40 40 0C 0x Vocal Transform 1 note enabled (0 off, 1 on) 00 40 40 0D 0x Vocal Transform 1 bend enabled (0 off, 1 on) 00 40 40 0E 0x Vocal Transform 2 receive channel (0 - F) 00 40 40 0F 0x Vocal Transform 2 note enabled (0 off, 1 on) 00 40 40 10 0x Vocal Transform 2 bend enabled (0 off, 1 on) 00 40 50 00 0x Record source (Mixer: 0 line/mic, 1 mic2, 2 wave1, 3 wave2, 4-7 ch 1-4, 8 submaster, 9 master) (VT: 0 line/mic, 1 mic3, 2 wave1, 3 wave2, 4 VT-out, 5 master) 00 40 50 01 0x Output (see record source) 00 40 50 02 xx Recording level 00 40 50 03 xx Master level n = 0 (Voice Transformer), 1 (Vocal), 2 (Guitar), 3 (Game) (NOT FOR PC MODE) 00 40 6n 00 xx Preset effect parameter 1 (0 - 39) 00 40 6n 01 xx Preset effect parameter 2 (0 - 39) 00 40 6n 02 xx Preset effect parameter 3 (0 - 39) 00 40 6n 03 xx Preset effect parameter 4 (0 - 39) 00 40 6n 04 xx Preset effect default Value 1 (0 - 127) 00 40 6n 05 xx Preset effect default Value 2 (0 - 127) 00 40 6n 06 xx Preset effect default Value 3 (0 - 127) 00 40 6n 07 xx Preset effect default Value 4 (0 - 127) 00 40 6n 08 xx Preset effect default Value 5 (0 - 127) 00 40 6n 09 xx Preset effect default Value 6 (0 - 127) 00 40 6n 0A xx Preset effect default Value 7 (0 - 127) 00 40 6n 0B xx Preset effect default Value 8 (0 - 127) 00 40 6n 0C xx Preset effect default Value 9 (0 - 127) 00 40 6n 0D xx Preset effect default Value 10 (0 - 127) 00 40 6n 0E xx Preset effect default Value 11 (0 - 127) 00 40 6n 0F xx Preset effect default Value 12 (0 - 127) 00 40 6n 10 xx Preset effect default Value 13 (0 - 127) 00 40 6n 11 xx Preset effect default Value 14 (0 - 127) 00 40 6n 12 xx Preset effect default Value 15 (0 - 127) 00 40 6n 13 xx Preset effect default Value 16 (0 - 127) 00 40 6n 14 xx Preset effect default Value 17 (0 - 127) 00 40 6n 15 xx Preset effect default Value 18 (0 - 127) 00 40 6n 16 xx Preset effect default Value 19 (0 - 127) 00 40 6n 17 xx Preset effect default Value 20 (0 - 127) 00 40 6n 18 xx Preset effect default Value 21 (0 - 127) 00 40 6n 19 xx Preset effect default Value 22 (0 - 127) 00 40 6n 1A xx Preset effect default Value 23 (0 - 127) 00 40 6n 1B xx Preset effect default Value 24 (0 - 127) 00 40 6n 1C xx Preset effect default Value 25 (0 - 127) 00 40 6n 1D xx Preset effect default Value 26 (0 - 127) 00 40 6n 1E xx Preset effect default Value 27 (0 - 127) 00 40 6n 1F xx Preset effect default Value 28 (0 - 127) 00 40 6n 20 xx Preset effect default Value 29 (0 - 127) 00 40 6n 21 xx Preset effect default Value 30 (0 - 127) 00 40 6n 22 xx Preset effect default Value 31 (0 - 127) 00 40 6n 23 xx Preset effect default Value 32 (0 - 127) 00 40 6n 24 xx Preset effect default Value 33 (0 - 127) 00 40 6n 25 xx Preset effect default Value 34 (0 - 127) 00 40 6n 26 xx Preset effect default Value 35 (0 - 127) 00 40 6n 27 xx Preset effect default Value 36 (0 - 127) 00 40 6n 28 xx Preset effect default Value 37 (0 - 127) 00 40 6n 29 xx Preset effect default Value 38 (0 - 127) 00 40 6n 2A xx Preset effect default Value 39 (0 - 127) 00 40 6n 2B xx Preset effect default Value 40 (0 - 127) 00 40 60 7F 00 Preset effect parameter write --------------------------------------------------------- System Effect 1 0021: Delay 0022: Chorus System Effect 2 0031: Delay 0032: Reverb Full Effects 0011: High Quality Reverb 0012: Mic Simulator 0013: Vocoder 0014: Vocal Multi 0016: Game with 3D Reverb 0300: Rotary Multi (same parameters as insertion #47) 0400: Guitar Multi 1 (same parameters as insertion #48) 0401: Guitar Multi 2 (same parameters as insertion #49) 0402: Guitar Multi 3 (same parameters as insertion #50) 0403: Clean Guitar Multi 1 (same parameters as insertion #51) 0404: Clean Guitar Multi 2 (same parameters as insertion #52) 0405: Bass Multi (same parameters as insertion #53) 0406: Electric Piano Multi (same parameters as insertion #54) 0500: Keyboard Multi ( (same parameters as insertion #55) Insertion Effects 0000: (00) Noise Suppressor 0100: (01) Stereo Equalizer 0101: (02) Spectrum 0102: (03) Enhancer 0103: (04) Humanizer 0110: (05) Overdrive 0111: (06) Distortion 0120: (07) Phaser 0121: (08) Auto Wah 0122: (09) Rotary 0123: (10) Stereo Flanger 0124: (11) Step Flanger 0125: (12) Tremolo 0126: (13) Auto Pan 0130: (14) Compressor 0131: (15) Limiter 0140: (16) Hexa Chorus 0141: (17) Tremolo Chorus 0142: (18) Stereo Chorus 0143: (19) Space D 0144: (20) 3D Chorus 0150: (21) Stereo Delay 0151: (22) Modulation Delay 0152: (23) 3 Tap Delay 0153: (24) 4 Tap Delay 0154: (25) Time Control Delay 0155: (26) Reverb 0156: (27) Gate Reverb 0157: (28) 3D Delay 0160: (29) 2-voice Pitch Shifter 0161: (30) Feedback Pitch Shifter 0170: (31) 3D Auto 0171: (32) 3D Manual 0172: (33) Lo-Fi 1 0173: (34) Lo-Fi 2 0200: (35) Overdrive/Chorus 0201: (36) Overdrive/Flanger 0202: (37) Overdrive/Delay 0203: (38) Distortion/Chorus 0204: (39) Distortion/Flanger 0205: (40) Distortion/Delay 0206: (41) Enhancer/Chorus 0207: (42) Enhancer/Flanger 0208: (43) Enhancer/Delay 0209: (44) Chorus/Delay 020a: (45) Flanger/Delay 020b: (46) Chorus/Flanger 0300: (47) Rotary Multi 0400: (48) Guitar Multi1 0401: (49) Guitar Multi2 0402: (50) Guitar Multi3 0403: (51) Clean Guitar Multi1 0404: (52) Clean Guitar Multi2 0405: (53) Bass Multi 0406: (54) E.Piano Multi 0500: (55) Keyboard Multi 1100: (56) Chorus/Delay 1101: (57) Flanger/Delay 1102: (58) Chorus/Flanger 1103: (59) Overdrive/Distortion1,2 1104: (60) Overdrive/Distortion/Rotary 1105: (61) Overdrive/Distortion/Phaser 1106: (62) Overdrive/Distortion/Auto-wah 1107: (63) Phaser/Rotary 1108: (64) Phaser/Auto-wah
Version 2007.06.22:
Additional functions in mmfakealsa: snd_format_mask*, get_period_size_min/max, get_buffer_size_min/max
Increase default buffer size to 100 URBs (100ms)
Fix tarball extraction pathVersion 2007.05.08:
Created mmjackplay so audio files could be mastered through Jamin
Created mmfakealsa (mmfakealsa.so) to permit ALSA-enabled applications to use mmusbaudio via OSS
Added rudamentary support for poll() to permit mmfakealsa mmap-ingVersion 2006.12.29:
Rewrote to eliminate standalone configuration and circular buffer URB resubmission
URB resubmission causing kernel oops with quick Flash player open() and close()
URBs now submitted on demand
Wrote null_audio_device diagnostic module
Add try_module_get(THIS_MODULE) and module_put(THIS_MODULE) to modify module use counter
Module use counter prevents browser crash when rmmod mmusbaudioVersion 2006.10.31:
Bug fix - had a length = copy_from_user() in midi write, which set length to zero and produced no MIDI output
Documentation upgrade for ALSA / SuSE play problems using ALSA librariesVersion 2006.10.10:
Changes for 2.6.15 kernel (Fedora core 5)
Added new file_operations fields unlocked_ioctl and compat_ioctl (new as of 2.6.11 kernel)
Removed open / close / format kernel messages
Fix bug with copy_to/from_user() while in a spin_lock() (see http://lkml.org/lkml/2005/9/9/141)
spinlocks removed from audio_read() - are they needed anywhere?
Fix spurious -512 error in URB loop when device is closedVersion 2006.05.31:
Upgrade to support UA-1EX.
Change mmusbaudio_find_audio_endpoints() to assign devices based on endpoint rather than simply using endpoints as signatures for device type. Needed since UA-1EX and UA-5 use different endpoint addresses.Version 2006.02.09:
Implement fake mixer device so XMMS/ALSA don't clog system logs with error messages
Add time and level display to mmusbrecord
Separate device_channels into device_read and device_write for UA-100
Initial memset(0) of read URB transfer buffer to get rid of nasty start transient when recordingVersion 2005.01.15:
Fix bug not copying R channel when recording stereo.
Fix bug with invalid source index increment causing R channel ticks when playing mono files.Version 2004.11.16:
Extensive rewrite for the 2.6 kernel that uses self-submitting URBs that read from a ring buffer.Version 2004.10.16:
Ignore but acknowledge unused UA-5 interfaces to avoid unnecessary /var/log/messages errors
Discovered SNDCTL_DSP_GETOSPACE is used like poll() by mplayer to get free space - implemented it
Moved mmcdplay to a separate command line project.Version 2004.02.14:
Added a conditional compilation option so MMUSBAUDIO can be compiled to operate either as part of OSS or as a stand-alone module that uses the existing /dev/dsp* and /dev/midi* files.Version 2003.08.09:
Replaced purb_t and urb_t with struct urb - typedefs have been removed in new kernel code
Added hotplugging support (MODULE_DEVICE_TABLE)
Moved UA100MIX source selector to fader from dropdown
Removed preallocation of devices on module load (didn't work anyway)
Simplified format conversions using floating-point indexing
Added correct handling of SNDCTL_DSP_STEREO ioctl for monophonic
Extensive rewrite to support the UA-5
Added MMUSBPLAY and MMUSBRECORDVersion 2003.04.14:
Renamed to MMUSBAUDIO
Moved OSS calls for device reservation to init/cleanup routines so soundcore will allocate devices based on when the module is loaded rather than when the device is turned on. This permits the sound-slot-* assignments in /etc/modules.conf to work consistently (i.e. if mmusbaudio is assigned to /dev/dsp, it will always be /dev/dsp regardless of whether the module is on when the computer is booted)
Makefile cleanup so source includes will be found based on uname -r
Added ioctl SND_DSP_GETFMTS so shell play command will work
Added linux/modversions.h to module source so depmod does not give unresolves symbol errors
Fixed disconnect() to release all devices associated with usb_device - bug caused MIDI devices to be unavailable if rebooting device
Added MMCDPLAYVersion 2003.01.18:
Makefile include path for Red Hat 8.0
Returned to one frame per URB protocol (differing length URBs) to reduce latency;
Added a sleep to retries on usb_set_interface() to reduce timeout errors on open
Handling for SNDCTL_DSP_GETOSPACE for Real Player
Added check to make sure not opening an already opened MIDI device - writing to the same MIDI device from two different applications causes kernel oops crash there is no handling for multithreading.
Added handling for sample rates not even dividends of 44100 - for NPR News via RealPlayerVersion 2002.10.25:
Reverted to old protocol with all audio URB submission handled in foreground (no ring buffer). The uneven URB length protocol was too messy and caused frequent timeout errors.
Isolated format conversion in separate function
Was having problem with read timeouts - retry multiple calls to sleep_on_interruptible() - same as writes (probably related to old URB submission technique)
Added midi port as required UA100MIX command line option - removed settings file as command line optionVersion 2002.07.23:
Used 1 frame per write URB - 32 frame sequence with 128 URB buffer - to reduce latency
Added handling for sample rates below 44,100, mono and 8-bit resolution
Ring buffer of URBs - URB completion callback submits the next URB
Foreground process just fills free URB transfer buffers
mmusbaudiomix converted to MOTIFVersion 2002.01.31:
Fixed bug with MIDI nonblocking read skipping events (read leaves URB submitted between read() calls)
Converted all parameters to combo boxes for more accurate setting
Fixed compilation problems?Version 2001.11.28:
Removed closing save prompt
Record select also resends line/mic mode
Fixed load of insertion effect
Effect path change resets effect so effect type/parameters will be sent to new path
Parameters: Guitar Multi I, Clean Guitar Multi I, Reverb insertion
Incorporated Naoki Takehiro's SMP patch with initialization of read and write spin locks
Added support for ioctl SNDCTL_DSP_SPEED - only supports 44,100
Changed MIDI read to nonblockingVersion 2001.07.01: Documentation corrections, corrected bug handling sysex input and output, release to Source Forge.
Version 2001.06.24: Initial public release
I wish to acknowledge a huge debt of gratitude to Daisuke Nagano for developing the USB-MIDI kernel module that supports MIDI on the Roland desktop music products. Thanks also go out to Roland and Tom for writing USB Snoopy/SniffUSB the MS-Windows software USB packet sniffer used to investigate the UA-100 USB protocol. Markus did further work to figure out the strange audio write URB protocol.