Turtle Beach Audio Advantage Micro / C-Media CM-102

Works fine by default w/ the usb-audio linux driver with normal analog output. It's USB vendor:product 0x0d8C:0x0001, which indicates a C-Media CM-102 chip.

/proc/bus/usb/devices


T:  Bus=02 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12  MxCh= 0
D:  Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
P:  Vendor=0d8c ProdID=0001 Rev= 0.10
S:  Manufacturer=C-Media INC.
S:  Product=USB Audio
C:* #Ifs= 2 Cfg#= 1 Atr=80 MxPwr=500mA
I:  If#= 0 Alt= 0 #EPs= 0 Cls=01(audio) Sub=01 Prot=00 Driver=snd-usb-audio
I:  If#= 1 Alt= 0 #EPs= 0 Cls=01(audio) Sub=02 Prot=00 Driver=snd-usb-audio
I:  If#= 1 Alt= 1 #EPs= 1 Cls=01(audio) Sub=02 Prot=00 Driver=snd-usb-audio
E:  Ad=06(O) Atr=09(Isoc) MxPS= 192 Ivl=1ms

lsusb -v output

lsusb -v output is here.

Guts

It's a C-Media CM102 It claims to be able to do S/PDIF, as does Turtle Beach, but not quite sure what that means to the linux USB Audio driver... looking into that.

Using a usb snooper w/ windows, this trace seems to be what's going on when switching from default 2 speaker mode to S/PDIF output. The full trace is here. In the full trace, I did:

plug in
wait
open control panel
wait
switch 2 speaker to s/pdif
wait
switch spdif to 2 speaker
wait
switch 2 spkr to headphone
wait
switch headhpone to spdif
wait
unplug

GPIO vendor requests...

Hm, found a specsheet.

5. VENDOR SPECIFIC REQUEST FOR GPIO ACCESS
   GPIO Write

    Offset        Field     Size Value   Description
                                 (Hex)
      0       bmRequestType  1    43
      1         bRequest     1    01
      2          wValue      2   Value   Bit 0: GPIO value
                                         Bit 1: 1: output; 0: input
      4          wIndex      2   0000
      6         wLength      2   0000

   GPIO Read
    Offset        Field     Size Value   Description
                                 (Hex)
      0       bmRequestType  1    C3
      1         bRequest     1    81
      2          wValue      2   Value   Bit 0: GPIO value
                                         Bit 1: 1: output; 0: input
      4          wIndex      2   0000
      6         wLength      2   0001
So, it looks like the vendor-specific requests I see are for GPIO reads and writes - they're all 0x81 and 0x01 requests.

The bmRequest types mean (see Table 9-2 in the USB 2.0 spec...):


0x43
0 10 00011	host-to-device	Vendor	Other
0xC3
1 10 00011	device-to-host	Vendor	Other
I'm sure this is obvious to a USB-savvy person, but that's not me :)

Anyway, I've traced both a c-media driver and the driver from turtle beach; in both cases, turning SPDIF on sends these two vendor-specific requests:

SPDIF ON
-- URB_FUNCTION_VENDOR_OTHER:
  Request                 = 00000001
  Value                   = 00000009
  Index                   = 00000009
-- URB_FUNCTION_VENDOR_OTHER:
  Request                 = 00000001
  Value                   = 000000a0
  Index                   = 00000003
And turning SPDIF back off sends these two:
-- URB_FUNCTION_VENDOR_OTHER:
  Request                 = 00000001
  Value                   = 0000000b
  Index                   = 00000009
-- URB_FUNCTION_VENDOR_OTHER:
  Request                 = 00000001
  Value                   = 000000a0
  Index                   = 00000003
So that looks like a pretty good bet. Switching from headphone to 2-speaker and back each sends these commands, twice:
-- URB_FUNCTION_VENDOR_OTHER:
  Request                 = 00000001
  Value                   = 00000020
  Index                   = 00000003
-- URB_FUNCTION_VENDOR_OTHER:
  Request                 = 00000001
  Value                   = 000000a0
  Index                   = 00000003
So I'm not sure what's going on there; I don't see a big difference between 2 spkr vs. headphones... but I'm less interested in that anyway.

Prior to any manual switching, when I simply open the control panel, it's doing both GPIO reads and writes, but I'm not sure what it's doing with that info. I also see some other GPIO writes of the form:

-- URB_FUNCTION_VENDOR_OTHER:
  Request                 = 00000001
  Value                   = 00000010
  Index                   = 00000002
but not sure what that's doing...