[PATCH] Add quirk to enable Avid Mbox 3 support
From: Conner Knox connerknoxpublic@gmail.com
Hi all,
I believe these are the right emails to send this patch to, but if I've missed something please let me know.
This patch enables the Avid Mbox 3 audio interface to be used through ALSA. It locks the device at a 48khz sample rate. Then it mutes and raises the appropriate channels/inputs to allow for expected functionality.
Thanks for your time.
--- sound/usb/quirks-table.h | 76 ++++++++++ sound/usb/quirks.c | 311 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 387 insertions(+)
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 0ea39565e623..5f43863e5a5f 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -2978,6 +2978,82 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, +/* DIGIDESIGN MBOX 3 */ +{ + USB_DEVICE(0x0dba, 0x5000), + .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + .vendor_name = "Digidesign", + .product_name = "Mbox 3", + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_COMPOSITE, + .data = (const struct snd_usb_audio_quirk[]) { + { + .ifnum = 0, + .type = QUIRK_IGNORE_INTERFACE + }, + { + .ifnum = 1, + .type = QUIRK_IGNORE_INTERFACE + }, + { + .ifnum = 2, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .channels = 4, + .iface = 2, + .altsetting = 1, + .altset_idx = 1, + .attributes = 0x00, + .endpoint = 0x01, + .ep_attr = USB_ENDPOINT_XFER_ISOC | + USB_ENDPOINT_SYNC_ASYNC, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .nr_rates = 1, + .rate_table = (unsigned int[]) { + 48000 + } + } + }, + { + .ifnum = 3, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .channels = 4, + .iface = 3, + .altsetting = 1, + .altset_idx = 1, + .endpoint = 0x81, + .attributes = 0x00, + .ep_attr = USB_ENDPOINT_XFER_ISOC | + USB_ENDPOINT_SYNC_ASYNC, + .maxpacksize = 0x009c, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .nr_rates = 1, + .rate_table = (unsigned int[]) { + 48000 + } + } + }, + { + .ifnum = 4, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const struct snd_usb_midi_endpoint_info) { + .out_cables = 0x0001, + .in_cables = 0x0001 + } + }, + { + .ifnum = -1 + } + } + } +}, { /* Tascam US122 MKII - playback-only support */ USB_DEVICE_VENDOR_SPEC(0x0644, 0x8021), diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index ab9f3da49941..e7caa7eeb955 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1020,6 +1020,313 @@ static int snd_usb_axefx3_boot_quirk(struct usb_device *dev) return 0; }
+static void mbox3_setup_48_24_magic(struct usb_device *dev) +{ + u8 com_buff[4]; + + /* Load 48000Hz rate into buffer */ + com_buff[0] = 0x80; + com_buff[1] = 0xbb; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + + /* Set 48000Hz sample rate */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 0x01, 0x21, 0x0100, 0x0001, &com_buff, 0x0004); + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 0x01, 0x21, 0x0100, 0x8101, &com_buff, 0x0004); + + /* Set clock source to Internal (as opposed to S/PDIF) */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x01; + com_buff[1] = 0x00; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0100, 0x8001, &com_buff, 1); + + /* Mute the hardware loopbacks to start the device in a known state. + * The Mbox 3 is little endian and + * the data written here seems a bit odd. + * 0x8000 (shown in big endian form) is muted + * and volume increases to 0xffff it seems. + * I've yet to observe 0xffff being sent. + * Instead, full volume seems to be 0x0000. + * Per my understanding of 16 bit integers, this is seems strange, but maybe I'm missing something + */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x00; + com_buff[1] = 0x80; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + /* Analogue input 1 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0110, 0x4001, &com_buff, 2); + /* Analogue input 1 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0111, 0x4001, &com_buff, 2); + /* Analogue input 2 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0114, 0x4001, &com_buff, 2); + /* Analogue input 2 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0115, 0x4001, &com_buff, 2); + /* Analogue input 3 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0118, 0x4001, &com_buff, 2); + /* Analogue input 3 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0119, 0x4001, &com_buff, 2); + /* Analogue input 4 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x011c, 0x4001, &com_buff, 2); + /* Analogue input 4 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x011d, 0x4001, &com_buff, 2); + + /* Set software sends to output */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x00; + com_buff[1] = 0x00; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + /* Analogue software return 1 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0100, 0x4001, &com_buff, 2); + /* Analogue software return 1 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0101, 0x4001, &com_buff, 2); + /* Analogue software return 2 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0104, 0x4001, &com_buff, 2); + /* Analogue software return 2 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0105, 0x4001, &com_buff, 2); + /* Analogue software return 3 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0108, 0x4001, &com_buff, 2); + /* Analogue software return 3 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0109, 0x4001, &com_buff, 2); + /* Analogue software return 4 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x010c, 0x4001, &com_buff, 2); + /* Analogue software return 4 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x010d, 0x4001, &com_buff, 2); + + /* Return to muting sends */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x00; + com_buff[1] = 0x80; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + /* Analogue fx return left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0120, 0x4001, &com_buff, 2); + /* Analogue fx return right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0121, 0x4001, &com_buff, 2); + + /* Analogue software input 1 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0100, 0x4201, &com_buff, 2); + /* Analogue software input 2 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0101, 0x4201, &com_buff, 2); + /* Analogue software input 3 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0102, 0x4201, &com_buff, 2); + /* Analogue software input 4 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0103, 0x4201, &com_buff, 2); + /* Analogue input 1 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0104, 0x4201, &com_buff, 2); + /* Analogue input 2 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0105, 0x4201, &com_buff, 2); + /* Analogue input 3 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0106, 0x4201, &com_buff, 2); + /* Analogue input 4 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0107, 0x4201, &com_buff, 2); + + /* Toggle allowing host control */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x02; + com_buff[1] = 0x00; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 3, 0x21, 0x0000, 0x2001, &com_buff, 1); + + /* Do not dim fx returns */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x00; + com_buff[1] = 0x00; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 3, 0x21, 0x0002, 0x2001, &com_buff, 1); + + /* Do not set fx returns to mono */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x00; + com_buff[1] = 0x00; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 3, 0x21, 0x0001, 0x2001, &com_buff, 1); + + /* Mute the S/PDIF hardware loopback + * same odd volume logic here as above + */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x00; + com_buff[1] = 0x80; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + /* S/PDIF hardware input 1 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0112, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 1 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0113, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 2 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0116, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 2 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0117, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 3 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x011a, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 3 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x011b, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 4 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x011e, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 4 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x011f, 0x4001, &com_buff, 2); + /* S/PDIF software return 1 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0102, 0x4001, &com_buff, 2); + /* S/PDIF software return 1 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0103, 0x4001, &com_buff, 2); + /* S/PDIF software return 2 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0106, 0x4001, &com_buff, 2); + /* S/PDIF software return 2 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0107, 0x4001, &com_buff, 2); + /* S/PDIF software return 3 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x010a, 0x4001, &com_buff, 2); + /* S/PDIF software return 3 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x010b, 0x4001, &com_buff, 2); + /* S/PDIF software return 4 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x010e, 0x4001, &com_buff, 2); + /* S/PDIF software return 4 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x010f, 0x4001, &com_buff, 2); + /* S/PDIF fx returns left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0122, 0x4001, &com_buff, 2); + /* S/PDIF fx returns right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0123, 0x4001, &com_buff, 2); + + /* Set the dropdown "Effect" to the first option */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x00; + com_buff[1] = 0x00; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0200, 0x4301, &com_buff, 1); + + /* Set the effect duration to 0 */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x00; + com_buff[1] = 0x00; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0400, 0x4301, &com_buff, 2); + + /* Set the effect volume and feedback to 0 */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x00; + com_buff[1] = 0x00; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + /* feedback: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0500, 0x4301, &com_buff, 1); + /* volume: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0300, 0x4301, &com_buff, 1); + + /* Set soft button hold duration */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x05; + com_buff[1] = 0x00; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 3, 0x21, 0x0005, 0x2001, &com_buff, 1); + + /* Use dim LEDs for button of state */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x00; + com_buff[1] = 0x00; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 3, 0x21, 0x0004, 0x2001, &com_buff, 1); + + return; +} + +#define MBOX3_DESCRIPTOR_SIZE 464 + +static int snd_usb_mbox3_boot_quirk(struct usb_device *dev) +{ + struct usb_host_config *config = dev->actconfig; + int err; + int descriptor_size; + + descriptor_size = le16_to_cpu(get_cfg_desc(config)->wTotalLength); + + if (descriptor_size != MBOX3_DESCRIPTOR_SIZE) { + dev_err(&dev->dev, "Invalid descriptor size=%d.\n", descriptor_size); + return -ENODEV; + } + + dev_dbg(&dev->dev, "device initialised!\n"); + + err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, + &dev->descriptor, sizeof(dev->descriptor)); + config = dev->actconfig; + if (err < 0) + dev_dbg(&dev->dev, "error usb_get_descriptor: %d\n", err); + + err = usb_reset_configuration(dev); + if (err < 0) + dev_dbg(&dev->dev, "error usb_reset_configuration: %d\n", err); + dev_dbg(&dev->dev, "mbox3_boot: new boot length = %d\n", + le16_to_cpu(get_cfg_desc(config)->wTotalLength)); + + mbox3_setup_48_24_magic(dev); + dev_info(&dev->dev, "Digidesign Mbox 3: 24bit 48kHz"); + + return 0; /* Successful boot */ +}
#define MICROBOOK_BUF_SIZE 128
@@ -1324,6 +1631,10 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev, case USB_ID(0x0dba, 0x3000): /* Digidesign Mbox 2 */ return snd_usb_mbox2_boot_quirk(dev); + case USB_ID(0x0dba, 0x5000): + /* Digidesign Mbox 3 */ + return snd_usb_mbox3_boot_quirk(dev); +
case USB_ID(0x1235, 0x0010): /* Focusrite Novation Saffire 6 USB */ case USB_ID(0x1235, 0x0018): /* Focusrite Novation Twitch */
Hi all,
I believe these are the right emails to send this patch to, but if I've missed something please let me know.
This patch enables the Avid Mbox 3 audio interface to be used through ALSA. It locks the device at a 48khz sample rate. Then it mutes and raises the appropriate channels/inputs to allow for expected functionality.
Thanks for your time.
Thanks Conner for taking the time to write and submit this!
I have an MBox 3 (USB) and I've tested the patch:
1. Have not tested S/PDIF i/o because I don't have hardware to plug it. 2. Output is in mono. It seems the monitor outputs work only in MONO. (with and without the front mono button switched on or off). 3. Haven't tested if Headphones output work in stereo because I don't have hardware for testing. 3. Inputs work great.
I'll get a stereo 1/4'' jack to 3.5mm for testing the headphones out. You can contact me directly if needed.
On Tue, 16 Aug 2022 02:44:27 +0200, mbarriolinares wrote:
Hi all,
I believe these are the right emails to send this patch to, but if I've missed something please let me know.
This patch enables the Avid Mbox 3 audio interface to be used through ALSA. It locks the device at a 48khz sample rate. Then it mutes and raises the appropriate channels/inputs to allow for expected functionality.
Thanks for your time.
Thanks Conner for taking the time to write and submit this!
I have an MBox 3 (USB) and I've tested the patch:
- Have not tested S/PDIF i/o because I don't have hardware to plug it.
- Output is in mono. It seems the monitor outputs work only in MONO. (with and without the front mono button switched on or off).
- Haven't tested if Headphones output work in stereo because I don't have hardware for testing.
- Inputs work great.
I'll get a stereo 1/4'' jack to 3.5mm for testing the headphones out. You can contact me directly if needed.
It seems that I overlooked this patch some how.
Through a quick glance, the patch needs the proper Signed-off-by line, at least, for merging to the upstream. Also, simple memset() with zero could be used for clearing the com_buf. Otherwise, it's fine to apply as long as the stuff works more or less (at least improving things).
thanks,
Takashi
From: Conner Knox connerknoxpublic@gmail.com
Appreciate the attention on this, no worries on the wait. I figured I might have sent something to the wrong spot.
I've added the Signed-off-by line, appologies for missing that requirement - first time contributor. As such, please let me know if I need to change anything else.
I had some memset's in the code already, and the excess 0s were for clarity of what was in the buffer. Since I wasn't sure exactly what the recommendation was I left the code alone. Let me know if it needs changed.
I may make further changes to address the aforementioned shortcomings when I get time as well.
Thanks again for your time.
Signed-off-by: Conner Knox connerknoxpublic@gmail.com --- sound/usb/quirks-table.h | 76 ++++++++++ sound/usb/quirks.c | 311 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 387 insertions(+)
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 0ea39565e623..5f43863e5a5f 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -2978,6 +2978,82 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, +/* DIGIDESIGN MBOX 3 */ +{ + USB_DEVICE(0x0dba, 0x5000), + .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + .vendor_name = "Digidesign", + .product_name = "Mbox 3", + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_COMPOSITE, + .data = (const struct snd_usb_audio_quirk[]) { + { + .ifnum = 0, + .type = QUIRK_IGNORE_INTERFACE + }, + { + .ifnum = 1, + .type = QUIRK_IGNORE_INTERFACE + }, + { + .ifnum = 2, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .channels = 4, + .iface = 2, + .altsetting = 1, + .altset_idx = 1, + .attributes = 0x00, + .endpoint = 0x01, + .ep_attr = USB_ENDPOINT_XFER_ISOC | + USB_ENDPOINT_SYNC_ASYNC, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .nr_rates = 1, + .rate_table = (unsigned int[]) { + 48000 + } + } + }, + { + .ifnum = 3, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .channels = 4, + .iface = 3, + .altsetting = 1, + .altset_idx = 1, + .endpoint = 0x81, + .attributes = 0x00, + .ep_attr = USB_ENDPOINT_XFER_ISOC | + USB_ENDPOINT_SYNC_ASYNC, + .maxpacksize = 0x009c, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .nr_rates = 1, + .rate_table = (unsigned int[]) { + 48000 + } + } + }, + { + .ifnum = 4, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const struct snd_usb_midi_endpoint_info) { + .out_cables = 0x0001, + .in_cables = 0x0001 + } + }, + { + .ifnum = -1 + } + } + } +}, { /* Tascam US122 MKII - playback-only support */ USB_DEVICE_VENDOR_SPEC(0x0644, 0x8021), diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index ab9f3da49941..e7caa7eeb955 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1020,6 +1020,313 @@ static int snd_usb_axefx3_boot_quirk(struct usb_device *dev) return 0; }
+static void mbox3_setup_48_24_magic(struct usb_device *dev) +{ + u8 com_buff[4]; + + /* Load 48000Hz rate into buffer */ + com_buff[0] = 0x80; + com_buff[1] = 0xbb; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + + /* Set 48000Hz sample rate */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 0x01, 0x21, 0x0100, 0x0001, &com_buff, 0x0004); + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 0x01, 0x21, 0x0100, 0x8101, &com_buff, 0x0004); + + /* Set clock source to Internal (as opposed to S/PDIF) */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x01; + com_buff[1] = 0x00; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0100, 0x8001, &com_buff, 1); + + /* Mute the hardware loopbacks to start the device in a known state. + * The Mbox 3 is little endian and + * the data written here seems a bit odd. + * 0x8000 (shown in big endian form) is muted + * and volume increases to 0xffff it seems. + * I've yet to observe 0xffff being sent. + * Instead, full volume seems to be 0x0000. + * Per my understanding of 16 bit integers, this is seems strange, but maybe I'm missing something + */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x00; + com_buff[1] = 0x80; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + /* Analogue input 1 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0110, 0x4001, &com_buff, 2); + /* Analogue input 1 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0111, 0x4001, &com_buff, 2); + /* Analogue input 2 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0114, 0x4001, &com_buff, 2); + /* Analogue input 2 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0115, 0x4001, &com_buff, 2); + /* Analogue input 3 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0118, 0x4001, &com_buff, 2); + /* Analogue input 3 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0119, 0x4001, &com_buff, 2); + /* Analogue input 4 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x011c, 0x4001, &com_buff, 2); + /* Analogue input 4 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x011d, 0x4001, &com_buff, 2); + + /* Set software sends to output */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x00; + com_buff[1] = 0x00; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + /* Analogue software return 1 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0100, 0x4001, &com_buff, 2); + /* Analogue software return 1 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0101, 0x4001, &com_buff, 2); + /* Analogue software return 2 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0104, 0x4001, &com_buff, 2); + /* Analogue software return 2 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0105, 0x4001, &com_buff, 2); + /* Analogue software return 3 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0108, 0x4001, &com_buff, 2); + /* Analogue software return 3 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0109, 0x4001, &com_buff, 2); + /* Analogue software return 4 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x010c, 0x4001, &com_buff, 2); + /* Analogue software return 4 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x010d, 0x4001, &com_buff, 2); + + /* Return to muting sends */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x00; + com_buff[1] = 0x80; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + /* Analogue fx return left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0120, 0x4001, &com_buff, 2); + /* Analogue fx return right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0121, 0x4001, &com_buff, 2); + + /* Analogue software input 1 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0100, 0x4201, &com_buff, 2); + /* Analogue software input 2 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0101, 0x4201, &com_buff, 2); + /* Analogue software input 3 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0102, 0x4201, &com_buff, 2); + /* Analogue software input 4 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0103, 0x4201, &com_buff, 2); + /* Analogue input 1 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0104, 0x4201, &com_buff, 2); + /* Analogue input 2 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0105, 0x4201, &com_buff, 2); + /* Analogue input 3 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0106, 0x4201, &com_buff, 2); + /* Analogue input 4 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0107, 0x4201, &com_buff, 2); + + /* Toggle allowing host control */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x02; + com_buff[1] = 0x00; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 3, 0x21, 0x0000, 0x2001, &com_buff, 1); + + /* Do not dim fx returns */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x00; + com_buff[1] = 0x00; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 3, 0x21, 0x0002, 0x2001, &com_buff, 1); + + /* Do not set fx returns to mono */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x00; + com_buff[1] = 0x00; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 3, 0x21, 0x0001, 0x2001, &com_buff, 1); + + /* Mute the S/PDIF hardware loopback + * same odd volume logic here as above + */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x00; + com_buff[1] = 0x80; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + /* S/PDIF hardware input 1 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0112, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 1 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0113, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 2 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0116, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 2 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0117, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 3 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x011a, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 3 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x011b, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 4 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x011e, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 4 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x011f, 0x4001, &com_buff, 2); + /* S/PDIF software return 1 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0102, 0x4001, &com_buff, 2); + /* S/PDIF software return 1 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0103, 0x4001, &com_buff, 2); + /* S/PDIF software return 2 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0106, 0x4001, &com_buff, 2); + /* S/PDIF software return 2 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0107, 0x4001, &com_buff, 2); + /* S/PDIF software return 3 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x010a, 0x4001, &com_buff, 2); + /* S/PDIF software return 3 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x010b, 0x4001, &com_buff, 2); + /* S/PDIF software return 4 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x010e, 0x4001, &com_buff, 2); + /* S/PDIF software return 4 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x010f, 0x4001, &com_buff, 2); + /* S/PDIF fx returns left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0122, 0x4001, &com_buff, 2); + /* S/PDIF fx returns right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0123, 0x4001, &com_buff, 2); + + /* Set the dropdown "Effect" to the first option */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x00; + com_buff[1] = 0x00; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0200, 0x4301, &com_buff, 1); + + /* Set the effect duration to 0 */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x00; + com_buff[1] = 0x00; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0400, 0x4301, &com_buff, 2); + + /* Set the effect volume and feedback to 0 */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x00; + com_buff[1] = 0x00; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + /* feedback: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0500, 0x4301, &com_buff, 1); + /* volume: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0300, 0x4301, &com_buff, 1); + + /* Set soft button hold duration */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x05; + com_buff[1] = 0x00; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 3, 0x21, 0x0005, 0x2001, &com_buff, 1); + + /* Use dim LEDs for button of state */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x00; + com_buff[1] = 0x00; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 3, 0x21, 0x0004, 0x2001, &com_buff, 1); + + return; +} + +#define MBOX3_DESCRIPTOR_SIZE 464 + +static int snd_usb_mbox3_boot_quirk(struct usb_device *dev) +{ + struct usb_host_config *config = dev->actconfig; + int err; + int descriptor_size; + + descriptor_size = le16_to_cpu(get_cfg_desc(config)->wTotalLength); + + if (descriptor_size != MBOX3_DESCRIPTOR_SIZE) { + dev_err(&dev->dev, "Invalid descriptor size=%d.\n", descriptor_size); + return -ENODEV; + } + + dev_dbg(&dev->dev, "device initialised!\n"); + + err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, + &dev->descriptor, sizeof(dev->descriptor)); + config = dev->actconfig; + if (err < 0) + dev_dbg(&dev->dev, "error usb_get_descriptor: %d\n", err); + + err = usb_reset_configuration(dev); + if (err < 0) + dev_dbg(&dev->dev, "error usb_reset_configuration: %d\n", err); + dev_dbg(&dev->dev, "mbox3_boot: new boot length = %d\n", + le16_to_cpu(get_cfg_desc(config)->wTotalLength)); + + mbox3_setup_48_24_magic(dev); + dev_info(&dev->dev, "Digidesign Mbox 3: 24bit 48kHz"); + + return 0; /* Successful boot */ +}
#define MICROBOOK_BUF_SIZE 128
@@ -1324,6 +1631,10 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev, case USB_ID(0x0dba, 0x3000): /* Digidesign Mbox 2 */ return snd_usb_mbox2_boot_quirk(dev); + case USB_ID(0x0dba, 0x5000): + /* Digidesign Mbox 3 */ + return snd_usb_mbox3_boot_quirk(dev); +
case USB_ID(0x1235, 0x0010): /* Focusrite Novation Saffire 6 USB */ case USB_ID(0x1235, 0x0018): /* Focusrite Novation Twitch */
On Wed, 17 Aug 2022 09:15:50 +0200, connerknoxpublic@gmail.com wrote:
From: Conner Knox connerknoxpublic@gmail.com
Appreciate the attention on this, no worries on the wait. I figured I might have sent something to the wrong spot.
I've added the Signed-off-by line, appologies for missing that requirement - first time contributor. As such, please let me know if I need to change anything else.
I had some memset's in the code already, and the excess 0s were for clarity of what was in the buffer. Since I wasn't sure exactly what the recommendation was I left the code alone. Let me know if it needs changed.
I may make further changes to address the aforementioned shortcomings when I get time as well.
Thanks again for your time.
Signed-off-by: Conner Knox connerknoxpublic@gmail.com
Now we have signed-off-by line, but the patch description should contain what to be put in the git commit log. So please write what your patch fixes and some technical details if you want to add there.
The rest comments could be put after the line "---" if you want, but usually not needed unless you need extra notes.
Care to resubmit with the proper patch description, so that I can take it as is?
thanks,
Takashi
sound/usb/quirks-table.h | 76 ++++++++++ sound/usb/quirks.c | 311 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 387 insertions(+)
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 0ea39565e623..5f43863e5a5f 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -2978,6 +2978,82 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, +/* DIGIDESIGN MBOX 3 */ +{
- USB_DEVICE(0x0dba, 0x5000),
- .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
.vendor_name = "Digidesign",
.product_name = "Mbox 3",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_COMPOSITE,
.data = (const struct snd_usb_audio_quirk[]) {
{
.ifnum = 0,
.type = QUIRK_IGNORE_INTERFACE
},
{
.ifnum = 1,
.type = QUIRK_IGNORE_INTERFACE
},
{
.ifnum = 2,
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
.data = &(const struct audioformat) {
.formats = SNDRV_PCM_FMTBIT_S24_3LE,
.channels = 4,
.iface = 2,
.altsetting = 1,
.altset_idx = 1,
.attributes = 0x00,
.endpoint = 0x01,
.ep_attr = USB_ENDPOINT_XFER_ISOC |
USB_ENDPOINT_SYNC_ASYNC,
.rates = SNDRV_PCM_RATE_48000,
.rate_min = 48000,
.rate_max = 48000,
.nr_rates = 1,
.rate_table = (unsigned int[]) {
48000
}
}
},
{
.ifnum = 3,
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
.data = &(const struct audioformat) {
.formats = SNDRV_PCM_FMTBIT_S24_3LE,
.channels = 4,
.iface = 3,
.altsetting = 1,
.altset_idx = 1,
.endpoint = 0x81,
.attributes = 0x00,
.ep_attr = USB_ENDPOINT_XFER_ISOC |
USB_ENDPOINT_SYNC_ASYNC,
.maxpacksize = 0x009c,
.rates = SNDRV_PCM_RATE_48000,
.rate_min = 48000,
.rate_max = 48000,
.nr_rates = 1,
.rate_table = (unsigned int[]) {
48000
}
}
},
{
.ifnum = 4,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
.data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0001,
.in_cables = 0x0001
}
},
{
.ifnum = -1
}
}
- }
+}, { /* Tascam US122 MKII - playback-only support */ USB_DEVICE_VENDOR_SPEC(0x0644, 0x8021), diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index ab9f3da49941..e7caa7eeb955 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1020,6 +1020,313 @@ static int snd_usb_axefx3_boot_quirk(struct usb_device *dev) return 0; }
+static void mbox3_setup_48_24_magic(struct usb_device *dev) +{
- u8 com_buff[4];
- /* Load 48000Hz rate into buffer */
- com_buff[0] = 0x80;
- com_buff[1] = 0xbb;
- com_buff[2] = 0x00;
- com_buff[3] = 0x00;
- /* Set 48000Hz sample rate */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
0x01, 0x21, 0x0100, 0x0001, &com_buff, 0x0004);
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
0x01, 0x21, 0x0100, 0x8101, &com_buff, 0x0004);
- /* Set clock source to Internal (as opposed to S/PDIF) */
- memset(com_buff, 0x00, 4);
- com_buff[0] = 0x01;
- com_buff[1] = 0x00;
- com_buff[2] = 0x00;
- com_buff[3] = 0x00;
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0100, 0x8001, &com_buff, 1);
- /* Mute the hardware loopbacks to start the device in a known state.
* The Mbox 3 is little endian and
* the data written here seems a bit odd.
* 0x8000 (shown in big endian form) is muted
* and volume increases to 0xffff it seems.
* I've yet to observe 0xffff being sent.
* Instead, full volume seems to be 0x0000.
* Per my understanding of 16 bit integers, this is seems strange, but maybe I'm missing something
*/
- memset(com_buff, 0x00, 4);
- com_buff[0] = 0x00;
- com_buff[1] = 0x80;
- com_buff[2] = 0x00;
- com_buff[3] = 0x00;
- /* Analogue input 1 left channel: */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0110, 0x4001, &com_buff, 2);
- /* Analogue input 1 right channel: */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0111, 0x4001, &com_buff, 2);
- /* Analogue input 2 left channel: */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0114, 0x4001, &com_buff, 2);
- /* Analogue input 2 right channel: */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0115, 0x4001, &com_buff, 2);
- /* Analogue input 3 left channel: */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0118, 0x4001, &com_buff, 2);
- /* Analogue input 3 right channel: */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0119, 0x4001, &com_buff, 2);
- /* Analogue input 4 left channel: */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x011c, 0x4001, &com_buff, 2);
- /* Analogue input 4 right channel: */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x011d, 0x4001, &com_buff, 2);
- /* Set software sends to output */
- memset(com_buff, 0x00, 4);
- com_buff[0] = 0x00;
- com_buff[1] = 0x00;
- com_buff[2] = 0x00;
- com_buff[3] = 0x00;
- /* Analogue software return 1 left channel: */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0100, 0x4001, &com_buff, 2);
- /* Analogue software return 1 right channel: */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0101, 0x4001, &com_buff, 2);
- /* Analogue software return 2 left channel: */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0104, 0x4001, &com_buff, 2);
- /* Analogue software return 2 right channel: */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0105, 0x4001, &com_buff, 2);
- /* Analogue software return 3 left channel: */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0108, 0x4001, &com_buff, 2);
- /* Analogue software return 3 right channel: */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0109, 0x4001, &com_buff, 2);
- /* Analogue software return 4 left channel: */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x010c, 0x4001, &com_buff, 2);
- /* Analogue software return 4 right channel: */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x010d, 0x4001, &com_buff, 2);
- /* Return to muting sends */
- memset(com_buff, 0x00, 4);
- com_buff[0] = 0x00;
- com_buff[1] = 0x80;
- com_buff[2] = 0x00;
- com_buff[3] = 0x00;
- /* Analogue fx return left channel: */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0120, 0x4001, &com_buff, 2);
- /* Analogue fx return right channel: */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0121, 0x4001, &com_buff, 2);
- /* Analogue software input 1 fx send: */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0100, 0x4201, &com_buff, 2);
- /* Analogue software input 2 fx send: */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0101, 0x4201, &com_buff, 2);
- /* Analogue software input 3 fx send: */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0102, 0x4201, &com_buff, 2);
- /* Analogue software input 4 fx send: */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0103, 0x4201, &com_buff, 2);
- /* Analogue input 1 fx send: */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0104, 0x4201, &com_buff, 2);
- /* Analogue input 2 fx send: */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0105, 0x4201, &com_buff, 2);
- /* Analogue input 3 fx send: */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0106, 0x4201, &com_buff, 2);
- /* Analogue input 4 fx send: */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0107, 0x4201, &com_buff, 2);
- /* Toggle allowing host control */
- memset(com_buff, 0x00, 4);
- com_buff[0] = 0x02;
- com_buff[1] = 0x00;
- com_buff[2] = 0x00;
- com_buff[3] = 0x00;
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
3, 0x21, 0x0000, 0x2001, &com_buff, 1);
- /* Do not dim fx returns */
- memset(com_buff, 0x00, 4);
- com_buff[0] = 0x00;
- com_buff[1] = 0x00;
- com_buff[2] = 0x00;
- com_buff[3] = 0x00;
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 3, 0x21, 0x0002, 0x2001, &com_buff, 1);
- /* Do not set fx returns to mono */
- memset(com_buff, 0x00, 4);
- com_buff[0] = 0x00;
- com_buff[1] = 0x00;
- com_buff[2] = 0x00;
- com_buff[3] = 0x00;
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 3, 0x21, 0x0001, 0x2001, &com_buff, 1);
- /* Mute the S/PDIF hardware loopback
* same odd volume logic here as above
*/
- memset(com_buff, 0x00, 4);
- com_buff[0] = 0x00;
- com_buff[1] = 0x80;
- com_buff[2] = 0x00;
- com_buff[3] = 0x00;
- /* S/PDIF hardware input 1 left channel */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0112, 0x4001, &com_buff, 2);
- /* S/PDIF hardware input 1 right channel */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0113, 0x4001, &com_buff, 2);
- /* S/PDIF hardware input 2 left channel */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0116, 0x4001, &com_buff, 2);
- /* S/PDIF hardware input 2 right channel */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0117, 0x4001, &com_buff, 2);
- /* S/PDIF hardware input 3 left channel */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x011a, 0x4001, &com_buff, 2);
- /* S/PDIF hardware input 3 right channel */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x011b, 0x4001, &com_buff, 2);
- /* S/PDIF hardware input 4 left channel */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x011e, 0x4001, &com_buff, 2);
- /* S/PDIF hardware input 4 right channel */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x011f, 0x4001, &com_buff, 2);
- /* S/PDIF software return 1 left channel */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0102, 0x4001, &com_buff, 2);
- /* S/PDIF software return 1 right channel */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0103, 0x4001, &com_buff, 2);
- /* S/PDIF software return 2 left channel */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0106, 0x4001, &com_buff, 2);
- /* S/PDIF software return 2 right channel */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0107, 0x4001, &com_buff, 2);
- /* S/PDIF software return 3 left channel */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x010a, 0x4001, &com_buff, 2);
- /* S/PDIF software return 3 right channel */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x010b, 0x4001, &com_buff, 2);
- /* S/PDIF software return 4 left channel */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x010e, 0x4001, &com_buff, 2);
- /* S/PDIF software return 4 right channel */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x010f, 0x4001, &com_buff, 2);
- /* S/PDIF fx returns left channel */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0122, 0x4001, &com_buff, 2);
- /* S/PDIF fx returns right channel */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0123, 0x4001, &com_buff, 2);
- /* Set the dropdown "Effect" to the first option */
- memset(com_buff, 0x00, 4);
- com_buff[0] = 0x00;
- com_buff[1] = 0x00;
- com_buff[2] = 0x00;
- com_buff[3] = 0x00;
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0200, 0x4301, &com_buff, 1);
- /* Set the effect duration to 0 */
- memset(com_buff, 0x00, 4);
- com_buff[0] = 0x00;
- com_buff[1] = 0x00;
- com_buff[2] = 0x00;
- com_buff[3] = 0x00;
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0400, 0x4301, &com_buff, 2);
- /* Set the effect volume and feedback to 0 */
- memset(com_buff, 0x00, 4);
- com_buff[0] = 0x00;
- com_buff[1] = 0x00;
- com_buff[2] = 0x00;
- com_buff[3] = 0x00;
- /* feedback: */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0500, 0x4301, &com_buff, 1);
- /* volume: */
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0300, 0x4301, &com_buff, 1);
- /* Set soft button hold duration */
- memset(com_buff, 0x00, 4);
- com_buff[0] = 0x05;
- com_buff[1] = 0x00;
- com_buff[2] = 0x00;
- com_buff[3] = 0x00;
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
3, 0x21, 0x0005, 0x2001, &com_buff, 1);
- /* Use dim LEDs for button of state */
- memset(com_buff, 0x00, 4);
- com_buff[0] = 0x00;
- com_buff[1] = 0x00;
- com_buff[2] = 0x00;
- com_buff[3] = 0x00;
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
3, 0x21, 0x0004, 0x2001, &com_buff, 1);
- return;
+}
+#define MBOX3_DESCRIPTOR_SIZE 464
+static int snd_usb_mbox3_boot_quirk(struct usb_device *dev) +{
- struct usb_host_config *config = dev->actconfig;
- int err;
- int descriptor_size;
- descriptor_size = le16_to_cpu(get_cfg_desc(config)->wTotalLength);
- if (descriptor_size != MBOX3_DESCRIPTOR_SIZE) {
dev_err(&dev->dev, "Invalid descriptor size=%d.\n", descriptor_size);
return -ENODEV;
- }
- dev_dbg(&dev->dev, "device initialised!\n");
- err = usb_get_descriptor(dev, USB_DT_DEVICE, 0,
&dev->descriptor, sizeof(dev->descriptor));
- config = dev->actconfig;
- if (err < 0)
dev_dbg(&dev->dev, "error usb_get_descriptor: %d\n", err);
- err = usb_reset_configuration(dev);
- if (err < 0)
dev_dbg(&dev->dev, "error usb_reset_configuration: %d\n", err);
- dev_dbg(&dev->dev, "mbox3_boot: new boot length = %d\n",
le16_to_cpu(get_cfg_desc(config)->wTotalLength));
- mbox3_setup_48_24_magic(dev);
- dev_info(&dev->dev, "Digidesign Mbox 3: 24bit 48kHz");
- return 0; /* Successful boot */
+}
#define MICROBOOK_BUF_SIZE 128
@@ -1324,6 +1631,10 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev, case USB_ID(0x0dba, 0x3000): /* Digidesign Mbox 2 */ return snd_usb_mbox2_boot_quirk(dev);
case USB_ID(0x0dba, 0x5000):
/* Digidesign Mbox 3 */
return snd_usb_mbox3_boot_quirk(dev);
case USB_ID(0x1235, 0x0010): /* Focusrite Novation Saffire 6 USB */ case USB_ID(0x1235, 0x0018): /* Focusrite Novation Twitch */
-- 2.37.2
From: Conner Knox connerknoxpublic@gmail.com
Add support for Avid Mbox3 USB audio interface at 48kHz
Signed-off-by: Conner Knox connerknoxpublic@gmail.com --- sound/usb/quirks-table.h | 76 ++++++++++ sound/usb/quirks.c | 311 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 387 insertions(+)
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 0ea39565e623..5f43863e5a5f 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -2978,6 +2978,82 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, +/* DIGIDESIGN MBOX 3 */ +{ + USB_DEVICE(0x0dba, 0x5000), + .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + .vendor_name = "Digidesign", + .product_name = "Mbox 3", + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_COMPOSITE, + .data = (const struct snd_usb_audio_quirk[]) { + { + .ifnum = 0, + .type = QUIRK_IGNORE_INTERFACE + }, + { + .ifnum = 1, + .type = QUIRK_IGNORE_INTERFACE + }, + { + .ifnum = 2, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .channels = 4, + .iface = 2, + .altsetting = 1, + .altset_idx = 1, + .attributes = 0x00, + .endpoint = 0x01, + .ep_attr = USB_ENDPOINT_XFER_ISOC | + USB_ENDPOINT_SYNC_ASYNC, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .nr_rates = 1, + .rate_table = (unsigned int[]) { + 48000 + } + } + }, + { + .ifnum = 3, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .channels = 4, + .iface = 3, + .altsetting = 1, + .altset_idx = 1, + .endpoint = 0x81, + .attributes = 0x00, + .ep_attr = USB_ENDPOINT_XFER_ISOC | + USB_ENDPOINT_SYNC_ASYNC, + .maxpacksize = 0x009c, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .nr_rates = 1, + .rate_table = (unsigned int[]) { + 48000 + } + } + }, + { + .ifnum = 4, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const struct snd_usb_midi_endpoint_info) { + .out_cables = 0x0001, + .in_cables = 0x0001 + } + }, + { + .ifnum = -1 + } + } + } +}, { /* Tascam US122 MKII - playback-only support */ USB_DEVICE_VENDOR_SPEC(0x0644, 0x8021), diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index ab9f3da49941..e7caa7eeb955 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1020,6 +1020,313 @@ static int snd_usb_axefx3_boot_quirk(struct usb_device *dev) return 0; }
+static void mbox3_setup_48_24_magic(struct usb_device *dev) +{ + u8 com_buff[4]; + + /* Load 48000Hz rate into buffer */ + com_buff[0] = 0x80; + com_buff[1] = 0xbb; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + + /* Set 48000Hz sample rate */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 0x01, 0x21, 0x0100, 0x0001, &com_buff, 0x0004); + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 0x01, 0x21, 0x0100, 0x8101, &com_buff, 0x0004); + + /* Set clock source to Internal (as opposed to S/PDIF) */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x01; + com_buff[1] = 0x00; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0100, 0x8001, &com_buff, 1); + + /* Mute the hardware loopbacks to start the device in a known state. + * The Mbox 3 is little endian and + * the data written here seems a bit odd. + * 0x8000 (shown in big endian form) is muted + * and volume increases to 0xffff it seems. + * I've yet to observe 0xffff being sent. + * Instead, full volume seems to be 0x0000. + * Per my understanding of 16 bit integers, this is seems strange, but maybe I'm missing something + */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x00; + com_buff[1] = 0x80; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + /* Analogue input 1 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0110, 0x4001, &com_buff, 2); + /* Analogue input 1 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0111, 0x4001, &com_buff, 2); + /* Analogue input 2 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0114, 0x4001, &com_buff, 2); + /* Analogue input 2 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0115, 0x4001, &com_buff, 2); + /* Analogue input 3 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0118, 0x4001, &com_buff, 2); + /* Analogue input 3 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0119, 0x4001, &com_buff, 2); + /* Analogue input 4 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x011c, 0x4001, &com_buff, 2); + /* Analogue input 4 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x011d, 0x4001, &com_buff, 2); + + /* Set software sends to output */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x00; + com_buff[1] = 0x00; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + /* Analogue software return 1 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0100, 0x4001, &com_buff, 2); + /* Analogue software return 1 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0101, 0x4001, &com_buff, 2); + /* Analogue software return 2 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0104, 0x4001, &com_buff, 2); + /* Analogue software return 2 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0105, 0x4001, &com_buff, 2); + /* Analogue software return 3 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0108, 0x4001, &com_buff, 2); + /* Analogue software return 3 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0109, 0x4001, &com_buff, 2); + /* Analogue software return 4 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x010c, 0x4001, &com_buff, 2); + /* Analogue software return 4 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x010d, 0x4001, &com_buff, 2); + + /* Return to muting sends */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x00; + com_buff[1] = 0x80; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + /* Analogue fx return left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0120, 0x4001, &com_buff, 2); + /* Analogue fx return right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0121, 0x4001, &com_buff, 2); + + /* Analogue software input 1 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0100, 0x4201, &com_buff, 2); + /* Analogue software input 2 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0101, 0x4201, &com_buff, 2); + /* Analogue software input 3 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0102, 0x4201, &com_buff, 2); + /* Analogue software input 4 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0103, 0x4201, &com_buff, 2); + /* Analogue input 1 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0104, 0x4201, &com_buff, 2); + /* Analogue input 2 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0105, 0x4201, &com_buff, 2); + /* Analogue input 3 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0106, 0x4201, &com_buff, 2); + /* Analogue input 4 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0107, 0x4201, &com_buff, 2); + + /* Toggle allowing host control */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x02; + com_buff[1] = 0x00; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 3, 0x21, 0x0000, 0x2001, &com_buff, 1); + + /* Do not dim fx returns */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x00; + com_buff[1] = 0x00; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 3, 0x21, 0x0002, 0x2001, &com_buff, 1); + + /* Do not set fx returns to mono */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x00; + com_buff[1] = 0x00; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 3, 0x21, 0x0001, 0x2001, &com_buff, 1); + + /* Mute the S/PDIF hardware loopback + * same odd volume logic here as above + */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x00; + com_buff[1] = 0x80; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + /* S/PDIF hardware input 1 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0112, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 1 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0113, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 2 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0116, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 2 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0117, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 3 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x011a, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 3 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x011b, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 4 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x011e, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 4 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x011f, 0x4001, &com_buff, 2); + /* S/PDIF software return 1 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0102, 0x4001, &com_buff, 2); + /* S/PDIF software return 1 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0103, 0x4001, &com_buff, 2); + /* S/PDIF software return 2 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0106, 0x4001, &com_buff, 2); + /* S/PDIF software return 2 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0107, 0x4001, &com_buff, 2); + /* S/PDIF software return 3 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x010a, 0x4001, &com_buff, 2); + /* S/PDIF software return 3 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x010b, 0x4001, &com_buff, 2); + /* S/PDIF software return 4 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x010e, 0x4001, &com_buff, 2); + /* S/PDIF software return 4 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x010f, 0x4001, &com_buff, 2); + /* S/PDIF fx returns left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0122, 0x4001, &com_buff, 2); + /* S/PDIF fx returns right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0123, 0x4001, &com_buff, 2); + + /* Set the dropdown "Effect" to the first option */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x00; + com_buff[1] = 0x00; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0200, 0x4301, &com_buff, 1); + + /* Set the effect duration to 0 */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x00; + com_buff[1] = 0x00; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0400, 0x4301, &com_buff, 2); + + /* Set the effect volume and feedback to 0 */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x00; + com_buff[1] = 0x00; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + /* feedback: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0500, 0x4301, &com_buff, 1); + /* volume: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0300, 0x4301, &com_buff, 1); + + /* Set soft button hold duration */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x05; + com_buff[1] = 0x00; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 3, 0x21, 0x0005, 0x2001, &com_buff, 1); + + /* Use dim LEDs for button of state */ + memset(com_buff, 0x00, 4); + com_buff[0] = 0x00; + com_buff[1] = 0x00; + com_buff[2] = 0x00; + com_buff[3] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 3, 0x21, 0x0004, 0x2001, &com_buff, 1); + + return; +} + +#define MBOX3_DESCRIPTOR_SIZE 464 + +static int snd_usb_mbox3_boot_quirk(struct usb_device *dev) +{ + struct usb_host_config *config = dev->actconfig; + int err; + int descriptor_size; + + descriptor_size = le16_to_cpu(get_cfg_desc(config)->wTotalLength); + + if (descriptor_size != MBOX3_DESCRIPTOR_SIZE) { + dev_err(&dev->dev, "Invalid descriptor size=%d.\n", descriptor_size); + return -ENODEV; + } + + dev_dbg(&dev->dev, "device initialised!\n"); + + err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, + &dev->descriptor, sizeof(dev->descriptor)); + config = dev->actconfig; + if (err < 0) + dev_dbg(&dev->dev, "error usb_get_descriptor: %d\n", err); + + err = usb_reset_configuration(dev); + if (err < 0) + dev_dbg(&dev->dev, "error usb_reset_configuration: %d\n", err); + dev_dbg(&dev->dev, "mbox3_boot: new boot length = %d\n", + le16_to_cpu(get_cfg_desc(config)->wTotalLength)); + + mbox3_setup_48_24_magic(dev); + dev_info(&dev->dev, "Digidesign Mbox 3: 24bit 48kHz"); + + return 0; /* Successful boot */ +}
#define MICROBOOK_BUF_SIZE 128
@@ -1324,6 +1631,10 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev, case USB_ID(0x0dba, 0x3000): /* Digidesign Mbox 2 */ return snd_usb_mbox2_boot_quirk(dev); + case USB_ID(0x0dba, 0x5000): + /* Digidesign Mbox 3 */ + return snd_usb_mbox3_boot_quirk(dev); +
case USB_ID(0x1235, 0x0010): /* Focusrite Novation Saffire 6 USB */ case USB_ID(0x1235, 0x0018): /* Focusrite Novation Twitch */
Could you perhaps make this the defaults, for it to work in stereo? I've made the Analog 1 to be left, and Analog 2 to be right channels, and muted Analog 3 and 4, as they are detected as "surround". This works out of the box with the back Analog outs. (Still haven't tested front headphones out)
/* Set software sends to output */ com_buff[0] = 0x00; com_buff[1] = 0x00; /* Analogue software return 1 left channel: */ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 1, 0x21, 0x0100, 0x4001, &com_buff, 2); /* Analogue software return 2 right channel: */ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 1, 0x21, 0x0105, 0x4001, &com_buff, 2); com_buff[0] = 0x00; com_buff[1] = 0x80; /* Analogue software return 1 right channel: */ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 1, 0x21, 0x0101, 0x4001, &com_buff, 2); /* Analogue software return 2 left channel: */ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 1, 0x21, 0x0104, 0x4001, &com_buff, 2); com_buff[0] = 0x00; com_buff[1] = 0x80; /* Analogue software return 3 left channel: */ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 1, 0x21, 0x0108, 0x4001, &com_buff, 2); /* Analogue software return 3 right channel: */ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 1, 0x21, 0x0109, 0x4001, &com_buff, 2); /* Analogue software return 4 left channel: */ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 1, 0x21, 0x010c, 0x4001, &com_buff, 2); /* Analogue software return 4 right channel: */ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 1, 0x21, 0x010d, 0x4001, &com_buff, 2);
On Wed, Aug 17, 2022 at 1:28 PM connerknoxpublic@gmail.com wrote:
From: Conner Knox connerknoxpublic@gmail.com
Add support for Avid Mbox3 USB audio interface at 48kHz
Signed-off-by: Conner Knox connerknoxpublic@gmail.com
sound/usb/quirks-table.h | 76 ++++++++++ sound/usb/quirks.c | 311 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 387 insertions(+)
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 0ea39565e623..5f43863e5a5f 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -2978,6 +2978,82 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, +/* DIGIDESIGN MBOX 3 */ +{
USB_DEVICE(0x0dba, 0x5000),
.driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
.vendor_name = "Digidesign",
.product_name = "Mbox 3",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_COMPOSITE,
.data = (const struct snd_usb_audio_quirk[]) {
{
.ifnum = 0,
.type = QUIRK_IGNORE_INTERFACE
},
{
.ifnum = 1,
.type = QUIRK_IGNORE_INTERFACE
},
{
.ifnum = 2,
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
.data = &(const struct audioformat) {
.formats = SNDRV_PCM_FMTBIT_S24_3LE,
.channels = 4,
.iface = 2,
.altsetting = 1,
.altset_idx = 1,
.attributes = 0x00,
.endpoint = 0x01,
.ep_attr = USB_ENDPOINT_XFER_ISOC |
USB_ENDPOINT_SYNC_ASYNC,
.rates = SNDRV_PCM_RATE_48000,
.rate_min = 48000,
.rate_max = 48000,
.nr_rates = 1,
.rate_table = (unsigned int[]) {
48000
}
}
},
{
.ifnum = 3,
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
.data = &(const struct audioformat) {
.formats = SNDRV_PCM_FMTBIT_S24_3LE,
.channels = 4,
.iface = 3,
.altsetting = 1,
.altset_idx = 1,
.endpoint = 0x81,
.attributes = 0x00,
.ep_attr = USB_ENDPOINT_XFER_ISOC |
USB_ENDPOINT_SYNC_ASYNC,
.maxpacksize = 0x009c,
.rates = SNDRV_PCM_RATE_48000,
.rate_min = 48000,
.rate_max = 48000,
.nr_rates = 1,
.rate_table = (unsigned int[]) {
48000
}
}
},
{
.ifnum = 4,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
.data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0001,
.in_cables = 0x0001
}
},
{
.ifnum = -1
}
}
}
+}, { /* Tascam US122 MKII - playback-only support */ USB_DEVICE_VENDOR_SPEC(0x0644, 0x8021), diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index ab9f3da49941..e7caa7eeb955 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1020,6 +1020,313 @@ static int snd_usb_axefx3_boot_quirk(struct usb_device *dev) return 0; }
+static void mbox3_setup_48_24_magic(struct usb_device *dev) +{
u8 com_buff[4];
/* Load 48000Hz rate into buffer */
com_buff[0] = 0x80;
com_buff[1] = 0xbb;
com_buff[2] = 0x00;
com_buff[3] = 0x00;
/* Set 48000Hz sample rate */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
0x01, 0x21, 0x0100, 0x0001, &com_buff, 0x0004);
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
0x01, 0x21, 0x0100, 0x8101, &com_buff, 0x0004);
/* Set clock source to Internal (as opposed to S/PDIF) */
memset(com_buff, 0x00, 4);
com_buff[0] = 0x01;
com_buff[1] = 0x00;
com_buff[2] = 0x00;
com_buff[3] = 0x00;
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0100, 0x8001, &com_buff, 1);
/* Mute the hardware loopbacks to start the device in a known state.
* The Mbox 3 is little endian and
* the data written here seems a bit odd.
* 0x8000 (shown in big endian form) is muted
* and volume increases to 0xffff it seems.
* I've yet to observe 0xffff being sent.
* Instead, full volume seems to be 0x0000.
* Per my understanding of 16 bit integers, this is seems strange, but maybe I'm missing something
*/
memset(com_buff, 0x00, 4);
com_buff[0] = 0x00;
com_buff[1] = 0x80;
com_buff[2] = 0x00;
com_buff[3] = 0x00;
/* Analogue input 1 left channel: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0110, 0x4001, &com_buff, 2);
/* Analogue input 1 right channel: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0111, 0x4001, &com_buff, 2);
/* Analogue input 2 left channel: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0114, 0x4001, &com_buff, 2);
/* Analogue input 2 right channel: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0115, 0x4001, &com_buff, 2);
/* Analogue input 3 left channel: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0118, 0x4001, &com_buff, 2);
/* Analogue input 3 right channel: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0119, 0x4001, &com_buff, 2);
/* Analogue input 4 left channel: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x011c, 0x4001, &com_buff, 2);
/* Analogue input 4 right channel: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x011d, 0x4001, &com_buff, 2);
/* Set software sends to output */
memset(com_buff, 0x00, 4);
com_buff[0] = 0x00;
com_buff[1] = 0x00;
com_buff[2] = 0x00;
com_buff[3] = 0x00;
/* Analogue software return 1 left channel: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0100, 0x4001, &com_buff, 2);
/* Analogue software return 1 right channel: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0101, 0x4001, &com_buff, 2);
/* Analogue software return 2 left channel: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0104, 0x4001, &com_buff, 2);
/* Analogue software return 2 right channel: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0105, 0x4001, &com_buff, 2);
/* Analogue software return 3 left channel: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0108, 0x4001, &com_buff, 2);
/* Analogue software return 3 right channel: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0109, 0x4001, &com_buff, 2);
/* Analogue software return 4 left channel: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x010c, 0x4001, &com_buff, 2);
/* Analogue software return 4 right channel: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x010d, 0x4001, &com_buff, 2);
/* Return to muting sends */
memset(com_buff, 0x00, 4);
com_buff[0] = 0x00;
com_buff[1] = 0x80;
com_buff[2] = 0x00;
com_buff[3] = 0x00;
/* Analogue fx return left channel: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0120, 0x4001, &com_buff, 2);
/* Analogue fx return right channel: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0121, 0x4001, &com_buff, 2);
/* Analogue software input 1 fx send: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0100, 0x4201, &com_buff, 2);
/* Analogue software input 2 fx send: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0101, 0x4201, &com_buff, 2);
/* Analogue software input 3 fx send: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0102, 0x4201, &com_buff, 2);
/* Analogue software input 4 fx send: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0103, 0x4201, &com_buff, 2);
/* Analogue input 1 fx send: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0104, 0x4201, &com_buff, 2);
/* Analogue input 2 fx send: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0105, 0x4201, &com_buff, 2);
/* Analogue input 3 fx send: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0106, 0x4201, &com_buff, 2);
/* Analogue input 4 fx send: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0107, 0x4201, &com_buff, 2);
/* Toggle allowing host control */
memset(com_buff, 0x00, 4);
com_buff[0] = 0x02;
com_buff[1] = 0x00;
com_buff[2] = 0x00;
com_buff[3] = 0x00;
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
3, 0x21, 0x0000, 0x2001, &com_buff, 1);
/* Do not dim fx returns */
memset(com_buff, 0x00, 4);
com_buff[0] = 0x00;
com_buff[1] = 0x00;
com_buff[2] = 0x00;
com_buff[3] = 0x00;
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 3, 0x21, 0x0002, 0x2001, &com_buff, 1);
/* Do not set fx returns to mono */
memset(com_buff, 0x00, 4);
com_buff[0] = 0x00;
com_buff[1] = 0x00;
com_buff[2] = 0x00;
com_buff[3] = 0x00;
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 3, 0x21, 0x0001, 0x2001, &com_buff, 1);
/* Mute the S/PDIF hardware loopback
* same odd volume logic here as above
*/
memset(com_buff, 0x00, 4);
com_buff[0] = 0x00;
com_buff[1] = 0x80;
com_buff[2] = 0x00;
com_buff[3] = 0x00;
/* S/PDIF hardware input 1 left channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0112, 0x4001, &com_buff, 2);
/* S/PDIF hardware input 1 right channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0113, 0x4001, &com_buff, 2);
/* S/PDIF hardware input 2 left channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0116, 0x4001, &com_buff, 2);
/* S/PDIF hardware input 2 right channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0117, 0x4001, &com_buff, 2);
/* S/PDIF hardware input 3 left channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x011a, 0x4001, &com_buff, 2);
/* S/PDIF hardware input 3 right channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x011b, 0x4001, &com_buff, 2);
/* S/PDIF hardware input 4 left channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x011e, 0x4001, &com_buff, 2);
/* S/PDIF hardware input 4 right channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x011f, 0x4001, &com_buff, 2);
/* S/PDIF software return 1 left channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0102, 0x4001, &com_buff, 2);
/* S/PDIF software return 1 right channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0103, 0x4001, &com_buff, 2);
/* S/PDIF software return 2 left channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0106, 0x4001, &com_buff, 2);
/* S/PDIF software return 2 right channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0107, 0x4001, &com_buff, 2);
/* S/PDIF software return 3 left channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x010a, 0x4001, &com_buff, 2);
/* S/PDIF software return 3 right channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x010b, 0x4001, &com_buff, 2);
/* S/PDIF software return 4 left channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x010e, 0x4001, &com_buff, 2);
/* S/PDIF software return 4 right channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x010f, 0x4001, &com_buff, 2);
/* S/PDIF fx returns left channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0122, 0x4001, &com_buff, 2);
/* S/PDIF fx returns right channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0123, 0x4001, &com_buff, 2);
/* Set the dropdown "Effect" to the first option */
memset(com_buff, 0x00, 4);
com_buff[0] = 0x00;
com_buff[1] = 0x00;
com_buff[2] = 0x00;
com_buff[3] = 0x00;
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0200, 0x4301, &com_buff, 1);
/* Set the effect duration to 0 */
memset(com_buff, 0x00, 4);
com_buff[0] = 0x00;
com_buff[1] = 0x00;
com_buff[2] = 0x00;
com_buff[3] = 0x00;
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0400, 0x4301, &com_buff, 2);
/* Set the effect volume and feedback to 0 */
memset(com_buff, 0x00, 4);
com_buff[0] = 0x00;
com_buff[1] = 0x00;
com_buff[2] = 0x00;
com_buff[3] = 0x00;
/* feedback: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0500, 0x4301, &com_buff, 1);
/* volume: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0300, 0x4301, &com_buff, 1);
/* Set soft button hold duration */
memset(com_buff, 0x00, 4);
com_buff[0] = 0x05;
com_buff[1] = 0x00;
com_buff[2] = 0x00;
com_buff[3] = 0x00;
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
3, 0x21, 0x0005, 0x2001, &com_buff, 1);
/* Use dim LEDs for button of state */
memset(com_buff, 0x00, 4);
com_buff[0] = 0x00;
com_buff[1] = 0x00;
com_buff[2] = 0x00;
com_buff[3] = 0x00;
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
3, 0x21, 0x0004, 0x2001, &com_buff, 1);
return;
+}
+#define MBOX3_DESCRIPTOR_SIZE 464
+static int snd_usb_mbox3_boot_quirk(struct usb_device *dev) +{
struct usb_host_config *config = dev->actconfig;
int err;
int descriptor_size;
descriptor_size = le16_to_cpu(get_cfg_desc(config)->wTotalLength);
if (descriptor_size != MBOX3_DESCRIPTOR_SIZE) {
dev_err(&dev->dev, "Invalid descriptor size=%d.\n", descriptor_size);
return -ENODEV;
}
dev_dbg(&dev->dev, "device initialised!\n");
err = usb_get_descriptor(dev, USB_DT_DEVICE, 0,
&dev->descriptor, sizeof(dev->descriptor));
config = dev->actconfig;
if (err < 0)
dev_dbg(&dev->dev, "error usb_get_descriptor: %d\n", err);
err = usb_reset_configuration(dev);
if (err < 0)
dev_dbg(&dev->dev, "error usb_reset_configuration: %d\n", err);
dev_dbg(&dev->dev, "mbox3_boot: new boot length = %d\n",
le16_to_cpu(get_cfg_desc(config)->wTotalLength));
mbox3_setup_48_24_magic(dev);
dev_info(&dev->dev, "Digidesign Mbox 3: 24bit 48kHz");
return 0; /* Successful boot */
+}
#define MICROBOOK_BUF_SIZE 128
@@ -1324,6 +1631,10 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev, case USB_ID(0x0dba, 0x3000): /* Digidesign Mbox 2 */ return snd_usb_mbox2_boot_quirk(dev);
case USB_ID(0x0dba, 0x5000):
/* Digidesign Mbox 3 */
return snd_usb_mbox3_boot_quirk(dev);
case USB_ID(0x1235, 0x0010): /* Focusrite Novation Saffire 6 USB */ case USB_ID(0x1235, 0x0018): /* Focusrite Novation Twitch */
-- 2.37.2
From: Conner Knox connerknoxpublic@gmail.com
Add support for Avid Mbox3 USB audio interface at 48kHz
Signed-off-by: Conner Knox connerknoxpublic@gmail.com --- :Added some sane defaults for Stereo to work correctly. :Added comments to specify the complete interface api. :Cleaned up coding style
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index f93201a83..06dfdd45c 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -2985,6 +2985,82 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, +/* DIGIDESIGN MBOX 3 */ +{ + USB_DEVICE(0x0dba, 0x5000), + .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + .vendor_name = "Digidesign", + .product_name = "Mbox 3", + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_COMPOSITE, + .data = (const struct snd_usb_audio_quirk[]) { + { + .ifnum = 0, + .type = QUIRK_IGNORE_INTERFACE + }, + { + .ifnum = 1, + .type = QUIRK_IGNORE_INTERFACE + }, + { + .ifnum = 2, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .channels = 4, + .iface = 2, + .altsetting = 1, + .altset_idx = 1, + .attributes = 0x00, + .endpoint = 0x01, + .ep_attr = USB_ENDPOINT_XFER_ISOC | + USB_ENDPOINT_SYNC_ASYNC, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .nr_rates = 1, + .rate_table = (unsigned int[]) { + 48000 + } + } + }, + { + .ifnum = 3, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .channels = 4, + .iface = 3, + .altsetting = 1, + .altset_idx = 1, + .endpoint = 0x81, + .attributes = 0x00, + .ep_attr = USB_ENDPOINT_XFER_ISOC | + USB_ENDPOINT_SYNC_ASYNC, + .maxpacksize = 0x009c, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .nr_rates = 1, + .rate_table = (unsigned int[]) { + 48000 + } + } + }, + { + .ifnum = 4, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = &(const struct snd_usb_midi_endpoint_info) { + .out_cables = 0x0001, + .in_cables = 0x0001 + } + }, + { + .ifnum = -1 + } + } + } +}, { /* Tascam US122 MKII - playback-only support */ USB_DEVICE_VENDOR_SPEC(0x0644, 0x8021), diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 968d90cae..1d818ee64 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1020,6 +1020,304 @@ static int snd_usb_axefx3_boot_quirk(struct usb_device *dev) return 0; }
+static void mbox3_setup_48_24_magic(struct usb_device *dev) +{ + /* The Mbox 3 is "little endian" */ + /* max volume is: 0x0000. */ + /* min volume is: 0x0080 (shown in little endian form) */ + + + /* Load 48000Hz rate into buffer */ + u8 com_buff[4] = {0x80, 0xbb, 0x00, 0x00}; + + /* Set 48000Hz sample rate */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 0x01, 0x21, 0x0100, 0x0001, &com_buff, 4); //Is this really needed? + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 0x01, 0x21, 0x0100, 0x8101, &com_buff, 4); + + /* Deactivate Tuner */ + /* on = 0x01*/ + /* off = 0x00*/ + com_buff[0] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 0x01, 0x21, 0x0003, 0x2001, &com_buff, 1); + + /* Set clock source to Internal (as opposed to S/PDIF) */ + com_buff[0] = 0x01; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0100, 0x8001, &com_buff, 1); + + /* Mute the hardware loopbacks to start the device in a known state. */ + com_buff[0] = 0x00; + com_buff[1] = 0x80; + /* Analogue input 1 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0110, 0x4001, &com_buff, 2); + /* Analogue input 1 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0111, 0x4001, &com_buff, 2); + /* Analogue input 2 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0114, 0x4001, &com_buff, 2); + /* Analogue input 2 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0115, 0x4001, &com_buff, 2); + /* Analogue input 3 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0118, 0x4001, &com_buff, 2); + /* Analogue input 3 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0119, 0x4001, &com_buff, 2); + /* Analogue input 4 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x011c, 0x4001, &com_buff, 2); + /* Analogue input 4 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x011d, 0x4001, &com_buff, 2); + + /* Set software sends to output */ + com_buff[0] = 0x00; + com_buff[1] = 0x00; + /* Analogue software return 1 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0100, 0x4001, &com_buff, 2); + com_buff[0] = 0x00; + com_buff[1] = 0x80; + /* Analogue software return 1 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0101, 0x4001, &com_buff, 2); + com_buff[0] = 0x00; + com_buff[1] = 0x80; + /* Analogue software return 2 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0104, 0x4001, &com_buff, 2); + com_buff[0] = 0x00; + com_buff[1] = 0x00; + /* Analogue software return 2 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0105, 0x4001, &com_buff, 2); + + com_buff[0] = 0x00; + com_buff[1] = 0x80; + /* Analogue software return 3 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0108, 0x4001, &com_buff, 2); + /* Analogue software return 3 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0109, 0x4001, &com_buff, 2); + /* Analogue software return 4 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x010c, 0x4001, &com_buff, 2); + /* Analogue software return 4 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x010d, 0x4001, &com_buff, 2); + + /* Return to muting sends */ + com_buff[0] = 0x00; + com_buff[1] = 0x80; + /* Analogue fx return left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0120, 0x4001, &com_buff, 2); + /* Analogue fx return right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0121, 0x4001, &com_buff, 2); + + /* Analogue software input 1 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0100, 0x4201, &com_buff, 2); + /* Analogue software input 2 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0101, 0x4201, &com_buff, 2); + /* Analogue software input 3 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0102, 0x4201, &com_buff, 2); + /* Analogue software input 4 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0103, 0x4201, &com_buff, 2); + /* Analogue input 1 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0104, 0x4201, &com_buff, 2); + /* Analogue input 2 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0105, 0x4201, &com_buff, 2); + /* Analogue input 3 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0106, 0x4201, &com_buff, 2); + /* Analogue input 4 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0107, 0x4201, &com_buff, 2); + + /* Toggle allowing host control */ + com_buff[0] = 0x02; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 3, 0x21, 0x0000, 0x2001, &com_buff, 1); + + /* Do not dim fx returns */ + com_buff[0] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 3, 0x21, 0x0002, 0x2001, &com_buff, 1); + + /* Do not set fx returns to mono */ + com_buff[0] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 3, 0x21, 0x0001, 0x2001, &com_buff, 1); + + /* Mute the S/PDIF hardware loopback + * same odd volume logic here as above + */ + com_buff[0] = 0x00; + com_buff[1] = 0x80; + /* S/PDIF hardware input 1 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0112, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 1 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0113, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 2 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0116, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 2 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0117, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 3 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x011a, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 3 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x011b, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 4 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x011e, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 4 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x011f, 0x4001, &com_buff, 2); + /* S/PDIF software return 1 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0102, 0x4001, &com_buff, 2); + /* S/PDIF software return 1 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0103, 0x4001, &com_buff, 2); + /* S/PDIF software return 2 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0106, 0x4001, &com_buff, 2); + /* S/PDIF software return 2 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0107, 0x4001, &com_buff, 2); + + com_buff[0] = 0x00; + com_buff[1] = 0x00; + /* S/PDIF software return 3 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x010a, 0x4001, &com_buff, 2); + + com_buff[0] = 0x00; + com_buff[1] = 0x80; + /* S/PDIF software return 3 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x010b, 0x4001, &com_buff, 2); + /* S/PDIF software return 4 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x010e, 0x4001, &com_buff, 2); + + com_buff[0] = 0x00; + com_buff[1] = 0x00; + /* S/PDIF software return 4 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x010f, 0x4001, &com_buff, 2); + + com_buff[0] = 0x00; + com_buff[1] = 0x80; + /* S/PDIF fx returns left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0122, 0x4001, &com_buff, 2); + /* S/PDIF fx returns right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0123, 0x4001, &com_buff, 2); + + /* Set the dropdown "Effect" to the first option */ + /* Room1 = 0x00 */ + /* Room2 = 0x01 */ + /* Room3 = 0x02 */ + /* Hall 1 = 0x03 */ + /* Hall 2 = 0x04 */ + /* Plate = 0x05 */ + /* Delay = 0x06 */ + /* Echo = 0x07 */ + com_buff[0] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0200, 0x4301, &com_buff, 1); /* max is 0xff */ + /* min is 0x00 */ + + + /* Set the effect duration to 0 */ + /* max is 0xffff */ + /* min is 0x0000 */ + com_buff[0] = 0x00; + com_buff[1] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0400, 0x4301, &com_buff, 2); + + /* Set the effect volume and feedback to 0 */ + /* max is 0xff */ + /* min is 0x00 */ + com_buff[0] = 0x00; + /* feedback: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0500, 0x4301, &com_buff, 1); + /* volume: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0300, 0x4301, &com_buff, 1); + + /* Set soft button hold duration */ + /* 0x03 = 250ms */ + /* 0x05 = 500ms DEFAULT */ + /* 0x08 = 750ms */ + /* 0x0a = 1sec */ + com_buff[0] = 0x05; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 3, 0x21, 0x0005, 0x2001, &com_buff, 1); + + /* Use dim LEDs for button of state */ + com_buff[0] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 3, 0x21, 0x0004, 0x2001, &com_buff, 1); +} + +#define MBOX3_DESCRIPTOR_SIZE 464 + +static int snd_usb_mbox3_boot_quirk(struct usb_device *dev) +{ + struct usb_host_config *config = dev->actconfig; + int err; + int descriptor_size; + + descriptor_size = le16_to_cpu(get_cfg_desc(config)->wTotalLength); + + if (descriptor_size != MBOX3_DESCRIPTOR_SIZE) { + dev_err(&dev->dev, "Invalid descriptor size=%d.\n", descriptor_size); + return -ENODEV; + } + + dev_dbg(&dev->dev, "device initialised!\n"); + + err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, + &dev->descriptor, sizeof(dev->descriptor)); + config = dev->actconfig; + if (err < 0) + dev_dbg(&dev->dev, "error usb_get_descriptor: %d\n", err); + + err = usb_reset_configuration(dev); + if (err < 0) + dev_dbg(&dev->dev, "error usb_reset_configuration: %d\n", err); + dev_dbg(&dev->dev, "mbox3_boot: new boot length = %d\n", + le16_to_cpu(get_cfg_desc(config)->wTotalLength)); + + mbox3_setup_48_24_magic(dev); + dev_info(&dev->dev, "Digidesign Mbox 3: 24bit 48kHz"); + + return 0; /* Successful boot */ +}
#define MICROBOOK_BUF_SIZE 128
@@ -1324,6 +1622,10 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev, case USB_ID(0x0dba, 0x3000): /* Digidesign Mbox 2 */ return snd_usb_mbox2_boot_quirk(dev); + case USB_ID(0x0dba, 0x5000): + /* Digidesign Mbox 3 */ + return snd_usb_mbox3_boot_quirk(dev); +
case USB_ID(0x1235, 0x0010): /* Focusrite Novation Saffire 6 USB */ case USB_ID(0x1235, 0x0018): /* Focusrite Novation Twitch */
On Thu, 18 Aug 2022 22:14:33 +0200, mbarriolinares wrote:
From: Conner Knox connerknoxpublic@gmail.com
Add support for Avid Mbox3 USB audio interface at 48kHz
Signed-off-by: Conner Knox connerknoxpublic@gmail.com
:Added some sane defaults for Stereo to work correctly. :Added comments to specify the complete interface api. :Cleaned up coding style
Thanks, applied now to for-next branch.
Takashi
participants (4)
-
connerknoxpublic@gmail.com
-
Manu
-
mbarriolinares
-
Takashi Iwai