The Tascam US-122L (and US-144) under Linux

This page is about getting the Tascam US-122L (and US-144) work under Linux. If you have some more information, feel free to mail me at samuel.mimram@ens-lyon.org.

This page was last updated on 2009-10-14.

Happy news

Support for the US-122L has now been integrated to the kernel. In order to use it you need libasound2-plugins and use the usb_stream:US122L interface in jack. You first need to add the following in .asoundrc:

pcm.!usb_stream {
        @args [ CARD ]
        @args.CARD {
                type string
                default "2"
        }

        type usb_stream

        card $CARD
}

ctl.!usb_stream {
        @args [ CARD ]
        @args.CARD {
                type string
                default "2"
        }

        type hw

        card $CARD
}
  

A few good links

Patch for ALSA (and linux kernel)

Is the US-122L using standard protocols?

His predecessor, the US-122, has an alsa driver but has been discontinued. Loading a firmware was needed to get it running.

The hardware has apparently changed much between the US-122 and the US-122L. On the request of Derek Pidhirnyj, Martin Langer, who developed the firmware for the US-122, has looked at the usbsnoop logs and lsusb output. He thinks that the US-122L uses a different chip compared to the old usx2y boxes, and that firmware is not loaded at connection. Possibly the device fits better into the USB audio specification (snd-usb-audio driver) and may only need an entry into usbquirks.h (and possibly also usbaudio.c and usbaudio.h). Effectively, the logs show that the driver does hardly only isochronous transfers of data.

For example, here is a data reception:

[367 ms]  <<<  URB 33 coming back  <<<
-- URB_FUNCTION_ISOCH_TRANSFER:
  PipeHandle           = 896f89bc [endpoint 0x00000081]
  TransferFlags        = 00000003 (USBD_TRANSFER_DIRECTION_IN, USBD_SHORT_TRANSFER_OK
  TransferBufferLength = 00000528
  TransferBuffer       = 89143000
  TransferBufferMDL    = 897078d0
  StartFrame           = 00037009
  NumberOfPackets      = 00000028
  ErrorCount           = 00000000
  IsoPacket[0].Offset = 0
  IsoPacket[0].Length = 30
  IsoPacket[0].Status = 00000000
    00000000: 75 fb 00 5b f4 00 39 fd 00 d1 f4 00 c7 fb 00 1b
    00000010: f6 00 03 fc 00 da f5 00 a6 fb 00 83 f6 00
  IsoPacket[1].Offset = 78
  IsoPacket[1].Length = 36
  IsoPacket[1].Status = 00000000
    00000000: 8d f9 00 26 f6 00 8c fb 00 9c f5 00 7d fb 00 b9
    00000010: f6 00 bd fc 00 a2 f6 00 03 fc 00 38 f6 00 1a fb
    00000020: 00 e8 f6 00
  IsoPacket[2].Offset = 156
  IsoPacket[2].Length = 30
  IsoPacket[2].Status = 00000000
    00000000: b1 fc 00 ed f5 00 72 fb 00 2d f6 00 ed fa 00 21
    00000010: f6 00 d9 fb 00 2a f5 00 61 fc 00 23 f7 00
  IsoPacket[3].Offset = 234
  IsoPacket[3].Length = 36
  IsoPacket[3].Status = 00000000
    00000000: ae fa 00 90 f5 00 47 fb 00 66 f6 00 5f fb 00 7a
    00000010: f6 00 7e fc 00 74 f6 00 a0 fb 00 d8 f7 00 8f f9
    00000020: 00 bb f7 00
  [...]
        
Notice that by grouping the bytes by series of 3 you get similar values, and that the rightmost byte does not change much. This makes me think that the format of samples is S24_3LE (i.e. stereo, 24 bits per sample, grouped by 3 bytes, in little endian).

This lead me to the following entry in usbquirks.h:

{
	USB_DEVICE(0x644, 0x800e),
	.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
		.vendor_name = "Tascam",
		.product_name = "US-122L",
		.ifnum = QUIRK_ANY_INTERFACE,
		.type = QUIRK_COMPOSITE,
		.data = (const struct snd_usb_audio_quirk[]) {
			{
				.ifnum = 0,
				.type = QUIRK_IGNORE_INTERFACE
			},
			{
				.ifnum = 1,
				.type = QUIRK_AUDIO_FIXED_ENDPOINT,
				.data = & (const struct audioformat) {
					.format = SNDRV_PCM_FORMAT_S24_3LE,
					.channels = 2,
					.iface = 1,
					.altsetting = 1,
					.altset_idx = 1,
					.attributes = 0,
					.endpoint = 0x02,
					.ep_attr = 0x01,
					.rates = SNDRV_PCM_RATE_CONTINUOUS,
					.rate_min = 44100,
					.rate_max = 44100,
				}
			},
			{
				.ifnum = -1
			}
		}
	}
},
        
The good news is that aplay now accepts to play files using command lines like aplay --device=hw:1,0 -f S24_3LE -r 44100 -c 2 /tmp/test.raw. The bad news is that it only produces a very low noise... If someone has comments about how to improve this, I'd be glad to hear them!

An other idea would be to modify the usx2y module. I've made a simple patch to add support for the US-122L to this module but unfortunately, it makes my linux slow down and eventually crash after a few seconds as soon as I plug the US-122L...

Technical facts

A nice people opened up its US-144 and wrote a webpage about what he found inside. Maybe is it of interest for some of you?

Output of lsusb -vv:

Bus 002 Device 002: ID 0644:800e TEAC Corp.
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0
  bDeviceProtocol         0
  bMaxPacketSize0        64
  idVendor           0x0644 TEAC Corp.
  idProduct          0x800e
  bcdDevice            1.00
  iManufacturer           1 TASCAM
  iProduct                2 US-122L
  iSerial                 3 no serial number
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           72
    bNumInterfaces          2
    bConfigurationValue     1
    iConfiguration          0
    bmAttributes         0x80
    MaxPower              480mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass      0
      bInterfaceProtocol      0
      iInterface              0
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass      0
      bInterfaceProtocol      0
      iInterface              0
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       1
      bNumEndpoints           4
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass      0
      bInterfaceProtocol      0
      iInterface              0
      Endpoint Descriptor:
        bLength                 9
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            5
          Transfer Type            Isochronous
          Synch Type               Asynchronous
          Usage Type               Data
        wMaxPacketSize     0x0126  1x 294 bytes
        bInterval               1
        bRefresh                0
        bSynchAddress           0
      Endpoint Descriptor:
        bLength                 9
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            5
          Transfer Type            Isochronous
          Synch Type               Asynchronous
          Usage Type               Data
        wMaxPacketSize     0x0126  1x 294 bytes
        bInterval               1
        bRefresh                0
        bSynchAddress           0
      Endpoint Descriptor:
        bLength                 9
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0009  1x 9 bytes
        bInterval               1
        bRefresh                0
        bSynchAddress           0
      Endpoint Descriptor:
        bLength                 9
        bDescriptorType         5
        bEndpointAddress     0x04  EP 4 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0010  1x 16 bytes
        bInterval               1
        bRefresh                0
        bSynchAddress           0
Device Qualifier (for other device speed):
  bLength                10
  bDescriptorType         6
  bcdUSB               2.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0
  bDeviceProtocol         0
  bMaxPacketSize0        64
  bNumConfigurations      1
        

Infos given by usbfs:

T:  Bus=01 Lev=01 Prnt=01 Port=04 Cnt=01 Dev#= 16 Spd=480 MxCh= 0
D:  Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs=  1
P:  Vendor=0644 ProdID=800e Rev= 1.00
S:  Manufacturer=TASCAM
S:  Product=US-122L
S:  SerialNumber=no serial number
C:* #Ifs= 2 Cfg#= 1 Atr=80 MxPwr=480mA
I:  If#= 0 Alt= 0 #EPs= 0 Cls=ff(vend.) Sub=00 Prot=00 Driver=(none)
I:  If#= 1 Alt= 0 #EPs= 0 Cls=ff(vend.) Sub=00 Prot=00 Driver=(none)
I:  If#= 1 Alt= 1 #EPs= 4 Cls=ff(vend.) Sub=00 Prot=00 Driver=(none)
E:  Ad=81(I) Atr=05(Isoc) MxPS=  78 Ivl=125us
E:  Ad=02(O) Atr=05(Isoc) MxPS=  78 Ivl=125us
E:  Ad=83(I) Atr=02(Bulk) MxPS=   9 Ivl=0ms
E:  Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=500us