From 871480933a1c28f8a9fed4c4d34d06c439a7a422 Mon Sep 17 00:00:00 2001 From: Srikant Patnaik Date: Sun, 11 Jan 2015 12:28:04 +0530 Subject: Moved, renamed, and deleted files The original directory structure was scattered and unorganized. Changes are basically to make it look like kernel structure. --- ANDROID_3.4.5/sound/usb/6fire/Makefile | 3 - ANDROID_3.4.5/sound/usb/6fire/chip.c | 220 -- ANDROID_3.4.5/sound/usb/6fire/chip.h | 31 - ANDROID_3.4.5/sound/usb/6fire/comm.c | 175 -- ANDROID_3.4.5/sound/usb/6fire/comm.h | 43 - ANDROID_3.4.5/sound/usb/6fire/common.h | 29 - ANDROID_3.4.5/sound/usb/6fire/control.c | 631 ------ ANDROID_3.4.5/sound/usb/6fire/control.h | 57 - ANDROID_3.4.5/sound/usb/6fire/firmware.c | 418 ---- ANDROID_3.4.5/sound/usb/6fire/firmware.h | 27 - ANDROID_3.4.5/sound/usb/6fire/midi.c | 202 -- ANDROID_3.4.5/sound/usb/6fire/midi.h | 45 - ANDROID_3.4.5/sound/usb/6fire/pcm.c | 666 ------ ANDROID_3.4.5/sound/usb/6fire/pcm.h | 75 - ANDROID_3.4.5/sound/usb/Kconfig | 119 - ANDROID_3.4.5/sound/usb/Makefile | 26 - ANDROID_3.4.5/sound/usb/caiaq/Makefile | 4 - ANDROID_3.4.5/sound/usb/caiaq/audio.c | 889 -------- ANDROID_3.4.5/sound/usb/caiaq/audio.h | 7 - ANDROID_3.4.5/sound/usb/caiaq/control.c | 559 ----- ANDROID_3.4.5/sound/usb/caiaq/control.h | 6 - ANDROID_3.4.5/sound/usb/caiaq/device.c | 542 ----- ANDROID_3.4.5/sound/usb/caiaq/device.h | 140 -- ANDROID_3.4.5/sound/usb/caiaq/input.c | 842 ------- ANDROID_3.4.5/sound/usb/caiaq/input.h | 8 - ANDROID_3.4.5/sound/usb/caiaq/midi.c | 174 -- ANDROID_3.4.5/sound/usb/caiaq/midi.h | 8 - ANDROID_3.4.5/sound/usb/card.c | 729 ------ ANDROID_3.4.5/sound/usb/card.h | 111 - ANDROID_3.4.5/sound/usb/clock.c | 318 --- ANDROID_3.4.5/sound/usb/clock.h | 10 - ANDROID_3.4.5/sound/usb/debug.h | 15 - ANDROID_3.4.5/sound/usb/endpoint.c | 966 -------- ANDROID_3.4.5/sound/usb/endpoint.h | 21 - ANDROID_3.4.5/sound/usb/format.c | 515 ----- ANDROID_3.4.5/sound/usb/format.h | 9 - ANDROID_3.4.5/sound/usb/helper.c | 118 - ANDROID_3.4.5/sound/usb/helper.h | 36 - ANDROID_3.4.5/sound/usb/midi.c | 2237 ------------------ ANDROID_3.4.5/sound/usb/midi.h | 50 - ANDROID_3.4.5/sound/usb/misc/Makefile | 2 - ANDROID_3.4.5/sound/usb/misc/ua101.c | 1390 ------------ ANDROID_3.4.5/sound/usb/mixer.c | 2283 ------------------- ANDROID_3.4.5/sound/usb/mixer.h | 71 - ANDROID_3.4.5/sound/usb/mixer_maps.c | 376 --- ANDROID_3.4.5/sound/usb/mixer_quirks.c | 654 ------ ANDROID_3.4.5/sound/usb/mixer_quirks.h | 13 - ANDROID_3.4.5/sound/usb/pcm.c | 911 -------- ANDROID_3.4.5/sound/usb/pcm.h | 14 - ANDROID_3.4.5/sound/usb/power.h | 17 - ANDROID_3.4.5/sound/usb/proc.c | 173 -- ANDROID_3.4.5/sound/usb/proc.h | 8 - ANDROID_3.4.5/sound/usb/quirks-table.h | 2769 ----------------------- ANDROID_3.4.5/sound/usb/quirks.c | 763 ------- ANDROID_3.4.5/sound/usb/quirks.h | 23 - ANDROID_3.4.5/sound/usb/stream.c | 452 ---- ANDROID_3.4.5/sound/usb/stream.h | 12 - ANDROID_3.4.5/sound/usb/usbaudio.h | 105 - ANDROID_3.4.5/sound/usb/usx2y/Makefile | 5 - ANDROID_3.4.5/sound/usb/usx2y/us122l.c | 775 ------- ANDROID_3.4.5/sound/usb/usx2y/us122l.h | 31 - ANDROID_3.4.5/sound/usb/usx2y/usX2Yhwdep.c | 265 --- ANDROID_3.4.5/sound/usb/usx2y/usX2Yhwdep.h | 6 - ANDROID_3.4.5/sound/usb/usx2y/usb_stream.c | 754 ------ ANDROID_3.4.5/sound/usb/usx2y/usb_stream.h | 112 - ANDROID_3.4.5/sound/usb/usx2y/usbus428ctldefs.h | 104 - ANDROID_3.4.5/sound/usb/usx2y/usbusx2y.c | 462 ---- ANDROID_3.4.5/sound/usb/usx2y/usbusx2y.h | 88 - ANDROID_3.4.5/sound/usb/usx2y/usbusx2yaudio.c | 1028 --------- ANDROID_3.4.5/sound/usb/usx2y/usx2y.h | 51 - ANDROID_3.4.5/sound/usb/usx2y/usx2yhwdeppcm.c | 794 ------- ANDROID_3.4.5/sound/usb/usx2y/usx2yhwdeppcm.h | 22 - 72 files changed, 25614 deletions(-) delete mode 100644 ANDROID_3.4.5/sound/usb/6fire/Makefile delete mode 100644 ANDROID_3.4.5/sound/usb/6fire/chip.c delete mode 100644 ANDROID_3.4.5/sound/usb/6fire/chip.h delete mode 100644 ANDROID_3.4.5/sound/usb/6fire/comm.c delete mode 100644 ANDROID_3.4.5/sound/usb/6fire/comm.h delete mode 100644 ANDROID_3.4.5/sound/usb/6fire/common.h delete mode 100644 ANDROID_3.4.5/sound/usb/6fire/control.c delete mode 100644 ANDROID_3.4.5/sound/usb/6fire/control.h delete mode 100644 ANDROID_3.4.5/sound/usb/6fire/firmware.c delete mode 100644 ANDROID_3.4.5/sound/usb/6fire/firmware.h delete mode 100644 ANDROID_3.4.5/sound/usb/6fire/midi.c delete mode 100644 ANDROID_3.4.5/sound/usb/6fire/midi.h delete mode 100644 ANDROID_3.4.5/sound/usb/6fire/pcm.c delete mode 100644 ANDROID_3.4.5/sound/usb/6fire/pcm.h delete mode 100644 ANDROID_3.4.5/sound/usb/Kconfig delete mode 100644 ANDROID_3.4.5/sound/usb/Makefile delete mode 100644 ANDROID_3.4.5/sound/usb/caiaq/Makefile delete mode 100644 ANDROID_3.4.5/sound/usb/caiaq/audio.c delete mode 100644 ANDROID_3.4.5/sound/usb/caiaq/audio.h delete mode 100644 ANDROID_3.4.5/sound/usb/caiaq/control.c delete mode 100644 ANDROID_3.4.5/sound/usb/caiaq/control.h delete mode 100644 ANDROID_3.4.5/sound/usb/caiaq/device.c delete mode 100644 ANDROID_3.4.5/sound/usb/caiaq/device.h delete mode 100644 ANDROID_3.4.5/sound/usb/caiaq/input.c delete mode 100644 ANDROID_3.4.5/sound/usb/caiaq/input.h delete mode 100644 ANDROID_3.4.5/sound/usb/caiaq/midi.c delete mode 100644 ANDROID_3.4.5/sound/usb/caiaq/midi.h delete mode 100644 ANDROID_3.4.5/sound/usb/card.c delete mode 100644 ANDROID_3.4.5/sound/usb/card.h delete mode 100644 ANDROID_3.4.5/sound/usb/clock.c delete mode 100644 ANDROID_3.4.5/sound/usb/clock.h delete mode 100644 ANDROID_3.4.5/sound/usb/debug.h delete mode 100644 ANDROID_3.4.5/sound/usb/endpoint.c delete mode 100644 ANDROID_3.4.5/sound/usb/endpoint.h delete mode 100644 ANDROID_3.4.5/sound/usb/format.c delete mode 100644 ANDROID_3.4.5/sound/usb/format.h delete mode 100644 ANDROID_3.4.5/sound/usb/helper.c delete mode 100644 ANDROID_3.4.5/sound/usb/helper.h delete mode 100644 ANDROID_3.4.5/sound/usb/midi.c delete mode 100644 ANDROID_3.4.5/sound/usb/midi.h delete mode 100644 ANDROID_3.4.5/sound/usb/misc/Makefile delete mode 100644 ANDROID_3.4.5/sound/usb/misc/ua101.c delete mode 100644 ANDROID_3.4.5/sound/usb/mixer.c delete mode 100644 ANDROID_3.4.5/sound/usb/mixer.h delete mode 100644 ANDROID_3.4.5/sound/usb/mixer_maps.c delete mode 100644 ANDROID_3.4.5/sound/usb/mixer_quirks.c delete mode 100644 ANDROID_3.4.5/sound/usb/mixer_quirks.h delete mode 100644 ANDROID_3.4.5/sound/usb/pcm.c delete mode 100644 ANDROID_3.4.5/sound/usb/pcm.h delete mode 100644 ANDROID_3.4.5/sound/usb/power.h delete mode 100644 ANDROID_3.4.5/sound/usb/proc.c delete mode 100644 ANDROID_3.4.5/sound/usb/proc.h delete mode 100644 ANDROID_3.4.5/sound/usb/quirks-table.h delete mode 100644 ANDROID_3.4.5/sound/usb/quirks.c delete mode 100644 ANDROID_3.4.5/sound/usb/quirks.h delete mode 100644 ANDROID_3.4.5/sound/usb/stream.c delete mode 100644 ANDROID_3.4.5/sound/usb/stream.h delete mode 100644 ANDROID_3.4.5/sound/usb/usbaudio.h delete mode 100644 ANDROID_3.4.5/sound/usb/usx2y/Makefile delete mode 100644 ANDROID_3.4.5/sound/usb/usx2y/us122l.c delete mode 100644 ANDROID_3.4.5/sound/usb/usx2y/us122l.h delete mode 100644 ANDROID_3.4.5/sound/usb/usx2y/usX2Yhwdep.c delete mode 100644 ANDROID_3.4.5/sound/usb/usx2y/usX2Yhwdep.h delete mode 100644 ANDROID_3.4.5/sound/usb/usx2y/usb_stream.c delete mode 100644 ANDROID_3.4.5/sound/usb/usx2y/usb_stream.h delete mode 100644 ANDROID_3.4.5/sound/usb/usx2y/usbus428ctldefs.h delete mode 100644 ANDROID_3.4.5/sound/usb/usx2y/usbusx2y.c delete mode 100644 ANDROID_3.4.5/sound/usb/usx2y/usbusx2y.h delete mode 100644 ANDROID_3.4.5/sound/usb/usx2y/usbusx2yaudio.c delete mode 100644 ANDROID_3.4.5/sound/usb/usx2y/usx2y.h delete mode 100644 ANDROID_3.4.5/sound/usb/usx2y/usx2yhwdeppcm.c delete mode 100644 ANDROID_3.4.5/sound/usb/usx2y/usx2yhwdeppcm.h (limited to 'ANDROID_3.4.5/sound/usb') diff --git a/ANDROID_3.4.5/sound/usb/6fire/Makefile b/ANDROID_3.4.5/sound/usb/6fire/Makefile deleted file mode 100644 index dfce6ec5..00000000 --- a/ANDROID_3.4.5/sound/usb/6fire/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -snd-usb-6fire-objs += chip.o comm.o midi.o control.o firmware.o pcm.o -obj-$(CONFIG_SND_USB_6FIRE) += snd-usb-6fire.o - diff --git a/ANDROID_3.4.5/sound/usb/6fire/chip.c b/ANDROID_3.4.5/sound/usb/6fire/chip.c deleted file mode 100644 index fc8cc823..00000000 --- a/ANDROID_3.4.5/sound/usb/6fire/chip.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Linux driver for TerraTec DMX 6Fire USB - * - * Main routines and module definitions. - * - * Author: Torsten Schenk - * Created: Jan 01, 2011 - * Copyright: (C) Torsten Schenk - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include "chip.h" -#include "firmware.h" -#include "pcm.h" -#include "control.h" -#include "comm.h" -#include "midi.h" - -#include -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Torsten Schenk "); -MODULE_DESCRIPTION("TerraTec DMX 6Fire USB audio driver"); -MODULE_LICENSE("GPL v2"); -MODULE_SUPPORTED_DEVICE("{{TerraTec, DMX 6Fire USB}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable card */ -static struct sfire_chip *chips[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; -static struct usb_device *devices[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for the 6fire sound device"); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for the 6fire sound device."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable the 6fire sound device."); - -static DEFINE_MUTEX(register_mutex); - -static void usb6fire_chip_abort(struct sfire_chip *chip) -{ - if (chip) { - if (chip->pcm) - usb6fire_pcm_abort(chip); - if (chip->midi) - usb6fire_midi_abort(chip); - if (chip->comm) - usb6fire_comm_abort(chip); - if (chip->control) - usb6fire_control_abort(chip); - if (chip->card) { - snd_card_disconnect(chip->card); - snd_card_free_when_closed(chip->card); - chip->card = NULL; - } - } -} - -static void usb6fire_chip_destroy(struct sfire_chip *chip) -{ - if (chip) { - if (chip->pcm) - usb6fire_pcm_destroy(chip); - if (chip->midi) - usb6fire_midi_destroy(chip); - if (chip->comm) - usb6fire_comm_destroy(chip); - if (chip->control) - usb6fire_control_destroy(chip); - if (chip->card) - snd_card_free(chip->card); - } -} - -static int __devinit usb6fire_chip_probe(struct usb_interface *intf, - const struct usb_device_id *usb_id) -{ - int ret; - int i; - struct sfire_chip *chip = NULL; - struct usb_device *device = interface_to_usbdev(intf); - int regidx = -1; /* index in module parameter array */ - struct snd_card *card = NULL; - - /* look if we already serve this card and return if so */ - mutex_lock(®ister_mutex); - for (i = 0; i < SNDRV_CARDS; i++) { - if (devices[i] == device) { - if (chips[i]) - chips[i]->intf_count++; - usb_set_intfdata(intf, chips[i]); - mutex_unlock(®ister_mutex); - return 0; - } else if (regidx < 0) - regidx = i; - } - if (regidx < 0) { - mutex_unlock(®ister_mutex); - snd_printk(KERN_ERR PREFIX "too many cards registered.\n"); - return -ENODEV; - } - devices[regidx] = device; - mutex_unlock(®ister_mutex); - - /* check, if firmware is present on device, upload it if not */ - ret = usb6fire_fw_init(intf); - if (ret < 0) - return ret; - else if (ret == FW_NOT_READY) /* firmware update performed */ - return 0; - - /* if we are here, card can be registered in alsa. */ - if (usb_set_interface(device, 0, 0) != 0) { - snd_printk(KERN_ERR PREFIX "can't set first interface.\n"); - return -EIO; - } - ret = snd_card_create(index[regidx], id[regidx], THIS_MODULE, - sizeof(struct sfire_chip), &card); - if (ret < 0) { - snd_printk(KERN_ERR PREFIX "cannot create alsa card.\n"); - return ret; - } - strcpy(card->driver, "6FireUSB"); - strcpy(card->shortname, "TerraTec DMX6FireUSB"); - sprintf(card->longname, "%s at %d:%d", card->shortname, - device->bus->busnum, device->devnum); - snd_card_set_dev(card, &intf->dev); - - chip = card->private_data; - chips[regidx] = chip; - chip->dev = device; - chip->regidx = regidx; - chip->intf_count = 1; - chip->card = card; - - ret = usb6fire_comm_init(chip); - if (ret < 0) { - usb6fire_chip_destroy(chip); - return ret; - } - - ret = usb6fire_midi_init(chip); - if (ret < 0) { - usb6fire_chip_destroy(chip); - return ret; - } - - ret = usb6fire_pcm_init(chip); - if (ret < 0) { - usb6fire_chip_destroy(chip); - return ret; - } - - ret = usb6fire_control_init(chip); - if (ret < 0) { - usb6fire_chip_destroy(chip); - return ret; - } - - ret = snd_card_register(card); - if (ret < 0) { - snd_printk(KERN_ERR PREFIX "cannot register card."); - usb6fire_chip_destroy(chip); - return ret; - } - usb_set_intfdata(intf, chip); - return 0; -} - -static void usb6fire_chip_disconnect(struct usb_interface *intf) -{ - struct sfire_chip *chip; - struct snd_card *card; - - chip = usb_get_intfdata(intf); - if (chip) { /* if !chip, fw upload has been performed */ - card = chip->card; - chip->intf_count--; - if (!chip->intf_count) { - mutex_lock(®ister_mutex); - devices[chip->regidx] = NULL; - chips[chip->regidx] = NULL; - mutex_unlock(®ister_mutex); - - chip->shutdown = true; - usb6fire_chip_abort(chip); - usb6fire_chip_destroy(chip); - } - } -} - -static struct usb_device_id device_table[] = { - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x0ccd, - .idProduct = 0x0080 - }, - {} -}; - -MODULE_DEVICE_TABLE(usb, device_table); - -static struct usb_driver usb_driver = { - .name = "snd-usb-6fire", - .probe = usb6fire_chip_probe, - .disconnect = usb6fire_chip_disconnect, - .id_table = device_table, -}; - -module_usb_driver(usb_driver); diff --git a/ANDROID_3.4.5/sound/usb/6fire/chip.h b/ANDROID_3.4.5/sound/usb/6fire/chip.h deleted file mode 100644 index bde02d10..00000000 --- a/ANDROID_3.4.5/sound/usb/6fire/chip.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Linux driver for TerraTec DMX 6Fire USB - * - * Author: Torsten Schenk - * Created: Jan 01, 2011 - * Copyright: (C) Torsten Schenk - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ -#ifndef USB6FIRE_CHIP_H -#define USB6FIRE_CHIP_H - -#include "common.h" - -struct sfire_chip { - struct usb_device *dev; - struct snd_card *card; - int intf_count; /* number of registered interfaces */ - int regidx; /* index in module parameter arrays */ - bool shutdown; - - struct midi_runtime *midi; - struct pcm_runtime *pcm; - struct control_runtime *control; - struct comm_runtime *comm; -}; -#endif /* USB6FIRE_CHIP_H */ - diff --git a/ANDROID_3.4.5/sound/usb/6fire/comm.c b/ANDROID_3.4.5/sound/usb/6fire/comm.c deleted file mode 100644 index 6c3d531a..00000000 --- a/ANDROID_3.4.5/sound/usb/6fire/comm.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Linux driver for TerraTec DMX 6Fire USB - * - * Device communications - * - * Author: Torsten Schenk - * Created: Jan 01, 2011 - * Copyright: (C) Torsten Schenk - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include "comm.h" -#include "chip.h" -#include "midi.h" - -enum { - COMM_EP = 1, - COMM_FPGA_EP = 2 -}; - -static void usb6fire_comm_init_urb(struct comm_runtime *rt, struct urb *urb, - u8 *buffer, void *context, void(*handler)(struct urb *urb)) -{ - usb_init_urb(urb); - urb->transfer_buffer = buffer; - urb->pipe = usb_sndintpipe(rt->chip->dev, COMM_EP); - urb->complete = handler; - urb->context = context; - urb->interval = 1; - urb->dev = rt->chip->dev; -} - -static void usb6fire_comm_receiver_handler(struct urb *urb) -{ - struct comm_runtime *rt = urb->context; - struct midi_runtime *midi_rt = rt->chip->midi; - - if (!urb->status) { - if (rt->receiver_buffer[0] == 0x10) /* midi in event */ - if (midi_rt) - midi_rt->in_received(midi_rt, - rt->receiver_buffer + 2, - rt->receiver_buffer[1]); - } - - if (!rt->chip->shutdown) { - urb->status = 0; - urb->actual_length = 0; - if (usb_submit_urb(urb, GFP_ATOMIC) < 0) - snd_printk(KERN_WARNING PREFIX - "comm data receiver aborted.\n"); - } -} - -static void usb6fire_comm_init_buffer(u8 *buffer, u8 id, u8 request, - u8 reg, u8 vl, u8 vh) -{ - buffer[0] = 0x01; - buffer[2] = request; - buffer[3] = id; - switch (request) { - case 0x02: - buffer[1] = 0x05; /* length (starting at buffer[2]) */ - buffer[4] = reg; - buffer[5] = vl; - buffer[6] = vh; - break; - - case 0x12: - buffer[1] = 0x0b; /* length (starting at buffer[2]) */ - buffer[4] = 0x00; - buffer[5] = 0x18; - buffer[6] = 0x05; - buffer[7] = 0x00; - buffer[8] = 0x01; - buffer[9] = 0x00; - buffer[10] = 0x9e; - buffer[11] = reg; - buffer[12] = vl; - break; - - case 0x20: - case 0x21: - case 0x22: - buffer[1] = 0x04; - buffer[4] = reg; - buffer[5] = vl; - break; - } -} - -static int usb6fire_comm_send_buffer(u8 *buffer, struct usb_device *dev) -{ - int ret; - int actual_len; - - ret = usb_interrupt_msg(dev, usb_sndintpipe(dev, COMM_EP), - buffer, buffer[1] + 2, &actual_len, HZ); - if (ret < 0) - return ret; - else if (actual_len != buffer[1] + 2) - return -EIO; - return 0; -} - -static int usb6fire_comm_write8(struct comm_runtime *rt, u8 request, - u8 reg, u8 value) -{ - u8 buffer[13]; /* 13: maximum length of message */ - - usb6fire_comm_init_buffer(buffer, 0x00, request, reg, value, 0x00); - return usb6fire_comm_send_buffer(buffer, rt->chip->dev); -} - -static int usb6fire_comm_write16(struct comm_runtime *rt, u8 request, - u8 reg, u8 vl, u8 vh) -{ - u8 buffer[13]; /* 13: maximum length of message */ - - usb6fire_comm_init_buffer(buffer, 0x00, request, reg, vl, vh); - return usb6fire_comm_send_buffer(buffer, rt->chip->dev); -} - -int __devinit usb6fire_comm_init(struct sfire_chip *chip) -{ - struct comm_runtime *rt = kzalloc(sizeof(struct comm_runtime), - GFP_KERNEL); - struct urb *urb = &rt->receiver; - int ret; - - if (!rt) - return -ENOMEM; - - rt->serial = 1; - rt->chip = chip; - usb_init_urb(urb); - rt->init_urb = usb6fire_comm_init_urb; - rt->write8 = usb6fire_comm_write8; - rt->write16 = usb6fire_comm_write16; - - /* submit an urb that receives communication data from device */ - urb->transfer_buffer = rt->receiver_buffer; - urb->transfer_buffer_length = COMM_RECEIVER_BUFSIZE; - urb->pipe = usb_rcvintpipe(chip->dev, COMM_EP); - urb->dev = chip->dev; - urb->complete = usb6fire_comm_receiver_handler; - urb->context = rt; - urb->interval = 1; - ret = usb_submit_urb(urb, GFP_KERNEL); - if (ret < 0) { - kfree(rt); - snd_printk(KERN_ERR PREFIX "cannot create comm data receiver."); - return ret; - } - chip->comm = rt; - return 0; -} - -void usb6fire_comm_abort(struct sfire_chip *chip) -{ - struct comm_runtime *rt = chip->comm; - - if (rt) - usb_poison_urb(&rt->receiver); -} - -void usb6fire_comm_destroy(struct sfire_chip *chip) -{ - kfree(chip->comm); - chip->comm = NULL; -} diff --git a/ANDROID_3.4.5/sound/usb/6fire/comm.h b/ANDROID_3.4.5/sound/usb/6fire/comm.h deleted file mode 100644 index d2af0a5d..00000000 --- a/ANDROID_3.4.5/sound/usb/6fire/comm.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Linux driver for TerraTec DMX 6Fire USB - * - * Author: Torsten Schenk - * Created: Jan 01, 2011 - * Copyright: (C) Torsten Schenk - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ -#ifndef USB6FIRE_COMM_H -#define USB6FIRE_COMM_H - -#include "common.h" - -enum /* settings for comm */ -{ - COMM_RECEIVER_BUFSIZE = 64, -}; - -struct comm_runtime { - struct sfire_chip *chip; - - struct urb receiver; - u8 receiver_buffer[COMM_RECEIVER_BUFSIZE]; - - u8 serial; /* urb serial */ - - void (*init_urb)(struct comm_runtime *rt, struct urb *urb, u8 *buffer, - void *context, void(*handler)(struct urb *urb)); - /* writes control data to the device */ - int (*write8)(struct comm_runtime *rt, u8 request, u8 reg, u8 value); - int (*write16)(struct comm_runtime *rt, u8 request, u8 reg, - u8 vh, u8 vl); -}; - -int __devinit usb6fire_comm_init(struct sfire_chip *chip); -void usb6fire_comm_abort(struct sfire_chip *chip); -void usb6fire_comm_destroy(struct sfire_chip *chip); -#endif /* USB6FIRE_COMM_H */ - diff --git a/ANDROID_3.4.5/sound/usb/6fire/common.h b/ANDROID_3.4.5/sound/usb/6fire/common.h deleted file mode 100644 index b6eb03ed..00000000 --- a/ANDROID_3.4.5/sound/usb/6fire/common.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Linux driver for TerraTec DMX 6Fire USB - * - * Author: Torsten Schenk - * Created: Jan 01, 2011 - * Copyright: (C) Torsten Schenk - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#ifndef USB6FIRE_COMMON_H -#define USB6FIRE_COMMON_H - -#include -#include -#include - -#define PREFIX "6fire: " - -struct sfire_chip; -struct midi_runtime; -struct pcm_runtime; -struct control_runtime; -struct comm_runtime; -#endif /* USB6FIRE_COMMON_H */ - diff --git a/ANDROID_3.4.5/sound/usb/6fire/control.c b/ANDROID_3.4.5/sound/usb/6fire/control.c deleted file mode 100644 index 07ed914d..00000000 --- a/ANDROID_3.4.5/sound/usb/6fire/control.c +++ /dev/null @@ -1,631 +0,0 @@ -/* - * Linux driver for TerraTec DMX 6Fire USB - * - * Mixer control - * - * Author: Torsten Schenk - * Created: Jan 01, 2011 - * Copyright: (C) Torsten Schenk - * - * Thanks to: - * - Holger Ruckdeschel: he found out how to control individual channel - * volumes and introduced mute switch - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include -#include -#include - -#include "control.h" -#include "comm.h" -#include "chip.h" - -static char *opt_coax_texts[2] = { "Optical", "Coax" }; -static char *line_phono_texts[2] = { "Line", "Phono" }; - -/* - * data that needs to be sent to device. sets up card internal stuff. - * values dumped from windows driver and filtered by trial'n'error. - */ -static const struct { - u8 type; - u8 reg; - u8 value; -} -init_data[] = { - { 0x22, 0x00, 0x00 }, { 0x20, 0x00, 0x08 }, { 0x22, 0x01, 0x01 }, - { 0x20, 0x01, 0x08 }, { 0x22, 0x02, 0x00 }, { 0x20, 0x02, 0x08 }, - { 0x22, 0x03, 0x00 }, { 0x20, 0x03, 0x08 }, { 0x22, 0x04, 0x00 }, - { 0x20, 0x04, 0x08 }, { 0x22, 0x05, 0x01 }, { 0x20, 0x05, 0x08 }, - { 0x22, 0x04, 0x01 }, { 0x12, 0x04, 0x00 }, { 0x12, 0x05, 0x00 }, - { 0x12, 0x0d, 0x38 }, { 0x12, 0x21, 0x82 }, { 0x12, 0x22, 0x80 }, - { 0x12, 0x23, 0x00 }, { 0x12, 0x06, 0x02 }, { 0x12, 0x03, 0x00 }, - { 0x12, 0x02, 0x00 }, { 0x22, 0x03, 0x01 }, - { 0 } /* TERMINATING ENTRY */ -}; - -static const int rates_altsetting[] = { 1, 1, 2, 2, 3, 3 }; -/* values to write to soundcard register for all samplerates */ -static const u16 rates_6fire_vl[] = {0x00, 0x01, 0x00, 0x01, 0x00, 0x01}; -static const u16 rates_6fire_vh[] = {0x11, 0x11, 0x10, 0x10, 0x00, 0x00}; - -static DECLARE_TLV_DB_MINMAX(tlv_output, -9000, 0); -static DECLARE_TLV_DB_MINMAX(tlv_input, -1500, 1500); - -enum { - DIGITAL_THRU_ONLY_SAMPLERATE = 3 -}; - -static void usb6fire_control_output_vol_update(struct control_runtime *rt) -{ - struct comm_runtime *comm_rt = rt->chip->comm; - int i; - - if (comm_rt) - for (i = 0; i < 6; i++) - if (!(rt->ovol_updated & (1 << i))) { - comm_rt->write8(comm_rt, 0x12, 0x0f + i, - 180 - rt->output_vol[i]); - rt->ovol_updated |= 1 << i; - } -} - -static void usb6fire_control_output_mute_update(struct control_runtime *rt) -{ - struct comm_runtime *comm_rt = rt->chip->comm; - - if (comm_rt) - comm_rt->write8(comm_rt, 0x12, 0x0e, ~rt->output_mute); -} - -static void usb6fire_control_input_vol_update(struct control_runtime *rt) -{ - struct comm_runtime *comm_rt = rt->chip->comm; - int i; - - if (comm_rt) - for (i = 0; i < 2; i++) - if (!(rt->ivol_updated & (1 << i))) { - comm_rt->write8(comm_rt, 0x12, 0x1c + i, - rt->input_vol[i] & 0x3f); - rt->ivol_updated |= 1 << i; - } -} - -static void usb6fire_control_line_phono_update(struct control_runtime *rt) -{ - struct comm_runtime *comm_rt = rt->chip->comm; - if (comm_rt) { - comm_rt->write8(comm_rt, 0x22, 0x02, rt->line_phono_switch); - comm_rt->write8(comm_rt, 0x21, 0x02, rt->line_phono_switch); - } -} - -static void usb6fire_control_opt_coax_update(struct control_runtime *rt) -{ - struct comm_runtime *comm_rt = rt->chip->comm; - if (comm_rt) { - comm_rt->write8(comm_rt, 0x22, 0x00, rt->opt_coax_switch); - comm_rt->write8(comm_rt, 0x21, 0x00, rt->opt_coax_switch); - } -} - -static int usb6fire_control_set_rate(struct control_runtime *rt, int rate) -{ - int ret; - struct usb_device *device = rt->chip->dev; - struct comm_runtime *comm_rt = rt->chip->comm; - - if (rate < 0 || rate >= CONTROL_N_RATES) - return -EINVAL; - - ret = usb_set_interface(device, 1, rates_altsetting[rate]); - if (ret < 0) - return ret; - - /* set soundcard clock */ - ret = comm_rt->write16(comm_rt, 0x02, 0x01, rates_6fire_vl[rate], - rates_6fire_vh[rate]); - if (ret < 0) - return ret; - - return 0; -} - -static int usb6fire_control_set_channels( - struct control_runtime *rt, int n_analog_out, - int n_analog_in, bool spdif_out, bool spdif_in) -{ - int ret; - struct comm_runtime *comm_rt = rt->chip->comm; - - /* enable analog inputs and outputs - * (one bit per stereo-channel) */ - ret = comm_rt->write16(comm_rt, 0x02, 0x02, - (1 << (n_analog_out / 2)) - 1, - (1 << (n_analog_in / 2)) - 1); - if (ret < 0) - return ret; - - /* disable digital inputs and outputs */ - /* TODO: use spdif_x to enable/disable digital channels */ - ret = comm_rt->write16(comm_rt, 0x02, 0x03, 0x00, 0x00); - if (ret < 0) - return ret; - - return 0; -} - -static int usb6fire_control_streaming_update(struct control_runtime *rt) -{ - struct comm_runtime *comm_rt = rt->chip->comm; - - if (comm_rt) { - if (!rt->usb_streaming && rt->digital_thru_switch) - usb6fire_control_set_rate(rt, - DIGITAL_THRU_ONLY_SAMPLERATE); - return comm_rt->write16(comm_rt, 0x02, 0x00, 0x00, - (rt->usb_streaming ? 0x01 : 0x00) | - (rt->digital_thru_switch ? 0x08 : 0x00)); - } - return -EINVAL; -} - -static int usb6fire_control_output_vol_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 180; - return 0; -} - -static int usb6fire_control_output_vol_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct control_runtime *rt = snd_kcontrol_chip(kcontrol); - unsigned int ch = kcontrol->private_value; - int changed = 0; - - if (ch > 4) { - snd_printk(KERN_ERR PREFIX "Invalid channel in volume control."); - return -EINVAL; - } - - if (rt->output_vol[ch] != ucontrol->value.integer.value[0]) { - rt->output_vol[ch] = ucontrol->value.integer.value[0]; - rt->ovol_updated &= ~(1 << ch); - changed = 1; - } - if (rt->output_vol[ch + 1] != ucontrol->value.integer.value[1]) { - rt->output_vol[ch + 1] = ucontrol->value.integer.value[1]; - rt->ovol_updated &= ~(2 << ch); - changed = 1; - } - - if (changed) - usb6fire_control_output_vol_update(rt); - - return changed; -} - -static int usb6fire_control_output_vol_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct control_runtime *rt = snd_kcontrol_chip(kcontrol); - unsigned int ch = kcontrol->private_value; - - if (ch > 4) { - snd_printk(KERN_ERR PREFIX "Invalid channel in volume control."); - return -EINVAL; - } - - ucontrol->value.integer.value[0] = rt->output_vol[ch]; - ucontrol->value.integer.value[1] = rt->output_vol[ch + 1]; - return 0; -} - -static int usb6fire_control_output_mute_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct control_runtime *rt = snd_kcontrol_chip(kcontrol); - unsigned int ch = kcontrol->private_value; - u8 old = rt->output_mute; - u8 value = 0; - - if (ch > 4) { - snd_printk(KERN_ERR PREFIX "Invalid channel in volume control."); - return -EINVAL; - } - - rt->output_mute &= ~(3 << ch); - if (ucontrol->value.integer.value[0]) - value |= 1; - if (ucontrol->value.integer.value[1]) - value |= 2; - rt->output_mute |= value << ch; - - if (rt->output_mute != old) - usb6fire_control_output_mute_update(rt); - - return rt->output_mute != old; -} - -static int usb6fire_control_output_mute_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct control_runtime *rt = snd_kcontrol_chip(kcontrol); - unsigned int ch = kcontrol->private_value; - u8 value = rt->output_mute >> ch; - - if (ch > 4) { - snd_printk(KERN_ERR PREFIX "Invalid channel in volume control."); - return -EINVAL; - } - - ucontrol->value.integer.value[0] = 1 & value; - value >>= 1; - ucontrol->value.integer.value[1] = 1 & value; - - return 0; -} - -static int usb6fire_control_input_vol_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 30; - return 0; -} - -static int usb6fire_control_input_vol_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct control_runtime *rt = snd_kcontrol_chip(kcontrol); - int changed = 0; - - if (rt->input_vol[0] != ucontrol->value.integer.value[0]) { - rt->input_vol[0] = ucontrol->value.integer.value[0] - 15; - rt->ivol_updated &= ~(1 << 0); - changed = 1; - } - if (rt->input_vol[1] != ucontrol->value.integer.value[1]) { - rt->input_vol[1] = ucontrol->value.integer.value[1] - 15; - rt->ivol_updated &= ~(1 << 1); - changed = 1; - } - - if (changed) - usb6fire_control_input_vol_update(rt); - - return changed; -} - -static int usb6fire_control_input_vol_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct control_runtime *rt = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = rt->input_vol[0] + 15; - ucontrol->value.integer.value[1] = rt->input_vol[1] + 15; - - return 0; -} - -static int usb6fire_control_line_phono_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - if (uinfo->value.enumerated.item > 1) - uinfo->value.enumerated.item = 1; - strcpy(uinfo->value.enumerated.name, - line_phono_texts[uinfo->value.enumerated.item]); - return 0; -} - -static int usb6fire_control_line_phono_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct control_runtime *rt = snd_kcontrol_chip(kcontrol); - int changed = 0; - if (rt->line_phono_switch != ucontrol->value.integer.value[0]) { - rt->line_phono_switch = ucontrol->value.integer.value[0]; - usb6fire_control_line_phono_update(rt); - changed = 1; - } - return changed; -} - -static int usb6fire_control_line_phono_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct control_runtime *rt = snd_kcontrol_chip(kcontrol); - ucontrol->value.integer.value[0] = rt->line_phono_switch; - return 0; -} - -static int usb6fire_control_opt_coax_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - if (uinfo->value.enumerated.item > 1) - uinfo->value.enumerated.item = 1; - strcpy(uinfo->value.enumerated.name, - opt_coax_texts[uinfo->value.enumerated.item]); - return 0; -} - -static int usb6fire_control_opt_coax_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct control_runtime *rt = snd_kcontrol_chip(kcontrol); - int changed = 0; - - if (rt->opt_coax_switch != ucontrol->value.enumerated.item[0]) { - rt->opt_coax_switch = ucontrol->value.enumerated.item[0]; - usb6fire_control_opt_coax_update(rt); - changed = 1; - } - return changed; -} - -static int usb6fire_control_opt_coax_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct control_runtime *rt = snd_kcontrol_chip(kcontrol); - ucontrol->value.enumerated.item[0] = rt->opt_coax_switch; - return 0; -} - -static int usb6fire_control_digital_thru_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct control_runtime *rt = snd_kcontrol_chip(kcontrol); - int changed = 0; - - if (rt->digital_thru_switch != ucontrol->value.integer.value[0]) { - rt->digital_thru_switch = ucontrol->value.integer.value[0]; - usb6fire_control_streaming_update(rt); - changed = 1; - } - return changed; -} - -static int usb6fire_control_digital_thru_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct control_runtime *rt = snd_kcontrol_chip(kcontrol); - ucontrol->value.integer.value[0] = rt->digital_thru_switch; - return 0; -} - -static struct __devinitdata snd_kcontrol_new vol_elements[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Playback Volume", - .index = 0, - .private_value = 0, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .info = usb6fire_control_output_vol_info, - .get = usb6fire_control_output_vol_get, - .put = usb6fire_control_output_vol_put, - .tlv = { .p = tlv_output } - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Playback Volume", - .index = 1, - .private_value = 2, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .info = usb6fire_control_output_vol_info, - .get = usb6fire_control_output_vol_get, - .put = usb6fire_control_output_vol_put, - .tlv = { .p = tlv_output } - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Playback Volume", - .index = 2, - .private_value = 4, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .info = usb6fire_control_output_vol_info, - .get = usb6fire_control_output_vol_get, - .put = usb6fire_control_output_vol_put, - .tlv = { .p = tlv_output } - }, - {} -}; - -static struct __devinitdata snd_kcontrol_new mute_elements[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Playback Switch", - .index = 0, - .private_value = 0, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .info = snd_ctl_boolean_stereo_info, - .get = usb6fire_control_output_mute_get, - .put = usb6fire_control_output_mute_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Playback Switch", - .index = 1, - .private_value = 2, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .info = snd_ctl_boolean_stereo_info, - .get = usb6fire_control_output_mute_get, - .put = usb6fire_control_output_mute_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Playback Switch", - .index = 2, - .private_value = 4, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .info = snd_ctl_boolean_stereo_info, - .get = usb6fire_control_output_mute_get, - .put = usb6fire_control_output_mute_put, - }, - {} -}; - -static struct __devinitdata snd_kcontrol_new elements[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Line/Phono Capture Route", - .index = 0, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .info = usb6fire_control_line_phono_info, - .get = usb6fire_control_line_phono_get, - .put = usb6fire_control_line_phono_put - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Opt/Coax Capture Route", - .index = 0, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .info = usb6fire_control_opt_coax_info, - .get = usb6fire_control_opt_coax_get, - .put = usb6fire_control_opt_coax_put - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Digital Thru Playback Route", - .index = 0, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .info = snd_ctl_boolean_mono_info, - .get = usb6fire_control_digital_thru_get, - .put = usb6fire_control_digital_thru_put - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Capture Volume", - .index = 0, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .info = usb6fire_control_input_vol_info, - .get = usb6fire_control_input_vol_get, - .put = usb6fire_control_input_vol_put, - .tlv = { .p = tlv_input } - }, - {} -}; - -static int usb6fire_control_add_virtual( - struct control_runtime *rt, - struct snd_card *card, - char *name, - struct snd_kcontrol_new *elems) -{ - int ret; - int i; - struct snd_kcontrol *vmaster = - snd_ctl_make_virtual_master(name, tlv_output); - struct snd_kcontrol *control; - - if (!vmaster) - return -ENOMEM; - ret = snd_ctl_add(card, vmaster); - if (ret < 0) - return ret; - - i = 0; - while (elems[i].name) { - control = snd_ctl_new1(&elems[i], rt); - if (!control) - return -ENOMEM; - ret = snd_ctl_add(card, control); - if (ret < 0) - return ret; - ret = snd_ctl_add_slave(vmaster, control); - if (ret < 0) - return ret; - i++; - } - return 0; -} - -int __devinit usb6fire_control_init(struct sfire_chip *chip) -{ - int i; - int ret; - struct control_runtime *rt = kzalloc(sizeof(struct control_runtime), - GFP_KERNEL); - struct comm_runtime *comm_rt = chip->comm; - - if (!rt) - return -ENOMEM; - - rt->chip = chip; - rt->update_streaming = usb6fire_control_streaming_update; - rt->set_rate = usb6fire_control_set_rate; - rt->set_channels = usb6fire_control_set_channels; - - i = 0; - while (init_data[i].type) { - comm_rt->write8(comm_rt, init_data[i].type, init_data[i].reg, - init_data[i].value); - i++; - } - - usb6fire_control_opt_coax_update(rt); - usb6fire_control_line_phono_update(rt); - usb6fire_control_output_vol_update(rt); - usb6fire_control_output_mute_update(rt); - usb6fire_control_input_vol_update(rt); - usb6fire_control_streaming_update(rt); - - ret = usb6fire_control_add_virtual(rt, chip->card, - "Master Playback Volume", vol_elements); - if (ret) { - snd_printk(KERN_ERR PREFIX "cannot add control.\n"); - kfree(rt); - return ret; - } - ret = usb6fire_control_add_virtual(rt, chip->card, - "Master Playback Switch", mute_elements); - if (ret) { - snd_printk(KERN_ERR PREFIX "cannot add control.\n"); - kfree(rt); - return ret; - } - - i = 0; - while (elements[i].name) { - ret = snd_ctl_add(chip->card, snd_ctl_new1(&elements[i], rt)); - if (ret < 0) { - kfree(rt); - snd_printk(KERN_ERR PREFIX "cannot add control.\n"); - return ret; - } - i++; - } - - chip->control = rt; - return 0; -} - -void usb6fire_control_abort(struct sfire_chip *chip) -{} - -void usb6fire_control_destroy(struct sfire_chip *chip) -{ - kfree(chip->control); - chip->control = NULL; -} diff --git a/ANDROID_3.4.5/sound/usb/6fire/control.h b/ANDROID_3.4.5/sound/usb/6fire/control.h deleted file mode 100644 index 9a596d95..00000000 --- a/ANDROID_3.4.5/sound/usb/6fire/control.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Linux driver for TerraTec DMX 6Fire USB - * - * Author: Torsten Schenk - * Created: Jan 01, 2011 - * Copyright: (C) Torsten Schenk - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#ifndef USB6FIRE_CONTROL_H -#define USB6FIRE_CONTROL_H - -#include "common.h" - -enum { - CONTROL_MAX_ELEMENTS = 32 -}; - -enum { - CONTROL_RATE_44KHZ, - CONTROL_RATE_48KHZ, - CONTROL_RATE_88KHZ, - CONTROL_RATE_96KHZ, - CONTROL_RATE_176KHZ, - CONTROL_RATE_192KHZ, - CONTROL_N_RATES -}; - -struct control_runtime { - int (*update_streaming)(struct control_runtime *rt); - int (*set_rate)(struct control_runtime *rt, int rate); - int (*set_channels)(struct control_runtime *rt, int n_analog_out, - int n_analog_in, bool spdif_out, bool spdif_in); - - struct sfire_chip *chip; - - struct snd_kcontrol *element[CONTROL_MAX_ELEMENTS]; - bool opt_coax_switch; - bool line_phono_switch; - bool digital_thru_switch; - bool usb_streaming; - u8 output_vol[6]; - u8 ovol_updated; - u8 output_mute; - s8 input_vol[2]; - u8 ivol_updated; -}; - -int __devinit usb6fire_control_init(struct sfire_chip *chip); -void usb6fire_control_abort(struct sfire_chip *chip); -void usb6fire_control_destroy(struct sfire_chip *chip); -#endif /* USB6FIRE_CONTROL_H */ - diff --git a/ANDROID_3.4.5/sound/usb/6fire/firmware.c b/ANDROID_3.4.5/sound/usb/6fire/firmware.c deleted file mode 100644 index 6f9715ab..00000000 --- a/ANDROID_3.4.5/sound/usb/6fire/firmware.c +++ /dev/null @@ -1,418 +0,0 @@ -/* - * Linux driver for TerraTec DMX 6Fire USB - * - * Firmware loader - * - * Author: Torsten Schenk - * Created: Jan 01, 2011 - * Copyright: (C) Torsten Schenk - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include -#include -#include -#include - -#include "firmware.h" -#include "chip.h" - -MODULE_FIRMWARE("6fire/dmx6firel2.ihx"); -MODULE_FIRMWARE("6fire/dmx6fireap.ihx"); -MODULE_FIRMWARE("6fire/dmx6firecf.bin"); - -enum { - FPGA_BUFSIZE = 512, FPGA_EP = 2 -}; - -/* - * wMaxPacketSize of pcm endpoints. - * keep synced with rates_in_packet_size and rates_out_packet_size in pcm.c - * fpp: frames per isopacket - * - * CAUTION: keep sizeof <= buffer[] in usb6fire_fw_init - */ -static const u8 ep_w_max_packet_size[] = { - 0xe4, 0x00, 0xe4, 0x00, /* alt 1: 228 EP2 and EP6 (7 fpp) */ - 0xa4, 0x01, 0xa4, 0x01, /* alt 2: 420 EP2 and EP6 (13 fpp)*/ - 0x94, 0x01, 0x5c, 0x02 /* alt 3: 404 EP2 and 604 EP6 (25 fpp) */ -}; - -static const u8 known_fw_versions[][4] = { - { 0x03, 0x01, 0x0b, 0x00 } -}; - -struct ihex_record { - u16 address; - u8 len; - u8 data[256]; - char error; /* true if an error occurred parsing this record */ - - u8 max_len; /* maximum record length in whole ihex */ - - /* private */ - const char *txt_data; - unsigned int txt_length; - unsigned int txt_offset; /* current position in txt_data */ -}; - -static u8 usb6fire_fw_ihex_hex(const u8 *data, u8 *crc) -{ - u8 val = 0; - int hval; - - hval = hex_to_bin(data[0]); - if (hval >= 0) - val |= (hval << 4); - - hval = hex_to_bin(data[1]); - if (hval >= 0) - val |= hval; - - *crc += val; - return val; -} - -/* - * returns true if record is available, false otherwise. - * iff an error occurred, false will be returned and record->error will be true. - */ -static bool usb6fire_fw_ihex_next_record(struct ihex_record *record) -{ - u8 crc = 0; - u8 type; - int i; - - record->error = false; - - /* find begin of record (marked by a colon) */ - while (record->txt_offset < record->txt_length - && record->txt_data[record->txt_offset] != ':') - record->txt_offset++; - if (record->txt_offset == record->txt_length) - return false; - - /* number of characters needed for len, addr and type entries */ - record->txt_offset++; - if (record->txt_offset + 8 > record->txt_length) { - record->error = true; - return false; - } - - record->len = usb6fire_fw_ihex_hex(record->txt_data + - record->txt_offset, &crc); - record->txt_offset += 2; - record->address = usb6fire_fw_ihex_hex(record->txt_data + - record->txt_offset, &crc) << 8; - record->txt_offset += 2; - record->address |= usb6fire_fw_ihex_hex(record->txt_data + - record->txt_offset, &crc); - record->txt_offset += 2; - type = usb6fire_fw_ihex_hex(record->txt_data + - record->txt_offset, &crc); - record->txt_offset += 2; - - /* number of characters needed for data and crc entries */ - if (record->txt_offset + 2 * (record->len + 1) > record->txt_length) { - record->error = true; - return false; - } - for (i = 0; i < record->len; i++) { - record->data[i] = usb6fire_fw_ihex_hex(record->txt_data - + record->txt_offset, &crc); - record->txt_offset += 2; - } - usb6fire_fw_ihex_hex(record->txt_data + record->txt_offset, &crc); - if (crc) { - record->error = true; - return false; - } - - if (type == 1 || !record->len) /* eof */ - return false; - else if (type == 0) - return true; - else { - record->error = true; - return false; - } -} - -static int usb6fire_fw_ihex_init(const struct firmware *fw, - struct ihex_record *record) -{ - record->txt_data = fw->data; - record->txt_length = fw->size; - record->txt_offset = 0; - record->max_len = 0; - /* read all records, if loop ends, record->error indicates, - * whether ihex is valid. */ - while (usb6fire_fw_ihex_next_record(record)) - record->max_len = max(record->len, record->max_len); - if (record->error) - return -EINVAL; - record->txt_offset = 0; - return 0; -} - -static int usb6fire_fw_ezusb_write(struct usb_device *device, - int type, int value, char *data, int len) -{ - int ret; - - ret = usb_control_msg(device, usb_sndctrlpipe(device, 0), type, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, 0, data, len, HZ); - if (ret < 0) - return ret; - else if (ret != len) - return -EIO; - return 0; -} - -static int usb6fire_fw_ezusb_read(struct usb_device *device, - int type, int value, char *data, int len) -{ - int ret = usb_control_msg(device, usb_rcvctrlpipe(device, 0), type, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value, - 0, data, len, HZ); - if (ret < 0) - return ret; - else if (ret != len) - return -EIO; - return 0; -} - -static int usb6fire_fw_fpga_write(struct usb_device *device, - char *data, int len) -{ - int actual_len; - int ret; - - ret = usb_bulk_msg(device, usb_sndbulkpipe(device, FPGA_EP), data, len, - &actual_len, HZ); - if (ret < 0) - return ret; - else if (actual_len != len) - return -EIO; - return 0; -} - -static int usb6fire_fw_ezusb_upload( - struct usb_interface *intf, const char *fwname, - unsigned int postaddr, u8 *postdata, unsigned int postlen) -{ - int ret; - u8 data; - struct usb_device *device = interface_to_usbdev(intf); - const struct firmware *fw = 0; - struct ihex_record *rec = kmalloc(sizeof(struct ihex_record), - GFP_KERNEL); - - if (!rec) - return -ENOMEM; - - ret = request_firmware(&fw, fwname, &device->dev); - if (ret < 0) { - kfree(rec); - snd_printk(KERN_ERR PREFIX "error requesting ezusb " - "firmware %s.\n", fwname); - return ret; - } - ret = usb6fire_fw_ihex_init(fw, rec); - if (ret < 0) { - kfree(rec); - release_firmware(fw); - snd_printk(KERN_ERR PREFIX "error validating ezusb " - "firmware %s.\n", fwname); - return ret; - } - /* upload firmware image */ - data = 0x01; /* stop ezusb cpu */ - ret = usb6fire_fw_ezusb_write(device, 0xa0, 0xe600, &data, 1); - if (ret < 0) { - kfree(rec); - release_firmware(fw); - snd_printk(KERN_ERR PREFIX "unable to upload ezusb " - "firmware %s: begin message.\n", fwname); - return ret; - } - - while (usb6fire_fw_ihex_next_record(rec)) { /* write firmware */ - ret = usb6fire_fw_ezusb_write(device, 0xa0, rec->address, - rec->data, rec->len); - if (ret < 0) { - kfree(rec); - release_firmware(fw); - snd_printk(KERN_ERR PREFIX "unable to upload ezusb " - "firmware %s: data urb.\n", fwname); - return ret; - } - } - - release_firmware(fw); - kfree(rec); - if (postdata) { /* write data after firmware has been uploaded */ - ret = usb6fire_fw_ezusb_write(device, 0xa0, postaddr, - postdata, postlen); - if (ret < 0) { - snd_printk(KERN_ERR PREFIX "unable to upload ezusb " - "firmware %s: post urb.\n", fwname); - return ret; - } - } - - data = 0x00; /* resume ezusb cpu */ - ret = usb6fire_fw_ezusb_write(device, 0xa0, 0xe600, &data, 1); - if (ret < 0) { - snd_printk(KERN_ERR PREFIX "unable to upload ezusb " - "firmware %s: end message.\n", fwname); - return ret; - } - return 0; -} - -static int usb6fire_fw_fpga_upload( - struct usb_interface *intf, const char *fwname) -{ - int ret; - int i; - struct usb_device *device = interface_to_usbdev(intf); - u8 *buffer = kmalloc(FPGA_BUFSIZE, GFP_KERNEL); - const char *c; - const char *end; - const struct firmware *fw; - - if (!buffer) - return -ENOMEM; - - ret = request_firmware(&fw, fwname, &device->dev); - if (ret < 0) { - snd_printk(KERN_ERR PREFIX "unable to get fpga firmware %s.\n", - fwname); - kfree(buffer); - return -EIO; - } - - c = fw->data; - end = fw->data + fw->size; - - ret = usb6fire_fw_ezusb_write(device, 8, 0, NULL, 0); - if (ret < 0) { - kfree(buffer); - release_firmware(fw); - snd_printk(KERN_ERR PREFIX "unable to upload fpga firmware: " - "begin urb.\n"); - return ret; - } - - while (c != end) { - for (i = 0; c != end && i < FPGA_BUFSIZE; i++, c++) - buffer[i] = byte_rev_table[(u8) *c]; - - ret = usb6fire_fw_fpga_write(device, buffer, i); - if (ret < 0) { - release_firmware(fw); - kfree(buffer); - snd_printk(KERN_ERR PREFIX "unable to upload fpga " - "firmware: fw urb.\n"); - return ret; - } - } - release_firmware(fw); - kfree(buffer); - - ret = usb6fire_fw_ezusb_write(device, 9, 0, NULL, 0); - if (ret < 0) { - snd_printk(KERN_ERR PREFIX "unable to upload fpga firmware: " - "end urb.\n"); - return ret; - } - return 0; -} - -/* check, if the firmware version the devices has currently loaded - * is known by this driver. 'version' needs to have 4 bytes version - * info data. */ -static int usb6fire_fw_check(u8 *version) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(known_fw_versions); i++) - if (!memcmp(version, known_fw_versions + i, 4)) - return 0; - - snd_printk(KERN_ERR PREFIX "invalid fimware version in device: " - "%02x %02x %02x %02x. " - "please reconnect to power. if this failure " - "still happens, check your firmware installation.", - version[0], version[1], version[2], version[3]); - return -EINVAL; -} - -int usb6fire_fw_init(struct usb_interface *intf) -{ - int i; - int ret; - struct usb_device *device = interface_to_usbdev(intf); - /* buffer: 8 receiving bytes from device and - * sizeof(EP_W_MAX_PACKET_SIZE) bytes for non-const copy */ - u8 buffer[12]; - - ret = usb6fire_fw_ezusb_read(device, 1, 0, buffer, 8); - if (ret < 0) { - snd_printk(KERN_ERR PREFIX "unable to receive device " - "firmware state.\n"); - return ret; - } - if (buffer[0] != 0xeb || buffer[1] != 0xaa || buffer[2] != 0x55) { - snd_printk(KERN_ERR PREFIX "unknown device firmware state " - "received from device: "); - for (i = 0; i < 8; i++) - snd_printk("%02x ", buffer[i]); - snd_printk("\n"); - return -EIO; - } - /* do we need fpga loader ezusb firmware? */ - if (buffer[3] == 0x01) { - ret = usb6fire_fw_ezusb_upload(intf, - "6fire/dmx6firel2.ihx", 0, NULL, 0); - if (ret < 0) - return ret; - return FW_NOT_READY; - } - /* do we need fpga firmware and application ezusb firmware? */ - else if (buffer[3] == 0x02) { - ret = usb6fire_fw_check(buffer + 4); - if (ret < 0) - return ret; - ret = usb6fire_fw_fpga_upload(intf, "6fire/dmx6firecf.bin"); - if (ret < 0) - return ret; - memcpy(buffer, ep_w_max_packet_size, - sizeof(ep_w_max_packet_size)); - ret = usb6fire_fw_ezusb_upload(intf, "6fire/dmx6fireap.ihx", - 0x0003, buffer, sizeof(ep_w_max_packet_size)); - if (ret < 0) - return ret; - return FW_NOT_READY; - } - /* all fw loaded? */ - else if (buffer[3] == 0x03) - return usb6fire_fw_check(buffer + 4); - /* unknown data? */ - else { - snd_printk(KERN_ERR PREFIX "unknown device firmware state " - "received from device: "); - for (i = 0; i < 8; i++) - snd_printk("%02x ", buffer[i]); - snd_printk("\n"); - return -EIO; - } - return 0; -} - diff --git a/ANDROID_3.4.5/sound/usb/6fire/firmware.h b/ANDROID_3.4.5/sound/usb/6fire/firmware.h deleted file mode 100644 index 00856989..00000000 --- a/ANDROID_3.4.5/sound/usb/6fire/firmware.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Linux driver for TerraTec DMX 6Fire USB - * - * Author: Torsten Schenk - * Created: Jan 01, 2011 - * Copyright: (C) Torsten Schenk - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#ifndef USB6FIRE_FIRMWARE_H -#define USB6FIRE_FIRMWARE_H - -#include "common.h" - -enum /* firmware state of device */ -{ - FW_READY = 0, - FW_NOT_READY = 1 -}; - -int __devinit usb6fire_fw_init(struct usb_interface *intf); -#endif /* USB6FIRE_FIRMWARE_H */ - diff --git a/ANDROID_3.4.5/sound/usb/6fire/midi.c b/ANDROID_3.4.5/sound/usb/6fire/midi.c deleted file mode 100644 index f0e5179b..00000000 --- a/ANDROID_3.4.5/sound/usb/6fire/midi.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Linux driver for TerraTec DMX 6Fire USB - * - * Rawmidi driver - * - * Author: Torsten Schenk - * Created: Jan 01, 2011 - * Copyright: (C) Torsten Schenk - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -#include "midi.h" -#include "chip.h" -#include "comm.h" - -static void usb6fire_midi_out_handler(struct urb *urb) -{ - struct midi_runtime *rt = urb->context; - int ret; - unsigned long flags; - - spin_lock_irqsave(&rt->out_lock, flags); - - if (rt->out) { - ret = snd_rawmidi_transmit(rt->out, rt->out_buffer + 4, - MIDI_BUFSIZE - 4); - if (ret > 0) { /* more data available, send next packet */ - rt->out_buffer[1] = ret + 2; - rt->out_buffer[3] = rt->out_serial++; - urb->transfer_buffer_length = ret + 4; - - ret = usb_submit_urb(urb, GFP_ATOMIC); - if (ret < 0) - snd_printk(KERN_ERR PREFIX "midi out urb " - "submit failed: %d\n", ret); - } else /* no more data to transmit */ - rt->out = NULL; - } - spin_unlock_irqrestore(&rt->out_lock, flags); -} - -static void usb6fire_midi_in_received( - struct midi_runtime *rt, u8 *data, int length) -{ - unsigned long flags; - - spin_lock_irqsave(&rt->in_lock, flags); - if (rt->in) - snd_rawmidi_receive(rt->in, data, length); - spin_unlock_irqrestore(&rt->in_lock, flags); -} - -static int usb6fire_midi_out_open(struct snd_rawmidi_substream *alsa_sub) -{ - return 0; -} - -static int usb6fire_midi_out_close(struct snd_rawmidi_substream *alsa_sub) -{ - return 0; -} - -static void usb6fire_midi_out_trigger( - struct snd_rawmidi_substream *alsa_sub, int up) -{ - struct midi_runtime *rt = alsa_sub->rmidi->private_data; - struct urb *urb = &rt->out_urb; - __s8 ret; - unsigned long flags; - - spin_lock_irqsave(&rt->out_lock, flags); - if (up) { /* start transfer */ - if (rt->out) { /* we are already transmitting so just return */ - spin_unlock_irqrestore(&rt->out_lock, flags); - return; - } - - ret = snd_rawmidi_transmit(alsa_sub, rt->out_buffer + 4, - MIDI_BUFSIZE - 4); - if (ret > 0) { - rt->out_buffer[1] = ret + 2; - rt->out_buffer[3] = rt->out_serial++; - urb->transfer_buffer_length = ret + 4; - - ret = usb_submit_urb(urb, GFP_ATOMIC); - if (ret < 0) - snd_printk(KERN_ERR PREFIX "midi out urb " - "submit failed: %d\n", ret); - else - rt->out = alsa_sub; - } - } else if (rt->out == alsa_sub) - rt->out = NULL; - spin_unlock_irqrestore(&rt->out_lock, flags); -} - -static void usb6fire_midi_out_drain(struct snd_rawmidi_substream *alsa_sub) -{ - struct midi_runtime *rt = alsa_sub->rmidi->private_data; - int retry = 0; - - while (rt->out && retry++ < 100) - msleep(10); -} - -static int usb6fire_midi_in_open(struct snd_rawmidi_substream *alsa_sub) -{ - return 0; -} - -static int usb6fire_midi_in_close(struct snd_rawmidi_substream *alsa_sub) -{ - return 0; -} - -static void usb6fire_midi_in_trigger( - struct snd_rawmidi_substream *alsa_sub, int up) -{ - struct midi_runtime *rt = alsa_sub->rmidi->private_data; - unsigned long flags; - - spin_lock_irqsave(&rt->in_lock, flags); - if (up) - rt->in = alsa_sub; - else - rt->in = NULL; - spin_unlock_irqrestore(&rt->in_lock, flags); -} - -static struct snd_rawmidi_ops out_ops = { - .open = usb6fire_midi_out_open, - .close = usb6fire_midi_out_close, - .trigger = usb6fire_midi_out_trigger, - .drain = usb6fire_midi_out_drain -}; - -static struct snd_rawmidi_ops in_ops = { - .open = usb6fire_midi_in_open, - .close = usb6fire_midi_in_close, - .trigger = usb6fire_midi_in_trigger -}; - -int __devinit usb6fire_midi_init(struct sfire_chip *chip) -{ - int ret; - struct midi_runtime *rt = kzalloc(sizeof(struct midi_runtime), - GFP_KERNEL); - struct comm_runtime *comm_rt = chip->comm; - - if (!rt) - return -ENOMEM; - - rt->chip = chip; - rt->in_received = usb6fire_midi_in_received; - rt->out_buffer[0] = 0x80; /* 'send midi' command */ - rt->out_buffer[1] = 0x00; /* size of data */ - rt->out_buffer[2] = 0x00; /* always 0 */ - spin_lock_init(&rt->in_lock); - spin_lock_init(&rt->out_lock); - - comm_rt->init_urb(comm_rt, &rt->out_urb, rt->out_buffer, rt, - usb6fire_midi_out_handler); - - ret = snd_rawmidi_new(chip->card, "6FireUSB", 0, 1, 1, &rt->instance); - if (ret < 0) { - kfree(rt); - snd_printk(KERN_ERR PREFIX "unable to create midi.\n"); - return ret; - } - rt->instance->private_data = rt; - strcpy(rt->instance->name, "DMX6FireUSB MIDI"); - rt->instance->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT | - SNDRV_RAWMIDI_INFO_INPUT | - SNDRV_RAWMIDI_INFO_DUPLEX; - snd_rawmidi_set_ops(rt->instance, SNDRV_RAWMIDI_STREAM_OUTPUT, - &out_ops); - snd_rawmidi_set_ops(rt->instance, SNDRV_RAWMIDI_STREAM_INPUT, - &in_ops); - - chip->midi = rt; - return 0; -} - -void usb6fire_midi_abort(struct sfire_chip *chip) -{ - struct midi_runtime *rt = chip->midi; - - if (rt) - usb_poison_urb(&rt->out_urb); -} - -void usb6fire_midi_destroy(struct sfire_chip *chip) -{ - kfree(chip->midi); - chip->midi = NULL; -} diff --git a/ANDROID_3.4.5/sound/usb/6fire/midi.h b/ANDROID_3.4.5/sound/usb/6fire/midi.h deleted file mode 100644 index 5114eccc..00000000 --- a/ANDROID_3.4.5/sound/usb/6fire/midi.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Linux driver for TerraTec DMX 6Fire USB - * - * Author: Torsten Schenk - * Created: Jan 01, 2011 - * Copyright: (C) Torsten Schenk - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#ifndef USB6FIRE_MIDI_H -#define USB6FIRE_MIDI_H - -#include "common.h" - -enum { - MIDI_BUFSIZE = 64 -}; - -struct midi_runtime { - struct sfire_chip *chip; - struct snd_rawmidi *instance; - - struct snd_rawmidi_substream *in; - char in_active; - - spinlock_t in_lock; - spinlock_t out_lock; - struct snd_rawmidi_substream *out; - struct urb out_urb; - u8 out_serial; /* serial number of out packet */ - u8 out_buffer[MIDI_BUFSIZE]; - int buffer_offset; - - void (*in_received)(struct midi_runtime *rt, u8 *data, int length); -}; - -int __devinit usb6fire_midi_init(struct sfire_chip *chip); -void usb6fire_midi_abort(struct sfire_chip *chip); -void usb6fire_midi_destroy(struct sfire_chip *chip); -#endif /* USB6FIRE_MIDI_H */ - diff --git a/ANDROID_3.4.5/sound/usb/6fire/pcm.c b/ANDROID_3.4.5/sound/usb/6fire/pcm.c deleted file mode 100644 index c97d05f0..00000000 --- a/ANDROID_3.4.5/sound/usb/6fire/pcm.c +++ /dev/null @@ -1,666 +0,0 @@ -/* - * Linux driver for TerraTec DMX 6Fire USB - * - * PCM driver - * - * Author: Torsten Schenk - * Created: Jan 01, 2011 - * Copyright: (C) Torsten Schenk - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include "pcm.h" -#include "chip.h" -#include "comm.h" -#include "control.h" - -enum { - OUT_N_CHANNELS = 6, IN_N_CHANNELS = 4 -}; - -/* keep next two synced with - * FW_EP_W_MAX_PACKET_SIZE[] and RATES_MAX_PACKET_SIZE - * and CONTROL_RATE_XXX in control.h */ -static const int rates_in_packet_size[] = { 228, 228, 420, 420, 404, 404 }; -static const int rates_out_packet_size[] = { 228, 228, 420, 420, 604, 604 }; -static const int rates[] = { 44100, 48000, 88200, 96000, 176400, 192000 }; -static const int rates_alsaid[] = { - SNDRV_PCM_RATE_44100, SNDRV_PCM_RATE_48000, - SNDRV_PCM_RATE_88200, SNDRV_PCM_RATE_96000, - SNDRV_PCM_RATE_176400, SNDRV_PCM_RATE_192000 }; - -enum { /* settings for pcm */ - OUT_EP = 6, IN_EP = 2, MAX_BUFSIZE = 128 * 1024 -}; - -enum { /* pcm streaming states */ - STREAM_DISABLED, /* no pcm streaming */ - STREAM_STARTING, /* pcm streaming requested, waiting to become ready */ - STREAM_RUNNING, /* pcm streaming running */ - STREAM_STOPPING -}; - -static const struct snd_pcm_hardware pcm_hw = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_BATCH, - - .formats = SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, - - .rates = SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000 | - SNDRV_PCM_RATE_176400 | - SNDRV_PCM_RATE_192000, - - .rate_min = 44100, - .rate_max = 192000, - .channels_min = 1, - .channels_max = 0, /* set in pcm_open, depending on capture/playback */ - .buffer_bytes_max = MAX_BUFSIZE, - .period_bytes_min = PCM_N_PACKETS_PER_URB * (PCM_MAX_PACKET_SIZE - 4), - .period_bytes_max = MAX_BUFSIZE, - .periods_min = 2, - .periods_max = 1024 -}; - -static int usb6fire_pcm_set_rate(struct pcm_runtime *rt) -{ - int ret; - struct control_runtime *ctrl_rt = rt->chip->control; - - ctrl_rt->usb_streaming = false; - ret = ctrl_rt->update_streaming(ctrl_rt); - if (ret < 0) { - snd_printk(KERN_ERR PREFIX "error stopping streaming while " - "setting samplerate %d.\n", rates[rt->rate]); - return ret; - } - - ret = ctrl_rt->set_rate(ctrl_rt, rt->rate); - if (ret < 0) { - snd_printk(KERN_ERR PREFIX "error setting samplerate %d.\n", - rates[rt->rate]); - return ret; - } - - ret = ctrl_rt->set_channels(ctrl_rt, OUT_N_CHANNELS, IN_N_CHANNELS, - false, false); - if (ret < 0) { - snd_printk(KERN_ERR PREFIX "error initializing channels " - "while setting samplerate %d.\n", - rates[rt->rate]); - return ret; - } - - ctrl_rt->usb_streaming = true; - ret = ctrl_rt->update_streaming(ctrl_rt); - if (ret < 0) { - snd_printk(KERN_ERR PREFIX "error starting streaming while " - "setting samplerate %d.\n", rates[rt->rate]); - return ret; - } - - rt->in_n_analog = IN_N_CHANNELS; - rt->out_n_analog = OUT_N_CHANNELS; - rt->in_packet_size = rates_in_packet_size[rt->rate]; - rt->out_packet_size = rates_out_packet_size[rt->rate]; - return 0; -} - -static struct pcm_substream *usb6fire_pcm_get_substream( - struct snd_pcm_substream *alsa_sub) -{ - struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub); - - if (alsa_sub->stream == SNDRV_PCM_STREAM_PLAYBACK) - return &rt->playback; - else if (alsa_sub->stream == SNDRV_PCM_STREAM_CAPTURE) - return &rt->capture; - snd_printk(KERN_ERR PREFIX "error getting pcm substream slot.\n"); - return NULL; -} - -/* call with stream_mutex locked */ -static void usb6fire_pcm_stream_stop(struct pcm_runtime *rt) -{ - int i; - struct control_runtime *ctrl_rt = rt->chip->control; - - if (rt->stream_state != STREAM_DISABLED) { - for (i = 0; i < PCM_N_URBS; i++) { - usb_kill_urb(&rt->in_urbs[i].instance); - usb_kill_urb(&rt->out_urbs[i].instance); - } - ctrl_rt->usb_streaming = false; - ctrl_rt->update_streaming(ctrl_rt); - rt->stream_state = STREAM_DISABLED; - } -} - -/* call with stream_mutex locked */ -static int usb6fire_pcm_stream_start(struct pcm_runtime *rt) -{ - int ret; - int i; - int k; - struct usb_iso_packet_descriptor *packet; - - if (rt->stream_state == STREAM_DISABLED) { - /* submit our in urbs */ - rt->stream_wait_cond = false; - rt->stream_state = STREAM_STARTING; - for (i = 0; i < PCM_N_URBS; i++) { - for (k = 0; k < PCM_N_PACKETS_PER_URB; k++) { - packet = &rt->in_urbs[i].packets[k]; - packet->offset = k * rt->in_packet_size; - packet->length = rt->in_packet_size; - packet->actual_length = 0; - packet->status = 0; - } - ret = usb_submit_urb(&rt->in_urbs[i].instance, - GFP_ATOMIC); - if (ret) { - usb6fire_pcm_stream_stop(rt); - return ret; - } - } - - /* wait for first out urb to return (sent in in urb handler) */ - wait_event_timeout(rt->stream_wait_queue, rt->stream_wait_cond, - HZ); - if (rt->stream_wait_cond) - rt->stream_state = STREAM_RUNNING; - else { - usb6fire_pcm_stream_stop(rt); - return -EIO; - } - } - return 0; -} - -/* call with substream locked */ -static void usb6fire_pcm_capture(struct pcm_substream *sub, struct pcm_urb *urb) -{ - int i; - int frame; - int frame_count; - unsigned int total_length = 0; - struct pcm_runtime *rt = snd_pcm_substream_chip(sub->instance); - struct snd_pcm_runtime *alsa_rt = sub->instance->runtime; - u32 *src = NULL; - u32 *dest = (u32 *) (alsa_rt->dma_area + sub->dma_off - * (alsa_rt->frame_bits >> 3)); - u32 *dest_end = (u32 *) (alsa_rt->dma_area + alsa_rt->buffer_size - * (alsa_rt->frame_bits >> 3)); - int bytes_per_frame = alsa_rt->channels << 2; - - for (i = 0; i < PCM_N_PACKETS_PER_URB; i++) { - /* at least 4 header bytes for valid packet. - * after that: 32 bits per sample for analog channels */ - if (urb->packets[i].actual_length > 4) - frame_count = (urb->packets[i].actual_length - 4) - / (rt->in_n_analog << 2); - else - frame_count = 0; - - if (alsa_rt->format == SNDRV_PCM_FORMAT_S24_LE) - src = (u32 *) (urb->buffer + total_length); - else if (alsa_rt->format == SNDRV_PCM_FORMAT_S32_LE) - src = (u32 *) (urb->buffer - 1 + total_length); - else - return; - src++; /* skip leading 4 bytes of every packet */ - total_length += urb->packets[i].length; - for (frame = 0; frame < frame_count; frame++) { - memcpy(dest, src, bytes_per_frame); - dest += alsa_rt->channels; - src += rt->in_n_analog; - sub->dma_off++; - sub->period_off++; - if (dest == dest_end) { - sub->dma_off = 0; - dest = (u32 *) alsa_rt->dma_area; - } - } - } -} - -/* call with substream locked */ -static void usb6fire_pcm_playback(struct pcm_substream *sub, - struct pcm_urb *urb) -{ - int i; - int frame; - int frame_count; - struct pcm_runtime *rt = snd_pcm_substream_chip(sub->instance); - struct snd_pcm_runtime *alsa_rt = sub->instance->runtime; - u32 *src = (u32 *) (alsa_rt->dma_area + sub->dma_off - * (alsa_rt->frame_bits >> 3)); - u32 *src_end = (u32 *) (alsa_rt->dma_area + alsa_rt->buffer_size - * (alsa_rt->frame_bits >> 3)); - u32 *dest; - int bytes_per_frame = alsa_rt->channels << 2; - - if (alsa_rt->format == SNDRV_PCM_FORMAT_S32_LE) - dest = (u32 *) (urb->buffer - 1); - else if (alsa_rt->format == SNDRV_PCM_FORMAT_S24_LE) - dest = (u32 *) (urb->buffer); - else { - snd_printk(KERN_ERR PREFIX "Unknown sample format."); - return; - } - - for (i = 0; i < PCM_N_PACKETS_PER_URB; i++) { - /* at least 4 header bytes for valid packet. - * after that: 32 bits per sample for analog channels */ - if (urb->packets[i].length > 4) - frame_count = (urb->packets[i].length - 4) - / (rt->out_n_analog << 2); - else - frame_count = 0; - dest++; /* skip leading 4 bytes of every frame */ - for (frame = 0; frame < frame_count; frame++) { - memcpy(dest, src, bytes_per_frame); - src += alsa_rt->channels; - dest += rt->out_n_analog; - sub->dma_off++; - sub->period_off++; - if (src == src_end) { - src = (u32 *) alsa_rt->dma_area; - sub->dma_off = 0; - } - } - } -} - -static void usb6fire_pcm_in_urb_handler(struct urb *usb_urb) -{ - struct pcm_urb *in_urb = usb_urb->context; - struct pcm_urb *out_urb = in_urb->peer; - struct pcm_runtime *rt = in_urb->chip->pcm; - struct pcm_substream *sub; - unsigned long flags; - int total_length = 0; - int frame_count; - int frame; - int channel; - int i; - u8 *dest; - - if (usb_urb->status || rt->panic || rt->stream_state == STREAM_STOPPING) - return; - for (i = 0; i < PCM_N_PACKETS_PER_URB; i++) - if (in_urb->packets[i].status) { - rt->panic = true; - return; - } - - if (rt->stream_state == STREAM_DISABLED) { - snd_printk(KERN_ERR PREFIX "internal error: " - "stream disabled in in-urb handler.\n"); - return; - } - - /* receive our capture data */ - sub = &rt->capture; - spin_lock_irqsave(&sub->lock, flags); - if (sub->active) { - usb6fire_pcm_capture(sub, in_urb); - if (sub->period_off >= sub->instance->runtime->period_size) { - sub->period_off %= sub->instance->runtime->period_size; - spin_unlock_irqrestore(&sub->lock, flags); - snd_pcm_period_elapsed(sub->instance); - } else - spin_unlock_irqrestore(&sub->lock, flags); - } else - spin_unlock_irqrestore(&sub->lock, flags); - - /* setup out urb structure */ - for (i = 0; i < PCM_N_PACKETS_PER_URB; i++) { - out_urb->packets[i].offset = total_length; - out_urb->packets[i].length = (in_urb->packets[i].actual_length - - 4) / (rt->in_n_analog << 2) - * (rt->out_n_analog << 2) + 4; - out_urb->packets[i].status = 0; - total_length += out_urb->packets[i].length; - } - memset(out_urb->buffer, 0, total_length); - - /* now send our playback data (if a free out urb was found) */ - sub = &rt->playback; - spin_lock_irqsave(&sub->lock, flags); - if (sub->active) { - usb6fire_pcm_playback(sub, out_urb); - if (sub->period_off >= sub->instance->runtime->period_size) { - sub->period_off %= sub->instance->runtime->period_size; - spin_unlock_irqrestore(&sub->lock, flags); - snd_pcm_period_elapsed(sub->instance); - } else - spin_unlock_irqrestore(&sub->lock, flags); - } else - spin_unlock_irqrestore(&sub->lock, flags); - - /* setup the 4th byte of each sample (0x40 for analog channels) */ - dest = out_urb->buffer; - for (i = 0; i < PCM_N_PACKETS_PER_URB; i++) - if (out_urb->packets[i].length >= 4) { - frame_count = (out_urb->packets[i].length - 4) - / (rt->out_n_analog << 2); - *(dest++) = 0xaa; - *(dest++) = 0xaa; - *(dest++) = frame_count; - *(dest++) = 0x00; - for (frame = 0; frame < frame_count; frame++) - for (channel = 0; - channel < rt->out_n_analog; - channel++) { - dest += 3; /* skip sample data */ - *(dest++) = 0x40; - } - } - usb_submit_urb(&out_urb->instance, GFP_ATOMIC); - usb_submit_urb(&in_urb->instance, GFP_ATOMIC); -} - -static void usb6fire_pcm_out_urb_handler(struct urb *usb_urb) -{ - struct pcm_urb *urb = usb_urb->context; - struct pcm_runtime *rt = urb->chip->pcm; - - if (rt->stream_state == STREAM_STARTING) { - rt->stream_wait_cond = true; - wake_up(&rt->stream_wait_queue); - } -} - -static int usb6fire_pcm_open(struct snd_pcm_substream *alsa_sub) -{ - struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub); - struct pcm_substream *sub = NULL; - struct snd_pcm_runtime *alsa_rt = alsa_sub->runtime; - - if (rt->panic) - return -EPIPE; - - mutex_lock(&rt->stream_mutex); - alsa_rt->hw = pcm_hw; - - if (alsa_sub->stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (rt->rate < ARRAY_SIZE(rates)) - alsa_rt->hw.rates = rates_alsaid[rt->rate]; - alsa_rt->hw.channels_max = OUT_N_CHANNELS; - sub = &rt->playback; - } else if (alsa_sub->stream == SNDRV_PCM_STREAM_CAPTURE) { - if (rt->rate < ARRAY_SIZE(rates)) - alsa_rt->hw.rates = rates_alsaid[rt->rate]; - alsa_rt->hw.channels_max = IN_N_CHANNELS; - sub = &rt->capture; - } - - if (!sub) { - mutex_unlock(&rt->stream_mutex); - snd_printk(KERN_ERR PREFIX "invalid stream type.\n"); - return -EINVAL; - } - - sub->instance = alsa_sub; - sub->active = false; - mutex_unlock(&rt->stream_mutex); - return 0; -} - -static int usb6fire_pcm_close(struct snd_pcm_substream *alsa_sub) -{ - struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub); - struct pcm_substream *sub = usb6fire_pcm_get_substream(alsa_sub); - unsigned long flags; - - if (rt->panic) - return 0; - - mutex_lock(&rt->stream_mutex); - if (sub) { - /* deactivate substream */ - spin_lock_irqsave(&sub->lock, flags); - sub->instance = NULL; - sub->active = false; - spin_unlock_irqrestore(&sub->lock, flags); - - /* all substreams closed? if so, stop streaming */ - if (!rt->playback.instance && !rt->capture.instance) { - usb6fire_pcm_stream_stop(rt); - rt->rate = ARRAY_SIZE(rates); - } - } - mutex_unlock(&rt->stream_mutex); - return 0; -} - -static int usb6fire_pcm_hw_params(struct snd_pcm_substream *alsa_sub, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_malloc_pages(alsa_sub, - params_buffer_bytes(hw_params)); -} - -static int usb6fire_pcm_hw_free(struct snd_pcm_substream *alsa_sub) -{ - return snd_pcm_lib_free_pages(alsa_sub); -} - -static int usb6fire_pcm_prepare(struct snd_pcm_substream *alsa_sub) -{ - struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub); - struct pcm_substream *sub = usb6fire_pcm_get_substream(alsa_sub); - struct snd_pcm_runtime *alsa_rt = alsa_sub->runtime; - int ret; - - if (rt->panic) - return -EPIPE; - if (!sub) - return -ENODEV; - - mutex_lock(&rt->stream_mutex); - sub->dma_off = 0; - sub->period_off = 0; - - if (rt->stream_state == STREAM_DISABLED) { - for (rt->rate = 0; rt->rate < ARRAY_SIZE(rates); rt->rate++) - if (alsa_rt->rate == rates[rt->rate]) - break; - if (rt->rate == ARRAY_SIZE(rates)) { - mutex_unlock(&rt->stream_mutex); - snd_printk("invalid rate %d in prepare.\n", - alsa_rt->rate); - return -EINVAL; - } - - ret = usb6fire_pcm_set_rate(rt); - if (ret) { - mutex_unlock(&rt->stream_mutex); - return ret; - } - ret = usb6fire_pcm_stream_start(rt); - if (ret) { - mutex_unlock(&rt->stream_mutex); - snd_printk(KERN_ERR PREFIX - "could not start pcm stream.\n"); - return ret; - } - } - mutex_unlock(&rt->stream_mutex); - return 0; -} - -static int usb6fire_pcm_trigger(struct snd_pcm_substream *alsa_sub, int cmd) -{ - struct pcm_substream *sub = usb6fire_pcm_get_substream(alsa_sub); - struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub); - unsigned long flags; - - if (rt->panic) - return -EPIPE; - if (!sub) - return -ENODEV; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - spin_lock_irqsave(&sub->lock, flags); - sub->active = true; - spin_unlock_irqrestore(&sub->lock, flags); - return 0; - - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - spin_lock_irqsave(&sub->lock, flags); - sub->active = false; - spin_unlock_irqrestore(&sub->lock, flags); - return 0; - - default: - return -EINVAL; - } -} - -static snd_pcm_uframes_t usb6fire_pcm_pointer( - struct snd_pcm_substream *alsa_sub) -{ - struct pcm_substream *sub = usb6fire_pcm_get_substream(alsa_sub); - struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub); - unsigned long flags; - snd_pcm_uframes_t ret; - - if (rt->panic || !sub) - return SNDRV_PCM_STATE_XRUN; - - spin_lock_irqsave(&sub->lock, flags); - ret = sub->dma_off; - spin_unlock_irqrestore(&sub->lock, flags); - return ret; -} - -static struct snd_pcm_ops pcm_ops = { - .open = usb6fire_pcm_open, - .close = usb6fire_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = usb6fire_pcm_hw_params, - .hw_free = usb6fire_pcm_hw_free, - .prepare = usb6fire_pcm_prepare, - .trigger = usb6fire_pcm_trigger, - .pointer = usb6fire_pcm_pointer, -}; - -static void __devinit usb6fire_pcm_init_urb(struct pcm_urb *urb, - struct sfire_chip *chip, bool in, int ep, - void (*handler)(struct urb *)) -{ - urb->chip = chip; - usb_init_urb(&urb->instance); - urb->instance.transfer_buffer = urb->buffer; - urb->instance.transfer_buffer_length = - PCM_N_PACKETS_PER_URB * PCM_MAX_PACKET_SIZE; - urb->instance.dev = chip->dev; - urb->instance.pipe = in ? usb_rcvisocpipe(chip->dev, ep) - : usb_sndisocpipe(chip->dev, ep); - urb->instance.interval = 1; - urb->instance.transfer_flags = URB_ISO_ASAP; - urb->instance.complete = handler; - urb->instance.context = urb; - urb->instance.number_of_packets = PCM_N_PACKETS_PER_URB; -} - -int __devinit usb6fire_pcm_init(struct sfire_chip *chip) -{ - int i; - int ret; - struct snd_pcm *pcm; - struct pcm_runtime *rt = - kzalloc(sizeof(struct pcm_runtime), GFP_KERNEL); - - if (!rt) - return -ENOMEM; - - rt->chip = chip; - rt->stream_state = STREAM_DISABLED; - rt->rate = ARRAY_SIZE(rates); - init_waitqueue_head(&rt->stream_wait_queue); - mutex_init(&rt->stream_mutex); - - spin_lock_init(&rt->playback.lock); - spin_lock_init(&rt->capture.lock); - - for (i = 0; i < PCM_N_URBS; i++) { - usb6fire_pcm_init_urb(&rt->in_urbs[i], chip, true, IN_EP, - usb6fire_pcm_in_urb_handler); - usb6fire_pcm_init_urb(&rt->out_urbs[i], chip, false, OUT_EP, - usb6fire_pcm_out_urb_handler); - - rt->in_urbs[i].peer = &rt->out_urbs[i]; - rt->out_urbs[i].peer = &rt->in_urbs[i]; - } - - ret = snd_pcm_new(chip->card, "DMX6FireUSB", 0, 1, 1, &pcm); - if (ret < 0) { - kfree(rt); - snd_printk(KERN_ERR PREFIX "cannot create pcm instance.\n"); - return ret; - } - - pcm->private_data = rt; - strcpy(pcm->name, "DMX 6Fire USB"); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_ops); - - ret = snd_pcm_lib_preallocate_pages_for_all(pcm, - SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data(GFP_KERNEL), - MAX_BUFSIZE, MAX_BUFSIZE); - if (ret) { - kfree(rt); - snd_printk(KERN_ERR PREFIX - "error preallocating pcm buffers.\n"); - return ret; - } - rt->instance = pcm; - - chip->pcm = rt; - return 0; -} - -void usb6fire_pcm_abort(struct sfire_chip *chip) -{ - struct pcm_runtime *rt = chip->pcm; - int i; - - if (rt) { - rt->panic = true; - - if (rt->playback.instance) - snd_pcm_stop(rt->playback.instance, - SNDRV_PCM_STATE_XRUN); - if (rt->capture.instance) - snd_pcm_stop(rt->capture.instance, - SNDRV_PCM_STATE_XRUN); - - for (i = 0; i < PCM_N_URBS; i++) { - usb_poison_urb(&rt->in_urbs[i].instance); - usb_poison_urb(&rt->out_urbs[i].instance); - } - - } -} - -void usb6fire_pcm_destroy(struct sfire_chip *chip) -{ - kfree(chip->pcm); - chip->pcm = NULL; -} diff --git a/ANDROID_3.4.5/sound/usb/6fire/pcm.h b/ANDROID_3.4.5/sound/usb/6fire/pcm.h deleted file mode 100644 index 3104301b..00000000 --- a/ANDROID_3.4.5/sound/usb/6fire/pcm.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Linux driver for TerraTec DMX 6Fire USB - * - * Author: Torsten Schenk - * Created: Jan 01, 2011 - * Copyright: (C) Torsten Schenk - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#ifndef USB6FIRE_PCM_H -#define USB6FIRE_PCM_H - -#include -#include - -#include "common.h" - -enum /* settings for pcm */ -{ - /* maximum of EP_W_MAX_PACKET_SIZE[] (see firmware.c) */ - PCM_N_URBS = 16, PCM_N_PACKETS_PER_URB = 8, PCM_MAX_PACKET_SIZE = 604 -}; - -struct pcm_urb { - struct sfire_chip *chip; - - /* BEGIN DO NOT SEPARATE */ - struct urb instance; - struct usb_iso_packet_descriptor packets[PCM_N_PACKETS_PER_URB]; - /* END DO NOT SEPARATE */ - u8 buffer[PCM_N_PACKETS_PER_URB * PCM_MAX_PACKET_SIZE]; - - struct pcm_urb *peer; -}; - -struct pcm_substream { - spinlock_t lock; - struct snd_pcm_substream *instance; - - bool active; - - snd_pcm_uframes_t dma_off; /* current position in alsa dma_area */ - snd_pcm_uframes_t period_off; /* current position in current period */ -}; - -struct pcm_runtime { - struct sfire_chip *chip; - struct snd_pcm *instance; - - struct pcm_substream playback; - struct pcm_substream capture; - bool panic; /* if set driver won't do anymore pcm on device */ - - struct pcm_urb in_urbs[PCM_N_URBS]; - struct pcm_urb out_urbs[PCM_N_URBS]; - int in_packet_size; - int out_packet_size; - int in_n_analog; /* number of analog channels soundcard sends */ - int out_n_analog; /* number of analog channels soundcard receives */ - - struct mutex stream_mutex; - u8 stream_state; /* one of STREAM_XXX (pcm.c) */ - u8 rate; /* one of PCM_RATE_XXX */ - wait_queue_head_t stream_wait_queue; - bool stream_wait_cond; -}; - -int __devinit usb6fire_pcm_init(struct sfire_chip *chip); -void usb6fire_pcm_abort(struct sfire_chip *chip); -void usb6fire_pcm_destroy(struct sfire_chip *chip); -#endif /* USB6FIRE_PCM_H */ diff --git a/ANDROID_3.4.5/sound/usb/Kconfig b/ANDROID_3.4.5/sound/usb/Kconfig deleted file mode 100644 index ff77b28f..00000000 --- a/ANDROID_3.4.5/sound/usb/Kconfig +++ /dev/null @@ -1,119 +0,0 @@ -# ALSA USB drivers - -menuconfig SND_USB - bool "USB sound devices" - depends on USB - default y - help - Support for sound devices connected via the USB bus. - -if SND_USB && USB - -config SND_USB_AUDIO - tristate "USB Audio/MIDI driver" - select SND_HWDEP - select SND_RAWMIDI - select SND_PCM - help - Say Y here to include support for USB audio and USB MIDI - devices. - - To compile this driver as a module, choose M here: the module - will be called snd-usb-audio. - -config SND_USB_UA101 - tristate "Edirol UA-101/UA-1000 driver" - select SND_PCM - select SND_RAWMIDI - help - Say Y here to include support for the Edirol UA-101 and UA-1000 - audio/MIDI interfaces. - - To compile this driver as a module, choose M here: the module - will be called snd-ua101. - -config SND_USB_USX2Y - tristate "Tascam US-122, US-224 and US-428 USB driver" - depends on X86 || PPC || ALPHA - select SND_HWDEP - select SND_RAWMIDI - select SND_PCM - help - Say Y here to include support for Tascam USB Audio/MIDI - interfaces or controllers US-122, US-224 and US-428. - - To compile this driver as a module, choose M here: the module - will be called snd-usb-usx2y. - -config SND_USB_CAIAQ - tristate "Native Instruments USB audio devices" - select SND_HWDEP - select SND_RAWMIDI - select SND_PCM - help - Say Y here to include support for caiaq USB audio interfaces, - namely: - - * Native Instruments RigKontrol2 - * Native Instruments RigKontrol3 - * Native Instruments Kore Controller - * Native Instruments Kore Controller 2 - * Native Instruments Audio Kontrol 1 - * Native Instruments Audio 2 DJ - * Native Instruments Audio 4 DJ - * Native Instruments Audio 8 DJ - * Native Instruments Traktor Audio 2 - * Native Instruments Guitar Rig Session I/O - * Native Instruments Guitar Rig mobile - * Native Instruments Traktor Kontrol X1 - * Native Instruments Traktor Kontrol S4 - * Native Instruments Maschine Controller - - To compile this driver as a module, choose M here: the module - will be called snd-usb-caiaq. - -config SND_USB_CAIAQ_INPUT - bool "enable input device for controllers" - depends on SND_USB_CAIAQ - depends on INPUT=y || INPUT=SND_USB_CAIAQ - help - Say Y here to support input controllers like buttons, knobs, - alpha dials and analog pedals on the following products: - - * Native Instruments RigKontrol2 - * Native Instruments RigKontrol3 - * Native Instruments Kore Controller - * Native Instruments Kore Controller 2 - * Native Instruments Audio Kontrol 1 - * Native Instruments Traktor Kontrol S4 - * Native Instruments Maschine Controller - -config SND_USB_US122L - tristate "Tascam US-122L USB driver" - depends on X86 && EXPERIMENTAL - select SND_HWDEP - select SND_RAWMIDI - help - Say Y here to include support for Tascam US-122L USB Audio/MIDI - interfaces. - - To compile this driver as a module, choose M here: the module - will be called snd-usb-us122l. - -config SND_USB_6FIRE - tristate "TerraTec DMX 6Fire USB" - select FW_LOADER - select BITREVERSE - select SND_RAWMIDI - select SND_PCM - select SND_VMASTER - help - Say Y here to include support for TerraTec 6fire DMX USB interface. - - You will need firmware files in order to be able to use the device - after it has been coldstarted. An install script for the firmware - and further help can be found at - http://sixfireusb.sourceforge.net - -endif # SND_USB - diff --git a/ANDROID_3.4.5/sound/usb/Makefile b/ANDROID_3.4.5/sound/usb/Makefile deleted file mode 100644 index ac256dc4..00000000 --- a/ANDROID_3.4.5/sound/usb/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -# -# Makefile for ALSA -# - -snd-usb-audio-objs := card.o \ - clock.o \ - endpoint.o \ - format.o \ - helper.o \ - mixer.o \ - mixer_quirks.o \ - pcm.o \ - proc.o \ - quirks.o \ - stream.o - -snd-usbmidi-lib-objs := midi.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_USB_AUDIO) += snd-usb-audio.o snd-usbmidi-lib.o - -obj-$(CONFIG_SND_USB_UA101) += snd-usbmidi-lib.o -obj-$(CONFIG_SND_USB_USX2Y) += snd-usbmidi-lib.o -obj-$(CONFIG_SND_USB_US122L) += snd-usbmidi-lib.o - -obj-$(CONFIG_SND) += misc/ usx2y/ caiaq/ 6fire/ diff --git a/ANDROID_3.4.5/sound/usb/caiaq/Makefile b/ANDROID_3.4.5/sound/usb/caiaq/Makefile deleted file mode 100644 index 38899965..00000000 --- a/ANDROID_3.4.5/sound/usb/caiaq/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -snd-usb-caiaq-y := device.o audio.o midi.o control.o -snd-usb-caiaq-$(CONFIG_SND_USB_CAIAQ_INPUT) += input.o - -obj-$(CONFIG_SND_USB_CAIAQ) += snd-usb-caiaq.o diff --git a/ANDROID_3.4.5/sound/usb/caiaq/audio.c b/ANDROID_3.4.5/sound/usb/caiaq/audio.c deleted file mode 100644 index fde9a7a2..00000000 --- a/ANDROID_3.4.5/sound/usb/caiaq/audio.c +++ /dev/null @@ -1,889 +0,0 @@ -/* - * Copyright (c) 2006-2008 Daniel Mack, Karsten Wiese - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include -#include -#include -#include -#include -#include - -#include "device.h" -#include "audio.h" - -#define N_URBS 32 -#define CLOCK_DRIFT_TOLERANCE 5 -#define FRAMES_PER_URB 8 -#define BYTES_PER_FRAME 512 -#define CHANNELS_PER_STREAM 2 -#define BYTES_PER_SAMPLE 3 -#define BYTES_PER_SAMPLE_USB 4 -#define MAX_BUFFER_SIZE (128*1024) -#define MAX_ENDPOINT_SIZE 512 - -#define ENDPOINT_CAPTURE 2 -#define ENDPOINT_PLAYBACK 6 - -#define MAKE_CHECKBYTE(dev,stream,i) \ - (stream << 1) | (~(i / (dev->n_streams * BYTES_PER_SAMPLE_USB)) & 1) - -static struct snd_pcm_hardware snd_usb_caiaq_pcm_hardware = { - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER), - .formats = SNDRV_PCM_FMTBIT_S24_3BE, - .rates = (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_96000), - .rate_min = 44100, - .rate_max = 0, /* will overwrite later */ - .channels_min = CHANNELS_PER_STREAM, - .channels_max = CHANNELS_PER_STREAM, - .buffer_bytes_max = MAX_BUFFER_SIZE, - .period_bytes_min = 128, - .period_bytes_max = MAX_BUFFER_SIZE, - .periods_min = 1, - .periods_max = 1024, -}; - -static void -activate_substream(struct snd_usb_caiaqdev *dev, - struct snd_pcm_substream *sub) -{ - spin_lock(&dev->spinlock); - - if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) - dev->sub_playback[sub->number] = sub; - else - dev->sub_capture[sub->number] = sub; - - spin_unlock(&dev->spinlock); -} - -static void -deactivate_substream(struct snd_usb_caiaqdev *dev, - struct snd_pcm_substream *sub) -{ - unsigned long flags; - spin_lock_irqsave(&dev->spinlock, flags); - - if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) - dev->sub_playback[sub->number] = NULL; - else - dev->sub_capture[sub->number] = NULL; - - spin_unlock_irqrestore(&dev->spinlock, flags); -} - -static int -all_substreams_zero(struct snd_pcm_substream **subs) -{ - int i; - for (i = 0; i < MAX_STREAMS; i++) - if (subs[i] != NULL) - return 0; - return 1; -} - -static int stream_start(struct snd_usb_caiaqdev *dev) -{ - int i, ret; - - debug("%s(%p)\n", __func__, dev); - - if (dev->streaming) - return -EINVAL; - - memset(dev->sub_playback, 0, sizeof(dev->sub_playback)); - memset(dev->sub_capture, 0, sizeof(dev->sub_capture)); - dev->input_panic = 0; - dev->output_panic = 0; - dev->first_packet = 4; - dev->streaming = 1; - dev->warned = 0; - - for (i = 0; i < N_URBS; i++) { - ret = usb_submit_urb(dev->data_urbs_in[i], GFP_ATOMIC); - if (ret) { - log("unable to trigger read #%d! (ret %d)\n", i, ret); - dev->streaming = 0; - return -EPIPE; - } - } - - return 0; -} - -static void stream_stop(struct snd_usb_caiaqdev *dev) -{ - int i; - - debug("%s(%p)\n", __func__, dev); - if (!dev->streaming) - return; - - dev->streaming = 0; - - for (i = 0; i < N_URBS; i++) { - usb_kill_urb(dev->data_urbs_in[i]); - - if (test_bit(i, &dev->outurb_active_mask)) - usb_kill_urb(dev->data_urbs_out[i]); - } - - dev->outurb_active_mask = 0; -} - -static int snd_usb_caiaq_substream_open(struct snd_pcm_substream *substream) -{ - struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream); - debug("%s(%p)\n", __func__, substream); - substream->runtime->hw = dev->pcm_info; - snd_pcm_limit_hw_rates(substream->runtime); - return 0; -} - -static int snd_usb_caiaq_substream_close(struct snd_pcm_substream *substream) -{ - struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream); - - debug("%s(%p)\n", __func__, substream); - if (all_substreams_zero(dev->sub_playback) && - all_substreams_zero(dev->sub_capture)) { - /* when the last client has stopped streaming, - * all sample rates are allowed again */ - stream_stop(dev); - dev->pcm_info.rates = dev->samplerates; - } - - return 0; -} - -static int snd_usb_caiaq_pcm_hw_params(struct snd_pcm_substream *sub, - struct snd_pcm_hw_params *hw_params) -{ - debug("%s(%p)\n", __func__, sub); - return snd_pcm_lib_malloc_pages(sub, params_buffer_bytes(hw_params)); -} - -static int snd_usb_caiaq_pcm_hw_free(struct snd_pcm_substream *sub) -{ - struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(sub); - debug("%s(%p)\n", __func__, sub); - deactivate_substream(dev, sub); - return snd_pcm_lib_free_pages(sub); -} - -/* this should probably go upstream */ -#if SNDRV_PCM_RATE_5512 != 1 << 0 || SNDRV_PCM_RATE_192000 != 1 << 12 -#error "Change this table" -#endif - -static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100, - 48000, 64000, 88200, 96000, 176400, 192000 }; - -static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream) -{ - int bytes_per_sample, bpp, ret, i; - int index = substream->number; - struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - debug("%s(%p)\n", __func__, substream); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - int out_pos; - - switch (dev->spec.data_alignment) { - case 0: - case 2: - out_pos = BYTES_PER_SAMPLE + 1; - break; - case 3: - default: - out_pos = 0; - break; - } - - dev->period_out_count[index] = out_pos; - dev->audio_out_buf_pos[index] = out_pos; - } else { - int in_pos; - - switch (dev->spec.data_alignment) { - case 0: - in_pos = BYTES_PER_SAMPLE + 2; - break; - case 2: - in_pos = BYTES_PER_SAMPLE; - break; - case 3: - default: - in_pos = 0; - break; - } - - dev->period_in_count[index] = in_pos; - dev->audio_in_buf_pos[index] = in_pos; - } - - if (dev->streaming) - return 0; - - /* the first client that opens a stream defines the sample rate - * setting for all subsequent calls, until the last client closed. */ - for (i=0; i < ARRAY_SIZE(rates); i++) - if (runtime->rate == rates[i]) - dev->pcm_info.rates = 1 << i; - - snd_pcm_limit_hw_rates(runtime); - - bytes_per_sample = BYTES_PER_SAMPLE; - if (dev->spec.data_alignment >= 2) - bytes_per_sample++; - - bpp = ((runtime->rate / 8000) + CLOCK_DRIFT_TOLERANCE) - * bytes_per_sample * CHANNELS_PER_STREAM * dev->n_streams; - - if (bpp > MAX_ENDPOINT_SIZE) - bpp = MAX_ENDPOINT_SIZE; - - ret = snd_usb_caiaq_set_audio_params(dev, runtime->rate, - runtime->sample_bits, bpp); - if (ret) - return ret; - - ret = stream_start(dev); - if (ret) - return ret; - - dev->output_running = 0; - wait_event_timeout(dev->prepare_wait_queue, dev->output_running, HZ); - if (!dev->output_running) { - stream_stop(dev); - return -EPIPE; - } - - return 0; -} - -static int snd_usb_caiaq_pcm_trigger(struct snd_pcm_substream *sub, int cmd) -{ - struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(sub); - - debug("%s(%p) cmd %d\n", __func__, sub, cmd); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - activate_substream(dev, sub); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - deactivate_substream(dev, sub); - break; - default: - return -EINVAL; - } - - return 0; -} - -static snd_pcm_uframes_t -snd_usb_caiaq_pcm_pointer(struct snd_pcm_substream *sub) -{ - int index = sub->number; - struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(sub); - snd_pcm_uframes_t ptr; - - spin_lock(&dev->spinlock); - - if (dev->input_panic || dev->output_panic) { - ptr = SNDRV_PCM_POS_XRUN; - goto unlock; - } - - if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) - ptr = bytes_to_frames(sub->runtime, - dev->audio_out_buf_pos[index]); - else - ptr = bytes_to_frames(sub->runtime, - dev->audio_in_buf_pos[index]); - -unlock: - spin_unlock(&dev->spinlock); - return ptr; -} - -/* operators for both playback and capture */ -static struct snd_pcm_ops snd_usb_caiaq_ops = { - .open = snd_usb_caiaq_substream_open, - .close = snd_usb_caiaq_substream_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_usb_caiaq_pcm_hw_params, - .hw_free = snd_usb_caiaq_pcm_hw_free, - .prepare = snd_usb_caiaq_pcm_prepare, - .trigger = snd_usb_caiaq_pcm_trigger, - .pointer = snd_usb_caiaq_pcm_pointer -}; - -static void check_for_elapsed_periods(struct snd_usb_caiaqdev *dev, - struct snd_pcm_substream **subs) -{ - int stream, pb, *cnt; - struct snd_pcm_substream *sub; - - for (stream = 0; stream < dev->n_streams; stream++) { - sub = subs[stream]; - if (!sub) - continue; - - pb = snd_pcm_lib_period_bytes(sub); - cnt = (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) ? - &dev->period_out_count[stream] : - &dev->period_in_count[stream]; - - if (*cnt >= pb) { - snd_pcm_period_elapsed(sub); - *cnt %= pb; - } - } -} - -static void read_in_urb_mode0(struct snd_usb_caiaqdev *dev, - const struct urb *urb, - const struct usb_iso_packet_descriptor *iso) -{ - unsigned char *usb_buf = urb->transfer_buffer + iso->offset; - struct snd_pcm_substream *sub; - int stream, i; - - if (all_substreams_zero(dev->sub_capture)) - return; - - for (i = 0; i < iso->actual_length;) { - for (stream = 0; stream < dev->n_streams; stream++, i++) { - sub = dev->sub_capture[stream]; - if (sub) { - struct snd_pcm_runtime *rt = sub->runtime; - char *audio_buf = rt->dma_area; - int sz = frames_to_bytes(rt, rt->buffer_size); - audio_buf[dev->audio_in_buf_pos[stream]++] - = usb_buf[i]; - dev->period_in_count[stream]++; - if (dev->audio_in_buf_pos[stream] == sz) - dev->audio_in_buf_pos[stream] = 0; - } - } - } -} - -static void read_in_urb_mode2(struct snd_usb_caiaqdev *dev, - const struct urb *urb, - const struct usb_iso_packet_descriptor *iso) -{ - unsigned char *usb_buf = urb->transfer_buffer + iso->offset; - unsigned char check_byte; - struct snd_pcm_substream *sub; - int stream, i; - - for (i = 0; i < iso->actual_length;) { - if (i % (dev->n_streams * BYTES_PER_SAMPLE_USB) == 0) { - for (stream = 0; - stream < dev->n_streams; - stream++, i++) { - if (dev->first_packet) - continue; - - check_byte = MAKE_CHECKBYTE(dev, stream, i); - - if ((usb_buf[i] & 0x3f) != check_byte) - dev->input_panic = 1; - - if (usb_buf[i] & 0x80) - dev->output_panic = 1; - } - } - dev->first_packet = 0; - - for (stream = 0; stream < dev->n_streams; stream++, i++) { - sub = dev->sub_capture[stream]; - if (dev->input_panic) - usb_buf[i] = 0; - - if (sub) { - struct snd_pcm_runtime *rt = sub->runtime; - char *audio_buf = rt->dma_area; - int sz = frames_to_bytes(rt, rt->buffer_size); - audio_buf[dev->audio_in_buf_pos[stream]++] = - usb_buf[i]; - dev->period_in_count[stream]++; - if (dev->audio_in_buf_pos[stream] == sz) - dev->audio_in_buf_pos[stream] = 0; - } - } - } -} - -static void read_in_urb_mode3(struct snd_usb_caiaqdev *dev, - const struct urb *urb, - const struct usb_iso_packet_descriptor *iso) -{ - unsigned char *usb_buf = urb->transfer_buffer + iso->offset; - int stream, i; - - /* paranoia check */ - if (iso->actual_length % (BYTES_PER_SAMPLE_USB * CHANNELS_PER_STREAM)) - return; - - for (i = 0; i < iso->actual_length;) { - for (stream = 0; stream < dev->n_streams; stream++) { - struct snd_pcm_substream *sub = dev->sub_capture[stream]; - char *audio_buf = NULL; - int c, n, sz = 0; - - if (sub && !dev->input_panic) { - struct snd_pcm_runtime *rt = sub->runtime; - audio_buf = rt->dma_area; - sz = frames_to_bytes(rt, rt->buffer_size); - } - - for (c = 0; c < CHANNELS_PER_STREAM; c++) { - /* 3 audio data bytes, followed by 1 check byte */ - if (audio_buf) { - for (n = 0; n < BYTES_PER_SAMPLE; n++) { - audio_buf[dev->audio_in_buf_pos[stream]++] = usb_buf[i+n]; - - if (dev->audio_in_buf_pos[stream] == sz) - dev->audio_in_buf_pos[stream] = 0; - } - - dev->period_in_count[stream] += BYTES_PER_SAMPLE; - } - - i += BYTES_PER_SAMPLE; - - if (usb_buf[i] != ((stream << 1) | c) && - !dev->first_packet) { - if (!dev->input_panic) - printk(" EXPECTED: %02x got %02x, c %d, stream %d, i %d\n", - ((stream << 1) | c), usb_buf[i], c, stream, i); - dev->input_panic = 1; - } - - i++; - } - } - } - - if (dev->first_packet > 0) - dev->first_packet--; -} - -static void read_in_urb(struct snd_usb_caiaqdev *dev, - const struct urb *urb, - const struct usb_iso_packet_descriptor *iso) -{ - if (!dev->streaming) - return; - - if (iso->actual_length < dev->bpp) - return; - - switch (dev->spec.data_alignment) { - case 0: - read_in_urb_mode0(dev, urb, iso); - break; - case 2: - read_in_urb_mode2(dev, urb, iso); - break; - case 3: - read_in_urb_mode3(dev, urb, iso); - break; - } - - if ((dev->input_panic || dev->output_panic) && !dev->warned) { - debug("streaming error detected %s %s\n", - dev->input_panic ? "(input)" : "", - dev->output_panic ? "(output)" : ""); - dev->warned = 1; - } -} - -static void fill_out_urb_mode_0(struct snd_usb_caiaqdev *dev, - struct urb *urb, - const struct usb_iso_packet_descriptor *iso) -{ - unsigned char *usb_buf = urb->transfer_buffer + iso->offset; - struct snd_pcm_substream *sub; - int stream, i; - - for (i = 0; i < iso->length;) { - for (stream = 0; stream < dev->n_streams; stream++, i++) { - sub = dev->sub_playback[stream]; - if (sub) { - struct snd_pcm_runtime *rt = sub->runtime; - char *audio_buf = rt->dma_area; - int sz = frames_to_bytes(rt, rt->buffer_size); - usb_buf[i] = - audio_buf[dev->audio_out_buf_pos[stream]]; - dev->period_out_count[stream]++; - dev->audio_out_buf_pos[stream]++; - if (dev->audio_out_buf_pos[stream] == sz) - dev->audio_out_buf_pos[stream] = 0; - } else - usb_buf[i] = 0; - } - - /* fill in the check bytes */ - if (dev->spec.data_alignment == 2 && - i % (dev->n_streams * BYTES_PER_SAMPLE_USB) == - (dev->n_streams * CHANNELS_PER_STREAM)) - for (stream = 0; stream < dev->n_streams; stream++, i++) - usb_buf[i] = MAKE_CHECKBYTE(dev, stream, i); - } -} - -static void fill_out_urb_mode_3(struct snd_usb_caiaqdev *dev, - struct urb *urb, - const struct usb_iso_packet_descriptor *iso) -{ - unsigned char *usb_buf = urb->transfer_buffer + iso->offset; - int stream, i; - - for (i = 0; i < iso->length;) { - for (stream = 0; stream < dev->n_streams; stream++) { - struct snd_pcm_substream *sub = dev->sub_playback[stream]; - char *audio_buf = NULL; - int c, n, sz = 0; - - if (sub) { - struct snd_pcm_runtime *rt = sub->runtime; - audio_buf = rt->dma_area; - sz = frames_to_bytes(rt, rt->buffer_size); - } - - for (c = 0; c < CHANNELS_PER_STREAM; c++) { - for (n = 0; n < BYTES_PER_SAMPLE; n++) { - if (audio_buf) { - usb_buf[i+n] = audio_buf[dev->audio_out_buf_pos[stream]++]; - - if (dev->audio_out_buf_pos[stream] == sz) - dev->audio_out_buf_pos[stream] = 0; - } else { - usb_buf[i+n] = 0; - } - } - - if (audio_buf) - dev->period_out_count[stream] += BYTES_PER_SAMPLE; - - i += BYTES_PER_SAMPLE; - - /* fill in the check byte pattern */ - usb_buf[i++] = (stream << 1) | c; - } - } - } -} - -static inline void fill_out_urb(struct snd_usb_caiaqdev *dev, - struct urb *urb, - const struct usb_iso_packet_descriptor *iso) -{ - switch (dev->spec.data_alignment) { - case 0: - case 2: - fill_out_urb_mode_0(dev, urb, iso); - break; - case 3: - fill_out_urb_mode_3(dev, urb, iso); - break; - } -} - -static void read_completed(struct urb *urb) -{ - struct snd_usb_caiaq_cb_info *info = urb->context; - struct snd_usb_caiaqdev *dev; - struct urb *out = NULL; - int i, frame, len, send_it = 0, outframe = 0; - size_t offset = 0; - - if (urb->status || !info) - return; - - dev = info->dev; - - if (!dev->streaming) - return; - - /* find an unused output urb that is unused */ - for (i = 0; i < N_URBS; i++) - if (test_and_set_bit(i, &dev->outurb_active_mask) == 0) { - out = dev->data_urbs_out[i]; - break; - } - - if (!out) { - log("Unable to find an output urb to use\n"); - goto requeue; - } - - /* read the recently received packet and send back one which has - * the same layout */ - for (frame = 0; frame < FRAMES_PER_URB; frame++) { - if (urb->iso_frame_desc[frame].status) - continue; - - len = urb->iso_frame_desc[outframe].actual_length; - out->iso_frame_desc[outframe].length = len; - out->iso_frame_desc[outframe].actual_length = 0; - out->iso_frame_desc[outframe].offset = offset; - offset += len; - - if (len > 0) { - spin_lock(&dev->spinlock); - fill_out_urb(dev, out, &out->iso_frame_desc[outframe]); - read_in_urb(dev, urb, &urb->iso_frame_desc[frame]); - spin_unlock(&dev->spinlock); - check_for_elapsed_periods(dev, dev->sub_playback); - check_for_elapsed_periods(dev, dev->sub_capture); - send_it = 1; - } - - outframe++; - } - - if (send_it) { - out->number_of_packets = outframe; - out->transfer_flags = URB_ISO_ASAP; - usb_submit_urb(out, GFP_ATOMIC); - } else { - struct snd_usb_caiaq_cb_info *oinfo = out->context; - clear_bit(oinfo->index, &dev->outurb_active_mask); - } - -requeue: - /* re-submit inbound urb */ - for (frame = 0; frame < FRAMES_PER_URB; frame++) { - urb->iso_frame_desc[frame].offset = BYTES_PER_FRAME * frame; - urb->iso_frame_desc[frame].length = BYTES_PER_FRAME; - urb->iso_frame_desc[frame].actual_length = 0; - } - - urb->number_of_packets = FRAMES_PER_URB; - urb->transfer_flags = URB_ISO_ASAP; - usb_submit_urb(urb, GFP_ATOMIC); -} - -static void write_completed(struct urb *urb) -{ - struct snd_usb_caiaq_cb_info *info = urb->context; - struct snd_usb_caiaqdev *dev = info->dev; - - if (!dev->output_running) { - dev->output_running = 1; - wake_up(&dev->prepare_wait_queue); - } - - clear_bit(info->index, &dev->outurb_active_mask); -} - -static struct urb **alloc_urbs(struct snd_usb_caiaqdev *dev, int dir, int *ret) -{ - int i, frame; - struct urb **urbs; - struct usb_device *usb_dev = dev->chip.dev; - unsigned int pipe; - - pipe = (dir == SNDRV_PCM_STREAM_PLAYBACK) ? - usb_sndisocpipe(usb_dev, ENDPOINT_PLAYBACK) : - usb_rcvisocpipe(usb_dev, ENDPOINT_CAPTURE); - - urbs = kmalloc(N_URBS * sizeof(*urbs), GFP_KERNEL); - if (!urbs) { - log("unable to kmalloc() urbs, OOM!?\n"); - *ret = -ENOMEM; - return NULL; - } - - for (i = 0; i < N_URBS; i++) { - urbs[i] = usb_alloc_urb(FRAMES_PER_URB, GFP_KERNEL); - if (!urbs[i]) { - log("unable to usb_alloc_urb(), OOM!?\n"); - *ret = -ENOMEM; - return urbs; - } - - urbs[i]->transfer_buffer = - kmalloc(FRAMES_PER_URB * BYTES_PER_FRAME, GFP_KERNEL); - if (!urbs[i]->transfer_buffer) { - log("unable to kmalloc() transfer buffer, OOM!?\n"); - *ret = -ENOMEM; - return urbs; - } - - for (frame = 0; frame < FRAMES_PER_URB; frame++) { - struct usb_iso_packet_descriptor *iso = - &urbs[i]->iso_frame_desc[frame]; - - iso->offset = BYTES_PER_FRAME * frame; - iso->length = BYTES_PER_FRAME; - } - - urbs[i]->dev = usb_dev; - urbs[i]->pipe = pipe; - urbs[i]->transfer_buffer_length = FRAMES_PER_URB - * BYTES_PER_FRAME; - urbs[i]->context = &dev->data_cb_info[i]; - urbs[i]->interval = 1; - urbs[i]->transfer_flags = URB_ISO_ASAP; - urbs[i]->number_of_packets = FRAMES_PER_URB; - urbs[i]->complete = (dir == SNDRV_PCM_STREAM_CAPTURE) ? - read_completed : write_completed; - } - - *ret = 0; - return urbs; -} - -static void free_urbs(struct urb **urbs) -{ - int i; - - if (!urbs) - return; - - for (i = 0; i < N_URBS; i++) { - if (!urbs[i]) - continue; - - usb_kill_urb(urbs[i]); - kfree(urbs[i]->transfer_buffer); - usb_free_urb(urbs[i]); - } - - kfree(urbs); -} - -int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev) -{ - int i, ret; - - dev->n_audio_in = max(dev->spec.num_analog_audio_in, - dev->spec.num_digital_audio_in) / - CHANNELS_PER_STREAM; - dev->n_audio_out = max(dev->spec.num_analog_audio_out, - dev->spec.num_digital_audio_out) / - CHANNELS_PER_STREAM; - dev->n_streams = max(dev->n_audio_in, dev->n_audio_out); - - debug("dev->n_audio_in = %d\n", dev->n_audio_in); - debug("dev->n_audio_out = %d\n", dev->n_audio_out); - debug("dev->n_streams = %d\n", dev->n_streams); - - if (dev->n_streams > MAX_STREAMS) { - log("unable to initialize device, too many streams.\n"); - return -EINVAL; - } - - ret = snd_pcm_new(dev->chip.card, dev->product_name, 0, - dev->n_audio_out, dev->n_audio_in, &dev->pcm); - - if (ret < 0) { - log("snd_pcm_new() returned %d\n", ret); - return ret; - } - - dev->pcm->private_data = dev; - strlcpy(dev->pcm->name, dev->product_name, sizeof(dev->pcm->name)); - - memset(dev->sub_playback, 0, sizeof(dev->sub_playback)); - memset(dev->sub_capture, 0, sizeof(dev->sub_capture)); - - memcpy(&dev->pcm_info, &snd_usb_caiaq_pcm_hardware, - sizeof(snd_usb_caiaq_pcm_hardware)); - - /* setup samplerates */ - dev->samplerates = dev->pcm_info.rates; - switch (dev->chip.usb_id) { - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3): - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_SESSIONIO): - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_GUITARRIGMOBILE): - dev->samplerates |= SNDRV_PCM_RATE_192000; - /* fall thru */ - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO2DJ): - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ): - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ): - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORAUDIO2): - dev->samplerates |= SNDRV_PCM_RATE_88200; - break; - } - - snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK, - &snd_usb_caiaq_ops); - snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_CAPTURE, - &snd_usb_caiaq_ops); - - snd_pcm_lib_preallocate_pages_for_all(dev->pcm, - SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data(GFP_KERNEL), - MAX_BUFFER_SIZE, MAX_BUFFER_SIZE); - - dev->data_cb_info = - kmalloc(sizeof(struct snd_usb_caiaq_cb_info) * N_URBS, - GFP_KERNEL); - - if (!dev->data_cb_info) - return -ENOMEM; - - dev->outurb_active_mask = 0; - BUILD_BUG_ON(N_URBS > (sizeof(dev->outurb_active_mask) * 8)); - - for (i = 0; i < N_URBS; i++) { - dev->data_cb_info[i].dev = dev; - dev->data_cb_info[i].index = i; - } - - dev->data_urbs_in = alloc_urbs(dev, SNDRV_PCM_STREAM_CAPTURE, &ret); - if (ret < 0) { - kfree(dev->data_cb_info); - free_urbs(dev->data_urbs_in); - return ret; - } - - dev->data_urbs_out = alloc_urbs(dev, SNDRV_PCM_STREAM_PLAYBACK, &ret); - if (ret < 0) { - kfree(dev->data_cb_info); - free_urbs(dev->data_urbs_in); - free_urbs(dev->data_urbs_out); - return ret; - } - - return 0; -} - -void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *dev) -{ - debug("%s(%p)\n", __func__, dev); - stream_stop(dev); - free_urbs(dev->data_urbs_in); - free_urbs(dev->data_urbs_out); - kfree(dev->data_cb_info); -} - diff --git a/ANDROID_3.4.5/sound/usb/caiaq/audio.h b/ANDROID_3.4.5/sound/usb/caiaq/audio.h deleted file mode 100644 index 8ab1f8d9..00000000 --- a/ANDROID_3.4.5/sound/usb/caiaq/audio.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef CAIAQ_AUDIO_H -#define CAIAQ_AUDIO_H - -int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev); -void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *dev); - -#endif /* CAIAQ_AUDIO_H */ diff --git a/ANDROID_3.4.5/sound/usb/caiaq/control.c b/ANDROID_3.4.5/sound/usb/caiaq/control.c deleted file mode 100644 index 00e5d0a4..00000000 --- a/ANDROID_3.4.5/sound/usb/caiaq/control.c +++ /dev/null @@ -1,559 +0,0 @@ -/* - * Copyright (c) 2007 Daniel Mack - * friendly supported by NI. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include - -#include "device.h" -#include "control.h" - -#define CNT_INTVAL 0x10000 - -static int control_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct snd_usb_audio *chip = snd_kcontrol_chip(kcontrol); - struct snd_usb_caiaqdev *dev = caiaqdev(chip->card); - int pos = kcontrol->private_value; - int is_intval = pos & CNT_INTVAL; - int maxval = 63; - - uinfo->count = 1; - pos &= ~CNT_INTVAL; - - switch (dev->chip.usb_id) { - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ): - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ): - if (pos == 0) { - /* current input mode of A8DJ and A4DJ */ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 2; - return 0; - } - break; - - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1): - maxval = 127; - break; - - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4): - maxval = 31; - break; - } - - if (is_intval) { - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = maxval; - } else { - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - } - - return 0; -} - -static int control_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_usb_audio *chip = snd_kcontrol_chip(kcontrol); - struct snd_usb_caiaqdev *dev = caiaqdev(chip->card); - int pos = kcontrol->private_value; - - if (pos & CNT_INTVAL) - ucontrol->value.integer.value[0] - = dev->control_state[pos & ~CNT_INTVAL]; - else - ucontrol->value.integer.value[0] - = !!(dev->control_state[pos / 8] & (1 << pos % 8)); - - return 0; -} - -static int control_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_usb_audio *chip = snd_kcontrol_chip(kcontrol); - struct snd_usb_caiaqdev *dev = caiaqdev(chip->card); - int pos = kcontrol->private_value; - int v = ucontrol->value.integer.value[0]; - unsigned char cmd = EP1_CMD_WRITE_IO; - - if (dev->chip.usb_id == - USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1)) - cmd = EP1_CMD_DIMM_LEDS; - - if (pos & CNT_INTVAL) { - int i = pos & ~CNT_INTVAL; - - dev->control_state[i] = v; - - if (dev->chip.usb_id == - USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4)) { - int actual_len; - - dev->ep8_out_buf[0] = i; - dev->ep8_out_buf[1] = v; - - usb_bulk_msg(dev->chip.dev, - usb_sndbulkpipe(dev->chip.dev, 8), - dev->ep8_out_buf, sizeof(dev->ep8_out_buf), - &actual_len, 200); - } else { - snd_usb_caiaq_send_command(dev, cmd, - dev->control_state, sizeof(dev->control_state)); - } - } else { - if (v) - dev->control_state[pos / 8] |= 1 << (pos % 8); - else - dev->control_state[pos / 8] &= ~(1 << (pos % 8)); - - snd_usb_caiaq_send_command(dev, cmd, - dev->control_state, sizeof(dev->control_state)); - } - - return 1; -} - -static struct snd_kcontrol_new kcontrol_template __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .index = 0, - .info = control_info, - .get = control_get, - .put = control_put, - /* name and private_value filled later */ -}; - -struct caiaq_controller { - char *name; - int index; -}; - -static struct caiaq_controller ak1_controller[] = { - { "LED left", 2 }, - { "LED middle", 1 }, - { "LED right", 0 }, - { "LED ring", 3 } -}; - -static struct caiaq_controller rk2_controller[] = { - { "LED 1", 5 }, - { "LED 2", 4 }, - { "LED 3", 3 }, - { "LED 4", 2 }, - { "LED 5", 1 }, - { "LED 6", 0 }, - { "LED pedal", 6 }, - { "LED 7seg_1b", 8 }, - { "LED 7seg_1c", 9 }, - { "LED 7seg_2a", 10 }, - { "LED 7seg_2b", 11 }, - { "LED 7seg_2c", 12 }, - { "LED 7seg_2d", 13 }, - { "LED 7seg_2e", 14 }, - { "LED 7seg_2f", 15 }, - { "LED 7seg_2g", 16 }, - { "LED 7seg_3a", 17 }, - { "LED 7seg_3b", 18 }, - { "LED 7seg_3c", 19 }, - { "LED 7seg_3d", 20 }, - { "LED 7seg_3e", 21 }, - { "LED 7seg_3f", 22 }, - { "LED 7seg_3g", 23 } -}; - -static struct caiaq_controller rk3_controller[] = { - { "LED 7seg_1a", 0 + 0 }, - { "LED 7seg_1b", 0 + 1 }, - { "LED 7seg_1c", 0 + 2 }, - { "LED 7seg_1d", 0 + 3 }, - { "LED 7seg_1e", 0 + 4 }, - { "LED 7seg_1f", 0 + 5 }, - { "LED 7seg_1g", 0 + 6 }, - { "LED 7seg_1p", 0 + 7 }, - - { "LED 7seg_2a", 8 + 0 }, - { "LED 7seg_2b", 8 + 1 }, - { "LED 7seg_2c", 8 + 2 }, - { "LED 7seg_2d", 8 + 3 }, - { "LED 7seg_2e", 8 + 4 }, - { "LED 7seg_2f", 8 + 5 }, - { "LED 7seg_2g", 8 + 6 }, - { "LED 7seg_2p", 8 + 7 }, - - { "LED 7seg_3a", 16 + 0 }, - { "LED 7seg_3b", 16 + 1 }, - { "LED 7seg_3c", 16 + 2 }, - { "LED 7seg_3d", 16 + 3 }, - { "LED 7seg_3e", 16 + 4 }, - { "LED 7seg_3f", 16 + 5 }, - { "LED 7seg_3g", 16 + 6 }, - { "LED 7seg_3p", 16 + 7 }, - - { "LED 7seg_4a", 24 + 0 }, - { "LED 7seg_4b", 24 + 1 }, - { "LED 7seg_4c", 24 + 2 }, - { "LED 7seg_4d", 24 + 3 }, - { "LED 7seg_4e", 24 + 4 }, - { "LED 7seg_4f", 24 + 5 }, - { "LED 7seg_4g", 24 + 6 }, - { "LED 7seg_4p", 24 + 7 }, - - { "LED 1", 32 + 0 }, - { "LED 2", 32 + 1 }, - { "LED 3", 32 + 2 }, - { "LED 4", 32 + 3 }, - { "LED 5", 32 + 4 }, - { "LED 6", 32 + 5 }, - { "LED 7", 32 + 6 }, - { "LED 8", 32 + 7 }, - { "LED pedal", 32 + 8 } -}; - -static struct caiaq_controller kore_controller[] = { - { "LED F1", 8 | CNT_INTVAL }, - { "LED F2", 12 | CNT_INTVAL }, - { "LED F3", 0 | CNT_INTVAL }, - { "LED F4", 4 | CNT_INTVAL }, - { "LED F5", 11 | CNT_INTVAL }, - { "LED F6", 15 | CNT_INTVAL }, - { "LED F7", 3 | CNT_INTVAL }, - { "LED F8", 7 | CNT_INTVAL }, - { "LED touch1", 10 | CNT_INTVAL }, - { "LED touch2", 14 | CNT_INTVAL }, - { "LED touch3", 2 | CNT_INTVAL }, - { "LED touch4", 6 | CNT_INTVAL }, - { "LED touch5", 9 | CNT_INTVAL }, - { "LED touch6", 13 | CNT_INTVAL }, - { "LED touch7", 1 | CNT_INTVAL }, - { "LED touch8", 5 | CNT_INTVAL }, - { "LED left", 18 | CNT_INTVAL }, - { "LED right", 22 | CNT_INTVAL }, - { "LED up", 16 | CNT_INTVAL }, - { "LED down", 20 | CNT_INTVAL }, - { "LED stop", 23 | CNT_INTVAL }, - { "LED play", 21 | CNT_INTVAL }, - { "LED record", 19 | CNT_INTVAL }, - { "LED listen", 17 | CNT_INTVAL }, - { "LED lcd", 30 | CNT_INTVAL }, - { "LED menu", 28 | CNT_INTVAL }, - { "LED sound", 31 | CNT_INTVAL }, - { "LED esc", 29 | CNT_INTVAL }, - { "LED view", 27 | CNT_INTVAL }, - { "LED enter", 24 | CNT_INTVAL }, - { "LED control", 26 | CNT_INTVAL } -}; - -static struct caiaq_controller a8dj_controller[] = { - { "Current input mode", 0 | CNT_INTVAL }, - { "GND lift for TC Vinyl mode", 24 + 0 }, - { "GND lift for TC CD/Line mode", 24 + 1 }, - { "GND lift for phono mode", 24 + 2 }, - { "Software lock", 40 } -}; - -static struct caiaq_controller a4dj_controller[] = { - { "Current input mode", 0 | CNT_INTVAL } -}; - -static struct caiaq_controller kontrolx1_controller[] = { - { "LED FX A: ON", 7 | CNT_INTVAL }, - { "LED FX A: 1", 6 | CNT_INTVAL }, - { "LED FX A: 2", 5 | CNT_INTVAL }, - { "LED FX A: 3", 4 | CNT_INTVAL }, - { "LED FX B: ON", 3 | CNT_INTVAL }, - { "LED FX B: 1", 2 | CNT_INTVAL }, - { "LED FX B: 2", 1 | CNT_INTVAL }, - { "LED FX B: 3", 0 | CNT_INTVAL }, - - { "LED Hotcue", 28 | CNT_INTVAL }, - { "LED Shift (white)", 29 | CNT_INTVAL }, - { "LED Shift (green)", 30 | CNT_INTVAL }, - - { "LED Deck A: FX1", 24 | CNT_INTVAL }, - { "LED Deck A: FX2", 25 | CNT_INTVAL }, - { "LED Deck A: IN", 17 | CNT_INTVAL }, - { "LED Deck A: OUT", 16 | CNT_INTVAL }, - { "LED Deck A: < BEAT", 19 | CNT_INTVAL }, - { "LED Deck A: BEAT >", 18 | CNT_INTVAL }, - { "LED Deck A: CUE/ABS", 21 | CNT_INTVAL }, - { "LED Deck A: CUP/REL", 20 | CNT_INTVAL }, - { "LED Deck A: PLAY", 23 | CNT_INTVAL }, - { "LED Deck A: SYNC", 22 | CNT_INTVAL }, - - { "LED Deck B: FX1", 26 | CNT_INTVAL }, - { "LED Deck B: FX2", 27 | CNT_INTVAL }, - { "LED Deck B: IN", 15 | CNT_INTVAL }, - { "LED Deck B: OUT", 14 | CNT_INTVAL }, - { "LED Deck B: < BEAT", 13 | CNT_INTVAL }, - { "LED Deck B: BEAT >", 12 | CNT_INTVAL }, - { "LED Deck B: CUE/ABS", 11 | CNT_INTVAL }, - { "LED Deck B: CUP/REL", 10 | CNT_INTVAL }, - { "LED Deck B: PLAY", 9 | CNT_INTVAL }, - { "LED Deck B: SYNC", 8 | CNT_INTVAL }, -}; - -static struct caiaq_controller kontrols4_controller[] = { - { "LED: Master: Quant", 10 | CNT_INTVAL }, - { "LED: Master: Headphone", 11 | CNT_INTVAL }, - { "LED: Master: Master", 12 | CNT_INTVAL }, - { "LED: Master: Snap", 14 | CNT_INTVAL }, - { "LED: Master: Warning", 15 | CNT_INTVAL }, - { "LED: Master: Master button", 112 | CNT_INTVAL }, - { "LED: Master: Snap button", 113 | CNT_INTVAL }, - { "LED: Master: Rec", 118 | CNT_INTVAL }, - { "LED: Master: Size", 119 | CNT_INTVAL }, - { "LED: Master: Quant button", 120 | CNT_INTVAL }, - { "LED: Master: Browser button", 121 | CNT_INTVAL }, - { "LED: Master: Play button", 126 | CNT_INTVAL }, - { "LED: Master: Undo button", 127 | CNT_INTVAL }, - - { "LED: Channel A: >", 4 | CNT_INTVAL }, - { "LED: Channel A: <", 5 | CNT_INTVAL }, - { "LED: Channel A: Meter 1", 97 | CNT_INTVAL }, - { "LED: Channel A: Meter 2", 98 | CNT_INTVAL }, - { "LED: Channel A: Meter 3", 99 | CNT_INTVAL }, - { "LED: Channel A: Meter 4", 100 | CNT_INTVAL }, - { "LED: Channel A: Meter 5", 101 | CNT_INTVAL }, - { "LED: Channel A: Meter 6", 102 | CNT_INTVAL }, - { "LED: Channel A: Meter clip", 103 | CNT_INTVAL }, - { "LED: Channel A: Active", 114 | CNT_INTVAL }, - { "LED: Channel A: Cue", 116 | CNT_INTVAL }, - { "LED: Channel A: FX1", 149 | CNT_INTVAL }, - { "LED: Channel A: FX2", 148 | CNT_INTVAL }, - - { "LED: Channel B: >", 2 | CNT_INTVAL }, - { "LED: Channel B: <", 3 | CNT_INTVAL }, - { "LED: Channel B: Meter 1", 89 | CNT_INTVAL }, - { "LED: Channel B: Meter 2", 90 | CNT_INTVAL }, - { "LED: Channel B: Meter 3", 91 | CNT_INTVAL }, - { "LED: Channel B: Meter 4", 92 | CNT_INTVAL }, - { "LED: Channel B: Meter 5", 93 | CNT_INTVAL }, - { "LED: Channel B: Meter 6", 94 | CNT_INTVAL }, - { "LED: Channel B: Meter clip", 95 | CNT_INTVAL }, - { "LED: Channel B: Active", 122 | CNT_INTVAL }, - { "LED: Channel B: Cue", 125 | CNT_INTVAL }, - { "LED: Channel B: FX1", 147 | CNT_INTVAL }, - { "LED: Channel B: FX2", 146 | CNT_INTVAL }, - - { "LED: Channel C: >", 6 | CNT_INTVAL }, - { "LED: Channel C: <", 7 | CNT_INTVAL }, - { "LED: Channel C: Meter 1", 105 | CNT_INTVAL }, - { "LED: Channel C: Meter 2", 106 | CNT_INTVAL }, - { "LED: Channel C: Meter 3", 107 | CNT_INTVAL }, - { "LED: Channel C: Meter 4", 108 | CNT_INTVAL }, - { "LED: Channel C: Meter 5", 109 | CNT_INTVAL }, - { "LED: Channel C: Meter 6", 110 | CNT_INTVAL }, - { "LED: Channel C: Meter clip", 111 | CNT_INTVAL }, - { "LED: Channel C: Active", 115 | CNT_INTVAL }, - { "LED: Channel C: Cue", 117 | CNT_INTVAL }, - { "LED: Channel C: FX1", 151 | CNT_INTVAL }, - { "LED: Channel C: FX2", 150 | CNT_INTVAL }, - - { "LED: Channel D: >", 0 | CNT_INTVAL }, - { "LED: Channel D: <", 1 | CNT_INTVAL }, - { "LED: Channel D: Meter 1", 81 | CNT_INTVAL }, - { "LED: Channel D: Meter 2", 82 | CNT_INTVAL }, - { "LED: Channel D: Meter 3", 83 | CNT_INTVAL }, - { "LED: Channel D: Meter 4", 84 | CNT_INTVAL }, - { "LED: Channel D: Meter 5", 85 | CNT_INTVAL }, - { "LED: Channel D: Meter 6", 86 | CNT_INTVAL }, - { "LED: Channel D: Meter clip", 87 | CNT_INTVAL }, - { "LED: Channel D: Active", 123 | CNT_INTVAL }, - { "LED: Channel D: Cue", 124 | CNT_INTVAL }, - { "LED: Channel D: FX1", 145 | CNT_INTVAL }, - { "LED: Channel D: FX2", 144 | CNT_INTVAL }, - - { "LED: Deck A: 1 (blue)", 22 | CNT_INTVAL }, - { "LED: Deck A: 1 (green)", 23 | CNT_INTVAL }, - { "LED: Deck A: 2 (blue)", 20 | CNT_INTVAL }, - { "LED: Deck A: 2 (green)", 21 | CNT_INTVAL }, - { "LED: Deck A: 3 (blue)", 18 | CNT_INTVAL }, - { "LED: Deck A: 3 (green)", 19 | CNT_INTVAL }, - { "LED: Deck A: 4 (blue)", 16 | CNT_INTVAL }, - { "LED: Deck A: 4 (green)", 17 | CNT_INTVAL }, - { "LED: Deck A: Load", 44 | CNT_INTVAL }, - { "LED: Deck A: Deck C button", 45 | CNT_INTVAL }, - { "LED: Deck A: In", 47 | CNT_INTVAL }, - { "LED: Deck A: Out", 46 | CNT_INTVAL }, - { "LED: Deck A: Shift", 24 | CNT_INTVAL }, - { "LED: Deck A: Sync", 27 | CNT_INTVAL }, - { "LED: Deck A: Cue", 26 | CNT_INTVAL }, - { "LED: Deck A: Play", 25 | CNT_INTVAL }, - { "LED: Deck A: Tempo up", 33 | CNT_INTVAL }, - { "LED: Deck A: Tempo down", 32 | CNT_INTVAL }, - { "LED: Deck A: Master", 34 | CNT_INTVAL }, - { "LED: Deck A: Keylock", 35 | CNT_INTVAL }, - { "LED: Deck A: Deck A", 37 | CNT_INTVAL }, - { "LED: Deck A: Deck C", 36 | CNT_INTVAL }, - { "LED: Deck A: Samples", 38 | CNT_INTVAL }, - { "LED: Deck A: On Air", 39 | CNT_INTVAL }, - { "LED: Deck A: Sample 1", 31 | CNT_INTVAL }, - { "LED: Deck A: Sample 2", 30 | CNT_INTVAL }, - { "LED: Deck A: Sample 3", 29 | CNT_INTVAL }, - { "LED: Deck A: Sample 4", 28 | CNT_INTVAL }, - { "LED: Deck A: Digit 1 - A", 55 | CNT_INTVAL }, - { "LED: Deck A: Digit 1 - B", 54 | CNT_INTVAL }, - { "LED: Deck A: Digit 1 - C", 53 | CNT_INTVAL }, - { "LED: Deck A: Digit 1 - D", 52 | CNT_INTVAL }, - { "LED: Deck A: Digit 1 - E", 51 | CNT_INTVAL }, - { "LED: Deck A: Digit 1 - F", 50 | CNT_INTVAL }, - { "LED: Deck A: Digit 1 - G", 49 | CNT_INTVAL }, - { "LED: Deck A: Digit 1 - dot", 48 | CNT_INTVAL }, - { "LED: Deck A: Digit 2 - A", 63 | CNT_INTVAL }, - { "LED: Deck A: Digit 2 - B", 62 | CNT_INTVAL }, - { "LED: Deck A: Digit 2 - C", 61 | CNT_INTVAL }, - { "LED: Deck A: Digit 2 - D", 60 | CNT_INTVAL }, - { "LED: Deck A: Digit 2 - E", 59 | CNT_INTVAL }, - { "LED: Deck A: Digit 2 - F", 58 | CNT_INTVAL }, - { "LED: Deck A: Digit 2 - G", 57 | CNT_INTVAL }, - { "LED: Deck A: Digit 2 - dot", 56 | CNT_INTVAL }, - - { "LED: Deck B: 1 (blue)", 78 | CNT_INTVAL }, - { "LED: Deck B: 1 (green)", 79 | CNT_INTVAL }, - { "LED: Deck B: 2 (blue)", 76 | CNT_INTVAL }, - { "LED: Deck B: 2 (green)", 77 | CNT_INTVAL }, - { "LED: Deck B: 3 (blue)", 74 | CNT_INTVAL }, - { "LED: Deck B: 3 (green)", 75 | CNT_INTVAL }, - { "LED: Deck B: 4 (blue)", 72 | CNT_INTVAL }, - { "LED: Deck B: 4 (green)", 73 | CNT_INTVAL }, - { "LED: Deck B: Load", 180 | CNT_INTVAL }, - { "LED: Deck B: Deck D button", 181 | CNT_INTVAL }, - { "LED: Deck B: In", 183 | CNT_INTVAL }, - { "LED: Deck B: Out", 182 | CNT_INTVAL }, - { "LED: Deck B: Shift", 64 | CNT_INTVAL }, - { "LED: Deck B: Sync", 67 | CNT_INTVAL }, - { "LED: Deck B: Cue", 66 | CNT_INTVAL }, - { "LED: Deck B: Play", 65 | CNT_INTVAL }, - { "LED: Deck B: Tempo up", 185 | CNT_INTVAL }, - { "LED: Deck B: Tempo down", 184 | CNT_INTVAL }, - { "LED: Deck B: Master", 186 | CNT_INTVAL }, - { "LED: Deck B: Keylock", 187 | CNT_INTVAL }, - { "LED: Deck B: Deck B", 189 | CNT_INTVAL }, - { "LED: Deck B: Deck D", 188 | CNT_INTVAL }, - { "LED: Deck B: Samples", 190 | CNT_INTVAL }, - { "LED: Deck B: On Air", 191 | CNT_INTVAL }, - { "LED: Deck B: Sample 1", 71 | CNT_INTVAL }, - { "LED: Deck B: Sample 2", 70 | CNT_INTVAL }, - { "LED: Deck B: Sample 3", 69 | CNT_INTVAL }, - { "LED: Deck B: Sample 4", 68 | CNT_INTVAL }, - { "LED: Deck B: Digit 1 - A", 175 | CNT_INTVAL }, - { "LED: Deck B: Digit 1 - B", 174 | CNT_INTVAL }, - { "LED: Deck B: Digit 1 - C", 173 | CNT_INTVAL }, - { "LED: Deck B: Digit 1 - D", 172 | CNT_INTVAL }, - { "LED: Deck B: Digit 1 - E", 171 | CNT_INTVAL }, - { "LED: Deck B: Digit 1 - F", 170 | CNT_INTVAL }, - { "LED: Deck B: Digit 1 - G", 169 | CNT_INTVAL }, - { "LED: Deck B: Digit 1 - dot", 168 | CNT_INTVAL }, - { "LED: Deck B: Digit 2 - A", 167 | CNT_INTVAL }, - { "LED: Deck B: Digit 2 - B", 166 | CNT_INTVAL }, - { "LED: Deck B: Digit 2 - C", 165 | CNT_INTVAL }, - { "LED: Deck B: Digit 2 - D", 164 | CNT_INTVAL }, - { "LED: Deck B: Digit 2 - E", 163 | CNT_INTVAL }, - { "LED: Deck B: Digit 2 - F", 162 | CNT_INTVAL }, - { "LED: Deck B: Digit 2 - G", 161 | CNT_INTVAL }, - { "LED: Deck B: Digit 2 - dot", 160 | CNT_INTVAL }, - - { "LED: FX1: dry/wet", 153 | CNT_INTVAL }, - { "LED: FX1: 1", 154 | CNT_INTVAL }, - { "LED: FX1: 2", 155 | CNT_INTVAL }, - { "LED: FX1: 3", 156 | CNT_INTVAL }, - { "LED: FX1: Mode", 157 | CNT_INTVAL }, - { "LED: FX2: dry/wet", 129 | CNT_INTVAL }, - { "LED: FX2: 1", 130 | CNT_INTVAL }, - { "LED: FX2: 2", 131 | CNT_INTVAL }, - { "LED: FX2: 3", 132 | CNT_INTVAL }, - { "LED: FX2: Mode", 133 | CNT_INTVAL }, -}; - -static int __devinit add_controls(struct caiaq_controller *c, int num, - struct snd_usb_caiaqdev *dev) -{ - int i, ret; - struct snd_kcontrol *kc; - - for (i = 0; i < num; i++, c++) { - kcontrol_template.name = c->name; - kcontrol_template.private_value = c->index; - kc = snd_ctl_new1(&kcontrol_template, dev); - ret = snd_ctl_add(dev->chip.card, kc); - if (ret < 0) - return ret; - } - - return 0; -} - -int __devinit snd_usb_caiaq_control_init(struct snd_usb_caiaqdev *dev) -{ - int ret = 0; - - switch (dev->chip.usb_id) { - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): - ret = add_controls(ak1_controller, - ARRAY_SIZE(ak1_controller), dev); - break; - - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2): - ret = add_controls(rk2_controller, - ARRAY_SIZE(rk2_controller), dev); - break; - - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3): - ret = add_controls(rk3_controller, - ARRAY_SIZE(rk3_controller), dev); - break; - - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER): - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2): - ret = add_controls(kore_controller, - ARRAY_SIZE(kore_controller), dev); - break; - - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ): - ret = add_controls(a8dj_controller, - ARRAY_SIZE(a8dj_controller), dev); - break; - - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ): - ret = add_controls(a4dj_controller, - ARRAY_SIZE(a4dj_controller), dev); - break; - - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1): - ret = add_controls(kontrolx1_controller, - ARRAY_SIZE(kontrolx1_controller), dev); - break; - - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4): - ret = add_controls(kontrols4_controller, - ARRAY_SIZE(kontrols4_controller), dev); - break; - } - - return ret; -} - diff --git a/ANDROID_3.4.5/sound/usb/caiaq/control.h b/ANDROID_3.4.5/sound/usb/caiaq/control.h deleted file mode 100644 index 2e7ab1aa..00000000 --- a/ANDROID_3.4.5/sound/usb/caiaq/control.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef CAIAQ_CONTROL_H -#define CAIAQ_CONTROL_H - -int snd_usb_caiaq_control_init(struct snd_usb_caiaqdev *dev); - -#endif /* CAIAQ_CONTROL_H */ diff --git a/ANDROID_3.4.5/sound/usb/caiaq/device.c b/ANDROID_3.4.5/sound/usb/caiaq/device.c deleted file mode 100644 index 64aed432..00000000 --- a/ANDROID_3.4.5/sound/usb/caiaq/device.c +++ /dev/null @@ -1,542 +0,0 @@ -/* - * caiaq.c: ALSA driver for caiaq/NativeInstruments devices - * - * Copyright (c) 2007 Daniel Mack - * Karsten Wiese - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "device.h" -#include "audio.h" -#include "midi.h" -#include "control.h" -#include "input.h" - -MODULE_AUTHOR("Daniel Mack "); -MODULE_DESCRIPTION("caiaq USB audio"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2}," - "{Native Instruments, RigKontrol3}," - "{Native Instruments, Kore Controller}," - "{Native Instruments, Kore Controller 2}," - "{Native Instruments, Audio Kontrol 1}," - "{Native Instruments, Audio 2 DJ}," - "{Native Instruments, Audio 4 DJ}," - "{Native Instruments, Audio 8 DJ}," - "{Native Instruments, Traktor Audio 2}," - "{Native Instruments, Session I/O}," - "{Native Instruments, GuitarRig mobile}" - "{Native Instruments, Traktor Kontrol X1}" - "{Native Instruments, Traktor Kontrol S4}" - "{Native Instruments, Maschine Controller}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */ -static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ -static int snd_card_used[SNDRV_CARDS]; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for the caiaq sound device"); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for the caiaq soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable the caiaq soundcard."); - -enum { - SAMPLERATE_44100 = 0, - SAMPLERATE_48000 = 1, - SAMPLERATE_96000 = 2, - SAMPLERATE_192000 = 3, - SAMPLERATE_88200 = 4, - SAMPLERATE_INVALID = 0xff -}; - -enum { - DEPTH_NONE = 0, - DEPTH_16 = 1, - DEPTH_24 = 2, - DEPTH_32 = 3 -}; - -static struct usb_device_id snd_usb_id_table[] = { - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = USB_VID_NATIVEINSTRUMENTS, - .idProduct = USB_PID_RIGKONTROL2 - }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = USB_VID_NATIVEINSTRUMENTS, - .idProduct = USB_PID_RIGKONTROL3 - }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = USB_VID_NATIVEINSTRUMENTS, - .idProduct = USB_PID_KORECONTROLLER - }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = USB_VID_NATIVEINSTRUMENTS, - .idProduct = USB_PID_KORECONTROLLER2 - }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = USB_VID_NATIVEINSTRUMENTS, - .idProduct = USB_PID_AK1 - }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = USB_VID_NATIVEINSTRUMENTS, - .idProduct = USB_PID_AUDIO8DJ - }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = USB_VID_NATIVEINSTRUMENTS, - .idProduct = USB_PID_SESSIONIO - }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = USB_VID_NATIVEINSTRUMENTS, - .idProduct = USB_PID_GUITARRIGMOBILE - }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = USB_VID_NATIVEINSTRUMENTS, - .idProduct = USB_PID_AUDIO4DJ - }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = USB_VID_NATIVEINSTRUMENTS, - .idProduct = USB_PID_AUDIO2DJ - }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = USB_VID_NATIVEINSTRUMENTS, - .idProduct = USB_PID_TRAKTORKONTROLX1 - }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = USB_VID_NATIVEINSTRUMENTS, - .idProduct = USB_PID_TRAKTORKONTROLS4 - }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = USB_VID_NATIVEINSTRUMENTS, - .idProduct = USB_PID_TRAKTORAUDIO2 - }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = USB_VID_NATIVEINSTRUMENTS, - .idProduct = USB_PID_MASCHINECONTROLLER - }, - { /* terminator */ } -}; - -static void usb_ep1_command_reply_dispatch (struct urb* urb) -{ - int ret; - struct snd_usb_caiaqdev *dev = urb->context; - unsigned char *buf = urb->transfer_buffer; - - if (urb->status || !dev) { - log("received EP1 urb->status = %i\n", urb->status); - return; - } - - switch(buf[0]) { - case EP1_CMD_GET_DEVICE_INFO: - memcpy(&dev->spec, buf+1, sizeof(struct caiaq_device_spec)); - dev->spec.fw_version = le16_to_cpu(dev->spec.fw_version); - debug("device spec (firmware %d): audio: %d in, %d out, " - "MIDI: %d in, %d out, data alignment %d\n", - dev->spec.fw_version, - dev->spec.num_analog_audio_in, - dev->spec.num_analog_audio_out, - dev->spec.num_midi_in, - dev->spec.num_midi_out, - dev->spec.data_alignment); - - dev->spec_received++; - wake_up(&dev->ep1_wait_queue); - break; - case EP1_CMD_AUDIO_PARAMS: - dev->audio_parm_answer = buf[1]; - wake_up(&dev->ep1_wait_queue); - break; - case EP1_CMD_MIDI_READ: - snd_usb_caiaq_midi_handle_input(dev, buf[1], buf + 3, buf[2]); - break; - case EP1_CMD_READ_IO: - if (dev->chip.usb_id == - USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ)) { - if (urb->actual_length > sizeof(dev->control_state)) - urb->actual_length = sizeof(dev->control_state); - memcpy(dev->control_state, buf + 1, urb->actual_length); - wake_up(&dev->ep1_wait_queue); - break; - } -#ifdef CONFIG_SND_USB_CAIAQ_INPUT - case EP1_CMD_READ_ERP: - case EP1_CMD_READ_ANALOG: - snd_usb_caiaq_input_dispatch(dev, buf, urb->actual_length); -#endif - break; - } - - dev->ep1_in_urb.actual_length = 0; - ret = usb_submit_urb(&dev->ep1_in_urb, GFP_ATOMIC); - if (ret < 0) - log("unable to submit urb. OOM!?\n"); -} - -int snd_usb_caiaq_send_command(struct snd_usb_caiaqdev *dev, - unsigned char command, - const unsigned char *buffer, - int len) -{ - int actual_len; - struct usb_device *usb_dev = dev->chip.dev; - - if (!usb_dev) - return -EIO; - - if (len > EP1_BUFSIZE - 1) - len = EP1_BUFSIZE - 1; - - if (buffer && len > 0) - memcpy(dev->ep1_out_buf+1, buffer, len); - - dev->ep1_out_buf[0] = command; - return usb_bulk_msg(usb_dev, usb_sndbulkpipe(usb_dev, 1), - dev->ep1_out_buf, len+1, &actual_len, 200); -} - -int snd_usb_caiaq_set_audio_params (struct snd_usb_caiaqdev *dev, - int rate, int depth, int bpp) -{ - int ret; - char tmp[5]; - - switch (rate) { - case 44100: tmp[0] = SAMPLERATE_44100; break; - case 48000: tmp[0] = SAMPLERATE_48000; break; - case 88200: tmp[0] = SAMPLERATE_88200; break; - case 96000: tmp[0] = SAMPLERATE_96000; break; - case 192000: tmp[0] = SAMPLERATE_192000; break; - default: return -EINVAL; - } - - switch (depth) { - case 16: tmp[1] = DEPTH_16; break; - case 24: tmp[1] = DEPTH_24; break; - default: return -EINVAL; - } - - tmp[2] = bpp & 0xff; - tmp[3] = bpp >> 8; - tmp[4] = 1; /* packets per microframe */ - - debug("setting audio params: %d Hz, %d bits, %d bpp\n", - rate, depth, bpp); - - dev->audio_parm_answer = -1; - ret = snd_usb_caiaq_send_command(dev, EP1_CMD_AUDIO_PARAMS, - tmp, sizeof(tmp)); - - if (ret) - return ret; - - if (!wait_event_timeout(dev->ep1_wait_queue, - dev->audio_parm_answer >= 0, HZ)) - return -EPIPE; - - if (dev->audio_parm_answer != 1) - debug("unable to set the device's audio params\n"); - else - dev->bpp = bpp; - - return dev->audio_parm_answer == 1 ? 0 : -EINVAL; -} - -int snd_usb_caiaq_set_auto_msg(struct snd_usb_caiaqdev *dev, - int digital, int analog, int erp) -{ - char tmp[3] = { digital, analog, erp }; - return snd_usb_caiaq_send_command(dev, EP1_CMD_AUTO_MSG, - tmp, sizeof(tmp)); -} - -static void __devinit setup_card(struct snd_usb_caiaqdev *dev) -{ - int ret; - char val[4]; - - /* device-specific startup specials */ - switch (dev->chip.usb_id) { - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2): - /* RigKontrol2 - display centered dash ('-') */ - val[0] = 0x00; - val[1] = 0x00; - val[2] = 0x01; - snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO, val, 3); - break; - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3): - /* RigKontrol2 - display two centered dashes ('--') */ - val[0] = 0x00; - val[1] = 0x40; - val[2] = 0x40; - val[3] = 0x00; - snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO, val, 4); - break; - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): - /* Audio Kontrol 1 - make USB-LED stop blinking */ - val[0] = 0x00; - snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO, val, 1); - break; - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ): - /* Audio 8 DJ - trigger read of current settings */ - dev->control_state[0] = 0xff; - snd_usb_caiaq_set_auto_msg(dev, 1, 0, 0); - snd_usb_caiaq_send_command(dev, EP1_CMD_READ_IO, NULL, 0); - - if (!wait_event_timeout(dev->ep1_wait_queue, - dev->control_state[0] != 0xff, HZ)) - return; - - /* fix up some defaults */ - if ((dev->control_state[1] != 2) || - (dev->control_state[2] != 3) || - (dev->control_state[4] != 2)) { - dev->control_state[1] = 2; - dev->control_state[2] = 3; - dev->control_state[4] = 2; - snd_usb_caiaq_send_command(dev, - EP1_CMD_WRITE_IO, dev->control_state, 6); - } - - break; - } - - if (dev->spec.num_analog_audio_out + - dev->spec.num_analog_audio_in + - dev->spec.num_digital_audio_out + - dev->spec.num_digital_audio_in > 0) { - ret = snd_usb_caiaq_audio_init(dev); - if (ret < 0) - log("Unable to set up audio system (ret=%d)\n", ret); - } - - if (dev->spec.num_midi_in + - dev->spec.num_midi_out > 0) { - ret = snd_usb_caiaq_midi_init(dev); - if (ret < 0) - log("Unable to set up MIDI system (ret=%d)\n", ret); - } - -#ifdef CONFIG_SND_USB_CAIAQ_INPUT - ret = snd_usb_caiaq_input_init(dev); - if (ret < 0) - log("Unable to set up input system (ret=%d)\n", ret); -#endif - - /* finally, register the card and all its sub-instances */ - ret = snd_card_register(dev->chip.card); - if (ret < 0) { - log("snd_card_register() returned %d\n", ret); - snd_card_free(dev->chip.card); - } - - ret = snd_usb_caiaq_control_init(dev); - if (ret < 0) - log("Unable to set up control system (ret=%d)\n", ret); -} - -static int create_card(struct usb_device *usb_dev, - struct usb_interface *intf, - struct snd_card **cardp) -{ - int devnum; - int err; - struct snd_card *card; - struct snd_usb_caiaqdev *dev; - - for (devnum = 0; devnum < SNDRV_CARDS; devnum++) - if (enable[devnum] && !snd_card_used[devnum]) - break; - - if (devnum >= SNDRV_CARDS) - return -ENODEV; - - err = snd_card_create(index[devnum], id[devnum], THIS_MODULE, - sizeof(struct snd_usb_caiaqdev), &card); - if (err < 0) - return err; - - dev = caiaqdev(card); - dev->chip.dev = usb_dev; - dev->chip.card = card; - dev->chip.usb_id = USB_ID(le16_to_cpu(usb_dev->descriptor.idVendor), - le16_to_cpu(usb_dev->descriptor.idProduct)); - spin_lock_init(&dev->spinlock); - snd_card_set_dev(card, &intf->dev); - - *cardp = card; - return 0; -} - -static int __devinit init_card(struct snd_usb_caiaqdev *dev) -{ - char *c, usbpath[32]; - struct usb_device *usb_dev = dev->chip.dev; - struct snd_card *card = dev->chip.card; - int err, len; - - if (usb_set_interface(usb_dev, 0, 1) != 0) { - log("can't set alt interface.\n"); - return -EIO; - } - - usb_init_urb(&dev->ep1_in_urb); - usb_init_urb(&dev->midi_out_urb); - - usb_fill_bulk_urb(&dev->ep1_in_urb, usb_dev, - usb_rcvbulkpipe(usb_dev, 0x1), - dev->ep1_in_buf, EP1_BUFSIZE, - usb_ep1_command_reply_dispatch, dev); - - usb_fill_bulk_urb(&dev->midi_out_urb, usb_dev, - usb_sndbulkpipe(usb_dev, 0x1), - dev->midi_out_buf, EP1_BUFSIZE, - snd_usb_caiaq_midi_output_done, dev); - - init_waitqueue_head(&dev->ep1_wait_queue); - init_waitqueue_head(&dev->prepare_wait_queue); - - if (usb_submit_urb(&dev->ep1_in_urb, GFP_KERNEL) != 0) - return -EIO; - - err = snd_usb_caiaq_send_command(dev, EP1_CMD_GET_DEVICE_INFO, NULL, 0); - if (err) - return err; - - if (!wait_event_timeout(dev->ep1_wait_queue, dev->spec_received, HZ)) - return -ENODEV; - - usb_string(usb_dev, usb_dev->descriptor.iManufacturer, - dev->vendor_name, CAIAQ_USB_STR_LEN); - - usb_string(usb_dev, usb_dev->descriptor.iProduct, - dev->product_name, CAIAQ_USB_STR_LEN); - - strlcpy(card->driver, MODNAME, sizeof(card->driver)); - strlcpy(card->shortname, dev->product_name, sizeof(card->shortname)); - strlcpy(card->mixername, dev->product_name, sizeof(card->mixername)); - - /* if the id was not passed as module option, fill it with a shortened - * version of the product string which does not contain any - * whitespaces */ - - if (*card->id == '\0') { - char id[sizeof(card->id)]; - - memset(id, 0, sizeof(id)); - - for (c = card->shortname, len = 0; - *c && len < sizeof(card->id); c++) - if (*c != ' ') - id[len++] = *c; - - snd_card_set_id(card, id); - } - - usb_make_path(usb_dev, usbpath, sizeof(usbpath)); - snprintf(card->longname, sizeof(card->longname), - "%s %s (%s)", - dev->vendor_name, dev->product_name, usbpath); - - setup_card(dev); - return 0; -} - -static int __devinit snd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - int ret; - struct snd_card *card; - struct usb_device *device = interface_to_usbdev(intf); - - ret = create_card(device, intf, &card); - - if (ret < 0) - return ret; - - usb_set_intfdata(intf, card); - ret = init_card(caiaqdev(card)); - if (ret < 0) { - log("unable to init card! (ret=%d)\n", ret); - snd_card_free(card); - return ret; - } - - return 0; -} - -static void snd_disconnect(struct usb_interface *intf) -{ - struct snd_usb_caiaqdev *dev; - struct snd_card *card = usb_get_intfdata(intf); - - debug("%s(%p)\n", __func__, intf); - - if (!card) - return; - - dev = caiaqdev(card); - snd_card_disconnect(card); - -#ifdef CONFIG_SND_USB_CAIAQ_INPUT - snd_usb_caiaq_input_free(dev); -#endif - snd_usb_caiaq_audio_free(dev); - - usb_kill_urb(&dev->ep1_in_urb); - usb_kill_urb(&dev->midi_out_urb); - - snd_card_free(card); - usb_reset_device(interface_to_usbdev(intf)); -} - - -MODULE_DEVICE_TABLE(usb, snd_usb_id_table); -static struct usb_driver snd_usb_driver = { - .name = MODNAME, - .probe = snd_probe, - .disconnect = snd_disconnect, - .id_table = snd_usb_id_table, -}; - -module_usb_driver(snd_usb_driver); - diff --git a/ANDROID_3.4.5/sound/usb/caiaq/device.h b/ANDROID_3.4.5/sound/usb/caiaq/device.h deleted file mode 100644 index 562b0bff..00000000 --- a/ANDROID_3.4.5/sound/usb/caiaq/device.h +++ /dev/null @@ -1,140 +0,0 @@ -#ifndef CAIAQ_DEVICE_H -#define CAIAQ_DEVICE_H - -#include "../usbaudio.h" - -#define USB_VID_NATIVEINSTRUMENTS 0x17cc - -#define USB_PID_RIGKONTROL2 0x1969 -#define USB_PID_RIGKONTROL3 0x1940 -#define USB_PID_KORECONTROLLER 0x4711 -#define USB_PID_KORECONTROLLER2 0x4712 -#define USB_PID_AK1 0x0815 -#define USB_PID_AUDIO2DJ 0x041c -#define USB_PID_AUDIO4DJ 0x0839 -#define USB_PID_AUDIO8DJ 0x1978 -#define USB_PID_SESSIONIO 0x1915 -#define USB_PID_GUITARRIGMOBILE 0x0d8d -#define USB_PID_TRAKTORKONTROLX1 0x2305 -#define USB_PID_TRAKTORKONTROLS4 0xbaff -#define USB_PID_TRAKTORAUDIO2 0x041d -#define USB_PID_MASCHINECONTROLLER 0x0808 - -#define EP1_BUFSIZE 64 -#define EP4_BUFSIZE 512 -#define CAIAQ_USB_STR_LEN 0xff -#define MAX_STREAMS 32 - -//#define SND_USB_CAIAQ_DEBUG - -#define MODNAME "snd-usb-caiaq" -#define log(x...) snd_printk(KERN_WARNING MODNAME" log: " x) - -#ifdef SND_USB_CAIAQ_DEBUG -#define debug(x...) snd_printk(KERN_WARNING MODNAME " debug: " x) -#else -#define debug(x...) do { } while(0) -#endif - -#define EP1_CMD_GET_DEVICE_INFO 0x1 -#define EP1_CMD_READ_ERP 0x2 -#define EP1_CMD_READ_ANALOG 0x3 -#define EP1_CMD_READ_IO 0x4 -#define EP1_CMD_WRITE_IO 0x5 -#define EP1_CMD_MIDI_READ 0x6 -#define EP1_CMD_MIDI_WRITE 0x7 -#define EP1_CMD_AUDIO_PARAMS 0x9 -#define EP1_CMD_AUTO_MSG 0xb -#define EP1_CMD_DIMM_LEDS 0xc - -struct caiaq_device_spec { - unsigned short fw_version; - unsigned char hw_subtype; - unsigned char num_erp; - unsigned char num_analog_in; - unsigned char num_digital_in; - unsigned char num_digital_out; - unsigned char num_analog_audio_out; - unsigned char num_analog_audio_in; - unsigned char num_digital_audio_out; - unsigned char num_digital_audio_in; - unsigned char num_midi_out; - unsigned char num_midi_in; - unsigned char data_alignment; -} __attribute__ ((packed)); - -struct snd_usb_caiaq_cb_info; - -struct snd_usb_caiaqdev { - struct snd_usb_audio chip; - - struct urb ep1_in_urb; - struct urb midi_out_urb; - struct urb **data_urbs_in; - struct urb **data_urbs_out; - struct snd_usb_caiaq_cb_info *data_cb_info; - - unsigned char ep1_in_buf[EP1_BUFSIZE]; - unsigned char ep1_out_buf[EP1_BUFSIZE]; - unsigned char midi_out_buf[EP1_BUFSIZE]; - - struct caiaq_device_spec spec; - spinlock_t spinlock; - wait_queue_head_t ep1_wait_queue; - wait_queue_head_t prepare_wait_queue; - int spec_received, audio_parm_answer; - int midi_out_active; - - char vendor_name[CAIAQ_USB_STR_LEN]; - char product_name[CAIAQ_USB_STR_LEN]; - - int n_streams, n_audio_in, n_audio_out; - int streaming, first_packet, output_running; - int audio_in_buf_pos[MAX_STREAMS]; - int audio_out_buf_pos[MAX_STREAMS]; - int period_in_count[MAX_STREAMS]; - int period_out_count[MAX_STREAMS]; - int input_panic, output_panic, warned; - char *audio_in_buf, *audio_out_buf; - unsigned int samplerates, bpp; - unsigned long outurb_active_mask; - - struct snd_pcm_substream *sub_playback[MAX_STREAMS]; - struct snd_pcm_substream *sub_capture[MAX_STREAMS]; - - /* Controls */ - unsigned char control_state[256]; - unsigned char ep8_out_buf[2]; - - /* Linux input */ -#ifdef CONFIG_SND_USB_CAIAQ_INPUT - struct input_dev *input_dev; - char phys[64]; /* physical device path */ - unsigned short keycode[128]; - struct urb *ep4_in_urb; - unsigned char ep4_in_buf[EP4_BUFSIZE]; -#endif - - /* ALSA */ - struct snd_pcm *pcm; - struct snd_pcm_hardware pcm_info; - struct snd_rawmidi *rmidi; - struct snd_rawmidi_substream *midi_receive_substream; - struct snd_rawmidi_substream *midi_out_substream; -}; - -struct snd_usb_caiaq_cb_info { - struct snd_usb_caiaqdev *dev; - int index; -}; - -#define caiaqdev(c) ((struct snd_usb_caiaqdev*)(c)->private_data) - -int snd_usb_caiaq_set_audio_params (struct snd_usb_caiaqdev *dev, int rate, int depth, int bbp); -int snd_usb_caiaq_set_auto_msg (struct snd_usb_caiaqdev *dev, int digital, int analog, int erp); -int snd_usb_caiaq_send_command(struct snd_usb_caiaqdev *dev, - unsigned char command, - const unsigned char *buffer, - int len); - -#endif /* CAIAQ_DEVICE_H */ diff --git a/ANDROID_3.4.5/sound/usb/caiaq/input.c b/ANDROID_3.4.5/sound/usb/caiaq/input.c deleted file mode 100644 index 26a121b4..00000000 --- a/ANDROID_3.4.5/sound/usb/caiaq/input.c +++ /dev/null @@ -1,842 +0,0 @@ -/* - * Copyright (c) 2006,2007 Daniel Mack, Tim Ruetz - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include -#include -#include -#include -#include -#include - -#include "device.h" -#include "input.h" - -static unsigned short keycode_ak1[] = { KEY_C, KEY_B, KEY_A }; -static unsigned short keycode_rk2[] = { KEY_1, KEY_2, KEY_3, KEY_4, - KEY_5, KEY_6, KEY_7 }; -static unsigned short keycode_rk3[] = { KEY_1, KEY_2, KEY_3, KEY_4, - KEY_5, KEY_6, KEY_7, KEY_8, KEY_9 }; - -static unsigned short keycode_kore[] = { - KEY_FN_F1, /* "menu" */ - KEY_FN_F7, /* "lcd backlight */ - KEY_FN_F2, /* "control" */ - KEY_FN_F3, /* "enter" */ - KEY_FN_F4, /* "view" */ - KEY_FN_F5, /* "esc" */ - KEY_FN_F6, /* "sound" */ - KEY_FN_F8, /* array spacer, never triggered. */ - KEY_RIGHT, - KEY_DOWN, - KEY_UP, - KEY_LEFT, - KEY_SOUND, /* "listen" */ - KEY_RECORD, - KEY_PLAYPAUSE, - KEY_STOP, - BTN_4, /* 8 softkeys */ - BTN_3, - BTN_2, - BTN_1, - BTN_8, - BTN_7, - BTN_6, - BTN_5, - KEY_BRL_DOT4, /* touch sensitive knobs */ - KEY_BRL_DOT3, - KEY_BRL_DOT2, - KEY_BRL_DOT1, - KEY_BRL_DOT8, - KEY_BRL_DOT7, - KEY_BRL_DOT6, - KEY_BRL_DOT5 -}; - -#define MASCHINE_BUTTONS (42) -#define MASCHINE_BUTTON(X) ((X) + BTN_MISC) -#define MASCHINE_PADS (16) -#define MASCHINE_PAD(X) ((X) + ABS_PRESSURE) - -static unsigned short keycode_maschine[] = { - MASCHINE_BUTTON(40), /* mute */ - MASCHINE_BUTTON(39), /* solo */ - MASCHINE_BUTTON(38), /* select */ - MASCHINE_BUTTON(37), /* duplicate */ - MASCHINE_BUTTON(36), /* navigate */ - MASCHINE_BUTTON(35), /* pad mode */ - MASCHINE_BUTTON(34), /* pattern */ - MASCHINE_BUTTON(33), /* scene */ - KEY_RESERVED, /* spacer */ - - MASCHINE_BUTTON(30), /* rec */ - MASCHINE_BUTTON(31), /* erase */ - MASCHINE_BUTTON(32), /* shift */ - MASCHINE_BUTTON(28), /* grid */ - MASCHINE_BUTTON(27), /* > */ - MASCHINE_BUTTON(26), /* < */ - MASCHINE_BUTTON(25), /* restart */ - - MASCHINE_BUTTON(21), /* E */ - MASCHINE_BUTTON(22), /* F */ - MASCHINE_BUTTON(23), /* G */ - MASCHINE_BUTTON(24), /* H */ - MASCHINE_BUTTON(20), /* D */ - MASCHINE_BUTTON(19), /* C */ - MASCHINE_BUTTON(18), /* B */ - MASCHINE_BUTTON(17), /* A */ - - MASCHINE_BUTTON(0), /* control */ - MASCHINE_BUTTON(2), /* browse */ - MASCHINE_BUTTON(4), /* < */ - MASCHINE_BUTTON(6), /* snap */ - MASCHINE_BUTTON(7), /* autowrite */ - MASCHINE_BUTTON(5), /* > */ - MASCHINE_BUTTON(3), /* sampling */ - MASCHINE_BUTTON(1), /* step */ - - MASCHINE_BUTTON(15), /* 8 softkeys */ - MASCHINE_BUTTON(14), - MASCHINE_BUTTON(13), - MASCHINE_BUTTON(12), - MASCHINE_BUTTON(11), - MASCHINE_BUTTON(10), - MASCHINE_BUTTON(9), - MASCHINE_BUTTON(8), - - MASCHINE_BUTTON(16), /* note repeat */ - MASCHINE_BUTTON(29) /* play */ -}; - -#define KONTROLX1_INPUTS (40) -#define KONTROLS4_BUTTONS (12 * 8) -#define KONTROLS4_AXIS (46) - -#define KONTROLS4_BUTTON(X) ((X) + BTN_MISC) -#define KONTROLS4_ABS(X) ((X) + ABS_HAT0X) - -#define DEG90 (range / 2) -#define DEG180 (range) -#define DEG270 (DEG90 + DEG180) -#define DEG360 (DEG180 * 2) -#define HIGH_PEAK (268) -#define LOW_PEAK (-7) - -/* some of these devices have endless rotation potentiometers - * built in which use two tapers, 90 degrees phase shifted. - * this algorithm decodes them to one single value, ranging - * from 0 to 999 */ -static unsigned int decode_erp(unsigned char a, unsigned char b) -{ - int weight_a, weight_b; - int pos_a, pos_b; - int ret; - int range = HIGH_PEAK - LOW_PEAK; - int mid_value = (HIGH_PEAK + LOW_PEAK) / 2; - - weight_b = abs(mid_value - a) - (range / 2 - 100) / 2; - - if (weight_b < 0) - weight_b = 0; - - if (weight_b > 100) - weight_b = 100; - - weight_a = 100 - weight_b; - - if (a < mid_value) { - /* 0..90 and 270..360 degrees */ - pos_b = b - LOW_PEAK + DEG270; - if (pos_b >= DEG360) - pos_b -= DEG360; - } else - /* 90..270 degrees */ - pos_b = HIGH_PEAK - b + DEG90; - - - if (b > mid_value) - /* 0..180 degrees */ - pos_a = a - LOW_PEAK; - else - /* 180..360 degrees */ - pos_a = HIGH_PEAK - a + DEG180; - - /* interpolate both slider values, depending on weight factors */ - /* 0..99 x DEG360 */ - ret = pos_a * weight_a + pos_b * weight_b; - - /* normalize to 0..999 */ - ret *= 10; - ret /= DEG360; - - if (ret < 0) - ret += 1000; - - if (ret >= 1000) - ret -= 1000; - - return ret; -} - -#undef DEG90 -#undef DEG180 -#undef DEG270 -#undef DEG360 -#undef HIGH_PEAK -#undef LOW_PEAK - -static inline void snd_caiaq_input_report_abs(struct snd_usb_caiaqdev *dev, - int axis, const unsigned char *buf, - int offset) -{ - input_report_abs(dev->input_dev, axis, - (buf[offset * 2] << 8) | buf[offset * 2 + 1]); -} - -static void snd_caiaq_input_read_analog(struct snd_usb_caiaqdev *dev, - const unsigned char *buf, - unsigned int len) -{ - struct input_dev *input_dev = dev->input_dev; - - switch (dev->chip.usb_id) { - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2): - snd_caiaq_input_report_abs(dev, ABS_X, buf, 2); - snd_caiaq_input_report_abs(dev, ABS_Y, buf, 0); - snd_caiaq_input_report_abs(dev, ABS_Z, buf, 1); - break; - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3): - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER): - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2): - snd_caiaq_input_report_abs(dev, ABS_X, buf, 0); - snd_caiaq_input_report_abs(dev, ABS_Y, buf, 1); - snd_caiaq_input_report_abs(dev, ABS_Z, buf, 2); - break; - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1): - snd_caiaq_input_report_abs(dev, ABS_HAT0X, buf, 4); - snd_caiaq_input_report_abs(dev, ABS_HAT0Y, buf, 2); - snd_caiaq_input_report_abs(dev, ABS_HAT1X, buf, 6); - snd_caiaq_input_report_abs(dev, ABS_HAT1Y, buf, 1); - snd_caiaq_input_report_abs(dev, ABS_HAT2X, buf, 7); - snd_caiaq_input_report_abs(dev, ABS_HAT2Y, buf, 0); - snd_caiaq_input_report_abs(dev, ABS_HAT3X, buf, 5); - snd_caiaq_input_report_abs(dev, ABS_HAT3Y, buf, 3); - break; - } - - input_sync(input_dev); -} - -static void snd_caiaq_input_read_erp(struct snd_usb_caiaqdev *dev, - const char *buf, unsigned int len) -{ - struct input_dev *input_dev = dev->input_dev; - int i; - - switch (dev->chip.usb_id) { - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): - i = decode_erp(buf[0], buf[1]); - input_report_abs(input_dev, ABS_X, i); - input_sync(input_dev); - break; - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER): - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2): - i = decode_erp(buf[7], buf[5]); - input_report_abs(input_dev, ABS_HAT0X, i); - i = decode_erp(buf[12], buf[14]); - input_report_abs(input_dev, ABS_HAT0Y, i); - i = decode_erp(buf[15], buf[13]); - input_report_abs(input_dev, ABS_HAT1X, i); - i = decode_erp(buf[0], buf[2]); - input_report_abs(input_dev, ABS_HAT1Y, i); - i = decode_erp(buf[3], buf[1]); - input_report_abs(input_dev, ABS_HAT2X, i); - i = decode_erp(buf[8], buf[10]); - input_report_abs(input_dev, ABS_HAT2Y, i); - i = decode_erp(buf[11], buf[9]); - input_report_abs(input_dev, ABS_HAT3X, i); - i = decode_erp(buf[4], buf[6]); - input_report_abs(input_dev, ABS_HAT3Y, i); - input_sync(input_dev); - break; - - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER): - /* 4 under the left screen */ - input_report_abs(input_dev, ABS_HAT0X, decode_erp(buf[21], buf[20])); - input_report_abs(input_dev, ABS_HAT0Y, decode_erp(buf[15], buf[14])); - input_report_abs(input_dev, ABS_HAT1X, decode_erp(buf[9], buf[8])); - input_report_abs(input_dev, ABS_HAT1Y, decode_erp(buf[3], buf[2])); - - /* 4 under the right screen */ - input_report_abs(input_dev, ABS_HAT2X, decode_erp(buf[19], buf[18])); - input_report_abs(input_dev, ABS_HAT2Y, decode_erp(buf[13], buf[12])); - input_report_abs(input_dev, ABS_HAT3X, decode_erp(buf[7], buf[6])); - input_report_abs(input_dev, ABS_HAT3Y, decode_erp(buf[1], buf[0])); - - /* volume */ - input_report_abs(input_dev, ABS_RX, decode_erp(buf[17], buf[16])); - /* tempo */ - input_report_abs(input_dev, ABS_RY, decode_erp(buf[11], buf[10])); - /* swing */ - input_report_abs(input_dev, ABS_RZ, decode_erp(buf[5], buf[4])); - - input_sync(input_dev); - break; - } -} - -static void snd_caiaq_input_read_io(struct snd_usb_caiaqdev *dev, - unsigned char *buf, unsigned int len) -{ - struct input_dev *input_dev = dev->input_dev; - unsigned short *keycode = input_dev->keycode; - int i; - - if (!keycode) - return; - - if (input_dev->id.product == USB_PID_RIGKONTROL2) - for (i = 0; i < len; i++) - buf[i] = ~buf[i]; - - for (i = 0; i < input_dev->keycodemax && i < len * 8; i++) - input_report_key(input_dev, keycode[i], - buf[i / 8] & (1 << (i % 8))); - - switch (dev->chip.usb_id) { - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER): - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2): - input_report_abs(dev->input_dev, ABS_MISC, 255 - buf[4]); - break; - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1): - /* rotary encoders */ - input_report_abs(dev->input_dev, ABS_X, buf[5] & 0xf); - input_report_abs(dev->input_dev, ABS_Y, buf[5] >> 4); - input_report_abs(dev->input_dev, ABS_Z, buf[6] & 0xf); - input_report_abs(dev->input_dev, ABS_MISC, buf[6] >> 4); - break; - } - - input_sync(input_dev); -} - -#define TKS4_MSGBLOCK_SIZE 16 - -static void snd_usb_caiaq_tks4_dispatch(struct snd_usb_caiaqdev *dev, - const unsigned char *buf, - unsigned int len) -{ - while (len) { - unsigned int i, block_id = (buf[0] << 8) | buf[1]; - - switch (block_id) { - case 0: - /* buttons */ - for (i = 0; i < KONTROLS4_BUTTONS; i++) - input_report_key(dev->input_dev, KONTROLS4_BUTTON(i), - (buf[4 + (i / 8)] >> (i % 8)) & 1); - break; - - case 1: - /* left wheel */ - input_report_abs(dev->input_dev, KONTROLS4_ABS(36), buf[9] | ((buf[8] & 0x3) << 8)); - /* right wheel */ - input_report_abs(dev->input_dev, KONTROLS4_ABS(37), buf[13] | ((buf[12] & 0x3) << 8)); - - /* rotary encoders */ - input_report_abs(dev->input_dev, KONTROLS4_ABS(38), buf[3] & 0xf); - input_report_abs(dev->input_dev, KONTROLS4_ABS(39), buf[4] >> 4); - input_report_abs(dev->input_dev, KONTROLS4_ABS(40), buf[4] & 0xf); - input_report_abs(dev->input_dev, KONTROLS4_ABS(41), buf[5] >> 4); - input_report_abs(dev->input_dev, KONTROLS4_ABS(42), buf[5] & 0xf); - input_report_abs(dev->input_dev, KONTROLS4_ABS(43), buf[6] >> 4); - input_report_abs(dev->input_dev, KONTROLS4_ABS(44), buf[6] & 0xf); - input_report_abs(dev->input_dev, KONTROLS4_ABS(45), buf[7] >> 4); - input_report_abs(dev->input_dev, KONTROLS4_ABS(46), buf[7] & 0xf); - - break; - case 2: - /* Volume Fader Channel D */ - snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(0), buf, 1); - /* Volume Fader Channel B */ - snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(1), buf, 2); - /* Volume Fader Channel A */ - snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(2), buf, 3); - /* Volume Fader Channel C */ - snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(3), buf, 4); - /* Loop Volume */ - snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(4), buf, 6); - /* Crossfader */ - snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(7), buf, 7); - - break; - - case 3: - /* Tempo Fader R */ - snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(6), buf, 3); - /* Tempo Fader L */ - snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(5), buf, 4); - /* Mic Volume */ - snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(8), buf, 6); - /* Cue Mix */ - snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(9), buf, 7); - - break; - - case 4: - /* Wheel distance sensor L */ - snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(10), buf, 1); - /* Wheel distance sensor R */ - snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(11), buf, 2); - /* Channel D EQ - Filter */ - snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(12), buf, 3); - /* Channel D EQ - Low */ - snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(13), buf, 4); - /* Channel D EQ - Mid */ - snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(14), buf, 5); - /* Channel D EQ - Hi */ - snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(15), buf, 6); - /* FX2 - dry/wet */ - snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(16), buf, 7); - - break; - - case 5: - /* FX2 - 1 */ - snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(17), buf, 1); - /* FX2 - 2 */ - snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(18), buf, 2); - /* FX2 - 3 */ - snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(19), buf, 3); - /* Channel B EQ - Filter */ - snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(20), buf, 4); - /* Channel B EQ - Low */ - snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(21), buf, 5); - /* Channel B EQ - Mid */ - snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(22), buf, 6); - /* Channel B EQ - Hi */ - snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(23), buf, 7); - - break; - - case 6: - /* Channel A EQ - Filter */ - snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(24), buf, 1); - /* Channel A EQ - Low */ - snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(25), buf, 2); - /* Channel A EQ - Mid */ - snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(26), buf, 3); - /* Channel A EQ - Hi */ - snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(27), buf, 4); - /* Channel C EQ - Filter */ - snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(28), buf, 5); - /* Channel C EQ - Low */ - snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(29), buf, 6); - /* Channel C EQ - Mid */ - snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(30), buf, 7); - - break; - - case 7: - /* Channel C EQ - Hi */ - snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(31), buf, 1); - /* FX1 - wet/dry */ - snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(32), buf, 2); - /* FX1 - 1 */ - snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(33), buf, 3); - /* FX1 - 2 */ - snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(34), buf, 4); - /* FX1 - 3 */ - snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(35), buf, 5); - - break; - - default: - debug("%s(): bogus block (id %d)\n", - __func__, block_id); - return; - } - - len -= TKS4_MSGBLOCK_SIZE; - buf += TKS4_MSGBLOCK_SIZE; - } - - input_sync(dev->input_dev); -} - -#define MASCHINE_MSGBLOCK_SIZE 2 - -static void snd_usb_caiaq_maschine_dispatch(struct snd_usb_caiaqdev *dev, - const unsigned char *buf, - unsigned int len) -{ - unsigned int i, pad_id; - uint16_t pressure; - - for (i = 0; i < MASCHINE_PADS; i++) { - pressure = be16_to_cpu(buf[i * 2] << 8 | buf[(i * 2) + 1]); - pad_id = pressure >> 12; - - input_report_abs(dev->input_dev, MASCHINE_PAD(pad_id), pressure & 0xfff); - } - - input_sync(dev->input_dev); -} - -static void snd_usb_caiaq_ep4_reply_dispatch(struct urb *urb) -{ - struct snd_usb_caiaqdev *dev = urb->context; - unsigned char *buf = urb->transfer_buffer; - int ret; - - if (urb->status || !dev || urb != dev->ep4_in_urb) - return; - - switch (dev->chip.usb_id) { - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1): - if (urb->actual_length < 24) - goto requeue; - - if (buf[0] & 0x3) - snd_caiaq_input_read_io(dev, buf + 1, 7); - - if (buf[0] & 0x4) - snd_caiaq_input_read_analog(dev, buf + 8, 16); - - break; - - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4): - snd_usb_caiaq_tks4_dispatch(dev, buf, urb->actual_length); - break; - - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER): - if (urb->actual_length < (MASCHINE_PADS * MASCHINE_MSGBLOCK_SIZE)) - goto requeue; - - snd_usb_caiaq_maschine_dispatch(dev, buf, urb->actual_length); - break; - } - -requeue: - dev->ep4_in_urb->actual_length = 0; - ret = usb_submit_urb(dev->ep4_in_urb, GFP_ATOMIC); - if (ret < 0) - log("unable to submit urb. OOM!?\n"); -} - -static int snd_usb_caiaq_input_open(struct input_dev *idev) -{ - struct snd_usb_caiaqdev *dev = input_get_drvdata(idev); - - if (!dev) - return -EINVAL; - - switch (dev->chip.usb_id) { - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1): - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4): - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER): - if (usb_submit_urb(dev->ep4_in_urb, GFP_KERNEL) != 0) - return -EIO; - break; - } - - return 0; -} - -static void snd_usb_caiaq_input_close(struct input_dev *idev) -{ - struct snd_usb_caiaqdev *dev = input_get_drvdata(idev); - - if (!dev) - return; - - switch (dev->chip.usb_id) { - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1): - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4): - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER): - usb_kill_urb(dev->ep4_in_urb); - break; - } -} - -void snd_usb_caiaq_input_dispatch(struct snd_usb_caiaqdev *dev, - char *buf, - unsigned int len) -{ - if (!dev->input_dev || len < 1) - return; - - switch (buf[0]) { - case EP1_CMD_READ_ANALOG: - snd_caiaq_input_read_analog(dev, buf + 1, len - 1); - break; - case EP1_CMD_READ_ERP: - snd_caiaq_input_read_erp(dev, buf + 1, len - 1); - break; - case EP1_CMD_READ_IO: - snd_caiaq_input_read_io(dev, buf + 1, len - 1); - break; - } -} - -int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev) -{ - struct usb_device *usb_dev = dev->chip.dev; - struct input_dev *input; - int i, ret = 0; - - input = input_allocate_device(); - if (!input) - return -ENOMEM; - - usb_make_path(usb_dev, dev->phys, sizeof(dev->phys)); - strlcat(dev->phys, "/input0", sizeof(dev->phys)); - - input->name = dev->product_name; - input->phys = dev->phys; - usb_to_input_id(usb_dev, &input->id); - input->dev.parent = &usb_dev->dev; - - input_set_drvdata(input, dev); - - switch (dev->chip.usb_id) { - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2): - input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input->absbit[0] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) | - BIT_MASK(ABS_Z); - BUILD_BUG_ON(sizeof(dev->keycode) < sizeof(keycode_rk2)); - memcpy(dev->keycode, keycode_rk2, sizeof(keycode_rk2)); - input->keycodemax = ARRAY_SIZE(keycode_rk2); - input_set_abs_params(input, ABS_X, 0, 4096, 0, 10); - input_set_abs_params(input, ABS_Y, 0, 4096, 0, 10); - input_set_abs_params(input, ABS_Z, 0, 4096, 0, 10); - snd_usb_caiaq_set_auto_msg(dev, 1, 10, 0); - break; - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3): - input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input->absbit[0] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) | - BIT_MASK(ABS_Z); - BUILD_BUG_ON(sizeof(dev->keycode) < sizeof(keycode_rk3)); - memcpy(dev->keycode, keycode_rk3, sizeof(keycode_rk3)); - input->keycodemax = ARRAY_SIZE(keycode_rk3); - input_set_abs_params(input, ABS_X, 0, 1024, 0, 10); - input_set_abs_params(input, ABS_Y, 0, 1024, 0, 10); - input_set_abs_params(input, ABS_Z, 0, 1024, 0, 10); - snd_usb_caiaq_set_auto_msg(dev, 1, 10, 0); - break; - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): - input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input->absbit[0] = BIT_MASK(ABS_X); - BUILD_BUG_ON(sizeof(dev->keycode) < sizeof(keycode_ak1)); - memcpy(dev->keycode, keycode_ak1, sizeof(keycode_ak1)); - input->keycodemax = ARRAY_SIZE(keycode_ak1); - input_set_abs_params(input, ABS_X, 0, 999, 0, 10); - snd_usb_caiaq_set_auto_msg(dev, 1, 0, 5); - break; - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER): - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2): - input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input->absbit[0] = BIT_MASK(ABS_HAT0X) | BIT_MASK(ABS_HAT0Y) | - BIT_MASK(ABS_HAT1X) | BIT_MASK(ABS_HAT1Y) | - BIT_MASK(ABS_HAT2X) | BIT_MASK(ABS_HAT2Y) | - BIT_MASK(ABS_HAT3X) | BIT_MASK(ABS_HAT3Y) | - BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) | - BIT_MASK(ABS_Z); - input->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC); - BUILD_BUG_ON(sizeof(dev->keycode) < sizeof(keycode_kore)); - memcpy(dev->keycode, keycode_kore, sizeof(keycode_kore)); - input->keycodemax = ARRAY_SIZE(keycode_kore); - input_set_abs_params(input, ABS_HAT0X, 0, 999, 0, 10); - input_set_abs_params(input, ABS_HAT0Y, 0, 999, 0, 10); - input_set_abs_params(input, ABS_HAT1X, 0, 999, 0, 10); - input_set_abs_params(input, ABS_HAT1Y, 0, 999, 0, 10); - input_set_abs_params(input, ABS_HAT2X, 0, 999, 0, 10); - input_set_abs_params(input, ABS_HAT2Y, 0, 999, 0, 10); - input_set_abs_params(input, ABS_HAT3X, 0, 999, 0, 10); - input_set_abs_params(input, ABS_HAT3Y, 0, 999, 0, 10); - input_set_abs_params(input, ABS_X, 0, 4096, 0, 10); - input_set_abs_params(input, ABS_Y, 0, 4096, 0, 10); - input_set_abs_params(input, ABS_Z, 0, 4096, 0, 10); - input_set_abs_params(input, ABS_MISC, 0, 255, 0, 1); - snd_usb_caiaq_set_auto_msg(dev, 1, 10, 5); - break; - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1): - input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input->absbit[0] = BIT_MASK(ABS_HAT0X) | BIT_MASK(ABS_HAT0Y) | - BIT_MASK(ABS_HAT1X) | BIT_MASK(ABS_HAT1Y) | - BIT_MASK(ABS_HAT2X) | BIT_MASK(ABS_HAT2Y) | - BIT_MASK(ABS_HAT3X) | BIT_MASK(ABS_HAT3Y) | - BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) | - BIT_MASK(ABS_Z); - input->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC); - BUILD_BUG_ON(sizeof(dev->keycode) < KONTROLX1_INPUTS); - for (i = 0; i < KONTROLX1_INPUTS; i++) - dev->keycode[i] = BTN_MISC + i; - input->keycodemax = KONTROLX1_INPUTS; - - /* analog potentiometers */ - input_set_abs_params(input, ABS_HAT0X, 0, 4096, 0, 10); - input_set_abs_params(input, ABS_HAT0Y, 0, 4096, 0, 10); - input_set_abs_params(input, ABS_HAT1X, 0, 4096, 0, 10); - input_set_abs_params(input, ABS_HAT1Y, 0, 4096, 0, 10); - input_set_abs_params(input, ABS_HAT2X, 0, 4096, 0, 10); - input_set_abs_params(input, ABS_HAT2Y, 0, 4096, 0, 10); - input_set_abs_params(input, ABS_HAT3X, 0, 4096, 0, 10); - input_set_abs_params(input, ABS_HAT3Y, 0, 4096, 0, 10); - - /* rotary encoders */ - input_set_abs_params(input, ABS_X, 0, 0xf, 0, 1); - input_set_abs_params(input, ABS_Y, 0, 0xf, 0, 1); - input_set_abs_params(input, ABS_Z, 0, 0xf, 0, 1); - input_set_abs_params(input, ABS_MISC, 0, 0xf, 0, 1); - - dev->ep4_in_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!dev->ep4_in_urb) { - ret = -ENOMEM; - goto exit_free_idev; - } - - usb_fill_bulk_urb(dev->ep4_in_urb, usb_dev, - usb_rcvbulkpipe(usb_dev, 0x4), - dev->ep4_in_buf, EP4_BUFSIZE, - snd_usb_caiaq_ep4_reply_dispatch, dev); - - snd_usb_caiaq_set_auto_msg(dev, 1, 10, 5); - - break; - - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4): - input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - BUILD_BUG_ON(sizeof(dev->keycode) < KONTROLS4_BUTTONS); - for (i = 0; i < KONTROLS4_BUTTONS; i++) - dev->keycode[i] = KONTROLS4_BUTTON(i); - input->keycodemax = KONTROLS4_BUTTONS; - - for (i = 0; i < KONTROLS4_AXIS; i++) { - int axis = KONTROLS4_ABS(i); - input->absbit[BIT_WORD(axis)] |= BIT_MASK(axis); - } - - /* 36 analog potentiometers and faders */ - for (i = 0; i < 36; i++) - input_set_abs_params(input, KONTROLS4_ABS(i), 0, 0xfff, 0, 10); - - /* 2 encoder wheels */ - input_set_abs_params(input, KONTROLS4_ABS(36), 0, 0x3ff, 0, 1); - input_set_abs_params(input, KONTROLS4_ABS(37), 0, 0x3ff, 0, 1); - - /* 9 rotary encoders */ - for (i = 0; i < 9; i++) - input_set_abs_params(input, KONTROLS4_ABS(38+i), 0, 0xf, 0, 1); - - dev->ep4_in_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!dev->ep4_in_urb) { - ret = -ENOMEM; - goto exit_free_idev; - } - - usb_fill_bulk_urb(dev->ep4_in_urb, usb_dev, - usb_rcvbulkpipe(usb_dev, 0x4), - dev->ep4_in_buf, EP4_BUFSIZE, - snd_usb_caiaq_ep4_reply_dispatch, dev); - - snd_usb_caiaq_set_auto_msg(dev, 1, 10, 5); - - break; - - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER): - input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input->absbit[0] = BIT_MASK(ABS_HAT0X) | BIT_MASK(ABS_HAT0Y) | - BIT_MASK(ABS_HAT1X) | BIT_MASK(ABS_HAT1Y) | - BIT_MASK(ABS_HAT2X) | BIT_MASK(ABS_HAT2Y) | - BIT_MASK(ABS_HAT3X) | BIT_MASK(ABS_HAT3Y) | - BIT_MASK(ABS_RX) | BIT_MASK(ABS_RY) | - BIT_MASK(ABS_RZ); - - BUILD_BUG_ON(sizeof(dev->keycode) < sizeof(keycode_maschine)); - memcpy(dev->keycode, keycode_maschine, sizeof(keycode_maschine)); - input->keycodemax = ARRAY_SIZE(keycode_maschine); - - for (i = 0; i < MASCHINE_PADS; i++) { - input->absbit[0] |= MASCHINE_PAD(i); - input_set_abs_params(input, MASCHINE_PAD(i), 0, 0xfff, 5, 10); - } - - input_set_abs_params(input, ABS_HAT0X, 0, 999, 0, 10); - input_set_abs_params(input, ABS_HAT0Y, 0, 999, 0, 10); - input_set_abs_params(input, ABS_HAT1X, 0, 999, 0, 10); - input_set_abs_params(input, ABS_HAT1Y, 0, 999, 0, 10); - input_set_abs_params(input, ABS_HAT2X, 0, 999, 0, 10); - input_set_abs_params(input, ABS_HAT2Y, 0, 999, 0, 10); - input_set_abs_params(input, ABS_HAT3X, 0, 999, 0, 10); - input_set_abs_params(input, ABS_HAT3Y, 0, 999, 0, 10); - input_set_abs_params(input, ABS_RX, 0, 999, 0, 10); - input_set_abs_params(input, ABS_RY, 0, 999, 0, 10); - input_set_abs_params(input, ABS_RZ, 0, 999, 0, 10); - - dev->ep4_in_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!dev->ep4_in_urb) { - ret = -ENOMEM; - goto exit_free_idev; - } - - usb_fill_bulk_urb(dev->ep4_in_urb, usb_dev, - usb_rcvbulkpipe(usb_dev, 0x4), - dev->ep4_in_buf, EP4_BUFSIZE, - snd_usb_caiaq_ep4_reply_dispatch, dev); - - snd_usb_caiaq_set_auto_msg(dev, 1, 10, 5); - break; - - default: - /* no input methods supported on this device */ - goto exit_free_idev; - } - - input->open = snd_usb_caiaq_input_open; - input->close = snd_usb_caiaq_input_close; - input->keycode = dev->keycode; - input->keycodesize = sizeof(unsigned short); - for (i = 0; i < input->keycodemax; i++) - __set_bit(dev->keycode[i], input->keybit); - - dev->input_dev = input; - - ret = input_register_device(input); - if (ret < 0) - goto exit_free_idev; - - return 0; - -exit_free_idev: - input_free_device(input); - dev->input_dev = NULL; - return ret; -} - -void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *dev) -{ - if (!dev || !dev->input_dev) - return; - - usb_kill_urb(dev->ep4_in_urb); - usb_free_urb(dev->ep4_in_urb); - dev->ep4_in_urb = NULL; - - input_unregister_device(dev->input_dev); - dev->input_dev = NULL; -} diff --git a/ANDROID_3.4.5/sound/usb/caiaq/input.h b/ANDROID_3.4.5/sound/usb/caiaq/input.h deleted file mode 100644 index ced53557..00000000 --- a/ANDROID_3.4.5/sound/usb/caiaq/input.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef CAIAQ_INPUT_H -#define CAIAQ_INPUT_H - -void snd_usb_caiaq_input_dispatch(struct snd_usb_caiaqdev *dev, char *buf, unsigned int len); -int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev); -void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *dev); - -#endif diff --git a/ANDROID_3.4.5/sound/usb/caiaq/midi.c b/ANDROID_3.4.5/sound/usb/caiaq/midi.c deleted file mode 100644 index a1a47088..00000000 --- a/ANDROID_3.4.5/sound/usb/caiaq/midi.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (c) 2006,2007 Daniel Mack - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include -#include -#include -#include -#include - -#include "device.h" -#include "midi.h" - -static int snd_usb_caiaq_midi_input_open(struct snd_rawmidi_substream *substream) -{ - return 0; -} - -static int snd_usb_caiaq_midi_input_close(struct snd_rawmidi_substream *substream) -{ - return 0; -} - -static void snd_usb_caiaq_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) -{ - struct snd_usb_caiaqdev *dev = substream->rmidi->private_data; - - if (!dev) - return; - - dev->midi_receive_substream = up ? substream : NULL; -} - - -static int snd_usb_caiaq_midi_output_open(struct snd_rawmidi_substream *substream) -{ - return 0; -} - -static int snd_usb_caiaq_midi_output_close(struct snd_rawmidi_substream *substream) -{ - struct snd_usb_caiaqdev *dev = substream->rmidi->private_data; - if (dev->midi_out_active) { - usb_kill_urb(&dev->midi_out_urb); - dev->midi_out_active = 0; - } - return 0; -} - -static void snd_usb_caiaq_midi_send(struct snd_usb_caiaqdev *dev, - struct snd_rawmidi_substream *substream) -{ - int len, ret; - - dev->midi_out_buf[0] = EP1_CMD_MIDI_WRITE; - dev->midi_out_buf[1] = 0; /* port */ - len = snd_rawmidi_transmit(substream, dev->midi_out_buf + 3, - EP1_BUFSIZE - 3); - - if (len <= 0) - return; - - dev->midi_out_buf[2] = len; - dev->midi_out_urb.transfer_buffer_length = len+3; - - ret = usb_submit_urb(&dev->midi_out_urb, GFP_ATOMIC); - if (ret < 0) - log("snd_usb_caiaq_midi_send(%p): usb_submit_urb() failed," - "ret=%d, len=%d\n", - substream, ret, len); - else - dev->midi_out_active = 1; -} - -static void snd_usb_caiaq_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) -{ - struct snd_usb_caiaqdev *dev = substream->rmidi->private_data; - - if (up) { - dev->midi_out_substream = substream; - if (!dev->midi_out_active) - snd_usb_caiaq_midi_send(dev, substream); - } else { - dev->midi_out_substream = NULL; - } -} - - -static struct snd_rawmidi_ops snd_usb_caiaq_midi_output = -{ - .open = snd_usb_caiaq_midi_output_open, - .close = snd_usb_caiaq_midi_output_close, - .trigger = snd_usb_caiaq_midi_output_trigger, -}; - -static struct snd_rawmidi_ops snd_usb_caiaq_midi_input = -{ - .open = snd_usb_caiaq_midi_input_open, - .close = snd_usb_caiaq_midi_input_close, - .trigger = snd_usb_caiaq_midi_input_trigger, -}; - -void snd_usb_caiaq_midi_handle_input(struct snd_usb_caiaqdev *dev, - int port, const char *buf, int len) -{ - if (!dev->midi_receive_substream) - return; - - snd_rawmidi_receive(dev->midi_receive_substream, buf, len); -} - -int snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *device) -{ - int ret; - struct snd_rawmidi *rmidi; - - ret = snd_rawmidi_new(device->chip.card, device->product_name, 0, - device->spec.num_midi_out, - device->spec.num_midi_in, - &rmidi); - - if (ret < 0) - return ret; - - strlcpy(rmidi->name, device->product_name, sizeof(rmidi->name)); - - rmidi->info_flags = SNDRV_RAWMIDI_INFO_DUPLEX; - rmidi->private_data = device; - - if (device->spec.num_midi_out > 0) { - rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT; - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, - &snd_usb_caiaq_midi_output); - } - - if (device->spec.num_midi_in > 0) { - rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT; - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, - &snd_usb_caiaq_midi_input); - } - - device->rmidi = rmidi; - - return 0; -} - -void snd_usb_caiaq_midi_output_done(struct urb* urb) -{ - struct snd_usb_caiaqdev *dev = urb->context; - - dev->midi_out_active = 0; - if (urb->status != 0) - return; - - if (!dev->midi_out_substream) - return; - - snd_usb_caiaq_midi_send(dev, dev->midi_out_substream); -} - diff --git a/ANDROID_3.4.5/sound/usb/caiaq/midi.h b/ANDROID_3.4.5/sound/usb/caiaq/midi.h deleted file mode 100644 index 380f984b..00000000 --- a/ANDROID_3.4.5/sound/usb/caiaq/midi.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef CAIAQ_MIDI_H -#define CAIAQ_MIDI_H - -int snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *dev); -void snd_usb_caiaq_midi_handle_input(struct snd_usb_caiaqdev *dev, int port, const char *buf, int len); -void snd_usb_caiaq_midi_output_done(struct urb *urb); - -#endif /* CAIAQ_MIDI_H */ diff --git a/ANDROID_3.4.5/sound/usb/card.c b/ANDROID_3.4.5/sound/usb/card.c deleted file mode 100644 index 4a7be7b9..00000000 --- a/ANDROID_3.4.5/sound/usb/card.c +++ /dev/null @@ -1,729 +0,0 @@ -/* - * (Tentative) USB Audio Driver for ALSA - * - * Copyright (c) 2002 by Takashi Iwai - * - * Many codes borrowed from audio.c by - * Alan Cox (alan@lxorguk.ukuu.org.uk) - * Thomas Sailer (sailer@ife.ee.ethz.ch) - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * NOTES: - * - * - async unlink should be used for avoiding the sleep inside lock. - * 2.4.22 usb-uhci seems buggy for async unlinking and results in - * oops. in such a cse, pass async_unlink=0 option. - * - the linked URBs would be preferred but not used so far because of - * the instability of unlinking. - * - type II is not supported properly. there is no device which supports - * this type *correctly*. SB extigy looks as if it supports, but it's - * indeed an AC3 stream packed in SPDIF frames (i.e. no real AC3 stream). - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "usbaudio.h" -#include "card.h" -#include "midi.h" -#include "mixer.h" -#include "proc.h" -#include "quirks.h" -#include "endpoint.h" -#include "helper.h" -#include "debug.h" -#include "pcm.h" -#include "format.h" -#include "power.h" -#include "stream.h" - -MODULE_AUTHOR("Takashi Iwai "); -MODULE_DESCRIPTION("USB Audio"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Generic,USB Audio}}"); - - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */ -/* Vendor/product IDs for this card */ -static int vid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; -static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; -static int nrpacks = 8; /* max. number of packets per urb */ -static bool async_unlink = 1; -static int device_setup[SNDRV_CARDS]; /* device parameter for this card */ -static bool ignore_ctl_error; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for the USB audio adapter."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for the USB audio adapter."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable USB audio adapter."); -module_param_array(vid, int, NULL, 0444); -MODULE_PARM_DESC(vid, "Vendor ID for the USB audio device."); -module_param_array(pid, int, NULL, 0444); -MODULE_PARM_DESC(pid, "Product ID for the USB audio device."); -module_param(nrpacks, int, 0644); -MODULE_PARM_DESC(nrpacks, "Max. number of packets per URB."); -module_param(async_unlink, bool, 0444); -MODULE_PARM_DESC(async_unlink, "Use async unlink mode."); -module_param_array(device_setup, int, NULL, 0444); -MODULE_PARM_DESC(device_setup, "Specific device setup (if needed)."); -module_param(ignore_ctl_error, bool, 0444); -MODULE_PARM_DESC(ignore_ctl_error, - "Ignore errors from USB controller for mixer interfaces."); - -/* - * we keep the snd_usb_audio_t instances by ourselves for merging - * the all interfaces on the same card as one sound device. - */ - -static DEFINE_MUTEX(register_mutex); -static struct snd_usb_audio *usb_chip[SNDRV_CARDS]; -static struct usb_driver usb_audio_driver; - -/* - * disconnect streams - * called from snd_usb_audio_disconnect() - */ -static void snd_usb_stream_disconnect(struct list_head *head) -{ - int idx; - struct snd_usb_stream *as; - struct snd_usb_substream *subs; - - as = list_entry(head, struct snd_usb_stream, list); - for (idx = 0; idx < 2; idx++) { - subs = &as->substream[idx]; - if (!subs->num_formats) - continue; - snd_usb_release_substream_urbs(subs, 1); - subs->interface = -1; - } -} - -static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int interface) -{ - struct usb_device *dev = chip->dev; - struct usb_host_interface *alts; - struct usb_interface_descriptor *altsd; - struct usb_interface *iface = usb_ifnum_to_if(dev, interface); - - if (!iface) { - snd_printk(KERN_ERR "%d:%u:%d : does not exist\n", - dev->devnum, ctrlif, interface); - return -EINVAL; - } - - if (usb_interface_claimed(iface)) { - snd_printdd(KERN_INFO "%d:%d:%d: skipping, already claimed\n", - dev->devnum, ctrlif, interface); - return -EINVAL; - } - - alts = &iface->altsetting[0]; - altsd = get_iface_desc(alts); - if ((altsd->bInterfaceClass == USB_CLASS_AUDIO || - altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC) && - altsd->bInterfaceSubClass == USB_SUBCLASS_MIDISTREAMING) { - int err = snd_usbmidi_create(chip->card, iface, - &chip->midi_list, NULL); - if (err < 0) { - snd_printk(KERN_ERR "%d:%u:%d: cannot create sequencer device\n", - dev->devnum, ctrlif, interface); - return -EINVAL; - } - usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1L); - - return 0; - } - - if ((altsd->bInterfaceClass != USB_CLASS_AUDIO && - altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC) || - altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIOSTREAMING) { - snd_printdd(KERN_ERR "%d:%u:%d: skipping non-supported interface %d\n", - dev->devnum, ctrlif, interface, altsd->bInterfaceClass); - /* skip non-supported classes */ - return -EINVAL; - } - - if (snd_usb_get_speed(dev) == USB_SPEED_LOW) { - snd_printk(KERN_ERR "low speed audio streaming not supported\n"); - return -EINVAL; - } - - if (! snd_usb_parse_audio_interface(chip, interface)) { - usb_set_interface(dev, interface, 0); /* reset the current interface */ - usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1L); - return -EINVAL; - } - - return 0; -} - -/* - * parse audio control descriptor and create pcm/midi streams - */ -static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif) -{ - struct usb_device *dev = chip->dev; - struct usb_host_interface *host_iface; - struct usb_interface_descriptor *altsd; - void *control_header; - int i, protocol; - - /* find audiocontrol interface */ - host_iface = &usb_ifnum_to_if(dev, ctrlif)->altsetting[0]; - control_header = snd_usb_find_csint_desc(host_iface->extra, - host_iface->extralen, - NULL, UAC_HEADER); - altsd = get_iface_desc(host_iface); - protocol = altsd->bInterfaceProtocol; - - if (!control_header) { - snd_printk(KERN_ERR "cannot find UAC_HEADER\n"); - return -EINVAL; - } - - switch (protocol) { - default: - snd_printdd(KERN_WARNING "unknown interface protocol %#02x, assuming v1\n", - protocol); - /* fall through */ - - case UAC_VERSION_1: { - struct uac1_ac_header_descriptor *h1 = control_header; - - if (!h1->bInCollection) { - snd_printk(KERN_INFO "skipping empty audio interface (v1)\n"); - return -EINVAL; - } - - if (h1->bLength < sizeof(*h1) + h1->bInCollection) { - snd_printk(KERN_ERR "invalid UAC_HEADER (v1)\n"); - return -EINVAL; - } - - for (i = 0; i < h1->bInCollection; i++) - snd_usb_create_stream(chip, ctrlif, h1->baInterfaceNr[i]); - - break; - } - - case UAC_VERSION_2: { - struct usb_interface_assoc_descriptor *assoc = - usb_ifnum_to_if(dev, ctrlif)->intf_assoc; - - if (!assoc) { - snd_printk(KERN_ERR "Audio class v2 interfaces need an interface association\n"); - return -EINVAL; - } - - for (i = 0; i < assoc->bInterfaceCount; i++) { - int intf = assoc->bFirstInterface + i; - - if (intf != ctrlif) - snd_usb_create_stream(chip, ctrlif, intf); - } - - break; - } - } - - return 0; -} - -/* - * free the chip instance - * - * here we have to do not much, since pcm and controls are already freed - * - */ - -static int snd_usb_audio_free(struct snd_usb_audio *chip) -{ - kfree(chip); - return 0; -} - -static int snd_usb_audio_dev_free(struct snd_device *device) -{ - struct snd_usb_audio *chip = device->device_data; - return snd_usb_audio_free(chip); -} - -static void remove_trailing_spaces(char *str) -{ - char *p; - - if (!*str) - return; - for (p = str + strlen(str) - 1; p >= str && isspace(*p); p--) - *p = 0; -} - -/* - * create a chip instance and set its names. - */ -static int snd_usb_audio_create(struct usb_device *dev, int idx, - const struct snd_usb_audio_quirk *quirk, - struct snd_usb_audio **rchip) -{ - struct snd_card *card; - struct snd_usb_audio *chip; - int err, len; - char component[14]; - static struct snd_device_ops ops = { - .dev_free = snd_usb_audio_dev_free, - }; - - *rchip = NULL; - - switch (snd_usb_get_speed(dev)) { - case USB_SPEED_LOW: - case USB_SPEED_FULL: - case USB_SPEED_HIGH: - case USB_SPEED_SUPER: - break; - default: - snd_printk(KERN_ERR "unknown device speed %d\n", snd_usb_get_speed(dev)); - return -ENXIO; - } - - err = snd_card_create(index[idx], id[idx], THIS_MODULE, 0, &card); - if (err < 0) { - snd_printk(KERN_ERR "cannot create card instance %d\n", idx); - return err; - } - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (! chip) { - snd_card_free(card); - return -ENOMEM; - } - - mutex_init(&chip->shutdown_mutex); - chip->index = idx; - chip->dev = dev; - chip->card = card; - chip->setup = device_setup[idx]; - chip->nrpacks = nrpacks; - chip->async_unlink = async_unlink; - chip->probing = 1; - - chip->usb_id = USB_ID(le16_to_cpu(dev->descriptor.idVendor), - le16_to_cpu(dev->descriptor.idProduct)); - INIT_LIST_HEAD(&chip->pcm_list); - INIT_LIST_HEAD(&chip->midi_list); - INIT_LIST_HEAD(&chip->mixer_list); - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - snd_usb_audio_free(chip); - snd_card_free(card); - return err; - } - - strcpy(card->driver, "USB-Audio"); - sprintf(component, "USB%04x:%04x", - USB_ID_VENDOR(chip->usb_id), USB_ID_PRODUCT(chip->usb_id)); - snd_component_add(card, component); - - /* retrieve the device string as shortname */ - if (quirk && quirk->product_name && *quirk->product_name) { - strlcpy(card->shortname, quirk->product_name, sizeof(card->shortname)); - } else { - if (!dev->descriptor.iProduct || - usb_string(dev, dev->descriptor.iProduct, - card->shortname, sizeof(card->shortname)) <= 0) { - /* no name available from anywhere, so use ID */ - sprintf(card->shortname, "USB Device %#04x:%#04x", - USB_ID_VENDOR(chip->usb_id), - USB_ID_PRODUCT(chip->usb_id)); - } - } - remove_trailing_spaces(card->shortname); - - /* retrieve the vendor and device strings as longname */ - if (quirk && quirk->vendor_name && *quirk->vendor_name) { - len = strlcpy(card->longname, quirk->vendor_name, sizeof(card->longname)); - } else { - if (dev->descriptor.iManufacturer) - len = usb_string(dev, dev->descriptor.iManufacturer, - card->longname, sizeof(card->longname)); - else - len = 0; - /* we don't really care if there isn't any vendor string */ - } - if (len > 0) { - remove_trailing_spaces(card->longname); - if (*card->longname) - strlcat(card->longname, " ", sizeof(card->longname)); - } - - strlcat(card->longname, card->shortname, sizeof(card->longname)); - - len = strlcat(card->longname, " at ", sizeof(card->longname)); - - if (len < sizeof(card->longname)) - usb_make_path(dev, card->longname + len, sizeof(card->longname) - len); - - switch (snd_usb_get_speed(dev)) { - case USB_SPEED_LOW: - strlcat(card->longname, ", low speed", sizeof(card->longname)); - break; - case USB_SPEED_FULL: - strlcat(card->longname, ", full speed", sizeof(card->longname)); - break; - case USB_SPEED_HIGH: - strlcat(card->longname, ", high speed", sizeof(card->longname)); - break; - case USB_SPEED_SUPER: - strlcat(card->longname, ", super speed", sizeof(card->longname)); - break; - default: - break; - } - - snd_usb_audio_create_proc(chip); - - *rchip = chip; - return 0; -} - -/* - * probe the active usb device - * - * note that this can be called multiple times per a device, when it - * includes multiple audio control interfaces. - * - * thus we check the usb device pointer and creates the card instance - * only at the first time. the successive calls of this function will - * append the pcm interface to the corresponding card. - */ -static struct snd_usb_audio * -snd_usb_audio_probe(struct usb_device *dev, - struct usb_interface *intf, - const struct usb_device_id *usb_id) -{ - const struct snd_usb_audio_quirk *quirk = (const struct snd_usb_audio_quirk *)usb_id->driver_info; - int i, err; - struct snd_usb_audio *chip; - struct usb_host_interface *alts; - int ifnum; - u32 id; - - alts = &intf->altsetting[0]; - ifnum = get_iface_desc(alts)->bInterfaceNumber; - id = USB_ID(le16_to_cpu(dev->descriptor.idVendor), - le16_to_cpu(dev->descriptor.idProduct)); - if (quirk && quirk->ifnum >= 0 && ifnum != quirk->ifnum) - goto __err_val; - - if (snd_usb_apply_boot_quirk(dev, intf, quirk) < 0) - goto __err_val; - - /* - * found a config. now register to ALSA - */ - - /* check whether it's already registered */ - chip = NULL; - mutex_lock(®ister_mutex); - for (i = 0; i < SNDRV_CARDS; i++) { - if (usb_chip[i] && usb_chip[i]->dev == dev) { - if (usb_chip[i]->shutdown) { - snd_printk(KERN_ERR "USB device is in the shutdown state, cannot create a card instance\n"); - goto __error; - } - chip = usb_chip[i]; - chip->probing = 1; - break; - } - } - if (! chip) { - /* it's a fresh one. - * now look for an empty slot and create a new card instance - */ - for (i = 0; i < SNDRV_CARDS; i++) - if (enable[i] && ! usb_chip[i] && - (vid[i] == -1 || vid[i] == USB_ID_VENDOR(id)) && - (pid[i] == -1 || pid[i] == USB_ID_PRODUCT(id))) { - if (snd_usb_audio_create(dev, i, quirk, &chip) < 0) { - goto __error; - } - snd_card_set_dev(chip->card, &intf->dev); - chip->pm_intf = intf; - break; - } - if (!chip) { - printk(KERN_ERR "no available usb audio device\n"); - goto __error; - } - } - - /* - * For devices with more than one control interface, we assume the - * first contains the audio controls. We might need a more specific - * check here in the future. - */ - if (!chip->ctrl_intf) - chip->ctrl_intf = alts; - - chip->txfr_quirk = 0; - err = 1; /* continue */ - if (quirk && quirk->ifnum != QUIRK_NO_INTERFACE) { - /* need some special handlings */ - if ((err = snd_usb_create_quirk(chip, intf, &usb_audio_driver, quirk)) < 0) - goto __error; - } - - if (err > 0) { - /* create normal USB audio interfaces */ - if (snd_usb_create_streams(chip, ifnum) < 0 || - snd_usb_create_mixer(chip, ifnum, ignore_ctl_error) < 0) { - goto __error; - } - } - - /* we are allowed to call snd_card_register() many times */ - if (snd_card_register(chip->card) < 0) { - goto __error; - } - - usb_chip[chip->index] = chip; - chip->num_interfaces++; - chip->probing = 0; - mutex_unlock(®ister_mutex); - return chip; - - __error: - if (chip) { - if (!chip->num_interfaces) - snd_card_free(chip->card); - chip->probing = 0; - } - mutex_unlock(®ister_mutex); - __err_val: - return NULL; -} - -/* - * we need to take care of counter, since disconnection can be called also - * many times as well as usb_audio_probe(). - */ -static void snd_usb_audio_disconnect(struct usb_device *dev, - struct snd_usb_audio *chip) -{ - struct snd_card *card; - struct list_head *p; - - if (chip == (void *)-1L) - return; - - card = chip->card; - mutex_lock(®ister_mutex); - mutex_lock(&chip->shutdown_mutex); - chip->shutdown = 1; - chip->num_interfaces--; - if (chip->num_interfaces <= 0) { - snd_card_disconnect(card); - /* release the pcm resources */ - list_for_each(p, &chip->pcm_list) { - snd_usb_stream_disconnect(p); - } - /* release the midi resources */ - list_for_each(p, &chip->midi_list) { - snd_usbmidi_disconnect(p); - } - /* release mixer resources */ - list_for_each(p, &chip->mixer_list) { - snd_usb_mixer_disconnect(p); - } - usb_chip[chip->index] = NULL; - mutex_unlock(&chip->shutdown_mutex); - mutex_unlock(®ister_mutex); - snd_card_free_when_closed(card); - } else { - mutex_unlock(&chip->shutdown_mutex); - mutex_unlock(®ister_mutex); - } -} - -/* - * new 2.5 USB kernel API - */ -static int usb_audio_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct snd_usb_audio *chip; - chip = snd_usb_audio_probe(interface_to_usbdev(intf), intf, id); - if (chip) { - usb_set_intfdata(intf, chip); - return 0; - } else - return -EIO; -} - -static void usb_audio_disconnect(struct usb_interface *intf) -{ - snd_usb_audio_disconnect(interface_to_usbdev(intf), - usb_get_intfdata(intf)); -} - -#ifdef CONFIG_PM - -int snd_usb_autoresume(struct snd_usb_audio *chip) -{ - int err = -ENODEV; - - if (!chip->shutdown && !chip->probing) - err = usb_autopm_get_interface(chip->pm_intf); - - return err; -} - -void snd_usb_autosuspend(struct snd_usb_audio *chip) -{ - if (!chip->shutdown && !chip->probing) - usb_autopm_put_interface(chip->pm_intf); -} - -static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct snd_usb_audio *chip = usb_get_intfdata(intf); - struct list_head *p; - struct snd_usb_stream *as; - struct usb_mixer_interface *mixer; - - if (chip == (void *)-1L) - return 0; - - if (!PMSG_IS_AUTO(message)) { - snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot); - if (!chip->num_suspended_intf++) { - list_for_each(p, &chip->pcm_list) { - as = list_entry(p, struct snd_usb_stream, list); - snd_pcm_suspend_all(as->pcm); - } - } - } else { - /* - * otherwise we keep the rest of the system in the dark - * to keep this transparent - */ - if (!chip->num_suspended_intf++) - chip->autosuspended = 1; - } - - list_for_each_entry(mixer, &chip->mixer_list, list) - snd_usb_mixer_inactivate(mixer); - - return 0; -} - -static int usb_audio_resume(struct usb_interface *intf) -{ - struct snd_usb_audio *chip = usb_get_intfdata(intf); - struct usb_mixer_interface *mixer; - int err = 0; - - if (chip == (void *)-1L) - return 0; - if (--chip->num_suspended_intf) - return 0; - /* - * ALSA leaves material resumption to user space - * we just notify and restart the mixers - */ - list_for_each_entry(mixer, &chip->mixer_list, list) { - err = snd_usb_mixer_activate(mixer); - if (err < 0) - goto err_out; - } - - if (!chip->autosuspended) - snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0); - chip->autosuspended = 0; - -err_out: - return err; -} -#else -#define usb_audio_suspend NULL -#define usb_audio_resume NULL -#endif /* CONFIG_PM */ - -static struct usb_device_id usb_audio_ids [] = { -#include "quirks-table.h" - { .match_flags = (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS), - .bInterfaceClass = USB_CLASS_AUDIO, - .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE (usb, usb_audio_ids); - -/* - * entry point for linux usb interface - */ - -static struct usb_driver usb_audio_driver = { - .name = "snd-usb-audio", - .probe = usb_audio_probe, - .disconnect = usb_audio_disconnect, - .suspend = usb_audio_suspend, - .resume = usb_audio_resume, - .id_table = usb_audio_ids, - .supports_autosuspend = 1, -}; - -static int __init snd_usb_audio_init(void) -{ - if (nrpacks < 1 || nrpacks > MAX_PACKS) { - printk(KERN_WARNING "invalid nrpacks value.\n"); - return -EINVAL; - } - return usb_register(&usb_audio_driver); -} - -static void __exit snd_usb_audio_cleanup(void) -{ - usb_deregister(&usb_audio_driver); -} - -module_init(snd_usb_audio_init); -module_exit(snd_usb_audio_cleanup); diff --git a/ANDROID_3.4.5/sound/usb/card.h b/ANDROID_3.4.5/sound/usb/card.h deleted file mode 100644 index da5fa1ac..00000000 --- a/ANDROID_3.4.5/sound/usb/card.h +++ /dev/null @@ -1,111 +0,0 @@ -#ifndef __USBAUDIO_CARD_H -#define __USBAUDIO_CARD_H - -#define MAX_NR_RATES 1024 -#define MAX_PACKS 20 -#define MAX_PACKS_HS (MAX_PACKS * 8) /* in high speed mode */ -#define MAX_URBS 8 -#define SYNC_URBS 4 /* always four urbs for sync */ -#define MAX_QUEUE 24 /* try not to exceed this queue length, in ms */ - -struct audioformat { - struct list_head list; - u64 formats; /* ALSA format bits */ - unsigned int channels; /* # channels */ - unsigned int fmt_type; /* USB audio format type (1-3) */ - unsigned int frame_size; /* samples per frame for non-audio */ - int iface; /* interface number */ - unsigned char altsetting; /* corresponding alternate setting */ - unsigned char altset_idx; /* array index of altenate setting */ - unsigned char attributes; /* corresponding attributes of cs endpoint */ - unsigned char endpoint; /* endpoint */ - unsigned char ep_attr; /* endpoint attributes */ - unsigned char datainterval; /* log_2 of data packet interval */ - unsigned int maxpacksize; /* max. packet size */ - unsigned int rates; /* rate bitmasks */ - unsigned int rate_min, rate_max; /* min/max rates */ - unsigned int nr_rates; /* number of rate table entries */ - unsigned int *rate_table; /* rate table */ - unsigned char clock; /* associated clock */ -}; - -struct snd_usb_substream; - -struct snd_urb_ctx { - struct urb *urb; - unsigned int buffer_size; /* size of data buffer, if data URB */ - struct snd_usb_substream *subs; - int index; /* index for urb array */ - int packets; /* number of packets per urb */ -}; - -struct snd_urb_ops { - int (*prepare)(struct snd_usb_substream *subs, struct snd_pcm_runtime *runtime, struct urb *u); - int (*retire)(struct snd_usb_substream *subs, struct snd_pcm_runtime *runtime, struct urb *u); - int (*prepare_sync)(struct snd_usb_substream *subs, struct snd_pcm_runtime *runtime, struct urb *u); - int (*retire_sync)(struct snd_usb_substream *subs, struct snd_pcm_runtime *runtime, struct urb *u); -}; - -struct snd_usb_substream { - struct snd_usb_stream *stream; - struct usb_device *dev; - struct snd_pcm_substream *pcm_substream; - int direction; /* playback or capture */ - int interface; /* current interface */ - int endpoint; /* assigned endpoint */ - struct audioformat *cur_audiofmt; /* current audioformat pointer (for hw_params callback) */ - unsigned int cur_rate; /* current rate (for hw_params callback) */ - unsigned int period_bytes; /* current period bytes (for hw_params callback) */ - unsigned int altset_idx; /* USB data format: index of alternate setting */ - unsigned int datapipe; /* the data i/o pipe */ - unsigned int syncpipe; /* 1 - async out or adaptive in */ - unsigned int datainterval; /* log_2 of data packet interval */ - unsigned int syncinterval; /* P for adaptive mode, 0 otherwise */ - unsigned int freqn; /* nominal sampling rate in fs/fps in Q16.16 format */ - unsigned int freqm; /* momentary sampling rate in fs/fps in Q16.16 format */ - int freqshift; /* how much to shift the feedback value to get Q16.16 */ - unsigned int freqmax; /* maximum sampling rate, used for buffer management */ - unsigned int phase; /* phase accumulator */ - unsigned int maxpacksize; /* max packet size in bytes */ - unsigned int maxframesize; /* max packet size in frames */ - unsigned int curpacksize; /* current packet size in bytes (for capture) */ - unsigned int curframesize; /* current packet size in frames (for capture) */ - unsigned int syncmaxsize; /* sync endpoint packet size */ - unsigned int fill_max: 1; /* fill max packet size always */ - unsigned int txfr_quirk:1; /* allow sub-frame alignment */ - unsigned int fmt_type; /* USB audio format type (1-3) */ - - unsigned int running: 1; /* running status */ - - unsigned int hwptr_done; /* processed byte position in the buffer */ - unsigned int transfer_done; /* processed frames since last period update */ - unsigned long active_mask; /* bitmask of active urbs */ - unsigned long unlink_mask; /* bitmask of unlinked urbs */ - - unsigned int nurbs; /* # urbs */ - struct snd_urb_ctx dataurb[MAX_URBS]; /* data urb table */ - struct snd_urb_ctx syncurb[SYNC_URBS]; /* sync urb table */ - char *syncbuf; /* sync buffer for all sync URBs */ - dma_addr_t sync_dma; /* DMA address of syncbuf */ - - u64 formats; /* format bitmasks (all or'ed) */ - unsigned int num_formats; /* number of supported audio formats (list) */ - struct list_head fmt_list; /* format list */ - struct snd_pcm_hw_constraint_list rate_list; /* limited rates */ - spinlock_t lock; - - struct snd_urb_ops ops; /* callbacks (must be filled at init) */ - int last_frame_number; /* stored frame number */ - int last_delay; /* stored delay */ -}; - -struct snd_usb_stream { - struct snd_usb_audio *chip; - struct snd_pcm *pcm; - int pcm_index; - unsigned int fmt_type; /* USB audio format type (1-3) */ - struct snd_usb_substream substream[2]; - struct list_head list; -}; - -#endif /* __USBAUDIO_CARD_H */ diff --git a/ANDROID_3.4.5/sound/usb/clock.c b/ANDROID_3.4.5/sound/usb/clock.c deleted file mode 100644 index 6026e0e1..00000000 --- a/ANDROID_3.4.5/sound/usb/clock.c +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Clock domain and sample rate management functions - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "usbaudio.h" -#include "card.h" -#include "helper.h" -#include "clock.h" - -static struct uac_clock_source_descriptor * - snd_usb_find_clock_source(struct usb_host_interface *ctrl_iface, - int clock_id) -{ - struct uac_clock_source_descriptor *cs = NULL; - - while ((cs = snd_usb_find_csint_desc(ctrl_iface->extra, - ctrl_iface->extralen, - cs, UAC2_CLOCK_SOURCE))) { - if (cs->bClockID == clock_id) - return cs; - } - - return NULL; -} - -static struct uac_clock_selector_descriptor * - snd_usb_find_clock_selector(struct usb_host_interface *ctrl_iface, - int clock_id) -{ - struct uac_clock_selector_descriptor *cs = NULL; - - while ((cs = snd_usb_find_csint_desc(ctrl_iface->extra, - ctrl_iface->extralen, - cs, UAC2_CLOCK_SELECTOR))) { - if (cs->bClockID == clock_id) - return cs; - } - - return NULL; -} - -static struct uac_clock_multiplier_descriptor * - snd_usb_find_clock_multiplier(struct usb_host_interface *ctrl_iface, - int clock_id) -{ - struct uac_clock_multiplier_descriptor *cs = NULL; - - while ((cs = snd_usb_find_csint_desc(ctrl_iface->extra, - ctrl_iface->extralen, - cs, UAC2_CLOCK_MULTIPLIER))) { - if (cs->bClockID == clock_id) - return cs; - } - - return NULL; -} - -static int uac_clock_selector_get_val(struct snd_usb_audio *chip, int selector_id) -{ - unsigned char buf; - int ret; - - ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), - UAC2_CS_CUR, - USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, - UAC2_CX_CLOCK_SELECTOR << 8, - snd_usb_ctrl_intf(chip) | (selector_id << 8), - &buf, sizeof(buf)); - - if (ret < 0) - return ret; - - return buf; -} - -static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, int source_id) -{ - int err; - unsigned char data; - struct usb_device *dev = chip->dev; - struct uac_clock_source_descriptor *cs_desc = - snd_usb_find_clock_source(chip->ctrl_intf, source_id); - - if (!cs_desc) - return 0; - - /* If a clock source can't tell us whether it's valid, we assume it is */ - if (!uac2_control_is_readable(cs_desc->bmControls, UAC2_CS_CONTROL_CLOCK_VALID)) - return 1; - - err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR, - USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, - UAC2_CS_CONTROL_CLOCK_VALID << 8, - snd_usb_ctrl_intf(chip) | (source_id << 8), - &data, sizeof(data)); - - if (err < 0) { - snd_printk(KERN_WARNING "%s(): cannot get clock validity for id %d\n", - __func__, source_id); - return 0; - } - - return !!data; -} - -static int __uac_clock_find_source(struct snd_usb_audio *chip, - int entity_id, unsigned long *visited) -{ - struct uac_clock_source_descriptor *source; - struct uac_clock_selector_descriptor *selector; - struct uac_clock_multiplier_descriptor *multiplier; - - entity_id &= 0xff; - - if (test_and_set_bit(entity_id, visited)) { - snd_printk(KERN_WARNING - "%s(): recursive clock topology detected, id %d.\n", - __func__, entity_id); - return -EINVAL; - } - - /* first, see if the ID we're looking for is a clock source already */ - source = snd_usb_find_clock_source(chip->ctrl_intf, entity_id); - if (source) - return source->bClockID; - - selector = snd_usb_find_clock_selector(chip->ctrl_intf, entity_id); - if (selector) { - int ret; - - /* the entity ID we are looking for is a selector. - * find out what it currently selects */ - ret = uac_clock_selector_get_val(chip, selector->bClockID); - if (ret < 0) - return ret; - - /* Selector values are one-based */ - - if (ret > selector->bNrInPins || ret < 1) { - printk(KERN_ERR - "%s(): selector reported illegal value, id %d, ret %d\n", - __func__, selector->bClockID, ret); - - return -EINVAL; - } - - return __uac_clock_find_source(chip, selector->baCSourceID[ret-1], - visited); - } - - /* FIXME: multipliers only act as pass-thru element for now */ - multiplier = snd_usb_find_clock_multiplier(chip->ctrl_intf, entity_id); - if (multiplier) - return __uac_clock_find_source(chip, multiplier->bCSourceID, - visited); - - return -EINVAL; -} - -/* - * For all kinds of sample rate settings and other device queries, - * the clock source (end-leaf) must be used. However, clock selectors, - * clock multipliers and sample rate converters may be specified as - * clock source input to terminal. This functions walks the clock path - * to its end and tries to find the source. - * - * The 'visited' bitfield is used internally to detect recursive loops. - * - * Returns the clock source UnitID (>=0) on success, or an error. - */ -int snd_usb_clock_find_source(struct snd_usb_audio *chip, int entity_id) -{ - DECLARE_BITMAP(visited, 256); - memset(visited, 0, sizeof(visited)); - return __uac_clock_find_source(chip, entity_id, visited); -} - -static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface, - struct usb_host_interface *alts, - struct audioformat *fmt, int rate) -{ - struct usb_device *dev = chip->dev; - unsigned int ep; - unsigned char data[3]; - int err, crate; - - ep = get_endpoint(alts, 0)->bEndpointAddress; - - /* if endpoint doesn't have sampling rate control, bail out */ - if (!(fmt->attributes & UAC_EP_CS_ATTR_SAMPLE_RATE)) - return 0; - - data[0] = rate; - data[1] = rate >> 8; - data[2] = rate >> 16; - if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR, - USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT, - UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep, - data, sizeof(data))) < 0) { - snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep %#x\n", - dev->devnum, iface, fmt->altsetting, rate, ep); - //return err; //just not return, otherwise, logitech camera mic,can't use 2013-10-23 - //printk("%s snd_usb_ctl_msg set rate err! \n", __FUNCTION__); - //return 0;//dbg if application set the rate that usb audio support just return 0! 2013-10-23 - } - - if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR, - USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_IN, - UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep, - data, sizeof(data))) < 0) { - snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep %#x\n", - dev->devnum, iface, fmt->altsetting, ep); - printk("%s snd_usb_ctl_msg get rate err!\n", __FUNCTION__); - return 0; /* some devices don't support reading */ - } - - crate = data[0] | (data[1] << 8) | (data[2] << 16); - printk("%s snd_usb_ctl_msg get rate 2 :%d!\n", __FUNCTION__, crate); - if (crate != rate) { - snd_printd(KERN_WARNING "current rate %d is different from the runtime rate %d\n", crate, rate); - // runtime->rate = crate; - } - - return 0; -} - -static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface, - struct usb_host_interface *alts, - struct audioformat *fmt, int rate) -{ - struct usb_device *dev = chip->dev; - unsigned char data[4]; - int err, crate; - int clock = snd_usb_clock_find_source(chip, fmt->clock); - - if (clock < 0) - return clock; - - if (!uac_clock_source_is_valid(chip, clock)) { - /* TODO: should we try to find valid clock setups by ourself? */ - snd_printk(KERN_ERR "%d:%d:%d: clock source %d is not valid, cannot use\n", - dev->devnum, iface, fmt->altsetting, clock); - return -ENXIO; - } - - data[0] = rate; - data[1] = rate >> 8; - data[2] = rate >> 16; - data[3] = rate >> 24; - if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR, - USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, - UAC2_CS_CONTROL_SAM_FREQ << 8, - snd_usb_ctrl_intf(chip) | (clock << 8), - data, sizeof(data))) < 0) { - snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d (v2)\n", - dev->devnum, iface, fmt->altsetting, rate); - return err; - } - - if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR, - USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, - UAC2_CS_CONTROL_SAM_FREQ << 8, - snd_usb_ctrl_intf(chip) | (clock << 8), - data, sizeof(data))) < 0) { - snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq (v2)\n", - dev->devnum, iface, fmt->altsetting); - return err; - } - - crate = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); - if (crate != rate) - snd_printd(KERN_WARNING "current rate %d is different from the runtime rate %d\n", crate, rate); - - return 0; -} - -int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface, - struct usb_host_interface *alts, - struct audioformat *fmt, int rate) -{ - struct usb_interface_descriptor *altsd = get_iface_desc(alts); - - switch (altsd->bInterfaceProtocol) { - case UAC_VERSION_1: - default: - return set_sample_rate_v1(chip, iface, alts, fmt, rate); - - case UAC_VERSION_2: - return set_sample_rate_v2(chip, iface, alts, fmt, rate); - } -} - diff --git a/ANDROID_3.4.5/sound/usb/clock.h b/ANDROID_3.4.5/sound/usb/clock.h deleted file mode 100644 index 46630936..00000000 --- a/ANDROID_3.4.5/sound/usb/clock.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __USBAUDIO_CLOCK_H -#define __USBAUDIO_CLOCK_H - -int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface, - struct usb_host_interface *alts, - struct audioformat *fmt, int rate); - -int snd_usb_clock_find_source(struct snd_usb_audio *chip, int entity_id); - -#endif /* __USBAUDIO_CLOCK_H */ diff --git a/ANDROID_3.4.5/sound/usb/debug.h b/ANDROID_3.4.5/sound/usb/debug.h deleted file mode 100644 index 58030176..00000000 --- a/ANDROID_3.4.5/sound/usb/debug.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef __USBAUDIO_DEBUG_H -#define __USBAUDIO_DEBUG_H - -/* - * h/w constraints - */ - -#ifdef HW_CONST_DEBUG -#define hwc_debug(fmt, args...) printk(KERN_DEBUG fmt, ##args) -#else -#define hwc_debug(fmt, args...) do { } while(0) -#endif - -#endif /* __USBAUDIO_DEBUG_H */ - diff --git a/ANDROID_3.4.5/sound/usb/endpoint.c b/ANDROID_3.4.5/sound/usb/endpoint.c deleted file mode 100644 index 08dcce53..00000000 --- a/ANDROID_3.4.5/sound/usb/endpoint.c +++ /dev/null @@ -1,966 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include - -#include -#include - -#include "usbaudio.h" -#include "helper.h" -#include "card.h" -#include "endpoint.h" -#include "pcm.h" - -/* - * convert a sampling rate into our full speed format (fs/1000 in Q16.16) - * this will overflow at approx 524 kHz - */ -static inline unsigned get_usb_full_speed_rate(unsigned int rate) -{ - return ((rate << 13) + 62) / 125; -} - -/* - * convert a sampling rate into USB high speed format (fs/8000 in Q16.16) - * this will overflow at approx 4 MHz - */ -static inline unsigned get_usb_high_speed_rate(unsigned int rate) -{ - return ((rate << 10) + 62) / 125; -} - -/* - * unlink active urbs. - */ -static int deactivate_urbs(struct snd_usb_substream *subs, int force, int can_sleep) -{ - struct snd_usb_audio *chip = subs->stream->chip; - unsigned int i; - int async; - - subs->running = 0; - - if (!force && subs->stream->chip->shutdown) /* to be sure... */ - return -EBADFD; - - async = !can_sleep && chip->async_unlink; - - if (!async && in_interrupt()) - return 0; - - for (i = 0; i < subs->nurbs; i++) { - if (test_bit(i, &subs->active_mask)) { - if (!test_and_set_bit(i, &subs->unlink_mask)) { - struct urb *u = subs->dataurb[i].urb; - if (async) - usb_unlink_urb(u); - else - usb_kill_urb(u); - } - } - } - if (subs->syncpipe) { - for (i = 0; i < SYNC_URBS; i++) { - if (test_bit(i+16, &subs->active_mask)) { - if (!test_and_set_bit(i+16, &subs->unlink_mask)) { - struct urb *u = subs->syncurb[i].urb; - if (async) - usb_unlink_urb(u); - else - usb_kill_urb(u); - } - } - } - } - return 0; -} - - -/* - * release a urb data - */ -static void release_urb_ctx(struct snd_urb_ctx *u) -{ - if (u->urb) { - if (u->buffer_size) - usb_free_coherent(u->subs->dev, u->buffer_size, - u->urb->transfer_buffer, - u->urb->transfer_dma); - usb_free_urb(u->urb); - u->urb = NULL; - } -} - -/* - * wait until all urbs are processed. - */ -static int wait_clear_urbs(struct snd_usb_substream *subs) -{ - unsigned long end_time = jiffies + msecs_to_jiffies(1000); - unsigned int i; - int alive; - - do { - alive = 0; - for (i = 0; i < subs->nurbs; i++) { - if (test_bit(i, &subs->active_mask)) - alive++; - } - if (subs->syncpipe) { - for (i = 0; i < SYNC_URBS; i++) { - if (test_bit(i + 16, &subs->active_mask)) - alive++; - } - } - if (! alive) - break; - schedule_timeout_uninterruptible(1); - } while (time_before(jiffies, end_time)); - if (alive) - snd_printk(KERN_ERR "timeout: still %d active urbs..\n", alive); - return 0; -} - -/* - * release a substream - */ -void snd_usb_release_substream_urbs(struct snd_usb_substream *subs, int force) -{ - int i; - - /* stop urbs (to be sure) */ - deactivate_urbs(subs, force, 1); - wait_clear_urbs(subs); - - for (i = 0; i < MAX_URBS; i++) - release_urb_ctx(&subs->dataurb[i]); - for (i = 0; i < SYNC_URBS; i++) - release_urb_ctx(&subs->syncurb[i]); - usb_free_coherent(subs->dev, SYNC_URBS * 4, - subs->syncbuf, subs->sync_dma); - subs->syncbuf = NULL; - subs->nurbs = 0; -} - -/* - * complete callback from data urb - */ -static void snd_complete_urb(struct urb *urb) -{ - struct snd_urb_ctx *ctx = urb->context; - struct snd_usb_substream *subs = ctx->subs; - struct snd_pcm_substream *substream = ctx->subs->pcm_substream; - int err = 0; - - if ((subs->running && subs->ops.retire(subs, substream->runtime, urb)) || - !subs->running || /* can be stopped during retire callback */ - (err = subs->ops.prepare(subs, substream->runtime, urb)) < 0 || - (err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) { - clear_bit(ctx->index, &subs->active_mask); - if (err < 0) { - snd_printd(KERN_ERR "cannot submit urb (err = %d)\n", err); - snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); - } - } -} - - -/* - * complete callback from sync urb - */ -static void snd_complete_sync_urb(struct urb *urb) -{ - struct snd_urb_ctx *ctx = urb->context; - struct snd_usb_substream *subs = ctx->subs; - struct snd_pcm_substream *substream = ctx->subs->pcm_substream; - int err = 0; - - if ((subs->running && subs->ops.retire_sync(subs, substream->runtime, urb)) || - !subs->running || /* can be stopped during retire callback */ - (err = subs->ops.prepare_sync(subs, substream->runtime, urb)) < 0 || - (err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) { - clear_bit(ctx->index + 16, &subs->active_mask); - if (err < 0) { - snd_printd(KERN_ERR "cannot submit sync urb (err = %d)\n", err); - snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); - } - } -} - - -/* - * initialize a substream for plaback/capture - */ -int snd_usb_init_substream_urbs(struct snd_usb_substream *subs, - unsigned int period_bytes, - unsigned int rate, - unsigned int frame_bits) -{ - unsigned int maxsize, i; - int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK; - unsigned int urb_packs, total_packs, packs_per_ms; - struct snd_usb_audio *chip = subs->stream->chip; - - /* calculate the frequency in 16.16 format */ - if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) - subs->freqn = get_usb_full_speed_rate(rate); - else - subs->freqn = get_usb_high_speed_rate(rate); - subs->freqm = subs->freqn; - subs->freqshift = INT_MIN; - /* calculate max. frequency */ - if (subs->maxpacksize) { - /* whatever fits into a max. size packet */ - maxsize = subs->maxpacksize; - subs->freqmax = (maxsize / (frame_bits >> 3)) - << (16 - subs->datainterval); - } else { - /* no max. packet size: just take 25% higher than nominal */ - subs->freqmax = subs->freqn + (subs->freqn >> 2); - maxsize = ((subs->freqmax + 0xffff) * (frame_bits >> 3)) - >> (16 - subs->datainterval); - } - subs->phase = 0; - - if (subs->fill_max) - subs->curpacksize = subs->maxpacksize; - else - subs->curpacksize = maxsize; - - if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) - packs_per_ms = 8 >> subs->datainterval; - else - packs_per_ms = 1; - - if (is_playback) { - urb_packs = max(chip->nrpacks, 1); - urb_packs = min(urb_packs, (unsigned int)MAX_PACKS); - } else - urb_packs = 1; - urb_packs *= packs_per_ms; - if (subs->syncpipe) - urb_packs = min(urb_packs, 1U << subs->syncinterval); - - /* decide how many packets to be used */ - if (is_playback) { - unsigned int minsize, maxpacks; - /* determine how small a packet can be */ - minsize = (subs->freqn >> (16 - subs->datainterval)) - * (frame_bits >> 3); - /* with sync from device, assume it can be 12% lower */ - if (subs->syncpipe) - minsize -= minsize >> 3; - minsize = max(minsize, 1u); - total_packs = (period_bytes + minsize - 1) / minsize; - /* we need at least two URBs for queueing */ - if (total_packs < 2) { - total_packs = 2; - } else { - /* and we don't want too long a queue either */ - maxpacks = max(MAX_QUEUE * packs_per_ms, urb_packs * 2); - total_packs = min(total_packs, maxpacks); - } - } else { - while (urb_packs > 1 && urb_packs * maxsize >= period_bytes) - urb_packs >>= 1; - total_packs = MAX_URBS * urb_packs; - } - subs->nurbs = (total_packs + urb_packs - 1) / urb_packs; - if (subs->nurbs > MAX_URBS) { - /* too much... */ - subs->nurbs = MAX_URBS; - total_packs = MAX_URBS * urb_packs; - } else if (subs->nurbs < 2) { - /* too little - we need at least two packets - * to ensure contiguous playback/capture - */ - subs->nurbs = 2; - } - - /* allocate and initialize data urbs */ - for (i = 0; i < subs->nurbs; i++) { - struct snd_urb_ctx *u = &subs->dataurb[i]; - u->index = i; - u->subs = subs; - u->packets = (i + 1) * total_packs / subs->nurbs - - i * total_packs / subs->nurbs; - u->buffer_size = maxsize * u->packets; - if (subs->fmt_type == UAC_FORMAT_TYPE_II) - u->packets++; /* for transfer delimiter */ - u->urb = usb_alloc_urb(u->packets, GFP_KERNEL); - if (!u->urb) - goto out_of_memory; - u->urb->transfer_buffer = - usb_alloc_coherent(subs->dev, u->buffer_size, - GFP_KERNEL, &u->urb->transfer_dma); - if (!u->urb->transfer_buffer) - goto out_of_memory; - u->urb->pipe = subs->datapipe; - u->urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; - u->urb->interval = 1 << subs->datainterval; - u->urb->context = u; - u->urb->complete = snd_complete_urb; - } - - if (subs->syncpipe) { - /* allocate and initialize sync urbs */ - subs->syncbuf = usb_alloc_coherent(subs->dev, SYNC_URBS * 4, - GFP_KERNEL, &subs->sync_dma); - if (!subs->syncbuf) - goto out_of_memory; - for (i = 0; i < SYNC_URBS; i++) { - struct snd_urb_ctx *u = &subs->syncurb[i]; - u->index = i; - u->subs = subs; - u->packets = 1; - u->urb = usb_alloc_urb(1, GFP_KERNEL); - if (!u->urb) - goto out_of_memory; - u->urb->transfer_buffer = subs->syncbuf + i * 4; - u->urb->transfer_dma = subs->sync_dma + i * 4; - u->urb->transfer_buffer_length = 4; - u->urb->pipe = subs->syncpipe; - u->urb->transfer_flags = URB_ISO_ASAP | - URB_NO_TRANSFER_DMA_MAP; - u->urb->number_of_packets = 1; - u->urb->interval = 1 << subs->syncinterval; - u->urb->context = u; - u->urb->complete = snd_complete_sync_urb; - } - } - return 0; - -out_of_memory: - snd_usb_release_substream_urbs(subs, 0); - return -ENOMEM; -} - -/* - * prepare urb for full speed capture sync pipe - * - * fill the length and offset of each urb descriptor. - * the fixed 10.14 frequency is passed through the pipe. - */ -static int prepare_capture_sync_urb(struct snd_usb_substream *subs, - struct snd_pcm_runtime *runtime, - struct urb *urb) -{ - unsigned char *cp = urb->transfer_buffer; - struct snd_urb_ctx *ctx = urb->context; - - urb->dev = ctx->subs->dev; /* we need to set this at each time */ - urb->iso_frame_desc[0].length = 3; - urb->iso_frame_desc[0].offset = 0; - cp[0] = subs->freqn >> 2; - cp[1] = subs->freqn >> 10; - cp[2] = subs->freqn >> 18; - return 0; -} - -/* - * prepare urb for high speed capture sync pipe - * - * fill the length and offset of each urb descriptor. - * the fixed 12.13 frequency is passed as 16.16 through the pipe. - */ -static int prepare_capture_sync_urb_hs(struct snd_usb_substream *subs, - struct snd_pcm_runtime *runtime, - struct urb *urb) -{ - unsigned char *cp = urb->transfer_buffer; - struct snd_urb_ctx *ctx = urb->context; - - urb->dev = ctx->subs->dev; /* we need to set this at each time */ - urb->iso_frame_desc[0].length = 4; - urb->iso_frame_desc[0].offset = 0; - cp[0] = subs->freqn; - cp[1] = subs->freqn >> 8; - cp[2] = subs->freqn >> 16; - cp[3] = subs->freqn >> 24; - return 0; -} - -/* - * process after capture sync complete - * - nothing to do - */ -static int retire_capture_sync_urb(struct snd_usb_substream *subs, - struct snd_pcm_runtime *runtime, - struct urb *urb) -{ - return 0; -} - -/* - * prepare urb for capture data pipe - * - * fill the offset and length of each descriptor. - * - * we use a temporary buffer to write the captured data. - * since the length of written data is determined by host, we cannot - * write onto the pcm buffer directly... the data is thus copied - * later at complete callback to the global buffer. - */ -static int prepare_capture_urb(struct snd_usb_substream *subs, - struct snd_pcm_runtime *runtime, - struct urb *urb) -{ - int i, offs; - struct snd_urb_ctx *ctx = urb->context; - - offs = 0; - urb->dev = ctx->subs->dev; /* we need to set this at each time */ - for (i = 0; i < ctx->packets; i++) { - urb->iso_frame_desc[i].offset = offs; - urb->iso_frame_desc[i].length = subs->curpacksize; - offs += subs->curpacksize; - } - urb->transfer_buffer_length = offs; - urb->number_of_packets = ctx->packets; - return 0; -} - -/* - * process after capture complete - * - * copy the data from each desctiptor to the pcm buffer, and - * update the current position. - */ -static int retire_capture_urb(struct snd_usb_substream *subs, - struct snd_pcm_runtime *runtime, - struct urb *urb) -{ - unsigned long flags; - unsigned char *cp; - int i; - unsigned int stride, frames, bytes, oldptr; - int period_elapsed = 0; - - stride = runtime->frame_bits >> 3; - - for (i = 0; i < urb->number_of_packets; i++) { - cp = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset; - if (urb->iso_frame_desc[i].status && printk_ratelimit()) { - snd_printdd("frame %d active: %d\n", i, urb->iso_frame_desc[i].status); - // continue; - } - bytes = urb->iso_frame_desc[i].actual_length; - frames = bytes / stride; - if (!subs->txfr_quirk) - bytes = frames * stride; - if (bytes % (runtime->sample_bits >> 3) != 0) { -#ifdef CONFIG_SND_DEBUG_VERBOSE - int oldbytes = bytes; -#endif - bytes = frames * stride; - snd_printdd(KERN_ERR "Corrected urb data len. %d->%d\n", - oldbytes, bytes); - } - /* update the current pointer */ - spin_lock_irqsave(&subs->lock, flags); - oldptr = subs->hwptr_done; - subs->hwptr_done += bytes; - if (subs->hwptr_done >= runtime->buffer_size * stride) - subs->hwptr_done -= runtime->buffer_size * stride; - frames = (bytes + (oldptr % stride)) / stride; - subs->transfer_done += frames; - if (subs->transfer_done >= runtime->period_size) { - subs->transfer_done -= runtime->period_size; - period_elapsed = 1; - } - spin_unlock_irqrestore(&subs->lock, flags); - /* copy a data chunk */ - if (oldptr + bytes > runtime->buffer_size * stride) { - unsigned int bytes1 = - runtime->buffer_size * stride - oldptr; - memcpy(runtime->dma_area + oldptr, cp, bytes1); - memcpy(runtime->dma_area, cp + bytes1, bytes - bytes1); - } else { - memcpy(runtime->dma_area + oldptr, cp, bytes); - } - } - if (period_elapsed) - snd_pcm_period_elapsed(subs->pcm_substream); - return 0; -} - -/* - * Process after capture complete when paused. Nothing to do. - */ -static int retire_paused_capture_urb(struct snd_usb_substream *subs, - struct snd_pcm_runtime *runtime, - struct urb *urb) -{ - return 0; -} - - -/* - * prepare urb for playback sync pipe - * - * set up the offset and length to receive the current frequency. - */ -static int prepare_playback_sync_urb(struct snd_usb_substream *subs, - struct snd_pcm_runtime *runtime, - struct urb *urb) -{ - struct snd_urb_ctx *ctx = urb->context; - - urb->dev = ctx->subs->dev; /* we need to set this at each time */ - urb->iso_frame_desc[0].length = min(4u, ctx->subs->syncmaxsize); - urb->iso_frame_desc[0].offset = 0; - return 0; -} - -/* - * process after playback sync complete - * - * Full speed devices report feedback values in 10.14 format as samples per - * frame, high speed devices in 16.16 format as samples per microframe. - * Because the Audio Class 1 spec was written before USB 2.0, many high speed - * devices use a wrong interpretation, some others use an entirely different - * format. Therefore, we cannot predict what format any particular device uses - * and must detect it automatically. - */ -static int retire_playback_sync_urb(struct snd_usb_substream *subs, - struct snd_pcm_runtime *runtime, - struct urb *urb) -{ - unsigned int f; - int shift; - unsigned long flags; - - if (urb->iso_frame_desc[0].status != 0 || - urb->iso_frame_desc[0].actual_length < 3) - return 0; - - f = le32_to_cpup(urb->transfer_buffer); - if (urb->iso_frame_desc[0].actual_length == 3) - f &= 0x00ffffff; - else - f &= 0x0fffffff; - if (f == 0) - return 0; - - if (unlikely(subs->freqshift == INT_MIN)) { - /* - * The first time we see a feedback value, determine its format - * by shifting it left or right until it matches the nominal - * frequency value. This assumes that the feedback does not - * differ from the nominal value more than +50% or -25%. - */ - shift = 0; - while (f < subs->freqn - subs->freqn / 4) { - f <<= 1; - shift++; - } - while (f > subs->freqn + subs->freqn / 2) { - f >>= 1; - shift--; - } - subs->freqshift = shift; - } - else if (subs->freqshift >= 0) - f <<= subs->freqshift; - else - f >>= -subs->freqshift; - - if (likely(f >= subs->freqn - subs->freqn / 8 && f <= subs->freqmax)) { - /* - * If the frequency looks valid, set it. - * This value is referred to in prepare_playback_urb(). - */ - spin_lock_irqsave(&subs->lock, flags); - subs->freqm = f; - spin_unlock_irqrestore(&subs->lock, flags); - } else { - /* - * Out of range; maybe the shift value is wrong. - * Reset it so that we autodetect again the next time. - */ - subs->freqshift = INT_MIN; - } - - return 0; -} - -/* determine the number of frames in the next packet */ -static int snd_usb_audio_next_packet_size(struct snd_usb_substream *subs) -{ - if (subs->fill_max) - return subs->maxframesize; - else { - subs->phase = (subs->phase & 0xffff) - + (subs->freqm << subs->datainterval); - return min(subs->phase >> 16, subs->maxframesize); - } -} - -/* - * Prepare urb for streaming before playback starts or when paused. - * - * We don't have any data, so we send silence. - */ -static int prepare_nodata_playback_urb(struct snd_usb_substream *subs, - struct snd_pcm_runtime *runtime, - struct urb *urb) -{ - unsigned int i, offs, counts; - struct snd_urb_ctx *ctx = urb->context; - int stride = runtime->frame_bits >> 3; - - offs = 0; - urb->dev = ctx->subs->dev; - for (i = 0; i < ctx->packets; ++i) { - counts = snd_usb_audio_next_packet_size(subs); - urb->iso_frame_desc[i].offset = offs * stride; - urb->iso_frame_desc[i].length = counts * stride; - offs += counts; - } - urb->number_of_packets = ctx->packets; - urb->transfer_buffer_length = offs * stride; - memset(urb->transfer_buffer, - runtime->format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0, - offs * stride); - return 0; -} - -/* - * prepare urb for playback data pipe - * - * Since a URB can handle only a single linear buffer, we must use double - * buffering when the data to be transferred overflows the buffer boundary. - * To avoid inconsistencies when updating hwptr_done, we use double buffering - * for all URBs. - */ -static int prepare_playback_urb(struct snd_usb_substream *subs, - struct snd_pcm_runtime *runtime, - struct urb *urb) -{ - int i, stride; - unsigned int counts, frames, bytes; - unsigned long flags; - int period_elapsed = 0; - struct snd_urb_ctx *ctx = urb->context; - - stride = runtime->frame_bits >> 3; - - frames = 0; - urb->dev = ctx->subs->dev; /* we need to set this at each time */ - urb->number_of_packets = 0; - spin_lock_irqsave(&subs->lock, flags); - for (i = 0; i < ctx->packets; i++) { - counts = snd_usb_audio_next_packet_size(subs); - /* set up descriptor */ - urb->iso_frame_desc[i].offset = frames * stride; - urb->iso_frame_desc[i].length = counts * stride; - frames += counts; - urb->number_of_packets++; - subs->transfer_done += counts; - if (subs->transfer_done >= runtime->period_size) { - subs->transfer_done -= runtime->period_size; - period_elapsed = 1; - if (subs->fmt_type == UAC_FORMAT_TYPE_II) { - if (subs->transfer_done > 0) { - /* FIXME: fill-max mode is not - * supported yet */ - frames -= subs->transfer_done; - counts -= subs->transfer_done; - urb->iso_frame_desc[i].length = - counts * stride; - subs->transfer_done = 0; - } - i++; - if (i < ctx->packets) { - /* add a transfer delimiter */ - urb->iso_frame_desc[i].offset = - frames * stride; - urb->iso_frame_desc[i].length = 0; - urb->number_of_packets++; - } - break; - } - } - if (period_elapsed) /* finish at the period boundary */ - break; - } - bytes = frames * stride; - if (subs->hwptr_done + bytes > runtime->buffer_size * stride) { - /* err, the transferred area goes over buffer boundary. */ - unsigned int bytes1 = - runtime->buffer_size * stride - subs->hwptr_done; - memcpy(urb->transfer_buffer, - runtime->dma_area + subs->hwptr_done, bytes1); - memcpy(urb->transfer_buffer + bytes1, - runtime->dma_area, bytes - bytes1); - } else { - memcpy(urb->transfer_buffer, - runtime->dma_area + subs->hwptr_done, bytes); - } - subs->hwptr_done += bytes; - if (subs->hwptr_done >= runtime->buffer_size * stride) - subs->hwptr_done -= runtime->buffer_size * stride; - - /* update delay with exact number of samples queued */ - runtime->delay = subs->last_delay; - runtime->delay += frames; - subs->last_delay = runtime->delay; - - /* realign last_frame_number */ - subs->last_frame_number = usb_get_current_frame_number(subs->dev); - subs->last_frame_number &= 0xFF; /* keep 8 LSBs */ - - spin_unlock_irqrestore(&subs->lock, flags); - urb->transfer_buffer_length = bytes; - if (period_elapsed) - snd_pcm_period_elapsed(subs->pcm_substream); - return 0; -} - -/* - * process after playback data complete - * - decrease the delay count again - */ -static int retire_playback_urb(struct snd_usb_substream *subs, - struct snd_pcm_runtime *runtime, - struct urb *urb) -{ - unsigned long flags; - int stride = runtime->frame_bits >> 3; - int processed = urb->transfer_buffer_length / stride; - int est_delay; - - spin_lock_irqsave(&subs->lock, flags); - - est_delay = snd_usb_pcm_delay(subs, runtime->rate); - /* update delay with exact number of samples played */ - if (processed > subs->last_delay) - subs->last_delay = 0; - else - subs->last_delay -= processed; - runtime->delay = subs->last_delay; - - /* - * Report when delay estimate is off by more than 2ms. - * The error should be lower than 2ms since the estimate relies - * on two reads of a counter updated every ms. - */ - if (abs(est_delay - subs->last_delay) * 1000 > runtime->rate * 2) - snd_printk(KERN_DEBUG "delay: estimated %d, actual %d\n", - est_delay, subs->last_delay); - - spin_unlock_irqrestore(&subs->lock, flags); - return 0; -} - -static const char *usb_error_string(int err) -{ - switch (err) { - case -ENODEV: - return "no device"; - case -ENOENT: - return "endpoint not enabled"; - case -EPIPE: - return "endpoint stalled"; - case -ENOSPC: - return "not enough bandwidth"; - case -ESHUTDOWN: - return "device disabled"; - case -EHOSTUNREACH: - return "device suspended"; - case -EINVAL: - case -EAGAIN: - case -EFBIG: - case -EMSGSIZE: - return "internal error"; - default: - return "unknown error"; - } -} - -/* - * set up and start data/sync urbs - */ -static int start_urbs(struct snd_usb_substream *subs, struct snd_pcm_runtime *runtime) -{ - unsigned int i; - int err; - - if (subs->stream->chip->shutdown) - return -EBADFD; - - for (i = 0; i < subs->nurbs; i++) { - if (snd_BUG_ON(!subs->dataurb[i].urb)) - return -EINVAL; - if (subs->ops.prepare(subs, runtime, subs->dataurb[i].urb) < 0) { - snd_printk(KERN_ERR "cannot prepare datapipe for urb %d\n", i); - goto __error; - } - } - if (subs->syncpipe) { - for (i = 0; i < SYNC_URBS; i++) { - if (snd_BUG_ON(!subs->syncurb[i].urb)) - return -EINVAL; - if (subs->ops.prepare_sync(subs, runtime, subs->syncurb[i].urb) < 0) { - snd_printk(KERN_ERR "cannot prepare syncpipe for urb %d\n", i); - goto __error; - } - } - } - - subs->active_mask = 0; - subs->unlink_mask = 0; - subs->running = 1; - for (i = 0; i < subs->nurbs; i++) { - err = usb_submit_urb(subs->dataurb[i].urb, GFP_ATOMIC); - if (err < 0) { - snd_printk(KERN_ERR "cannot submit datapipe " - "for urb %d, error %d: %s\n", - i, err, usb_error_string(err)); - goto __error; - } - set_bit(i, &subs->active_mask); - } - if (subs->syncpipe) { - for (i = 0; i < SYNC_URBS; i++) { - err = usb_submit_urb(subs->syncurb[i].urb, GFP_ATOMIC); - if (err < 0) { - snd_printk(KERN_ERR "cannot submit syncpipe " - "for urb %d, error %d: %s\n", - i, err, usb_error_string(err)); - goto __error; - } - set_bit(i + 16, &subs->active_mask); - } - } - return 0; - - __error: - // snd_pcm_stop(subs->pcm_substream, SNDRV_PCM_STATE_XRUN); - deactivate_urbs(subs, 0, 0); - return -EPIPE; -} - - -/* - */ -static struct snd_urb_ops audio_urb_ops[2] = { - { - .prepare = prepare_nodata_playback_urb, - .retire = retire_playback_urb, - .prepare_sync = prepare_playback_sync_urb, - .retire_sync = retire_playback_sync_urb, - }, - { - .prepare = prepare_capture_urb, - .retire = retire_capture_urb, - .prepare_sync = prepare_capture_sync_urb, - .retire_sync = retire_capture_sync_urb, - }, -}; - -/* - * initialize the substream instance. - */ - -void snd_usb_init_substream(struct snd_usb_stream *as, - int stream, struct audioformat *fp) -{ - struct snd_usb_substream *subs = &as->substream[stream]; - - INIT_LIST_HEAD(&subs->fmt_list); - spin_lock_init(&subs->lock); - - subs->stream = as; - subs->direction = stream; - subs->dev = as->chip->dev; - subs->txfr_quirk = as->chip->txfr_quirk; - subs->ops = audio_urb_ops[stream]; - if (snd_usb_get_speed(subs->dev) >= USB_SPEED_HIGH) - subs->ops.prepare_sync = prepare_capture_sync_urb_hs; - - snd_usb_set_pcm_ops(as->pcm, stream); - - list_add_tail(&fp->list, &subs->fmt_list); - subs->formats |= fp->formats; - subs->endpoint = fp->endpoint; - subs->num_formats++; - subs->fmt_type = fp->fmt_type; -} - -int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_usb_substream *subs = substream->runtime->private_data; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - subs->ops.prepare = prepare_playback_urb; - return 0; - case SNDRV_PCM_TRIGGER_STOP: - return deactivate_urbs(subs, 0, 0); - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - subs->ops.prepare = prepare_nodata_playback_urb; - return 0; - } - - return -EINVAL; -} - -int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_usb_substream *subs = substream->runtime->private_data; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - subs->ops.retire = retire_capture_urb; - return start_urbs(subs, substream->runtime); - case SNDRV_PCM_TRIGGER_STOP: - return deactivate_urbs(subs, 0, 0); - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - subs->ops.retire = retire_paused_capture_urb; - return 0; - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - subs->ops.retire = retire_capture_urb; - return 0; - } - - return -EINVAL; -} - -int snd_usb_substream_prepare(struct snd_usb_substream *subs, - struct snd_pcm_runtime *runtime) -{ - /* clear urbs (to be sure) */ - deactivate_urbs(subs, 0, 1); - wait_clear_urbs(subs); - - /* for playback, submit the URBs now; otherwise, the first hwptr_done - * updates for all URBs would happen at the same time when starting */ - if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) { - subs->ops.prepare = prepare_nodata_playback_urb; - return start_urbs(subs, runtime); - } - - return 0; -} - diff --git a/ANDROID_3.4.5/sound/usb/endpoint.h b/ANDROID_3.4.5/sound/usb/endpoint.h deleted file mode 100644 index 88eb63a6..00000000 --- a/ANDROID_3.4.5/sound/usb/endpoint.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef __USBAUDIO_ENDPOINT_H -#define __USBAUDIO_ENDPOINT_H - -void snd_usb_init_substream(struct snd_usb_stream *as, - int stream, - struct audioformat *fp); - -int snd_usb_init_substream_urbs(struct snd_usb_substream *subs, - unsigned int period_bytes, - unsigned int rate, - unsigned int frame_bits); - -void snd_usb_release_substream_urbs(struct snd_usb_substream *subs, int force); - -int snd_usb_substream_prepare(struct snd_usb_substream *subs, - struct snd_pcm_runtime *runtime); - -int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream, int cmd); -int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream, int cmd); - -#endif /* __USBAUDIO_ENDPOINT_H */ diff --git a/ANDROID_3.4.5/sound/usb/format.c b/ANDROID_3.4.5/sound/usb/format.c deleted file mode 100644 index ddfef57c..00000000 --- a/ANDROID_3.4.5/sound/usb/format.c +++ /dev/null @@ -1,515 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include - -#include -#include - -#include "usbaudio.h" -#include "card.h" -#include "quirks.h" -#include "helper.h" -#include "debug.h" -#include "clock.h" -#include "format.h" - -/* - * parse the audio format type I descriptor - * and returns the corresponding pcm format - * - * @dev: usb device - * @fp: audioformat record - * @format: the format tag (wFormatTag) - * @fmt: the format type descriptor - */ -static u64 parse_audio_format_i_type(struct snd_usb_audio *chip, - struct audioformat *fp, - int format, void *_fmt, - int protocol) -{ - int sample_width, sample_bytes; - u64 pcm_formats; - - switch (protocol) { - case UAC_VERSION_1: - default: { - struct uac_format_type_i_discrete_descriptor *fmt = _fmt; - sample_width = fmt->bBitResolution; - sample_bytes = fmt->bSubframeSize; - format = 1 << format; - break; - } - - case UAC_VERSION_2: { - struct uac_format_type_i_ext_descriptor *fmt = _fmt; - sample_width = fmt->bBitResolution; - sample_bytes = fmt->bSubslotSize; - format <<= 1; - break; - } - } - - pcm_formats = 0; - - if (format == 0 || format == (1 << UAC_FORMAT_TYPE_I_UNDEFINED)) { - /* some devices don't define this correctly... */ - snd_printdd(KERN_INFO "%d:%u:%d : format type 0 is detected, processed as PCM\n", - chip->dev->devnum, fp->iface, fp->altsetting); - format = 1 << UAC_FORMAT_TYPE_I_PCM; - } - if (format & (1 << UAC_FORMAT_TYPE_I_PCM)) { - if (chip->usb_id == USB_ID(0x0582, 0x0016) /* Edirol SD-90 */ && - sample_width == 24 && sample_bytes == 2) - sample_bytes = 3; - else if (sample_width > sample_bytes * 8) { - snd_printk(KERN_INFO "%d:%u:%d : sample bitwidth %d in over sample bytes %d\n", - chip->dev->devnum, fp->iface, fp->altsetting, - sample_width, sample_bytes); - } - /* check the format byte size */ - switch (sample_bytes) { - case 1: - pcm_formats |= SNDRV_PCM_FMTBIT_S8; - break; - case 2: - if (snd_usb_is_big_endian_format(chip, fp)) - pcm_formats |= SNDRV_PCM_FMTBIT_S16_BE; /* grrr, big endian!! */ - else - pcm_formats |= SNDRV_PCM_FMTBIT_S16_LE; - break; - case 3: - if (snd_usb_is_big_endian_format(chip, fp)) - pcm_formats |= SNDRV_PCM_FMTBIT_S24_3BE; /* grrr, big endian!! */ - else - pcm_formats |= SNDRV_PCM_FMTBIT_S24_3LE; - break; - case 4: - pcm_formats |= SNDRV_PCM_FMTBIT_S32_LE; - break; - default: - snd_printk(KERN_INFO "%d:%u:%d : unsupported sample bitwidth %d in %d bytes\n", - chip->dev->devnum, fp->iface, fp->altsetting, - sample_width, sample_bytes); - break; - } - } - if (format & (1 << UAC_FORMAT_TYPE_I_PCM8)) { - /* Dallas DS4201 workaround: it advertises U8 format, but really - supports S8. */ - if (chip->usb_id == USB_ID(0x04fa, 0x4201)) - pcm_formats |= SNDRV_PCM_FMTBIT_S8; - else - pcm_formats |= SNDRV_PCM_FMTBIT_U8; - } - if (format & (1 << UAC_FORMAT_TYPE_I_IEEE_FLOAT)) { - pcm_formats |= SNDRV_PCM_FMTBIT_FLOAT_LE; - } - if (format & (1 << UAC_FORMAT_TYPE_I_ALAW)) { - pcm_formats |= SNDRV_PCM_FMTBIT_A_LAW; - } - if (format & (1 << UAC_FORMAT_TYPE_I_MULAW)) { - pcm_formats |= SNDRV_PCM_FMTBIT_MU_LAW; - } - if (format & ~0x3f) { - snd_printk(KERN_INFO "%d:%u:%d : unsupported format bits %#x\n", - chip->dev->devnum, fp->iface, fp->altsetting, format); - } - return pcm_formats; -} - - -/* - * parse the format descriptor and stores the possible sample rates - * on the audioformat table (audio class v1). - * - * @dev: usb device - * @fp: audioformat record - * @fmt: the format descriptor - * @offset: the start offset of descriptor pointing the rate type - * (7 for type I and II, 8 for type II) - */ -static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audioformat *fp, - unsigned char *fmt, int offset) -{ - int nr_rates = fmt[offset]; - - if (fmt[0] < offset + 1 + 3 * (nr_rates ? nr_rates : 2)) { - snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_FORMAT_TYPE desc\n", - chip->dev->devnum, fp->iface, fp->altsetting); - return -1; - } - - if (nr_rates) { - /* - * build the rate table and bitmap flags - */ - int r, idx; - - fp->rate_table = kmalloc(sizeof(int) * nr_rates, GFP_KERNEL); - if (fp->rate_table == NULL) { - snd_printk(KERN_ERR "cannot malloc\n"); - return -1; - } - - fp->nr_rates = 0; - fp->rate_min = fp->rate_max = 0; - for (r = 0, idx = offset + 1; r < nr_rates; r++, idx += 3) { - unsigned int rate = combine_triple(&fmt[idx]); - if (!rate) - continue; - /* C-Media CM6501 mislabels its 96 kHz altsetting */ - /* Terratec Aureon 7.1 USB C-Media 6206, too */ - if (rate == 48000 && nr_rates == 1 && - (chip->usb_id == USB_ID(0x0d8c, 0x0201) || - chip->usb_id == USB_ID(0x0d8c, 0x0102) || - chip->usb_id == USB_ID(0x0ccd, 0x00b1)) && - fp->altsetting == 5 && fp->maxpacksize == 392) - rate = 96000; - /* Creative VF0470 Live Cam reports 16 kHz instead of 8kHz */ - if (rate == 16000 && chip->usb_id == USB_ID(0x041e, 0x4068)) - rate = 8000; - - fp->rate_table[fp->nr_rates] = rate; - if (!fp->rate_min || rate < fp->rate_min) - fp->rate_min = rate; - if (!fp->rate_max || rate > fp->rate_max) - fp->rate_max = rate; - fp->rates |= snd_pcm_rate_to_rate_bit(rate); - fp->nr_rates++; - } - if (!fp->nr_rates) { - hwc_debug("All rates were zero. Skipping format!\n"); - return -1; - } - } else { - /* continuous rates */ - fp->rates = SNDRV_PCM_RATE_CONTINUOUS; - fp->rate_min = combine_triple(&fmt[offset + 1]); - fp->rate_max = combine_triple(&fmt[offset + 4]); - } - return 0; -} - -/* - * Helper function to walk the array of sample rate triplets reported by - * the device. The problem is that we need to parse whole array first to - * get to know how many sample rates we have to expect. - * Then fp->rate_table can be allocated and filled. - */ -static int parse_uac2_sample_rate_range(struct audioformat *fp, int nr_triplets, - const unsigned char *data) -{ - int i, nr_rates = 0; - - fp->rates = fp->rate_min = fp->rate_max = 0; - - for (i = 0; i < nr_triplets; i++) { - int min = combine_quad(&data[2 + 12 * i]); - int max = combine_quad(&data[6 + 12 * i]); - int res = combine_quad(&data[10 + 12 * i]); - unsigned int rate; - - if ((max < 0) || (min < 0) || (res < 0) || (max < min)) - continue; - - /* - * for ranges with res == 1, we announce a continuous sample - * rate range, and this function should return 0 for no further - * parsing. - */ - if (res == 1) { - fp->rate_min = min; - fp->rate_max = max; - fp->rates = SNDRV_PCM_RATE_CONTINUOUS; - return 0; - } - - for (rate = min; rate <= max; rate += res) { - if (fp->rate_table) - fp->rate_table[nr_rates] = rate; - if (!fp->rate_min || rate < fp->rate_min) - fp->rate_min = rate; - if (!fp->rate_max || rate > fp->rate_max) - fp->rate_max = rate; - fp->rates |= snd_pcm_rate_to_rate_bit(rate); - - nr_rates++; - if (nr_rates >= MAX_NR_RATES) { - snd_printk(KERN_ERR "invalid uac2 rates\n"); - break; - } - - /* avoid endless loop */ - if (res == 0) - break; - } - } - - return nr_rates; -} - -/* - * parse the format descriptor and stores the possible sample rates - * on the audioformat table (audio class v2). - */ -static int parse_audio_format_rates_v2(struct snd_usb_audio *chip, - struct audioformat *fp) -{ - struct usb_device *dev = chip->dev; - unsigned char tmp[2], *data; - int nr_triplets, data_size, ret = 0; - int clock = snd_usb_clock_find_source(chip, fp->clock); - - if (clock < 0) { - snd_printk(KERN_ERR "%s(): unable to find clock source (clock %d)\n", - __func__, clock); - goto err; - } - - /* get the number of sample rates first by only fetching 2 bytes */ - ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_RANGE, - USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, - UAC2_CS_CONTROL_SAM_FREQ << 8, - snd_usb_ctrl_intf(chip) | (clock << 8), - tmp, sizeof(tmp)); - - if (ret < 0) { - snd_printk(KERN_ERR "%s(): unable to retrieve number of sample rates (clock %d)\n", - __func__, clock); - goto err; - } - - nr_triplets = (tmp[1] << 8) | tmp[0]; - data_size = 2 + 12 * nr_triplets; - data = kzalloc(data_size, GFP_KERNEL); - if (!data) { - ret = -ENOMEM; - goto err; - } - - /* now get the full information */ - ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_RANGE, - USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, - UAC2_CS_CONTROL_SAM_FREQ << 8, - snd_usb_ctrl_intf(chip) | (clock << 8), - data, data_size); - - if (ret < 0) { - snd_printk(KERN_ERR "%s(): unable to retrieve sample rate range (clock %d)\n", - __func__, clock); - ret = -EINVAL; - goto err_free; - } - - /* Call the triplet parser, and make sure fp->rate_table is NULL. - * We just use the return value to know how many sample rates we - * will have to deal with. */ - kfree(fp->rate_table); - fp->rate_table = NULL; - fp->nr_rates = parse_uac2_sample_rate_range(fp, nr_triplets, data); - - if (fp->nr_rates == 0) { - /* SNDRV_PCM_RATE_CONTINUOUS */ - ret = 0; - goto err_free; - } - - fp->rate_table = kmalloc(sizeof(int) * fp->nr_rates, GFP_KERNEL); - if (!fp->rate_table) { - ret = -ENOMEM; - goto err_free; - } - - /* Call the triplet parser again, but this time, fp->rate_table is - * allocated, so the rates will be stored */ - parse_uac2_sample_rate_range(fp, nr_triplets, data); - -err_free: - kfree(data); -err: - return ret; -} - -/* - * parse the format type I and III descriptors - */ -static int parse_audio_format_i(struct snd_usb_audio *chip, - struct audioformat *fp, int format, - struct uac_format_type_i_continuous_descriptor *fmt, - struct usb_host_interface *iface) -{ - struct usb_interface_descriptor *altsd = get_iface_desc(iface); - int protocol = altsd->bInterfaceProtocol; - int pcm_format, ret; - - if (fmt->bFormatType == UAC_FORMAT_TYPE_III) { - /* FIXME: the format type is really IECxxx - * but we give normal PCM format to get the existing - * apps working... - */ - switch (chip->usb_id) { - - case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */ - if (chip->setup == 0x00 && - fp->altsetting == 6) - pcm_format = SNDRV_PCM_FORMAT_S16_BE; - else - pcm_format = SNDRV_PCM_FORMAT_S16_LE; - break; - default: - pcm_format = SNDRV_PCM_FORMAT_S16_LE; - } - fp->formats = 1uLL << pcm_format; - } else { - fp->formats = parse_audio_format_i_type(chip, fp, format, - fmt, protocol); - if (!fp->formats) - return -1; - } - - /* gather possible sample rates */ - /* audio class v1 reports possible sample rates as part of the - * proprietary class specific descriptor. - * audio class v2 uses class specific EP0 range requests for that. - */ - switch (protocol) { - default: - snd_printdd(KERN_WARNING "%d:%u:%d : invalid protocol version %d, assuming v1\n", - chip->dev->devnum, fp->iface, fp->altsetting, protocol); - /* fall through */ - case UAC_VERSION_1: - fp->channels = fmt->bNrChannels; - ret = parse_audio_format_rates_v1(chip, fp, (unsigned char *) fmt, 7); - break; - case UAC_VERSION_2: - /* fp->channels is already set in this case */ - ret = parse_audio_format_rates_v2(chip, fp); - break; - } - - if (fp->channels < 1) { - snd_printk(KERN_ERR "%d:%u:%d : invalid channels %d\n", - chip->dev->devnum, fp->iface, fp->altsetting, fp->channels); - return -1; - } - - return ret; -} - -/* - * parse the format type II descriptor - */ -static int parse_audio_format_ii(struct snd_usb_audio *chip, - struct audioformat *fp, - int format, void *_fmt, - struct usb_host_interface *iface) -{ - int brate, framesize, ret; - struct usb_interface_descriptor *altsd = get_iface_desc(iface); - int protocol = altsd->bInterfaceProtocol; - - switch (format) { - case UAC_FORMAT_TYPE_II_AC3: - /* FIXME: there is no AC3 format defined yet */ - // fp->formats = SNDRV_PCM_FMTBIT_AC3; - fp->formats = SNDRV_PCM_FMTBIT_U8; /* temporary hack to receive byte streams */ - break; - case UAC_FORMAT_TYPE_II_MPEG: - fp->formats = SNDRV_PCM_FMTBIT_MPEG; - break; - default: - snd_printd(KERN_INFO "%d:%u:%d : unknown format tag %#x is detected. processed as MPEG.\n", - chip->dev->devnum, fp->iface, fp->altsetting, format); - fp->formats = SNDRV_PCM_FMTBIT_MPEG; - break; - } - - fp->channels = 1; - - switch (protocol) { - default: - snd_printdd(KERN_WARNING "%d:%u:%d : invalid protocol version %d, assuming v1\n", - chip->dev->devnum, fp->iface, fp->altsetting, protocol); - /* fall through */ - case UAC_VERSION_1: { - struct uac_format_type_ii_discrete_descriptor *fmt = _fmt; - brate = le16_to_cpu(fmt->wMaxBitRate); - framesize = le16_to_cpu(fmt->wSamplesPerFrame); - snd_printd(KERN_INFO "found format II with max.bitrate = %d, frame size=%d\n", brate, framesize); - fp->frame_size = framesize; - ret = parse_audio_format_rates_v1(chip, fp, _fmt, 8); /* fmt[8..] sample rates */ - break; - } - case UAC_VERSION_2: { - struct uac_format_type_ii_ext_descriptor *fmt = _fmt; - brate = le16_to_cpu(fmt->wMaxBitRate); - framesize = le16_to_cpu(fmt->wSamplesPerFrame); - snd_printd(KERN_INFO "found format II with max.bitrate = %d, frame size=%d\n", brate, framesize); - fp->frame_size = framesize; - ret = parse_audio_format_rates_v2(chip, fp); - break; - } - } - - return ret; -} - -int snd_usb_parse_audio_format(struct snd_usb_audio *chip, struct audioformat *fp, - int format, struct uac_format_type_i_continuous_descriptor *fmt, - int stream, struct usb_host_interface *iface) -{ - int err; - - switch (fmt->bFormatType) { - case UAC_FORMAT_TYPE_I: - case UAC_FORMAT_TYPE_III: - err = parse_audio_format_i(chip, fp, format, fmt, iface); - break; - case UAC_FORMAT_TYPE_II: - err = parse_audio_format_ii(chip, fp, format, fmt, iface); - break; - default: - snd_printd(KERN_INFO "%d:%u:%d : format type %d is not supported yet\n", - chip->dev->devnum, fp->iface, fp->altsetting, - fmt->bFormatType); - return -ENOTSUPP; - } - fp->fmt_type = fmt->bFormatType; - if (err < 0) - return err; -#if 1 - /* FIXME: temporary hack for extigy/audigy 2 nx/zs */ - /* extigy apparently supports sample rates other than 48k - * but not in ordinary way. so we enable only 48k atm. - */ - if (chip->usb_id == USB_ID(0x041e, 0x3000) || - chip->usb_id == USB_ID(0x041e, 0x3020) || - chip->usb_id == USB_ID(0x041e, 0x3061)) { - if (fmt->bFormatType == UAC_FORMAT_TYPE_I && - fp->rates != SNDRV_PCM_RATE_48000 && - fp->rates != SNDRV_PCM_RATE_96000) - return -ENOTSUPP; - } -#endif - return 0; -} - diff --git a/ANDROID_3.4.5/sound/usb/format.h b/ANDROID_3.4.5/sound/usb/format.h deleted file mode 100644 index 387924f0..00000000 --- a/ANDROID_3.4.5/sound/usb/format.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef __USBAUDIO_FORMAT_H -#define __USBAUDIO_FORMAT_H - -int snd_usb_parse_audio_format(struct snd_usb_audio *chip, - struct audioformat *fp, int format, - struct uac_format_type_i_continuous_descriptor *fmt, - int stream, struct usb_host_interface *iface); - -#endif /* __USBAUDIO_FORMAT_H */ diff --git a/ANDROID_3.4.5/sound/usb/helper.c b/ANDROID_3.4.5/sound/usb/helper.c deleted file mode 100644 index 9eed8f40..00000000 --- a/ANDROID_3.4.5/sound/usb/helper.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include - -#include "usbaudio.h" -#include "helper.h" - -/* - * combine bytes and get an integer value - */ -unsigned int snd_usb_combine_bytes(unsigned char *bytes, int size) -{ - switch (size) { - case 1: return *bytes; - case 2: return combine_word(bytes); - case 3: return combine_triple(bytes); - case 4: return combine_quad(bytes); - default: return 0; - } -} - -/* - * parse descriptor buffer and return the pointer starting the given - * descriptor type. - */ -void *snd_usb_find_desc(void *descstart, int desclen, void *after, u8 dtype) -{ - u8 *p, *end, *next; - - p = descstart; - end = p + desclen; - for (; p < end;) { - if (p[0] < 2) - return NULL; - next = p + p[0]; - if (next > end) - return NULL; - if (p[1] == dtype && (!after || (void *)p > after)) { - return p; - } - p = next; - } - return NULL; -} - -/* - * find a class-specified interface descriptor with the given subtype. - */ -void *snd_usb_find_csint_desc(void *buffer, int buflen, void *after, u8 dsubtype) -{ - unsigned char *p = after; - - while ((p = snd_usb_find_desc(buffer, buflen, p, - USB_DT_CS_INTERFACE)) != NULL) { - if (p[0] >= 3 && p[2] == dsubtype) - return p; - } - return NULL; -} - -/* - * Wrapper for usb_control_msg(). - * Allocates a temp buffer to prevent dmaing from/to the stack. - */ -int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request, - __u8 requesttype, __u16 value, __u16 index, void *data, - __u16 size) -{ - int err; - void *buf = NULL; - - if (size > 0) { - buf = kmemdup(data, size, GFP_KERNEL); - if (!buf) - return -ENOMEM; - } - err = usb_control_msg(dev, pipe, request, requesttype, - value, index, buf, size, 1000); - if (size > 0) { - memcpy(data, buf, size); - kfree(buf); - } - return err; -} - -unsigned char snd_usb_parse_datainterval(struct snd_usb_audio *chip, - struct usb_host_interface *alts) -{ - switch (snd_usb_get_speed(chip->dev)) { - case USB_SPEED_HIGH: - case USB_SPEED_SUPER: - if (get_endpoint(alts, 0)->bInterval >= 1 && - get_endpoint(alts, 0)->bInterval <= 4) - return get_endpoint(alts, 0)->bInterval - 1; - break; - default: - break; - } - return 0; -} - diff --git a/ANDROID_3.4.5/sound/usb/helper.h b/ANDROID_3.4.5/sound/usb/helper.h deleted file mode 100644 index 805c300d..00000000 --- a/ANDROID_3.4.5/sound/usb/helper.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef __USBAUDIO_HELPER_H -#define __USBAUDIO_HELPER_H - -unsigned int snd_usb_combine_bytes(unsigned char *bytes, int size); - -void *snd_usb_find_desc(void *descstart, int desclen, void *after, u8 dtype); -void *snd_usb_find_csint_desc(void *descstart, int desclen, void *after, u8 dsubtype); - -int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, - __u8 request, __u8 requesttype, __u16 value, __u16 index, - void *data, __u16 size); - -unsigned char snd_usb_parse_datainterval(struct snd_usb_audio *chip, - struct usb_host_interface *alts); - -/* - * retrieve usb_interface descriptor from the host interface - * (conditional for compatibility with the older API) - */ -#ifndef get_iface_desc -#define get_iface_desc(iface) (&(iface)->desc) -#define get_endpoint(alt,ep) (&(alt)->endpoint[ep].desc) -#define get_ep_desc(ep) (&(ep)->desc) -#define get_cfg_desc(cfg) (&(cfg)->desc) -#endif - -#ifndef snd_usb_get_speed -#define snd_usb_get_speed(dev) ((dev)->speed) -#endif - -static inline int snd_usb_ctrl_intf(struct snd_usb_audio *chip) -{ - return get_iface_desc(chip->ctrl_intf)->bInterfaceNumber; -} - -#endif /* __USBAUDIO_HELPER_H */ diff --git a/ANDROID_3.4.5/sound/usb/midi.c b/ANDROID_3.4.5/sound/usb/midi.c deleted file mode 100644 index c83f6143..00000000 --- a/ANDROID_3.4.5/sound/usb/midi.c +++ /dev/null @@ -1,2237 +0,0 @@ -/* - * usbmidi.c - ALSA USB MIDI driver - * - * Copyright (c) 2002-2009 Clemens Ladisch - * All rights reserved. - * - * Based on the OSS usb-midi driver by NAGANO Daisuke, - * NetBSD's umidi driver by Takuya SHIOZAKI, - * the "USB Device Class Definition for MIDI Devices" by Roland - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * Alternatively, this software may be distributed and/or modified under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include "usbaudio.h" -#include "midi.h" -#include "power.h" -#include "helper.h" - -/* - * define this to log all USB packets - */ -/* #define DUMP_PACKETS */ - -/* - * how long to wait after some USB errors, so that khubd can disconnect() us - * without too many spurious errors - */ -#define ERROR_DELAY_JIFFIES (HZ / 10) - -#define OUTPUT_URBS 7 -#define INPUT_URBS 7 - - -MODULE_AUTHOR("Clemens Ladisch "); -MODULE_DESCRIPTION("USB Audio/MIDI helper module"); -MODULE_LICENSE("Dual BSD/GPL"); - - -struct usb_ms_header_descriptor { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubtype; - __u8 bcdMSC[2]; - __le16 wTotalLength; -} __attribute__ ((packed)); - -struct usb_ms_endpoint_descriptor { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubtype; - __u8 bNumEmbMIDIJack; - __u8 baAssocJackID[0]; -} __attribute__ ((packed)); - -struct snd_usb_midi_in_endpoint; -struct snd_usb_midi_out_endpoint; -struct snd_usb_midi_endpoint; - -struct usb_protocol_ops { - void (*input)(struct snd_usb_midi_in_endpoint*, uint8_t*, int); - void (*output)(struct snd_usb_midi_out_endpoint *ep, struct urb *urb); - void (*output_packet)(struct urb*, uint8_t, uint8_t, uint8_t, uint8_t); - void (*init_out_endpoint)(struct snd_usb_midi_out_endpoint*); - void (*finish_out_endpoint)(struct snd_usb_midi_out_endpoint*); -}; - -struct snd_usb_midi { - struct usb_device *dev; - struct snd_card *card; - struct usb_interface *iface; - const struct snd_usb_audio_quirk *quirk; - struct snd_rawmidi *rmidi; - struct usb_protocol_ops* usb_protocol_ops; - struct list_head list; - struct timer_list error_timer; - spinlock_t disc_lock; - struct mutex mutex; - u32 usb_id; - int next_midi_device; - - struct snd_usb_midi_endpoint { - struct snd_usb_midi_out_endpoint *out; - struct snd_usb_midi_in_endpoint *in; - } endpoints[MIDI_MAX_ENDPOINTS]; - unsigned long input_triggered; - unsigned int opened; - unsigned char disconnected; - - struct snd_kcontrol *roland_load_ctl; -}; - -struct snd_usb_midi_out_endpoint { - struct snd_usb_midi* umidi; - struct out_urb_context { - struct urb *urb; - struct snd_usb_midi_out_endpoint *ep; - } urbs[OUTPUT_URBS]; - unsigned int active_urbs; - unsigned int drain_urbs; - int max_transfer; /* size of urb buffer */ - struct tasklet_struct tasklet; - unsigned int next_urb; - spinlock_t buffer_lock; - - struct usbmidi_out_port { - struct snd_usb_midi_out_endpoint* ep; - struct snd_rawmidi_substream *substream; - int active; - uint8_t cable; /* cable number << 4 */ - uint8_t state; -#define STATE_UNKNOWN 0 -#define STATE_1PARAM 1 -#define STATE_2PARAM_1 2 -#define STATE_2PARAM_2 3 -#define STATE_SYSEX_0 4 -#define STATE_SYSEX_1 5 -#define STATE_SYSEX_2 6 - uint8_t data[2]; - } ports[0x10]; - int current_port; - - wait_queue_head_t drain_wait; -}; - -struct snd_usb_midi_in_endpoint { - struct snd_usb_midi* umidi; - struct urb* urbs[INPUT_URBS]; - struct usbmidi_in_port { - struct snd_rawmidi_substream *substream; - u8 running_status_length; - } ports[0x10]; - u8 seen_f5; - u8 error_resubmit; - int current_port; -}; - -static void snd_usbmidi_do_output(struct snd_usb_midi_out_endpoint* ep); - -static const uint8_t snd_usbmidi_cin_length[] = { - 0, 0, 2, 3, 3, 1, 2, 3, 3, 3, 3, 3, 2, 2, 3, 1 -}; - -/* - * Submits the URB, with error handling. - */ -static int snd_usbmidi_submit_urb(struct urb* urb, gfp_t flags) -{ - int err = usb_submit_urb(urb, flags); - if (err < 0 && err != -ENODEV) - snd_printk(KERN_ERR "usb_submit_urb: %d\n", err); - return err; -} - -/* - * Error handling for URB completion functions. - */ -static int snd_usbmidi_urb_error(int status) -{ - switch (status) { - /* manually unlinked, or device gone */ - case -ENOENT: - case -ECONNRESET: - case -ESHUTDOWN: - case -ENODEV: - return -ENODEV; - /* errors that might occur during unplugging */ - case -EPROTO: - case -ETIME: - case -EILSEQ: - return -EIO; - default: - snd_printk(KERN_ERR "urb status %d\n", status); - return 0; /* continue */ - } -} - -/* - * Receives a chunk of MIDI data. - */ -static void snd_usbmidi_input_data(struct snd_usb_midi_in_endpoint* ep, int portidx, - uint8_t* data, int length) -{ - struct usbmidi_in_port* port = &ep->ports[portidx]; - - if (!port->substream) { - snd_printd("unexpected port %d!\n", portidx); - return; - } - if (!test_bit(port->substream->number, &ep->umidi->input_triggered)) - return; - snd_rawmidi_receive(port->substream, data, length); -} - -#ifdef DUMP_PACKETS -static void dump_urb(const char *type, const u8 *data, int length) -{ - snd_printk(KERN_DEBUG "%s packet: [", type); - for (; length > 0; ++data, --length) - printk(" %02x", *data); - printk(" ]\n"); -} -#else -#define dump_urb(type, data, length) /* nothing */ -#endif - -/* - * Processes the data read from the device. - */ -static void snd_usbmidi_in_urb_complete(struct urb* urb) -{ - struct snd_usb_midi_in_endpoint* ep = urb->context; - - if (urb->status == 0) { - dump_urb("received", urb->transfer_buffer, urb->actual_length); - ep->umidi->usb_protocol_ops->input(ep, urb->transfer_buffer, - urb->actual_length); - } else { - int err = snd_usbmidi_urb_error(urb->status); - if (err < 0) { - if (err != -ENODEV) { - ep->error_resubmit = 1; - mod_timer(&ep->umidi->error_timer, - jiffies + ERROR_DELAY_JIFFIES); - } - return; - } - } - - urb->dev = ep->umidi->dev; - snd_usbmidi_submit_urb(urb, GFP_ATOMIC); -} - -static void snd_usbmidi_out_urb_complete(struct urb* urb) -{ - struct out_urb_context *context = urb->context; - struct snd_usb_midi_out_endpoint* ep = context->ep; - unsigned int urb_index; - - spin_lock(&ep->buffer_lock); - urb_index = context - ep->urbs; - ep->active_urbs &= ~(1 << urb_index); - if (unlikely(ep->drain_urbs)) { - ep->drain_urbs &= ~(1 << urb_index); - wake_up(&ep->drain_wait); - } - spin_unlock(&ep->buffer_lock); - if (urb->status < 0) { - int err = snd_usbmidi_urb_error(urb->status); - if (err < 0) { - if (err != -ENODEV) - mod_timer(&ep->umidi->error_timer, - jiffies + ERROR_DELAY_JIFFIES); - return; - } - } - snd_usbmidi_do_output(ep); -} - -/* - * This is called when some data should be transferred to the device - * (from one or more substreams). - */ -static void snd_usbmidi_do_output(struct snd_usb_midi_out_endpoint* ep) -{ - unsigned int urb_index; - struct urb* urb; - unsigned long flags; - - spin_lock_irqsave(&ep->buffer_lock, flags); - if (ep->umidi->disconnected) { - spin_unlock_irqrestore(&ep->buffer_lock, flags); - return; - } - - urb_index = ep->next_urb; - for (;;) { - if (!(ep->active_urbs & (1 << urb_index))) { - urb = ep->urbs[urb_index].urb; - urb->transfer_buffer_length = 0; - ep->umidi->usb_protocol_ops->output(ep, urb); - if (urb->transfer_buffer_length == 0) - break; - - dump_urb("sending", urb->transfer_buffer, - urb->transfer_buffer_length); - urb->dev = ep->umidi->dev; - if (snd_usbmidi_submit_urb(urb, GFP_ATOMIC) < 0) - break; - ep->active_urbs |= 1 << urb_index; - } - if (++urb_index >= OUTPUT_URBS) - urb_index = 0; - if (urb_index == ep->next_urb) - break; - } - ep->next_urb = urb_index; - spin_unlock_irqrestore(&ep->buffer_lock, flags); -} - -static void snd_usbmidi_out_tasklet(unsigned long data) -{ - struct snd_usb_midi_out_endpoint* ep = (struct snd_usb_midi_out_endpoint *) data; - - snd_usbmidi_do_output(ep); -} - -/* called after transfers had been interrupted due to some USB error */ -static void snd_usbmidi_error_timer(unsigned long data) -{ - struct snd_usb_midi *umidi = (struct snd_usb_midi *)data; - unsigned int i, j; - - spin_lock(&umidi->disc_lock); - if (umidi->disconnected) { - spin_unlock(&umidi->disc_lock); - return; - } - for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) { - struct snd_usb_midi_in_endpoint *in = umidi->endpoints[i].in; - if (in && in->error_resubmit) { - in->error_resubmit = 0; - for (j = 0; j < INPUT_URBS; ++j) { - in->urbs[j]->dev = umidi->dev; - snd_usbmidi_submit_urb(in->urbs[j], GFP_ATOMIC); - } - } - if (umidi->endpoints[i].out) - snd_usbmidi_do_output(umidi->endpoints[i].out); - } - spin_unlock(&umidi->disc_lock); -} - -/* helper function to send static data that may not DMA-able */ -static int send_bulk_static_data(struct snd_usb_midi_out_endpoint* ep, - const void *data, int len) -{ - int err = 0; - void *buf = kmemdup(data, len, GFP_KERNEL); - if (!buf) - return -ENOMEM; - dump_urb("sending", buf, len); - if (ep->urbs[0].urb) - err = usb_bulk_msg(ep->umidi->dev, ep->urbs[0].urb->pipe, - buf, len, NULL, 250); - kfree(buf); - return err; -} - -/* - * Standard USB MIDI protocol: see the spec. - * Midiman protocol: like the standard protocol, but the control byte is the - * fourth byte in each packet, and uses length instead of CIN. - */ - -static void snd_usbmidi_standard_input(struct snd_usb_midi_in_endpoint* ep, - uint8_t* buffer, int buffer_length) -{ - int i; - - for (i = 0; i + 3 < buffer_length; i += 4) - if (buffer[i] != 0) { - int cable = buffer[i] >> 4; - int length = snd_usbmidi_cin_length[buffer[i] & 0x0f]; - snd_usbmidi_input_data(ep, cable, &buffer[i + 1], length); - } -} - -static void snd_usbmidi_midiman_input(struct snd_usb_midi_in_endpoint* ep, - uint8_t* buffer, int buffer_length) -{ - int i; - - for (i = 0; i + 3 < buffer_length; i += 4) - if (buffer[i + 3] != 0) { - int port = buffer[i + 3] >> 4; - int length = buffer[i + 3] & 3; - snd_usbmidi_input_data(ep, port, &buffer[i], length); - } -} - -/* - * Buggy M-Audio device: running status on input results in a packet that has - * the data bytes but not the status byte and that is marked with CIN 4. - */ -static void snd_usbmidi_maudio_broken_running_status_input( - struct snd_usb_midi_in_endpoint* ep, - uint8_t* buffer, int buffer_length) -{ - int i; - - for (i = 0; i + 3 < buffer_length; i += 4) - if (buffer[i] != 0) { - int cable = buffer[i] >> 4; - u8 cin = buffer[i] & 0x0f; - struct usbmidi_in_port *port = &ep->ports[cable]; - int length; - - length = snd_usbmidi_cin_length[cin]; - if (cin == 0xf && buffer[i + 1] >= 0xf8) - ; /* realtime msg: no running status change */ - else if (cin >= 0x8 && cin <= 0xe) - /* channel msg */ - port->running_status_length = length - 1; - else if (cin == 0x4 && - port->running_status_length != 0 && - buffer[i + 1] < 0x80) - /* CIN 4 that is not a SysEx */ - length = port->running_status_length; - else - /* - * All other msgs cannot begin running status. - * (A channel msg sent as two or three CIN 0xF - * packets could in theory, but this device - * doesn't use this format.) - */ - port->running_status_length = 0; - snd_usbmidi_input_data(ep, cable, &buffer[i + 1], length); - } -} - -/* - * CME protocol: like the standard protocol, but SysEx commands are sent as a - * single USB packet preceded by a 0x0F byte. - */ -static void snd_usbmidi_cme_input(struct snd_usb_midi_in_endpoint *ep, - uint8_t *buffer, int buffer_length) -{ - if (buffer_length < 2 || (buffer[0] & 0x0f) != 0x0f) - snd_usbmidi_standard_input(ep, buffer, buffer_length); - else - snd_usbmidi_input_data(ep, buffer[0] >> 4, - &buffer[1], buffer_length - 1); -} - -/* - * Adds one USB MIDI packet to the output buffer. - */ -static void snd_usbmidi_output_standard_packet(struct urb* urb, uint8_t p0, - uint8_t p1, uint8_t p2, uint8_t p3) -{ - - uint8_t* buf = (uint8_t*)urb->transfer_buffer + urb->transfer_buffer_length; - buf[0] = p0; - buf[1] = p1; - buf[2] = p2; - buf[3] = p3; - urb->transfer_buffer_length += 4; -} - -/* - * Adds one Midiman packet to the output buffer. - */ -static void snd_usbmidi_output_midiman_packet(struct urb* urb, uint8_t p0, - uint8_t p1, uint8_t p2, uint8_t p3) -{ - - uint8_t* buf = (uint8_t*)urb->transfer_buffer + urb->transfer_buffer_length; - buf[0] = p1; - buf[1] = p2; - buf[2] = p3; - buf[3] = (p0 & 0xf0) | snd_usbmidi_cin_length[p0 & 0x0f]; - urb->transfer_buffer_length += 4; -} - -/* - * Converts MIDI commands to USB MIDI packets. - */ -static void snd_usbmidi_transmit_byte(struct usbmidi_out_port* port, - uint8_t b, struct urb* urb) -{ - uint8_t p0 = port->cable; - void (*output_packet)(struct urb*, uint8_t, uint8_t, uint8_t, uint8_t) = - port->ep->umidi->usb_protocol_ops->output_packet; - - if (b >= 0xf8) { - output_packet(urb, p0 | 0x0f, b, 0, 0); - } else if (b >= 0xf0) { - switch (b) { - case 0xf0: - port->data[0] = b; - port->state = STATE_SYSEX_1; - break; - case 0xf1: - case 0xf3: - port->data[0] = b; - port->state = STATE_1PARAM; - break; - case 0xf2: - port->data[0] = b; - port->state = STATE_2PARAM_1; - break; - case 0xf4: - case 0xf5: - port->state = STATE_UNKNOWN; - break; - case 0xf6: - output_packet(urb, p0 | 0x05, 0xf6, 0, 0); - port->state = STATE_UNKNOWN; - break; - case 0xf7: - switch (port->state) { - case STATE_SYSEX_0: - output_packet(urb, p0 | 0x05, 0xf7, 0, 0); - break; - case STATE_SYSEX_1: - output_packet(urb, p0 | 0x06, port->data[0], 0xf7, 0); - break; - case STATE_SYSEX_2: - output_packet(urb, p0 | 0x07, port->data[0], port->data[1], 0xf7); - break; - } - port->state = STATE_UNKNOWN; - break; - } - } else if (b >= 0x80) { - port->data[0] = b; - if (b >= 0xc0 && b <= 0xdf) - port->state = STATE_1PARAM; - else - port->state = STATE_2PARAM_1; - } else { /* b < 0x80 */ - switch (port->state) { - case STATE_1PARAM: - if (port->data[0] < 0xf0) { - p0 |= port->data[0] >> 4; - } else { - p0 |= 0x02; - port->state = STATE_UNKNOWN; - } - output_packet(urb, p0, port->data[0], b, 0); - break; - case STATE_2PARAM_1: - port->data[1] = b; - port->state = STATE_2PARAM_2; - break; - case STATE_2PARAM_2: - if (port->data[0] < 0xf0) { - p0 |= port->data[0] >> 4; - port->state = STATE_2PARAM_1; - } else { - p0 |= 0x03; - port->state = STATE_UNKNOWN; - } - output_packet(urb, p0, port->data[0], port->data[1], b); - break; - case STATE_SYSEX_0: - port->data[0] = b; - port->state = STATE_SYSEX_1; - break; - case STATE_SYSEX_1: - port->data[1] = b; - port->state = STATE_SYSEX_2; - break; - case STATE_SYSEX_2: - output_packet(urb, p0 | 0x04, port->data[0], port->data[1], b); - port->state = STATE_SYSEX_0; - break; - } - } -} - -static void snd_usbmidi_standard_output(struct snd_usb_midi_out_endpoint* ep, - struct urb *urb) -{ - int p; - - /* FIXME: lower-numbered ports can starve higher-numbered ports */ - for (p = 0; p < 0x10; ++p) { - struct usbmidi_out_port* port = &ep->ports[p]; - if (!port->active) - continue; - while (urb->transfer_buffer_length + 3 < ep->max_transfer) { - uint8_t b; - if (snd_rawmidi_transmit(port->substream, &b, 1) != 1) { - port->active = 0; - break; - } - snd_usbmidi_transmit_byte(port, b, urb); - } - } -} - -static struct usb_protocol_ops snd_usbmidi_standard_ops = { - .input = snd_usbmidi_standard_input, - .output = snd_usbmidi_standard_output, - .output_packet = snd_usbmidi_output_standard_packet, -}; - -static struct usb_protocol_ops snd_usbmidi_midiman_ops = { - .input = snd_usbmidi_midiman_input, - .output = snd_usbmidi_standard_output, - .output_packet = snd_usbmidi_output_midiman_packet, -}; - -static struct usb_protocol_ops snd_usbmidi_maudio_broken_running_status_ops = { - .input = snd_usbmidi_maudio_broken_running_status_input, - .output = snd_usbmidi_standard_output, - .output_packet = snd_usbmidi_output_standard_packet, -}; - -static struct usb_protocol_ops snd_usbmidi_cme_ops = { - .input = snd_usbmidi_cme_input, - .output = snd_usbmidi_standard_output, - .output_packet = snd_usbmidi_output_standard_packet, -}; - -/* - * AKAI MPD16 protocol: - * - * For control port (endpoint 1): - * ============================== - * One or more chunks consisting of first byte of (0x10 | msg_len) and then a - * SysEx message (msg_len=9 bytes long). - * - * For data port (endpoint 2): - * =========================== - * One or more chunks consisting of first byte of (0x20 | msg_len) and then a - * MIDI message (msg_len bytes long) - * - * Messages sent: Active Sense, Note On, Poly Pressure, Control Change. - */ -static void snd_usbmidi_akai_input(struct snd_usb_midi_in_endpoint *ep, - uint8_t *buffer, int buffer_length) -{ - unsigned int pos = 0; - unsigned int len = (unsigned int)buffer_length; - while (pos < len) { - unsigned int port = (buffer[pos] >> 4) - 1; - unsigned int msg_len = buffer[pos] & 0x0f; - pos++; - if (pos + msg_len <= len && port < 2) - snd_usbmidi_input_data(ep, 0, &buffer[pos], msg_len); - pos += msg_len; - } -} - -#define MAX_AKAI_SYSEX_LEN 9 - -static void snd_usbmidi_akai_output(struct snd_usb_midi_out_endpoint *ep, - struct urb *urb) -{ - uint8_t *msg; - int pos, end, count, buf_end; - uint8_t tmp[MAX_AKAI_SYSEX_LEN]; - struct snd_rawmidi_substream *substream = ep->ports[0].substream; - - if (!ep->ports[0].active) - return; - - msg = urb->transfer_buffer + urb->transfer_buffer_length; - buf_end = ep->max_transfer - MAX_AKAI_SYSEX_LEN - 1; - - /* only try adding more data when there's space for at least 1 SysEx */ - while (urb->transfer_buffer_length < buf_end) { - count = snd_rawmidi_transmit_peek(substream, - tmp, MAX_AKAI_SYSEX_LEN); - if (!count) { - ep->ports[0].active = 0; - return; - } - /* try to skip non-SysEx data */ - for (pos = 0; pos < count && tmp[pos] != 0xF0; pos++) - ; - - if (pos > 0) { - snd_rawmidi_transmit_ack(substream, pos); - continue; - } - - /* look for the start or end marker */ - for (end = 1; end < count && tmp[end] < 0xF0; end++) - ; - - /* next SysEx started before the end of current one */ - if (end < count && tmp[end] == 0xF0) { - /* it's incomplete - drop it */ - snd_rawmidi_transmit_ack(substream, end); - continue; - } - /* SysEx complete */ - if (end < count && tmp[end] == 0xF7) { - /* queue it, ack it, and get the next one */ - count = end + 1; - msg[0] = 0x10 | count; - memcpy(&msg[1], tmp, count); - snd_rawmidi_transmit_ack(substream, count); - urb->transfer_buffer_length += count + 1; - msg += count + 1; - continue; - } - /* less than 9 bytes and no end byte - wait for more */ - if (count < MAX_AKAI_SYSEX_LEN) { - ep->ports[0].active = 0; - return; - } - /* 9 bytes and no end marker in sight - malformed, skip it */ - snd_rawmidi_transmit_ack(substream, count); - } -} - -static struct usb_protocol_ops snd_usbmidi_akai_ops = { - .input = snd_usbmidi_akai_input, - .output = snd_usbmidi_akai_output, -}; - -/* - * Novation USB MIDI protocol: number of data bytes is in the first byte - * (when receiving) (+1!) or in the second byte (when sending); data begins - * at the third byte. - */ - -static void snd_usbmidi_novation_input(struct snd_usb_midi_in_endpoint* ep, - uint8_t* buffer, int buffer_length) -{ - if (buffer_length < 2 || !buffer[0] || buffer_length < buffer[0] + 1) - return; - snd_usbmidi_input_data(ep, 0, &buffer[2], buffer[0] - 1); -} - -static void snd_usbmidi_novation_output(struct snd_usb_midi_out_endpoint* ep, - struct urb *urb) -{ - uint8_t* transfer_buffer; - int count; - - if (!ep->ports[0].active) - return; - transfer_buffer = urb->transfer_buffer; - count = snd_rawmidi_transmit(ep->ports[0].substream, - &transfer_buffer[2], - ep->max_transfer - 2); - if (count < 1) { - ep->ports[0].active = 0; - return; - } - transfer_buffer[0] = 0; - transfer_buffer[1] = count; - urb->transfer_buffer_length = 2 + count; -} - -static struct usb_protocol_ops snd_usbmidi_novation_ops = { - .input = snd_usbmidi_novation_input, - .output = snd_usbmidi_novation_output, -}; - -/* - * "raw" protocol: just move raw MIDI bytes from/to the endpoint - */ - -static void snd_usbmidi_raw_input(struct snd_usb_midi_in_endpoint* ep, - uint8_t* buffer, int buffer_length) -{ - snd_usbmidi_input_data(ep, 0, buffer, buffer_length); -} - -static void snd_usbmidi_raw_output(struct snd_usb_midi_out_endpoint* ep, - struct urb *urb) -{ - int count; - - if (!ep->ports[0].active) - return; - count = snd_rawmidi_transmit(ep->ports[0].substream, - urb->transfer_buffer, - ep->max_transfer); - if (count < 1) { - ep->ports[0].active = 0; - return; - } - urb->transfer_buffer_length = count; -} - -static struct usb_protocol_ops snd_usbmidi_raw_ops = { - .input = snd_usbmidi_raw_input, - .output = snd_usbmidi_raw_output, -}; - -/* - * FTDI protocol: raw MIDI bytes, but input packets have two modem status bytes. - */ - -static void snd_usbmidi_ftdi_input(struct snd_usb_midi_in_endpoint* ep, - uint8_t* buffer, int buffer_length) -{ - if (buffer_length > 2) - snd_usbmidi_input_data(ep, 0, buffer + 2, buffer_length - 2); -} - -static struct usb_protocol_ops snd_usbmidi_ftdi_ops = { - .input = snd_usbmidi_ftdi_input, - .output = snd_usbmidi_raw_output, -}; - -static void snd_usbmidi_us122l_input(struct snd_usb_midi_in_endpoint *ep, - uint8_t *buffer, int buffer_length) -{ - if (buffer_length != 9) - return; - buffer_length = 8; - while (buffer_length && buffer[buffer_length - 1] == 0xFD) - buffer_length--; - if (buffer_length) - snd_usbmidi_input_data(ep, 0, buffer, buffer_length); -} - -static void snd_usbmidi_us122l_output(struct snd_usb_midi_out_endpoint *ep, - struct urb *urb) -{ - int count; - - if (!ep->ports[0].active) - return; - switch (snd_usb_get_speed(ep->umidi->dev)) { - case USB_SPEED_HIGH: - case USB_SPEED_SUPER: - count = 1; - break; - default: - count = 2; - } - count = snd_rawmidi_transmit(ep->ports[0].substream, - urb->transfer_buffer, - count); - if (count < 1) { - ep->ports[0].active = 0; - return; - } - - memset(urb->transfer_buffer + count, 0xFD, ep->max_transfer - count); - urb->transfer_buffer_length = ep->max_transfer; -} - -static struct usb_protocol_ops snd_usbmidi_122l_ops = { - .input = snd_usbmidi_us122l_input, - .output = snd_usbmidi_us122l_output, -}; - -/* - * Emagic USB MIDI protocol: raw MIDI with "F5 xx" port switching. - */ - -static void snd_usbmidi_emagic_init_out(struct snd_usb_midi_out_endpoint* ep) -{ - static const u8 init_data[] = { - /* initialization magic: "get version" */ - 0xf0, - 0x00, 0x20, 0x31, /* Emagic */ - 0x64, /* Unitor8 */ - 0x0b, /* version number request */ - 0x00, /* command version */ - 0x00, /* EEPROM, box 0 */ - 0xf7 - }; - send_bulk_static_data(ep, init_data, sizeof(init_data)); - /* while we're at it, pour on more magic */ - send_bulk_static_data(ep, init_data, sizeof(init_data)); -} - -static void snd_usbmidi_emagic_finish_out(struct snd_usb_midi_out_endpoint* ep) -{ - static const u8 finish_data[] = { - /* switch to patch mode with last preset */ - 0xf0, - 0x00, 0x20, 0x31, /* Emagic */ - 0x64, /* Unitor8 */ - 0x10, /* patch switch command */ - 0x00, /* command version */ - 0x7f, /* to all boxes */ - 0x40, /* last preset in EEPROM */ - 0xf7 - }; - send_bulk_static_data(ep, finish_data, sizeof(finish_data)); -} - -static void snd_usbmidi_emagic_input(struct snd_usb_midi_in_endpoint* ep, - uint8_t* buffer, int buffer_length) -{ - int i; - - /* FF indicates end of valid data */ - for (i = 0; i < buffer_length; ++i) - if (buffer[i] == 0xff) { - buffer_length = i; - break; - } - - /* handle F5 at end of last buffer */ - if (ep->seen_f5) - goto switch_port; - - while (buffer_length > 0) { - /* determine size of data until next F5 */ - for (i = 0; i < buffer_length; ++i) - if (buffer[i] == 0xf5) - break; - snd_usbmidi_input_data(ep, ep->current_port, buffer, i); - buffer += i; - buffer_length -= i; - - if (buffer_length <= 0) - break; - /* assert(buffer[0] == 0xf5); */ - ep->seen_f5 = 1; - ++buffer; - --buffer_length; - - switch_port: - if (buffer_length <= 0) - break; - if (buffer[0] < 0x80) { - ep->current_port = (buffer[0] - 1) & 15; - ++buffer; - --buffer_length; - } - ep->seen_f5 = 0; - } -} - -static void snd_usbmidi_emagic_output(struct snd_usb_midi_out_endpoint* ep, - struct urb *urb) -{ - int port0 = ep->current_port; - uint8_t* buf = urb->transfer_buffer; - int buf_free = ep->max_transfer; - int length, i; - - for (i = 0; i < 0x10; ++i) { - /* round-robin, starting at the last current port */ - int portnum = (port0 + i) & 15; - struct usbmidi_out_port* port = &ep->ports[portnum]; - - if (!port->active) - continue; - if (snd_rawmidi_transmit_peek(port->substream, buf, 1) != 1) { - port->active = 0; - continue; - } - - if (portnum != ep->current_port) { - if (buf_free < 2) - break; - ep->current_port = portnum; - buf[0] = 0xf5; - buf[1] = (portnum + 1) & 15; - buf += 2; - buf_free -= 2; - } - - if (buf_free < 1) - break; - length = snd_rawmidi_transmit(port->substream, buf, buf_free); - if (length > 0) { - buf += length; - buf_free -= length; - if (buf_free < 1) - break; - } - } - if (buf_free < ep->max_transfer && buf_free > 0) { - *buf = 0xff; - --buf_free; - } - urb->transfer_buffer_length = ep->max_transfer - buf_free; -} - -static struct usb_protocol_ops snd_usbmidi_emagic_ops = { - .input = snd_usbmidi_emagic_input, - .output = snd_usbmidi_emagic_output, - .init_out_endpoint = snd_usbmidi_emagic_init_out, - .finish_out_endpoint = snd_usbmidi_emagic_finish_out, -}; - - -static void update_roland_altsetting(struct snd_usb_midi* umidi) -{ - struct usb_interface *intf; - struct usb_host_interface *hostif; - struct usb_interface_descriptor *intfd; - int is_light_load; - - intf = umidi->iface; - is_light_load = intf->cur_altsetting != intf->altsetting; - if (umidi->roland_load_ctl->private_value == is_light_load) - return; - hostif = &intf->altsetting[umidi->roland_load_ctl->private_value]; - intfd = get_iface_desc(hostif); - snd_usbmidi_input_stop(&umidi->list); - usb_set_interface(umidi->dev, intfd->bInterfaceNumber, - intfd->bAlternateSetting); - snd_usbmidi_input_start(&umidi->list); -} - -static void substream_open(struct snd_rawmidi_substream *substream, int open) -{ - struct snd_usb_midi* umidi = substream->rmidi->private_data; - struct snd_kcontrol *ctl; - - mutex_lock(&umidi->mutex); - if (open) { - if (umidi->opened++ == 0 && umidi->roland_load_ctl) { - ctl = umidi->roland_load_ctl; - ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; - snd_ctl_notify(umidi->card, - SNDRV_CTL_EVENT_MASK_INFO, &ctl->id); - update_roland_altsetting(umidi); - } - } else { - if (--umidi->opened == 0 && umidi->roland_load_ctl) { - ctl = umidi->roland_load_ctl; - ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; - snd_ctl_notify(umidi->card, - SNDRV_CTL_EVENT_MASK_INFO, &ctl->id); - } - } - mutex_unlock(&umidi->mutex); -} - -static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream) -{ - struct snd_usb_midi* umidi = substream->rmidi->private_data; - struct usbmidi_out_port* port = NULL; - int i, j; - int err; - - for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) - if (umidi->endpoints[i].out) - for (j = 0; j < 0x10; ++j) - if (umidi->endpoints[i].out->ports[j].substream == substream) { - port = &umidi->endpoints[i].out->ports[j]; - break; - } - if (!port) { - snd_BUG(); - return -ENXIO; - } - err = usb_autopm_get_interface(umidi->iface); - if (err < 0) - return -EIO; - substream->runtime->private_data = port; - port->state = STATE_UNKNOWN; - substream_open(substream, 1); - return 0; -} - -static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream) -{ - struct snd_usb_midi* umidi = substream->rmidi->private_data; - - substream_open(substream, 0); - usb_autopm_put_interface(umidi->iface); - return 0; -} - -static void snd_usbmidi_output_trigger(struct snd_rawmidi_substream *substream, int up) -{ - struct usbmidi_out_port* port = (struct usbmidi_out_port*)substream->runtime->private_data; - - port->active = up; - if (up) { - if (port->ep->umidi->disconnected) { - /* gobble up remaining bytes to prevent wait in - * snd_rawmidi_drain_output */ - while (!snd_rawmidi_transmit_empty(substream)) - snd_rawmidi_transmit_ack(substream, 1); - return; - } - tasklet_schedule(&port->ep->tasklet); - } -} - -static void snd_usbmidi_output_drain(struct snd_rawmidi_substream *substream) -{ - struct usbmidi_out_port* port = substream->runtime->private_data; - struct snd_usb_midi_out_endpoint *ep = port->ep; - unsigned int drain_urbs; - DEFINE_WAIT(wait); - long timeout = msecs_to_jiffies(50); - - if (ep->umidi->disconnected) - return; - /* - * The substream buffer is empty, but some data might still be in the - * currently active URBs, so we have to wait for those to complete. - */ - spin_lock_irq(&ep->buffer_lock); - drain_urbs = ep->active_urbs; - if (drain_urbs) { - ep->drain_urbs |= drain_urbs; - do { - prepare_to_wait(&ep->drain_wait, &wait, - TASK_UNINTERRUPTIBLE); - spin_unlock_irq(&ep->buffer_lock); - timeout = schedule_timeout(timeout); - spin_lock_irq(&ep->buffer_lock); - drain_urbs &= ep->drain_urbs; - } while (drain_urbs && timeout); - finish_wait(&ep->drain_wait, &wait); - } - spin_unlock_irq(&ep->buffer_lock); -} - -static int snd_usbmidi_input_open(struct snd_rawmidi_substream *substream) -{ - substream_open(substream, 1); - return 0; -} - -static int snd_usbmidi_input_close(struct snd_rawmidi_substream *substream) -{ - substream_open(substream, 0); - return 0; -} - -static void snd_usbmidi_input_trigger(struct snd_rawmidi_substream *substream, int up) -{ - struct snd_usb_midi* umidi = substream->rmidi->private_data; - - if (up) - set_bit(substream->number, &umidi->input_triggered); - else - clear_bit(substream->number, &umidi->input_triggered); -} - -static struct snd_rawmidi_ops snd_usbmidi_output_ops = { - .open = snd_usbmidi_output_open, - .close = snd_usbmidi_output_close, - .trigger = snd_usbmidi_output_trigger, - .drain = snd_usbmidi_output_drain, -}; - -static struct snd_rawmidi_ops snd_usbmidi_input_ops = { - .open = snd_usbmidi_input_open, - .close = snd_usbmidi_input_close, - .trigger = snd_usbmidi_input_trigger -}; - -static void free_urb_and_buffer(struct snd_usb_midi *umidi, struct urb *urb, - unsigned int buffer_length) -{ - usb_free_coherent(umidi->dev, buffer_length, - urb->transfer_buffer, urb->transfer_dma); - usb_free_urb(urb); -} - -/* - * Frees an input endpoint. - * May be called when ep hasn't been initialized completely. - */ -static void snd_usbmidi_in_endpoint_delete(struct snd_usb_midi_in_endpoint* ep) -{ - unsigned int i; - - for (i = 0; i < INPUT_URBS; ++i) - if (ep->urbs[i]) - free_urb_and_buffer(ep->umidi, ep->urbs[i], - ep->urbs[i]->transfer_buffer_length); - kfree(ep); -} - -/* - * Creates an input endpoint. - */ -static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi* umidi, - struct snd_usb_midi_endpoint_info* ep_info, - struct snd_usb_midi_endpoint* rep) -{ - struct snd_usb_midi_in_endpoint* ep; - void* buffer; - unsigned int pipe; - int length; - unsigned int i; - - rep->in = NULL; - ep = kzalloc(sizeof(*ep), GFP_KERNEL); - if (!ep) - return -ENOMEM; - ep->umidi = umidi; - - for (i = 0; i < INPUT_URBS; ++i) { - ep->urbs[i] = usb_alloc_urb(0, GFP_KERNEL); - if (!ep->urbs[i]) { - snd_usbmidi_in_endpoint_delete(ep); - return -ENOMEM; - } - } - if (ep_info->in_interval) - pipe = usb_rcvintpipe(umidi->dev, ep_info->in_ep); - else - pipe = usb_rcvbulkpipe(umidi->dev, ep_info->in_ep); - length = usb_maxpacket(umidi->dev, pipe, 0); - for (i = 0; i < INPUT_URBS; ++i) { - buffer = usb_alloc_coherent(umidi->dev, length, GFP_KERNEL, - &ep->urbs[i]->transfer_dma); - if (!buffer) { - snd_usbmidi_in_endpoint_delete(ep); - return -ENOMEM; - } - if (ep_info->in_interval) - usb_fill_int_urb(ep->urbs[i], umidi->dev, - pipe, buffer, length, - snd_usbmidi_in_urb_complete, - ep, ep_info->in_interval); - else - usb_fill_bulk_urb(ep->urbs[i], umidi->dev, - pipe, buffer, length, - snd_usbmidi_in_urb_complete, ep); - ep->urbs[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP; - } - - rep->in = ep; - return 0; -} - -/* - * Frees an output endpoint. - * May be called when ep hasn't been initialized completely. - */ -static void snd_usbmidi_out_endpoint_clear(struct snd_usb_midi_out_endpoint *ep) -{ - unsigned int i; - - for (i = 0; i < OUTPUT_URBS; ++i) - if (ep->urbs[i].urb) { - free_urb_and_buffer(ep->umidi, ep->urbs[i].urb, - ep->max_transfer); - ep->urbs[i].urb = NULL; - } -} - -static void snd_usbmidi_out_endpoint_delete(struct snd_usb_midi_out_endpoint *ep) -{ - snd_usbmidi_out_endpoint_clear(ep); - kfree(ep); -} - -/* - * Creates an output endpoint, and initializes output ports. - */ -static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi* umidi, - struct snd_usb_midi_endpoint_info* ep_info, - struct snd_usb_midi_endpoint* rep) -{ - struct snd_usb_midi_out_endpoint* ep; - unsigned int i; - unsigned int pipe; - void* buffer; - - rep->out = NULL; - ep = kzalloc(sizeof(*ep), GFP_KERNEL); - if (!ep) - return -ENOMEM; - ep->umidi = umidi; - - for (i = 0; i < OUTPUT_URBS; ++i) { - ep->urbs[i].urb = usb_alloc_urb(0, GFP_KERNEL); - if (!ep->urbs[i].urb) { - snd_usbmidi_out_endpoint_delete(ep); - return -ENOMEM; - } - ep->urbs[i].ep = ep; - } - if (ep_info->out_interval) - pipe = usb_sndintpipe(umidi->dev, ep_info->out_ep); - else - pipe = usb_sndbulkpipe(umidi->dev, ep_info->out_ep); - switch (umidi->usb_id) { - default: - ep->max_transfer = usb_maxpacket(umidi->dev, pipe, 1); - break; - /* - * Various chips declare a packet size larger than 4 bytes, but - * do not actually work with larger packets: - */ - case USB_ID(0x0a92, 0x1020): /* ESI M4U */ - case USB_ID(0x1430, 0x474b): /* RedOctane GH MIDI INTERFACE */ - case USB_ID(0x15ca, 0x0101): /* Textech USB Midi Cable */ - case USB_ID(0x15ca, 0x1806): /* Textech USB Midi Cable */ - case USB_ID(0x1a86, 0x752d): /* QinHeng CH345 "USB2.0-MIDI" */ - case USB_ID(0xfc08, 0x0101): /* Unknown vendor Cable */ - ep->max_transfer = 4; - break; - /* - * Some devices only work with 9 bytes packet size: - */ - case USB_ID(0x0644, 0x800E): /* Tascam US-122L */ - case USB_ID(0x0644, 0x800F): /* Tascam US-144 */ - ep->max_transfer = 9; - break; - } - for (i = 0; i < OUTPUT_URBS; ++i) { - buffer = usb_alloc_coherent(umidi->dev, - ep->max_transfer, GFP_KERNEL, - &ep->urbs[i].urb->transfer_dma); - if (!buffer) { - snd_usbmidi_out_endpoint_delete(ep); - return -ENOMEM; - } - if (ep_info->out_interval) - usb_fill_int_urb(ep->urbs[i].urb, umidi->dev, - pipe, buffer, ep->max_transfer, - snd_usbmidi_out_urb_complete, - &ep->urbs[i], ep_info->out_interval); - else - usb_fill_bulk_urb(ep->urbs[i].urb, umidi->dev, - pipe, buffer, ep->max_transfer, - snd_usbmidi_out_urb_complete, - &ep->urbs[i]); - ep->urbs[i].urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; - } - - spin_lock_init(&ep->buffer_lock); - tasklet_init(&ep->tasklet, snd_usbmidi_out_tasklet, (unsigned long)ep); - init_waitqueue_head(&ep->drain_wait); - - for (i = 0; i < 0x10; ++i) - if (ep_info->out_cables & (1 << i)) { - ep->ports[i].ep = ep; - ep->ports[i].cable = i << 4; - } - - if (umidi->usb_protocol_ops->init_out_endpoint) - umidi->usb_protocol_ops->init_out_endpoint(ep); - - rep->out = ep; - return 0; -} - -/* - * Frees everything. - */ -static void snd_usbmidi_free(struct snd_usb_midi* umidi) -{ - int i; - - for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) { - struct snd_usb_midi_endpoint* ep = &umidi->endpoints[i]; - if (ep->out) - snd_usbmidi_out_endpoint_delete(ep->out); - if (ep->in) - snd_usbmidi_in_endpoint_delete(ep->in); - } - mutex_destroy(&umidi->mutex); - kfree(umidi); -} - -/* - * Unlinks all URBs (must be done before the usb_device is deleted). - */ -void snd_usbmidi_disconnect(struct list_head* p) -{ - struct snd_usb_midi* umidi; - unsigned int i, j; - - umidi = list_entry(p, struct snd_usb_midi, list); - /* - * an URB's completion handler may start the timer and - * a timer may submit an URB. To reliably break the cycle - * a flag under lock must be used - */ - spin_lock_irq(&umidi->disc_lock); - umidi->disconnected = 1; - spin_unlock_irq(&umidi->disc_lock); - for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) { - struct snd_usb_midi_endpoint* ep = &umidi->endpoints[i]; - if (ep->out) - tasklet_kill(&ep->out->tasklet); - if (ep->out) { - for (j = 0; j < OUTPUT_URBS; ++j) - usb_kill_urb(ep->out->urbs[j].urb); - if (umidi->usb_protocol_ops->finish_out_endpoint) - umidi->usb_protocol_ops->finish_out_endpoint(ep->out); - ep->out->active_urbs = 0; - if (ep->out->drain_urbs) { - ep->out->drain_urbs = 0; - wake_up(&ep->out->drain_wait); - } - } - if (ep->in) - for (j = 0; j < INPUT_URBS; ++j) - usb_kill_urb(ep->in->urbs[j]); - /* free endpoints here; later call can result in Oops */ - if (ep->out) - snd_usbmidi_out_endpoint_clear(ep->out); - if (ep->in) { - snd_usbmidi_in_endpoint_delete(ep->in); - ep->in = NULL; - } - } - del_timer_sync(&umidi->error_timer); -} - -static void snd_usbmidi_rawmidi_free(struct snd_rawmidi *rmidi) -{ - struct snd_usb_midi* umidi = rmidi->private_data; - snd_usbmidi_free(umidi); -} - -static struct snd_rawmidi_substream *snd_usbmidi_find_substream(struct snd_usb_midi* umidi, - int stream, int number) -{ - struct list_head* list; - - list_for_each(list, &umidi->rmidi->streams[stream].substreams) { - struct snd_rawmidi_substream *substream = list_entry(list, struct snd_rawmidi_substream, list); - if (substream->number == number) - return substream; - } - return NULL; -} - -/* - * This list specifies names for ports that do not fit into the standard - * "(product) MIDI (n)" schema because they aren't external MIDI ports, - * such as internal control or synthesizer ports. - */ -static struct port_info { - u32 id; - short int port; - short int voices; - const char *name; - unsigned int seq_flags; -} snd_usbmidi_port_info[] = { -#define PORT_INFO(vendor, product, num, name_, voices_, flags) \ - { .id = USB_ID(vendor, product), \ - .port = num, .voices = voices_, \ - .name = name_, .seq_flags = flags } -#define EXTERNAL_PORT(vendor, product, num, name) \ - PORT_INFO(vendor, product, num, name, 0, \ - SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | \ - SNDRV_SEQ_PORT_TYPE_HARDWARE | \ - SNDRV_SEQ_PORT_TYPE_PORT) -#define CONTROL_PORT(vendor, product, num, name) \ - PORT_INFO(vendor, product, num, name, 0, \ - SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | \ - SNDRV_SEQ_PORT_TYPE_HARDWARE) -#define ROLAND_SYNTH_PORT(vendor, product, num, name, voices) \ - PORT_INFO(vendor, product, num, name, voices, \ - SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | \ - SNDRV_SEQ_PORT_TYPE_MIDI_GM | \ - SNDRV_SEQ_PORT_TYPE_MIDI_GM2 | \ - SNDRV_SEQ_PORT_TYPE_MIDI_GS | \ - SNDRV_SEQ_PORT_TYPE_MIDI_XG | \ - SNDRV_SEQ_PORT_TYPE_HARDWARE | \ - SNDRV_SEQ_PORT_TYPE_SYNTHESIZER) -#define SOUNDCANVAS_PORT(vendor, product, num, name, voices) \ - PORT_INFO(vendor, product, num, name, voices, \ - SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | \ - SNDRV_SEQ_PORT_TYPE_MIDI_GM | \ - SNDRV_SEQ_PORT_TYPE_MIDI_GM2 | \ - SNDRV_SEQ_PORT_TYPE_MIDI_GS | \ - SNDRV_SEQ_PORT_TYPE_MIDI_XG | \ - SNDRV_SEQ_PORT_TYPE_MIDI_MT32 | \ - SNDRV_SEQ_PORT_TYPE_HARDWARE | \ - SNDRV_SEQ_PORT_TYPE_SYNTHESIZER) - /* Roland UA-100 */ - CONTROL_PORT(0x0582, 0x0000, 2, "%s Control"), - /* Roland SC-8850 */ - SOUNDCANVAS_PORT(0x0582, 0x0003, 0, "%s Part A", 128), - SOUNDCANVAS_PORT(0x0582, 0x0003, 1, "%s Part B", 128), - SOUNDCANVAS_PORT(0x0582, 0x0003, 2, "%s Part C", 128), - SOUNDCANVAS_PORT(0x0582, 0x0003, 3, "%s Part D", 128), - EXTERNAL_PORT(0x0582, 0x0003, 4, "%s MIDI 1"), - EXTERNAL_PORT(0x0582, 0x0003, 5, "%s MIDI 2"), - /* Roland U-8 */ - EXTERNAL_PORT(0x0582, 0x0004, 0, "%s MIDI"), - CONTROL_PORT(0x0582, 0x0004, 1, "%s Control"), - /* Roland SC-8820 */ - SOUNDCANVAS_PORT(0x0582, 0x0007, 0, "%s Part A", 64), - SOUNDCANVAS_PORT(0x0582, 0x0007, 1, "%s Part B", 64), - EXTERNAL_PORT(0x0582, 0x0007, 2, "%s MIDI"), - /* Roland SK-500 */ - SOUNDCANVAS_PORT(0x0582, 0x000b, 0, "%s Part A", 64), - SOUNDCANVAS_PORT(0x0582, 0x000b, 1, "%s Part B", 64), - EXTERNAL_PORT(0x0582, 0x000b, 2, "%s MIDI"), - /* Roland SC-D70 */ - SOUNDCANVAS_PORT(0x0582, 0x000c, 0, "%s Part A", 64), - SOUNDCANVAS_PORT(0x0582, 0x000c, 1, "%s Part B", 64), - EXTERNAL_PORT(0x0582, 0x000c, 2, "%s MIDI"), - /* Edirol UM-880 */ - CONTROL_PORT(0x0582, 0x0014, 8, "%s Control"), - /* Edirol SD-90 */ - ROLAND_SYNTH_PORT(0x0582, 0x0016, 0, "%s Part A", 128), - ROLAND_SYNTH_PORT(0x0582, 0x0016, 1, "%s Part B", 128), - EXTERNAL_PORT(0x0582, 0x0016, 2, "%s MIDI 1"), - EXTERNAL_PORT(0x0582, 0x0016, 3, "%s MIDI 2"), - /* Edirol UM-550 */ - CONTROL_PORT(0x0582, 0x0023, 5, "%s Control"), - /* Edirol SD-20 */ - ROLAND_SYNTH_PORT(0x0582, 0x0027, 0, "%s Part A", 64), - ROLAND_SYNTH_PORT(0x0582, 0x0027, 1, "%s Part B", 64), - EXTERNAL_PORT(0x0582, 0x0027, 2, "%s MIDI"), - /* Edirol SD-80 */ - ROLAND_SYNTH_PORT(0x0582, 0x0029, 0, "%s Part A", 128), - ROLAND_SYNTH_PORT(0x0582, 0x0029, 1, "%s Part B", 128), - EXTERNAL_PORT(0x0582, 0x0029, 2, "%s MIDI 1"), - EXTERNAL_PORT(0x0582, 0x0029, 3, "%s MIDI 2"), - /* Edirol UA-700 */ - EXTERNAL_PORT(0x0582, 0x002b, 0, "%s MIDI"), - CONTROL_PORT(0x0582, 0x002b, 1, "%s Control"), - /* Roland VariOS */ - EXTERNAL_PORT(0x0582, 0x002f, 0, "%s MIDI"), - EXTERNAL_PORT(0x0582, 0x002f, 1, "%s External MIDI"), - EXTERNAL_PORT(0x0582, 0x002f, 2, "%s Sync"), - /* Edirol PCR */ - EXTERNAL_PORT(0x0582, 0x0033, 0, "%s MIDI"), - EXTERNAL_PORT(0x0582, 0x0033, 1, "%s 1"), - EXTERNAL_PORT(0x0582, 0x0033, 2, "%s 2"), - /* BOSS GS-10 */ - EXTERNAL_PORT(0x0582, 0x003b, 0, "%s MIDI"), - CONTROL_PORT(0x0582, 0x003b, 1, "%s Control"), - /* Edirol UA-1000 */ - EXTERNAL_PORT(0x0582, 0x0044, 0, "%s MIDI"), - CONTROL_PORT(0x0582, 0x0044, 1, "%s Control"), - /* Edirol UR-80 */ - EXTERNAL_PORT(0x0582, 0x0048, 0, "%s MIDI"), - EXTERNAL_PORT(0x0582, 0x0048, 1, "%s 1"), - EXTERNAL_PORT(0x0582, 0x0048, 2, "%s 2"), - /* Edirol PCR-A */ - EXTERNAL_PORT(0x0582, 0x004d, 0, "%s MIDI"), - EXTERNAL_PORT(0x0582, 0x004d, 1, "%s 1"), - EXTERNAL_PORT(0x0582, 0x004d, 2, "%s 2"), - /* Edirol UM-3EX */ - CONTROL_PORT(0x0582, 0x009a, 3, "%s Control"), - /* M-Audio MidiSport 8x8 */ - CONTROL_PORT(0x0763, 0x1031, 8, "%s Control"), - CONTROL_PORT(0x0763, 0x1033, 8, "%s Control"), - /* MOTU Fastlane */ - EXTERNAL_PORT(0x07fd, 0x0001, 0, "%s MIDI A"), - EXTERNAL_PORT(0x07fd, 0x0001, 1, "%s MIDI B"), - /* Emagic Unitor8/AMT8/MT4 */ - EXTERNAL_PORT(0x086a, 0x0001, 8, "%s Broadcast"), - EXTERNAL_PORT(0x086a, 0x0002, 8, "%s Broadcast"), - EXTERNAL_PORT(0x086a, 0x0003, 4, "%s Broadcast"), - /* Akai MPD16 */ - CONTROL_PORT(0x09e8, 0x0062, 0, "%s Control"), - PORT_INFO(0x09e8, 0x0062, 1, "%s MIDI", 0, - SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | - SNDRV_SEQ_PORT_TYPE_HARDWARE), - /* Access Music Virus TI */ - EXTERNAL_PORT(0x133e, 0x0815, 0, "%s MIDI"), - PORT_INFO(0x133e, 0x0815, 1, "%s Synth", 0, - SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | - SNDRV_SEQ_PORT_TYPE_HARDWARE | - SNDRV_SEQ_PORT_TYPE_SYNTHESIZER), -}; - -static struct port_info *find_port_info(struct snd_usb_midi* umidi, int number) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(snd_usbmidi_port_info); ++i) { - if (snd_usbmidi_port_info[i].id == umidi->usb_id && - snd_usbmidi_port_info[i].port == number) - return &snd_usbmidi_port_info[i]; - } - return NULL; -} - -static void snd_usbmidi_get_port_info(struct snd_rawmidi *rmidi, int number, - struct snd_seq_port_info *seq_port_info) -{ - struct snd_usb_midi *umidi = rmidi->private_data; - struct port_info *port_info; - - /* TODO: read port flags from descriptors */ - port_info = find_port_info(umidi, number); - if (port_info) { - seq_port_info->type = port_info->seq_flags; - seq_port_info->midi_voices = port_info->voices; - } -} - -static void snd_usbmidi_init_substream(struct snd_usb_midi* umidi, - int stream, int number, - struct snd_rawmidi_substream ** rsubstream) -{ - struct port_info *port_info; - const char *name_format; - - struct snd_rawmidi_substream *substream = snd_usbmidi_find_substream(umidi, stream, number); - if (!substream) { - snd_printd(KERN_ERR "substream %d:%d not found\n", stream, number); - return; - } - - /* TODO: read port name from jack descriptor */ - port_info = find_port_info(umidi, number); - name_format = port_info ? port_info->name : "%s MIDI %d"; - snprintf(substream->name, sizeof(substream->name), - name_format, umidi->card->shortname, number + 1); - - *rsubstream = substream; -} - -/* - * Creates the endpoints and their ports. - */ -static int snd_usbmidi_create_endpoints(struct snd_usb_midi* umidi, - struct snd_usb_midi_endpoint_info* endpoints) -{ - int i, j, err; - int out_ports = 0, in_ports = 0; - - for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) { - if (endpoints[i].out_cables) { - err = snd_usbmidi_out_endpoint_create(umidi, &endpoints[i], - &umidi->endpoints[i]); - if (err < 0) - return err; - } - if (endpoints[i].in_cables) { - err = snd_usbmidi_in_endpoint_create(umidi, &endpoints[i], - &umidi->endpoints[i]); - if (err < 0) - return err; - } - - for (j = 0; j < 0x10; ++j) { - if (endpoints[i].out_cables & (1 << j)) { - snd_usbmidi_init_substream(umidi, SNDRV_RAWMIDI_STREAM_OUTPUT, out_ports, - &umidi->endpoints[i].out->ports[j].substream); - ++out_ports; - } - if (endpoints[i].in_cables & (1 << j)) { - snd_usbmidi_init_substream(umidi, SNDRV_RAWMIDI_STREAM_INPUT, in_ports, - &umidi->endpoints[i].in->ports[j].substream); - ++in_ports; - } - } - } - snd_printdd(KERN_INFO "created %d output and %d input ports\n", - out_ports, in_ports); - return 0; -} - -/* - * Returns MIDIStreaming device capabilities. - */ -static int snd_usbmidi_get_ms_info(struct snd_usb_midi* umidi, - struct snd_usb_midi_endpoint_info* endpoints) -{ - struct usb_interface* intf; - struct usb_host_interface *hostif; - struct usb_interface_descriptor* intfd; - struct usb_ms_header_descriptor* ms_header; - struct usb_host_endpoint *hostep; - struct usb_endpoint_descriptor* ep; - struct usb_ms_endpoint_descriptor* ms_ep; - int i, epidx; - - intf = umidi->iface; - if (!intf) - return -ENXIO; - hostif = &intf->altsetting[0]; - intfd = get_iface_desc(hostif); - ms_header = (struct usb_ms_header_descriptor*)hostif->extra; - if (hostif->extralen >= 7 && - ms_header->bLength >= 7 && - ms_header->bDescriptorType == USB_DT_CS_INTERFACE && - ms_header->bDescriptorSubtype == UAC_HEADER) - snd_printdd(KERN_INFO "MIDIStreaming version %02x.%02x\n", - ms_header->bcdMSC[1], ms_header->bcdMSC[0]); - else - snd_printk(KERN_WARNING "MIDIStreaming interface descriptor not found\n"); - - epidx = 0; - for (i = 0; i < intfd->bNumEndpoints; ++i) { - hostep = &hostif->endpoint[i]; - ep = get_ep_desc(hostep); - if (!usb_endpoint_xfer_bulk(ep) && !usb_endpoint_xfer_int(ep)) - continue; - ms_ep = (struct usb_ms_endpoint_descriptor*)hostep->extra; - if (hostep->extralen < 4 || - ms_ep->bLength < 4 || - ms_ep->bDescriptorType != USB_DT_CS_ENDPOINT || - ms_ep->bDescriptorSubtype != UAC_MS_GENERAL) - continue; - if (usb_endpoint_dir_out(ep)) { - if (endpoints[epidx].out_ep) { - if (++epidx >= MIDI_MAX_ENDPOINTS) { - snd_printk(KERN_WARNING "too many endpoints\n"); - break; - } - } - endpoints[epidx].out_ep = usb_endpoint_num(ep); - if (usb_endpoint_xfer_int(ep)) - endpoints[epidx].out_interval = ep->bInterval; - else if (snd_usb_get_speed(umidi->dev) == USB_SPEED_LOW) - /* - * Low speed bulk transfers don't exist, so - * force interrupt transfers for devices like - * ESI MIDI Mate that try to use them anyway. - */ - endpoints[epidx].out_interval = 1; - endpoints[epidx].out_cables = (1 << ms_ep->bNumEmbMIDIJack) - 1; - snd_printdd(KERN_INFO "EP %02X: %d jack(s)\n", - ep->bEndpointAddress, ms_ep->bNumEmbMIDIJack); - } else { - if (endpoints[epidx].in_ep) { - if (++epidx >= MIDI_MAX_ENDPOINTS) { - snd_printk(KERN_WARNING "too many endpoints\n"); - break; - } - } - endpoints[epidx].in_ep = usb_endpoint_num(ep); - if (usb_endpoint_xfer_int(ep)) - endpoints[epidx].in_interval = ep->bInterval; - else if (snd_usb_get_speed(umidi->dev) == USB_SPEED_LOW) - endpoints[epidx].in_interval = 1; - endpoints[epidx].in_cables = (1 << ms_ep->bNumEmbMIDIJack) - 1; - snd_printdd(KERN_INFO "EP %02X: %d jack(s)\n", - ep->bEndpointAddress, ms_ep->bNumEmbMIDIJack); - } - } - return 0; -} - -static int roland_load_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *info) -{ - static const char *const names[] = { "High Load", "Light Load" }; - - return snd_ctl_enum_info(info, 1, 2, names); -} - -static int roland_load_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *value) -{ - value->value.enumerated.item[0] = kcontrol->private_value; - return 0; -} - -static int roland_load_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *value) -{ - struct snd_usb_midi* umidi = kcontrol->private_data; - int changed; - - if (value->value.enumerated.item[0] > 1) - return -EINVAL; - mutex_lock(&umidi->mutex); - changed = value->value.enumerated.item[0] != kcontrol->private_value; - if (changed) - kcontrol->private_value = value->value.enumerated.item[0]; - mutex_unlock(&umidi->mutex); - return changed; -} - -static struct snd_kcontrol_new roland_load_ctl = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "MIDI Input Mode", - .info = roland_load_info, - .get = roland_load_get, - .put = roland_load_put, - .private_value = 1, -}; - -/* - * On Roland devices, use the second alternate setting to be able to use - * the interrupt input endpoint. - */ -static void snd_usbmidi_switch_roland_altsetting(struct snd_usb_midi* umidi) -{ - struct usb_interface* intf; - struct usb_host_interface *hostif; - struct usb_interface_descriptor* intfd; - - intf = umidi->iface; - if (!intf || intf->num_altsetting != 2) - return; - - hostif = &intf->altsetting[1]; - intfd = get_iface_desc(hostif); - if (intfd->bNumEndpoints != 2 || - (get_endpoint(hostif, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK || - (get_endpoint(hostif, 1)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) - return; - - snd_printdd(KERN_INFO "switching to altsetting %d with int ep\n", - intfd->bAlternateSetting); - usb_set_interface(umidi->dev, intfd->bInterfaceNumber, - intfd->bAlternateSetting); - - umidi->roland_load_ctl = snd_ctl_new1(&roland_load_ctl, umidi); - if (snd_ctl_add(umidi->card, umidi->roland_load_ctl) < 0) - umidi->roland_load_ctl = NULL; -} - -/* - * Try to find any usable endpoints in the interface. - */ -static int snd_usbmidi_detect_endpoints(struct snd_usb_midi* umidi, - struct snd_usb_midi_endpoint_info* endpoint, - int max_endpoints) -{ - struct usb_interface* intf; - struct usb_host_interface *hostif; - struct usb_interface_descriptor* intfd; - struct usb_endpoint_descriptor* epd; - int i, out_eps = 0, in_eps = 0; - - if (USB_ID_VENDOR(umidi->usb_id) == 0x0582) - snd_usbmidi_switch_roland_altsetting(umidi); - - if (endpoint[0].out_ep || endpoint[0].in_ep) - return 0; - - intf = umidi->iface; - if (!intf || intf->num_altsetting < 1) - return -ENOENT; - hostif = intf->cur_altsetting; - intfd = get_iface_desc(hostif); - - for (i = 0; i < intfd->bNumEndpoints; ++i) { - epd = get_endpoint(hostif, i); - if (!usb_endpoint_xfer_bulk(epd) && - !usb_endpoint_xfer_int(epd)) - continue; - if (out_eps < max_endpoints && - usb_endpoint_dir_out(epd)) { - endpoint[out_eps].out_ep = usb_endpoint_num(epd); - if (usb_endpoint_xfer_int(epd)) - endpoint[out_eps].out_interval = epd->bInterval; - ++out_eps; - } - if (in_eps < max_endpoints && - usb_endpoint_dir_in(epd)) { - endpoint[in_eps].in_ep = usb_endpoint_num(epd); - if (usb_endpoint_xfer_int(epd)) - endpoint[in_eps].in_interval = epd->bInterval; - ++in_eps; - } - } - return (out_eps || in_eps) ? 0 : -ENOENT; -} - -/* - * Detects the endpoints for one-port-per-endpoint protocols. - */ -static int snd_usbmidi_detect_per_port_endpoints(struct snd_usb_midi* umidi, - struct snd_usb_midi_endpoint_info* endpoints) -{ - int err, i; - - err = snd_usbmidi_detect_endpoints(umidi, endpoints, MIDI_MAX_ENDPOINTS); - for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) { - if (endpoints[i].out_ep) - endpoints[i].out_cables = 0x0001; - if (endpoints[i].in_ep) - endpoints[i].in_cables = 0x0001; - } - return err; -} - -/* - * Detects the endpoints and ports of Yamaha devices. - */ -static int snd_usbmidi_detect_yamaha(struct snd_usb_midi* umidi, - struct snd_usb_midi_endpoint_info* endpoint) -{ - struct usb_interface* intf; - struct usb_host_interface *hostif; - struct usb_interface_descriptor* intfd; - uint8_t* cs_desc; - - intf = umidi->iface; - if (!intf) - return -ENOENT; - hostif = intf->altsetting; - intfd = get_iface_desc(hostif); - if (intfd->bNumEndpoints < 1) - return -ENOENT; - - /* - * For each port there is one MIDI_IN/OUT_JACK descriptor, not - * necessarily with any useful contents. So simply count 'em. - */ - for (cs_desc = hostif->extra; - cs_desc < hostif->extra + hostif->extralen && cs_desc[0] >= 2; - cs_desc += cs_desc[0]) { - if (cs_desc[1] == USB_DT_CS_INTERFACE) { - if (cs_desc[2] == UAC_MIDI_IN_JACK) - endpoint->in_cables = (endpoint->in_cables << 1) | 1; - else if (cs_desc[2] == UAC_MIDI_OUT_JACK) - endpoint->out_cables = (endpoint->out_cables << 1) | 1; - } - } - if (!endpoint->in_cables && !endpoint->out_cables) - return -ENOENT; - - return snd_usbmidi_detect_endpoints(umidi, endpoint, 1); -} - -/* - * Creates the endpoints and their ports for Midiman devices. - */ -static int snd_usbmidi_create_endpoints_midiman(struct snd_usb_midi* umidi, - struct snd_usb_midi_endpoint_info* endpoint) -{ - struct snd_usb_midi_endpoint_info ep_info; - struct usb_interface* intf; - struct usb_host_interface *hostif; - struct usb_interface_descriptor* intfd; - struct usb_endpoint_descriptor* epd; - int cable, err; - - intf = umidi->iface; - if (!intf) - return -ENOENT; - hostif = intf->altsetting; - intfd = get_iface_desc(hostif); - /* - * The various MidiSport devices have more or less random endpoint - * numbers, so we have to identify the endpoints by their index in - * the descriptor array, like the driver for that other OS does. - * - * There is one interrupt input endpoint for all input ports, one - * bulk output endpoint for even-numbered ports, and one for odd- - * numbered ports. Both bulk output endpoints have corresponding - * input bulk endpoints (at indices 1 and 3) which aren't used. - */ - if (intfd->bNumEndpoints < (endpoint->out_cables > 0x0001 ? 5 : 3)) { - snd_printdd(KERN_ERR "not enough endpoints\n"); - return -ENOENT; - } - - epd = get_endpoint(hostif, 0); - if (!usb_endpoint_dir_in(epd) || !usb_endpoint_xfer_int(epd)) { - snd_printdd(KERN_ERR "endpoint[0] isn't interrupt\n"); - return -ENXIO; - } - epd = get_endpoint(hostif, 2); - if (!usb_endpoint_dir_out(epd) || !usb_endpoint_xfer_bulk(epd)) { - snd_printdd(KERN_ERR "endpoint[2] isn't bulk output\n"); - return -ENXIO; - } - if (endpoint->out_cables > 0x0001) { - epd = get_endpoint(hostif, 4); - if (!usb_endpoint_dir_out(epd) || - !usb_endpoint_xfer_bulk(epd)) { - snd_printdd(KERN_ERR "endpoint[4] isn't bulk output\n"); - return -ENXIO; - } - } - - ep_info.out_ep = get_endpoint(hostif, 2)->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; - ep_info.out_interval = 0; - ep_info.out_cables = endpoint->out_cables & 0x5555; - err = snd_usbmidi_out_endpoint_create(umidi, &ep_info, &umidi->endpoints[0]); - if (err < 0) - return err; - - ep_info.in_ep = get_endpoint(hostif, 0)->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; - ep_info.in_interval = get_endpoint(hostif, 0)->bInterval; - ep_info.in_cables = endpoint->in_cables; - err = snd_usbmidi_in_endpoint_create(umidi, &ep_info, &umidi->endpoints[0]); - if (err < 0) - return err; - - if (endpoint->out_cables > 0x0001) { - ep_info.out_ep = get_endpoint(hostif, 4)->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; - ep_info.out_cables = endpoint->out_cables & 0xaaaa; - err = snd_usbmidi_out_endpoint_create(umidi, &ep_info, &umidi->endpoints[1]); - if (err < 0) - return err; - } - - for (cable = 0; cable < 0x10; ++cable) { - if (endpoint->out_cables & (1 << cable)) - snd_usbmidi_init_substream(umidi, SNDRV_RAWMIDI_STREAM_OUTPUT, cable, - &umidi->endpoints[cable & 1].out->ports[cable].substream); - if (endpoint->in_cables & (1 << cable)) - snd_usbmidi_init_substream(umidi, SNDRV_RAWMIDI_STREAM_INPUT, cable, - &umidi->endpoints[0].in->ports[cable].substream); - } - return 0; -} - -static struct snd_rawmidi_global_ops snd_usbmidi_ops = { - .get_port_info = snd_usbmidi_get_port_info, -}; - -static int snd_usbmidi_create_rawmidi(struct snd_usb_midi* umidi, - int out_ports, int in_ports) -{ - struct snd_rawmidi *rmidi; - int err; - - err = snd_rawmidi_new(umidi->card, "USB MIDI", - umidi->next_midi_device++, - out_ports, in_ports, &rmidi); - if (err < 0) - return err; - strcpy(rmidi->name, umidi->card->shortname); - rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT | - SNDRV_RAWMIDI_INFO_INPUT | - SNDRV_RAWMIDI_INFO_DUPLEX; - rmidi->ops = &snd_usbmidi_ops; - rmidi->private_data = umidi; - rmidi->private_free = snd_usbmidi_rawmidi_free; - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_usbmidi_output_ops); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_usbmidi_input_ops); - - umidi->rmidi = rmidi; - return 0; -} - -/* - * Temporarily stop input. - */ -void snd_usbmidi_input_stop(struct list_head* p) -{ - struct snd_usb_midi* umidi; - unsigned int i, j; - - umidi = list_entry(p, struct snd_usb_midi, list); - for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) { - struct snd_usb_midi_endpoint* ep = &umidi->endpoints[i]; - if (ep->in) - for (j = 0; j < INPUT_URBS; ++j) - usb_kill_urb(ep->in->urbs[j]); - } -} - -static void snd_usbmidi_input_start_ep(struct snd_usb_midi_in_endpoint* ep) -{ - unsigned int i; - - if (!ep) - return; - for (i = 0; i < INPUT_URBS; ++i) { - struct urb* urb = ep->urbs[i]; - urb->dev = ep->umidi->dev; - snd_usbmidi_submit_urb(urb, GFP_KERNEL); - } -} - -/* - * Resume input after a call to snd_usbmidi_input_stop(). - */ -void snd_usbmidi_input_start(struct list_head* p) -{ - struct snd_usb_midi* umidi; - int i; - - umidi = list_entry(p, struct snd_usb_midi, list); - for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) - snd_usbmidi_input_start_ep(umidi->endpoints[i].in); -} - -/* - * Creates and registers everything needed for a MIDI streaming interface. - */ -int snd_usbmidi_create(struct snd_card *card, - struct usb_interface* iface, - struct list_head *midi_list, - const struct snd_usb_audio_quirk* quirk) -{ - struct snd_usb_midi* umidi; - struct snd_usb_midi_endpoint_info endpoints[MIDI_MAX_ENDPOINTS]; - int out_ports, in_ports; - int i, err; - - umidi = kzalloc(sizeof(*umidi), GFP_KERNEL); - if (!umidi) - return -ENOMEM; - umidi->dev = interface_to_usbdev(iface); - umidi->card = card; - umidi->iface = iface; - umidi->quirk = quirk; - umidi->usb_protocol_ops = &snd_usbmidi_standard_ops; - init_timer(&umidi->error_timer); - spin_lock_init(&umidi->disc_lock); - mutex_init(&umidi->mutex); - umidi->usb_id = USB_ID(le16_to_cpu(umidi->dev->descriptor.idVendor), - le16_to_cpu(umidi->dev->descriptor.idProduct)); - umidi->error_timer.function = snd_usbmidi_error_timer; - umidi->error_timer.data = (unsigned long)umidi; - - /* detect the endpoint(s) to use */ - memset(endpoints, 0, sizeof(endpoints)); - switch (quirk ? quirk->type : QUIRK_MIDI_STANDARD_INTERFACE) { - case QUIRK_MIDI_STANDARD_INTERFACE: - err = snd_usbmidi_get_ms_info(umidi, endpoints); - if (umidi->usb_id == USB_ID(0x0763, 0x0150)) /* M-Audio Uno */ - umidi->usb_protocol_ops = - &snd_usbmidi_maudio_broken_running_status_ops; - break; - case QUIRK_MIDI_US122L: - umidi->usb_protocol_ops = &snd_usbmidi_122l_ops; - /* fall through */ - case QUIRK_MIDI_FIXED_ENDPOINT: - memcpy(&endpoints[0], quirk->data, - sizeof(struct snd_usb_midi_endpoint_info)); - err = snd_usbmidi_detect_endpoints(umidi, &endpoints[0], 1); - break; - case QUIRK_MIDI_YAMAHA: - err = snd_usbmidi_detect_yamaha(umidi, &endpoints[0]); - break; - case QUIRK_MIDI_MIDIMAN: - umidi->usb_protocol_ops = &snd_usbmidi_midiman_ops; - memcpy(&endpoints[0], quirk->data, - sizeof(struct snd_usb_midi_endpoint_info)); - err = 0; - break; - case QUIRK_MIDI_NOVATION: - umidi->usb_protocol_ops = &snd_usbmidi_novation_ops; - err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); - break; - case QUIRK_MIDI_RAW_BYTES: - umidi->usb_protocol_ops = &snd_usbmidi_raw_ops; - /* - * Interface 1 contains isochronous endpoints, but with the same - * numbers as in interface 0. Since it is interface 1 that the - * USB core has most recently seen, these descriptors are now - * associated with the endpoint numbers. This will foul up our - * attempts to submit bulk/interrupt URBs to the endpoints in - * interface 0, so we have to make sure that the USB core looks - * again at interface 0 by calling usb_set_interface() on it. - */ - if (umidi->usb_id == USB_ID(0x07fd, 0x0001)) /* MOTU Fastlane */ - usb_set_interface(umidi->dev, 0, 0); - err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); - break; - case QUIRK_MIDI_EMAGIC: - umidi->usb_protocol_ops = &snd_usbmidi_emagic_ops; - memcpy(&endpoints[0], quirk->data, - sizeof(struct snd_usb_midi_endpoint_info)); - err = snd_usbmidi_detect_endpoints(umidi, &endpoints[0], 1); - break; - case QUIRK_MIDI_CME: - umidi->usb_protocol_ops = &snd_usbmidi_cme_ops; - err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); - break; - case QUIRK_MIDI_AKAI: - umidi->usb_protocol_ops = &snd_usbmidi_akai_ops; - err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); - /* endpoint 1 is input-only */ - endpoints[1].out_cables = 0; - break; - case QUIRK_MIDI_FTDI: - umidi->usb_protocol_ops = &snd_usbmidi_ftdi_ops; - - /* set baud rate to 31250 (48 MHz / 16 / 96) */ - err = usb_control_msg(umidi->dev, usb_sndctrlpipe(umidi->dev, 0), - 3, 0x40, 0x60, 0, NULL, 0, 1000); - if (err < 0) - break; - - err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); - break; - default: - snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type); - err = -ENXIO; - break; - } - if (err < 0) { - kfree(umidi); - return err; - } - - /* create rawmidi device */ - out_ports = 0; - in_ports = 0; - for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) { - out_ports += hweight16(endpoints[i].out_cables); - in_ports += hweight16(endpoints[i].in_cables); - } - err = snd_usbmidi_create_rawmidi(umidi, out_ports, in_ports); - if (err < 0) { - kfree(umidi); - return err; - } - - /* create endpoint/port structures */ - if (quirk && quirk->type == QUIRK_MIDI_MIDIMAN) - err = snd_usbmidi_create_endpoints_midiman(umidi, &endpoints[0]); - else - err = snd_usbmidi_create_endpoints(umidi, endpoints); - if (err < 0) { - snd_usbmidi_free(umidi); - return err; - } - - list_add_tail(&umidi->list, midi_list); - - for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) - snd_usbmidi_input_start_ep(umidi->endpoints[i].in); - return 0; -} - -EXPORT_SYMBOL(snd_usbmidi_create); -EXPORT_SYMBOL(snd_usbmidi_input_stop); -EXPORT_SYMBOL(snd_usbmidi_input_start); -EXPORT_SYMBOL(snd_usbmidi_disconnect); diff --git a/ANDROID_3.4.5/sound/usb/midi.h b/ANDROID_3.4.5/sound/usb/midi.h deleted file mode 100644 index 2fca80b7..00000000 --- a/ANDROID_3.4.5/sound/usb/midi.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef __USBMIDI_H -#define __USBMIDI_H - -/* maximum number of endpoints per interface */ -#define MIDI_MAX_ENDPOINTS 2 - -/* data for QUIRK_MIDI_FIXED_ENDPOINT */ -struct snd_usb_midi_endpoint_info { - int8_t out_ep; /* ep number, 0 autodetect */ - uint8_t out_interval; /* interval for interrupt endpoints */ - int8_t in_ep; - uint8_t in_interval; - uint16_t out_cables; /* bitmask */ - uint16_t in_cables; /* bitmask */ -}; - -/* for QUIRK_MIDI_YAMAHA, data is NULL */ - -/* for QUIRK_MIDI_MIDIMAN, data points to a snd_usb_midi_endpoint_info - * structure (out_cables and in_cables only) */ - -/* for QUIRK_COMPOSITE, data points to an array of snd_usb_audio_quirk - * structures, terminated with .ifnum = -1 */ - -/* for QUIRK_AUDIO_FIXED_ENDPOINT, data points to an audioformat structure */ - -/* for QUIRK_AUDIO/MIDI_STANDARD_INTERFACE, data is NULL */ - -/* for QUIRK_AUDIO_EDIROL_UA700_UA25/UA1000, data is NULL */ - -/* for QUIRK_IGNORE_INTERFACE, data is NULL */ - -/* for QUIRK_MIDI_NOVATION and _RAW, data is NULL */ - -/* for QUIRK_MIDI_EMAGIC, data points to a snd_usb_midi_endpoint_info - * structure (out_cables and in_cables only) */ - -/* for QUIRK_MIDI_CME, data is NULL */ - -/* for QUIRK_MIDI_AKAI, data is NULL */ - -int snd_usbmidi_create(struct snd_card *card, - struct usb_interface *iface, - struct list_head *midi_list, - const struct snd_usb_audio_quirk *quirk); -void snd_usbmidi_input_stop(struct list_head* p); -void snd_usbmidi_input_start(struct list_head* p); -void snd_usbmidi_disconnect(struct list_head *p); - -#endif /* __USBMIDI_H */ diff --git a/ANDROID_3.4.5/sound/usb/misc/Makefile b/ANDROID_3.4.5/sound/usb/misc/Makefile deleted file mode 100644 index ccefd815..00000000 --- a/ANDROID_3.4.5/sound/usb/misc/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -snd-ua101-objs := ua101.o -obj-$(CONFIG_SND_USB_UA101) += snd-ua101.o diff --git a/ANDROID_3.4.5/sound/usb/misc/ua101.c b/ANDROID_3.4.5/sound/usb/misc/ua101.c deleted file mode 100644 index 8b81cb54..00000000 --- a/ANDROID_3.4.5/sound/usb/misc/ua101.c +++ /dev/null @@ -1,1390 +0,0 @@ -/* - * Edirol UA-101/UA-1000 driver - * Copyright (c) Clemens Ladisch - * - * This driver is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License, version 2. - * - * This driver is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this driver. If not, see . - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../usbaudio.h" -#include "../midi.h" - -MODULE_DESCRIPTION("Edirol UA-101/1000 driver"); -MODULE_AUTHOR("Clemens Ladisch "); -MODULE_LICENSE("GPL v2"); -MODULE_SUPPORTED_DEVICE("{{Edirol,UA-101},{Edirol,UA-1000}}"); - -/* - * Should not be lower than the minimum scheduling delay of the host - * controller. Some Intel controllers need more than one frame; as long as - * that driver doesn't tell us about this, use 1.5 frames just to be sure. - */ -#define MIN_QUEUE_LENGTH 12 -/* Somewhat random. */ -#define MAX_QUEUE_LENGTH 30 -/* - * This magic value optimizes memory usage efficiency for the UA-101's packet - * sizes at all sample rates, taking into account the stupid cache pool sizes - * that usb_alloc_coherent() uses. - */ -#define DEFAULT_QUEUE_LENGTH 21 - -#define MAX_PACKET_SIZE 672 /* hardware specific */ -#define MAX_MEMORY_BUFFERS DIV_ROUND_UP(MAX_QUEUE_LENGTH, \ - PAGE_SIZE / MAX_PACKET_SIZE) - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; -static unsigned int queue_length = 21; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "card index"); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string"); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "enable card"); -module_param(queue_length, uint, 0644); -MODULE_PARM_DESC(queue_length, "USB queue length in microframes, " - __stringify(MIN_QUEUE_LENGTH)"-"__stringify(MAX_QUEUE_LENGTH)); - -enum { - INTF_PLAYBACK, - INTF_CAPTURE, - INTF_MIDI, - - INTF_COUNT -}; - -/* bits in struct ua101::states */ -enum { - USB_CAPTURE_RUNNING, - USB_PLAYBACK_RUNNING, - ALSA_CAPTURE_OPEN, - ALSA_PLAYBACK_OPEN, - ALSA_CAPTURE_RUNNING, - ALSA_PLAYBACK_RUNNING, - CAPTURE_URB_COMPLETED, - PLAYBACK_URB_COMPLETED, - DISCONNECTED, -}; - -struct ua101 { - struct usb_device *dev; - struct snd_card *card; - struct usb_interface *intf[INTF_COUNT]; - int card_index; - struct snd_pcm *pcm; - struct list_head midi_list; - u64 format_bit; - unsigned int rate; - unsigned int packets_per_second; - spinlock_t lock; - struct mutex mutex; - unsigned long states; - - /* FIFO to synchronize playback rate to capture rate */ - unsigned int rate_feedback_start; - unsigned int rate_feedback_count; - u8 rate_feedback[MAX_QUEUE_LENGTH]; - - struct list_head ready_playback_urbs; - struct tasklet_struct playback_tasklet; - wait_queue_head_t alsa_capture_wait; - wait_queue_head_t rate_feedback_wait; - wait_queue_head_t alsa_playback_wait; - struct ua101_stream { - struct snd_pcm_substream *substream; - unsigned int usb_pipe; - unsigned int channels; - unsigned int frame_bytes; - unsigned int max_packet_bytes; - unsigned int period_pos; - unsigned int buffer_pos; - unsigned int queue_length; - struct ua101_urb { - struct urb urb; - struct usb_iso_packet_descriptor iso_frame_desc[1]; - struct list_head ready_list; - } *urbs[MAX_QUEUE_LENGTH]; - struct { - unsigned int size; - void *addr; - dma_addr_t dma; - } buffers[MAX_MEMORY_BUFFERS]; - } capture, playback; -}; - -static DEFINE_MUTEX(devices_mutex); -static unsigned int devices_used; -static struct usb_driver ua101_driver; - -static void abort_alsa_playback(struct ua101 *ua); -static void abort_alsa_capture(struct ua101 *ua); - -static const char *usb_error_string(int err) -{ - switch (err) { - case -ENODEV: - return "no device"; - case -ENOENT: - return "endpoint not enabled"; - case -EPIPE: - return "endpoint stalled"; - case -ENOSPC: - return "not enough bandwidth"; - case -ESHUTDOWN: - return "device disabled"; - case -EHOSTUNREACH: - return "device suspended"; - case -EINVAL: - case -EAGAIN: - case -EFBIG: - case -EMSGSIZE: - return "internal error"; - default: - return "unknown error"; - } -} - -static void abort_usb_capture(struct ua101 *ua) -{ - if (test_and_clear_bit(USB_CAPTURE_RUNNING, &ua->states)) { - wake_up(&ua->alsa_capture_wait); - wake_up(&ua->rate_feedback_wait); - } -} - -static void abort_usb_playback(struct ua101 *ua) -{ - if (test_and_clear_bit(USB_PLAYBACK_RUNNING, &ua->states)) - wake_up(&ua->alsa_playback_wait); -} - -static void playback_urb_complete(struct urb *usb_urb) -{ - struct ua101_urb *urb = (struct ua101_urb *)usb_urb; - struct ua101 *ua = urb->urb.context; - unsigned long flags; - - if (unlikely(urb->urb.status == -ENOENT || /* unlinked */ - urb->urb.status == -ENODEV || /* device removed */ - urb->urb.status == -ECONNRESET || /* unlinked */ - urb->urb.status == -ESHUTDOWN)) { /* device disabled */ - abort_usb_playback(ua); - abort_alsa_playback(ua); - return; - } - - if (test_bit(USB_PLAYBACK_RUNNING, &ua->states)) { - /* append URB to FIFO */ - spin_lock_irqsave(&ua->lock, flags); - list_add_tail(&urb->ready_list, &ua->ready_playback_urbs); - if (ua->rate_feedback_count > 0) - tasklet_schedule(&ua->playback_tasklet); - ua->playback.substream->runtime->delay -= - urb->urb.iso_frame_desc[0].length / - ua->playback.frame_bytes; - spin_unlock_irqrestore(&ua->lock, flags); - } -} - -static void first_playback_urb_complete(struct urb *urb) -{ - struct ua101 *ua = urb->context; - - urb->complete = playback_urb_complete; - playback_urb_complete(urb); - - set_bit(PLAYBACK_URB_COMPLETED, &ua->states); - wake_up(&ua->alsa_playback_wait); -} - -/* copy data from the ALSA ring buffer into the URB buffer */ -static bool copy_playback_data(struct ua101_stream *stream, struct urb *urb, - unsigned int frames) -{ - struct snd_pcm_runtime *runtime; - unsigned int frame_bytes, frames1; - const u8 *source; - - runtime = stream->substream->runtime; - frame_bytes = stream->frame_bytes; - source = runtime->dma_area + stream->buffer_pos * frame_bytes; - if (stream->buffer_pos + frames <= runtime->buffer_size) { - memcpy(urb->transfer_buffer, source, frames * frame_bytes); - } else { - /* wrap around at end of ring buffer */ - frames1 = runtime->buffer_size - stream->buffer_pos; - memcpy(urb->transfer_buffer, source, frames1 * frame_bytes); - memcpy(urb->transfer_buffer + frames1 * frame_bytes, - runtime->dma_area, (frames - frames1) * frame_bytes); - } - - stream->buffer_pos += frames; - if (stream->buffer_pos >= runtime->buffer_size) - stream->buffer_pos -= runtime->buffer_size; - stream->period_pos += frames; - if (stream->period_pos >= runtime->period_size) { - stream->period_pos -= runtime->period_size; - return true; - } - return false; -} - -static inline void add_with_wraparound(struct ua101 *ua, - unsigned int *value, unsigned int add) -{ - *value += add; - if (*value >= ua->playback.queue_length) - *value -= ua->playback.queue_length; -} - -static void playback_tasklet(unsigned long data) -{ - struct ua101 *ua = (void *)data; - unsigned long flags; - unsigned int frames; - struct ua101_urb *urb; - bool do_period_elapsed = false; - int err; - - if (unlikely(!test_bit(USB_PLAYBACK_RUNNING, &ua->states))) - return; - - /* - * Synchronizing the playback rate to the capture rate is done by using - * the same sequence of packet sizes for both streams. - * Submitting a playback URB therefore requires both a ready URB and - * the size of the corresponding capture packet, i.e., both playback - * and capture URBs must have been completed. Since the USB core does - * not guarantee that playback and capture complete callbacks are - * called alternately, we use two FIFOs for packet sizes and read URBs; - * submitting playback URBs is possible as long as both FIFOs are - * nonempty. - */ - spin_lock_irqsave(&ua->lock, flags); - while (ua->rate_feedback_count > 0 && - !list_empty(&ua->ready_playback_urbs)) { - /* take packet size out of FIFO */ - frames = ua->rate_feedback[ua->rate_feedback_start]; - add_with_wraparound(ua, &ua->rate_feedback_start, 1); - ua->rate_feedback_count--; - - /* take URB out of FIFO */ - urb = list_first_entry(&ua->ready_playback_urbs, - struct ua101_urb, ready_list); - list_del(&urb->ready_list); - - /* fill packet with data or silence */ - urb->urb.iso_frame_desc[0].length = - frames * ua->playback.frame_bytes; - if (test_bit(ALSA_PLAYBACK_RUNNING, &ua->states)) - do_period_elapsed |= copy_playback_data(&ua->playback, - &urb->urb, - frames); - else - memset(urb->urb.transfer_buffer, 0, - urb->urb.iso_frame_desc[0].length); - - /* and off you go ... */ - err = usb_submit_urb(&urb->urb, GFP_ATOMIC); - if (unlikely(err < 0)) { - spin_unlock_irqrestore(&ua->lock, flags); - abort_usb_playback(ua); - abort_alsa_playback(ua); - dev_err(&ua->dev->dev, "USB request error %d: %s\n", - err, usb_error_string(err)); - return; - } - ua->playback.substream->runtime->delay += frames; - } - spin_unlock_irqrestore(&ua->lock, flags); - if (do_period_elapsed) - snd_pcm_period_elapsed(ua->playback.substream); -} - -/* copy data from the URB buffer into the ALSA ring buffer */ -static bool copy_capture_data(struct ua101_stream *stream, struct urb *urb, - unsigned int frames) -{ - struct snd_pcm_runtime *runtime; - unsigned int frame_bytes, frames1; - u8 *dest; - - runtime = stream->substream->runtime; - frame_bytes = stream->frame_bytes; - dest = runtime->dma_area + stream->buffer_pos * frame_bytes; - if (stream->buffer_pos + frames <= runtime->buffer_size) { - memcpy(dest, urb->transfer_buffer, frames * frame_bytes); - } else { - /* wrap around at end of ring buffer */ - frames1 = runtime->buffer_size - stream->buffer_pos; - memcpy(dest, urb->transfer_buffer, frames1 * frame_bytes); - memcpy(runtime->dma_area, - urb->transfer_buffer + frames1 * frame_bytes, - (frames - frames1) * frame_bytes); - } - - stream->buffer_pos += frames; - if (stream->buffer_pos >= runtime->buffer_size) - stream->buffer_pos -= runtime->buffer_size; - stream->period_pos += frames; - if (stream->period_pos >= runtime->period_size) { - stream->period_pos -= runtime->period_size; - return true; - } - return false; -} - -static void capture_urb_complete(struct urb *urb) -{ - struct ua101 *ua = urb->context; - struct ua101_stream *stream = &ua->capture; - unsigned long flags; - unsigned int frames, write_ptr; - bool do_period_elapsed; - int err; - - if (unlikely(urb->status == -ENOENT || /* unlinked */ - urb->status == -ENODEV || /* device removed */ - urb->status == -ECONNRESET || /* unlinked */ - urb->status == -ESHUTDOWN)) /* device disabled */ - goto stream_stopped; - - if (urb->status >= 0 && urb->iso_frame_desc[0].status >= 0) - frames = urb->iso_frame_desc[0].actual_length / - stream->frame_bytes; - else - frames = 0; - - spin_lock_irqsave(&ua->lock, flags); - - if (frames > 0 && test_bit(ALSA_CAPTURE_RUNNING, &ua->states)) - do_period_elapsed = copy_capture_data(stream, urb, frames); - else - do_period_elapsed = false; - - if (test_bit(USB_CAPTURE_RUNNING, &ua->states)) { - err = usb_submit_urb(urb, GFP_ATOMIC); - if (unlikely(err < 0)) { - spin_unlock_irqrestore(&ua->lock, flags); - dev_err(&ua->dev->dev, "USB request error %d: %s\n", - err, usb_error_string(err)); - goto stream_stopped; - } - - /* append packet size to FIFO */ - write_ptr = ua->rate_feedback_start; - add_with_wraparound(ua, &write_ptr, ua->rate_feedback_count); - ua->rate_feedback[write_ptr] = frames; - if (ua->rate_feedback_count < ua->playback.queue_length) { - ua->rate_feedback_count++; - if (ua->rate_feedback_count == - ua->playback.queue_length) - wake_up(&ua->rate_feedback_wait); - } else { - /* - * Ring buffer overflow; this happens when the playback - * stream is not running. Throw away the oldest entry, - * so that the playback stream, when it starts, sees - * the most recent packet sizes. - */ - add_with_wraparound(ua, &ua->rate_feedback_start, 1); - } - if (test_bit(USB_PLAYBACK_RUNNING, &ua->states) && - !list_empty(&ua->ready_playback_urbs)) - tasklet_schedule(&ua->playback_tasklet); - } - - spin_unlock_irqrestore(&ua->lock, flags); - - if (do_period_elapsed) - snd_pcm_period_elapsed(stream->substream); - - return; - -stream_stopped: - abort_usb_playback(ua); - abort_usb_capture(ua); - abort_alsa_playback(ua); - abort_alsa_capture(ua); -} - -static void first_capture_urb_complete(struct urb *urb) -{ - struct ua101 *ua = urb->context; - - urb->complete = capture_urb_complete; - capture_urb_complete(urb); - - set_bit(CAPTURE_URB_COMPLETED, &ua->states); - wake_up(&ua->alsa_capture_wait); -} - -static int submit_stream_urbs(struct ua101 *ua, struct ua101_stream *stream) -{ - unsigned int i; - - for (i = 0; i < stream->queue_length; ++i) { - int err = usb_submit_urb(&stream->urbs[i]->urb, GFP_KERNEL); - if (err < 0) { - dev_err(&ua->dev->dev, "USB request error %d: %s\n", - err, usb_error_string(err)); - return err; - } - } - return 0; -} - -static void kill_stream_urbs(struct ua101_stream *stream) -{ - unsigned int i; - - for (i = 0; i < stream->queue_length; ++i) - if (stream->urbs[i]) - usb_kill_urb(&stream->urbs[i]->urb); -} - -static int enable_iso_interface(struct ua101 *ua, unsigned int intf_index) -{ - struct usb_host_interface *alts; - - alts = ua->intf[intf_index]->cur_altsetting; - if (alts->desc.bAlternateSetting != 1) { - int err = usb_set_interface(ua->dev, - alts->desc.bInterfaceNumber, 1); - if (err < 0) { - dev_err(&ua->dev->dev, - "cannot initialize interface; error %d: %s\n", - err, usb_error_string(err)); - return err; - } - } - return 0; -} - -static void disable_iso_interface(struct ua101 *ua, unsigned int intf_index) -{ - struct usb_host_interface *alts; - - if (!ua->intf[intf_index]) - return; - - alts = ua->intf[intf_index]->cur_altsetting; - if (alts->desc.bAlternateSetting != 0) { - int err = usb_set_interface(ua->dev, - alts->desc.bInterfaceNumber, 0); - if (err < 0 && !test_bit(DISCONNECTED, &ua->states)) - dev_warn(&ua->dev->dev, - "interface reset failed; error %d: %s\n", - err, usb_error_string(err)); - } -} - -static void stop_usb_capture(struct ua101 *ua) -{ - clear_bit(USB_CAPTURE_RUNNING, &ua->states); - - kill_stream_urbs(&ua->capture); - - disable_iso_interface(ua, INTF_CAPTURE); -} - -static int start_usb_capture(struct ua101 *ua) -{ - int err; - - if (test_bit(DISCONNECTED, &ua->states)) - return -ENODEV; - - if (test_bit(USB_CAPTURE_RUNNING, &ua->states)) - return 0; - - kill_stream_urbs(&ua->capture); - - err = enable_iso_interface(ua, INTF_CAPTURE); - if (err < 0) - return err; - - clear_bit(CAPTURE_URB_COMPLETED, &ua->states); - ua->capture.urbs[0]->urb.complete = first_capture_urb_complete; - ua->rate_feedback_start = 0; - ua->rate_feedback_count = 0; - - set_bit(USB_CAPTURE_RUNNING, &ua->states); - err = submit_stream_urbs(ua, &ua->capture); - if (err < 0) - stop_usb_capture(ua); - return err; -} - -static void stop_usb_playback(struct ua101 *ua) -{ - clear_bit(USB_PLAYBACK_RUNNING, &ua->states); - - kill_stream_urbs(&ua->playback); - - tasklet_kill(&ua->playback_tasklet); - - disable_iso_interface(ua, INTF_PLAYBACK); -} - -static int start_usb_playback(struct ua101 *ua) -{ - unsigned int i, frames; - struct urb *urb; - int err = 0; - - if (test_bit(DISCONNECTED, &ua->states)) - return -ENODEV; - - if (test_bit(USB_PLAYBACK_RUNNING, &ua->states)) - return 0; - - kill_stream_urbs(&ua->playback); - tasklet_kill(&ua->playback_tasklet); - - err = enable_iso_interface(ua, INTF_PLAYBACK); - if (err < 0) - return err; - - clear_bit(PLAYBACK_URB_COMPLETED, &ua->states); - ua->playback.urbs[0]->urb.complete = - first_playback_urb_complete; - spin_lock_irq(&ua->lock); - INIT_LIST_HEAD(&ua->ready_playback_urbs); - spin_unlock_irq(&ua->lock); - - /* - * We submit the initial URBs all at once, so we have to wait for the - * packet size FIFO to be full. - */ - wait_event(ua->rate_feedback_wait, - ua->rate_feedback_count >= ua->playback.queue_length || - !test_bit(USB_CAPTURE_RUNNING, &ua->states) || - test_bit(DISCONNECTED, &ua->states)); - if (test_bit(DISCONNECTED, &ua->states)) { - stop_usb_playback(ua); - return -ENODEV; - } - if (!test_bit(USB_CAPTURE_RUNNING, &ua->states)) { - stop_usb_playback(ua); - return -EIO; - } - - for (i = 0; i < ua->playback.queue_length; ++i) { - /* all initial URBs contain silence */ - spin_lock_irq(&ua->lock); - frames = ua->rate_feedback[ua->rate_feedback_start]; - add_with_wraparound(ua, &ua->rate_feedback_start, 1); - ua->rate_feedback_count--; - spin_unlock_irq(&ua->lock); - urb = &ua->playback.urbs[i]->urb; - urb->iso_frame_desc[0].length = - frames * ua->playback.frame_bytes; - memset(urb->transfer_buffer, 0, - urb->iso_frame_desc[0].length); - } - - set_bit(USB_PLAYBACK_RUNNING, &ua->states); - err = submit_stream_urbs(ua, &ua->playback); - if (err < 0) - stop_usb_playback(ua); - return err; -} - -static void abort_alsa_capture(struct ua101 *ua) -{ - if (test_bit(ALSA_CAPTURE_RUNNING, &ua->states)) - snd_pcm_stop(ua->capture.substream, SNDRV_PCM_STATE_XRUN); -} - -static void abort_alsa_playback(struct ua101 *ua) -{ - if (test_bit(ALSA_PLAYBACK_RUNNING, &ua->states)) - snd_pcm_stop(ua->playback.substream, SNDRV_PCM_STATE_XRUN); -} - -static int set_stream_hw(struct ua101 *ua, struct snd_pcm_substream *substream, - unsigned int channels) -{ - int err; - - substream->runtime->hw.info = - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_BATCH | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_FIFO_IN_FRAMES; - substream->runtime->hw.formats = ua->format_bit; - substream->runtime->hw.rates = snd_pcm_rate_to_rate_bit(ua->rate); - substream->runtime->hw.rate_min = ua->rate; - substream->runtime->hw.rate_max = ua->rate; - substream->runtime->hw.channels_min = channels; - substream->runtime->hw.channels_max = channels; - substream->runtime->hw.buffer_bytes_max = 45000 * 1024; - substream->runtime->hw.period_bytes_min = 1; - substream->runtime->hw.period_bytes_max = UINT_MAX; - substream->runtime->hw.periods_min = 2; - substream->runtime->hw.periods_max = UINT_MAX; - err = snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_PERIOD_TIME, - 1500000 / ua->packets_per_second, - UINT_MAX); - if (err < 0) - return err; - err = snd_pcm_hw_constraint_msbits(substream->runtime, 0, 32, 24); - return err; -} - -static int capture_pcm_open(struct snd_pcm_substream *substream) -{ - struct ua101 *ua = substream->private_data; - int err; - - ua->capture.substream = substream; - err = set_stream_hw(ua, substream, ua->capture.channels); - if (err < 0) - return err; - substream->runtime->hw.fifo_size = - DIV_ROUND_CLOSEST(ua->rate, ua->packets_per_second); - substream->runtime->delay = substream->runtime->hw.fifo_size; - - mutex_lock(&ua->mutex); - err = start_usb_capture(ua); - if (err >= 0) - set_bit(ALSA_CAPTURE_OPEN, &ua->states); - mutex_unlock(&ua->mutex); - return err; -} - -static int playback_pcm_open(struct snd_pcm_substream *substream) -{ - struct ua101 *ua = substream->private_data; - int err; - - ua->playback.substream = substream; - err = set_stream_hw(ua, substream, ua->playback.channels); - if (err < 0) - return err; - substream->runtime->hw.fifo_size = - DIV_ROUND_CLOSEST(ua->rate * ua->playback.queue_length, - ua->packets_per_second); - - mutex_lock(&ua->mutex); - err = start_usb_capture(ua); - if (err < 0) - goto error; - err = start_usb_playback(ua); - if (err < 0) { - if (!test_bit(ALSA_CAPTURE_OPEN, &ua->states)) - stop_usb_capture(ua); - goto error; - } - set_bit(ALSA_PLAYBACK_OPEN, &ua->states); -error: - mutex_unlock(&ua->mutex); - return err; -} - -static int capture_pcm_close(struct snd_pcm_substream *substream) -{ - struct ua101 *ua = substream->private_data; - - mutex_lock(&ua->mutex); - clear_bit(ALSA_CAPTURE_OPEN, &ua->states); - if (!test_bit(ALSA_PLAYBACK_OPEN, &ua->states)) - stop_usb_capture(ua); - mutex_unlock(&ua->mutex); - return 0; -} - -static int playback_pcm_close(struct snd_pcm_substream *substream) -{ - struct ua101 *ua = substream->private_data; - - mutex_lock(&ua->mutex); - stop_usb_playback(ua); - clear_bit(ALSA_PLAYBACK_OPEN, &ua->states); - if (!test_bit(ALSA_CAPTURE_OPEN, &ua->states)) - stop_usb_capture(ua); - mutex_unlock(&ua->mutex); - return 0; -} - -static int capture_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct ua101 *ua = substream->private_data; - int err; - - mutex_lock(&ua->mutex); - err = start_usb_capture(ua); - mutex_unlock(&ua->mutex); - if (err < 0) - return err; - - return snd_pcm_lib_alloc_vmalloc_buffer(substream, - params_buffer_bytes(hw_params)); -} - -static int playback_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct ua101 *ua = substream->private_data; - int err; - - mutex_lock(&ua->mutex); - err = start_usb_capture(ua); - if (err >= 0) - err = start_usb_playback(ua); - mutex_unlock(&ua->mutex); - if (err < 0) - return err; - - return snd_pcm_lib_alloc_vmalloc_buffer(substream, - params_buffer_bytes(hw_params)); -} - -static int ua101_pcm_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_vmalloc_buffer(substream); -} - -static int capture_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct ua101 *ua = substream->private_data; - int err; - - mutex_lock(&ua->mutex); - err = start_usb_capture(ua); - mutex_unlock(&ua->mutex); - if (err < 0) - return err; - - /* - * The EHCI driver schedules the first packet of an iso stream at 10 ms - * in the future, i.e., no data is actually captured for that long. - * Take the wait here so that the stream is known to be actually - * running when the start trigger has been called. - */ - wait_event(ua->alsa_capture_wait, - test_bit(CAPTURE_URB_COMPLETED, &ua->states) || - !test_bit(USB_CAPTURE_RUNNING, &ua->states)); - if (test_bit(DISCONNECTED, &ua->states)) - return -ENODEV; - if (!test_bit(USB_CAPTURE_RUNNING, &ua->states)) - return -EIO; - - ua->capture.period_pos = 0; - ua->capture.buffer_pos = 0; - return 0; -} - -static int playback_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct ua101 *ua = substream->private_data; - int err; - - mutex_lock(&ua->mutex); - err = start_usb_capture(ua); - if (err >= 0) - err = start_usb_playback(ua); - mutex_unlock(&ua->mutex); - if (err < 0) - return err; - - /* see the comment in capture_pcm_prepare() */ - wait_event(ua->alsa_playback_wait, - test_bit(PLAYBACK_URB_COMPLETED, &ua->states) || - !test_bit(USB_PLAYBACK_RUNNING, &ua->states)); - if (test_bit(DISCONNECTED, &ua->states)) - return -ENODEV; - if (!test_bit(USB_PLAYBACK_RUNNING, &ua->states)) - return -EIO; - - substream->runtime->delay = 0; - ua->playback.period_pos = 0; - ua->playback.buffer_pos = 0; - return 0; -} - -static int capture_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct ua101 *ua = substream->private_data; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - if (!test_bit(USB_CAPTURE_RUNNING, &ua->states)) - return -EIO; - set_bit(ALSA_CAPTURE_RUNNING, &ua->states); - return 0; - case SNDRV_PCM_TRIGGER_STOP: - clear_bit(ALSA_CAPTURE_RUNNING, &ua->states); - return 0; - default: - return -EINVAL; - } -} - -static int playback_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct ua101 *ua = substream->private_data; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - if (!test_bit(USB_PLAYBACK_RUNNING, &ua->states)) - return -EIO; - set_bit(ALSA_PLAYBACK_RUNNING, &ua->states); - return 0; - case SNDRV_PCM_TRIGGER_STOP: - clear_bit(ALSA_PLAYBACK_RUNNING, &ua->states); - return 0; - default: - return -EINVAL; - } -} - -static inline snd_pcm_uframes_t ua101_pcm_pointer(struct ua101 *ua, - struct ua101_stream *stream) -{ - unsigned long flags; - unsigned int pos; - - spin_lock_irqsave(&ua->lock, flags); - pos = stream->buffer_pos; - spin_unlock_irqrestore(&ua->lock, flags); - return pos; -} - -static snd_pcm_uframes_t capture_pcm_pointer(struct snd_pcm_substream *subs) -{ - struct ua101 *ua = subs->private_data; - - return ua101_pcm_pointer(ua, &ua->capture); -} - -static snd_pcm_uframes_t playback_pcm_pointer(struct snd_pcm_substream *subs) -{ - struct ua101 *ua = subs->private_data; - - return ua101_pcm_pointer(ua, &ua->playback); -} - -static struct snd_pcm_ops capture_pcm_ops = { - .open = capture_pcm_open, - .close = capture_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = capture_pcm_hw_params, - .hw_free = ua101_pcm_hw_free, - .prepare = capture_pcm_prepare, - .trigger = capture_pcm_trigger, - .pointer = capture_pcm_pointer, - .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, -}; - -static struct snd_pcm_ops playback_pcm_ops = { - .open = playback_pcm_open, - .close = playback_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = playback_pcm_hw_params, - .hw_free = ua101_pcm_hw_free, - .prepare = playback_pcm_prepare, - .trigger = playback_pcm_trigger, - .pointer = playback_pcm_pointer, - .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, -}; - -static const struct uac_format_type_i_discrete_descriptor * -find_format_descriptor(struct usb_interface *interface) -{ - struct usb_host_interface *alt; - u8 *extra; - int extralen; - - if (interface->num_altsetting != 2) { - dev_err(&interface->dev, "invalid num_altsetting\n"); - return NULL; - } - - alt = &interface->altsetting[0]; - if (alt->desc.bNumEndpoints != 0) { - dev_err(&interface->dev, "invalid bNumEndpoints\n"); - return NULL; - } - - alt = &interface->altsetting[1]; - if (alt->desc.bNumEndpoints != 1) { - dev_err(&interface->dev, "invalid bNumEndpoints\n"); - return NULL; - } - - extra = alt->extra; - extralen = alt->extralen; - while (extralen >= sizeof(struct usb_descriptor_header)) { - struct uac_format_type_i_discrete_descriptor *desc; - - desc = (struct uac_format_type_i_discrete_descriptor *)extra; - if (desc->bLength > extralen) { - dev_err(&interface->dev, "descriptor overflow\n"); - return NULL; - } - if (desc->bLength == UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(1) && - desc->bDescriptorType == USB_DT_CS_INTERFACE && - desc->bDescriptorSubtype == UAC_FORMAT_TYPE) { - if (desc->bFormatType != UAC_FORMAT_TYPE_I_PCM || - desc->bSamFreqType != 1) { - dev_err(&interface->dev, - "invalid format type\n"); - return NULL; - } - return desc; - } - extralen -= desc->bLength; - extra += desc->bLength; - } - dev_err(&interface->dev, "sample format descriptor not found\n"); - return NULL; -} - -static int detect_usb_format(struct ua101 *ua) -{ - const struct uac_format_type_i_discrete_descriptor *fmt_capture; - const struct uac_format_type_i_discrete_descriptor *fmt_playback; - const struct usb_endpoint_descriptor *epd; - unsigned int rate2; - - fmt_capture = find_format_descriptor(ua->intf[INTF_CAPTURE]); - fmt_playback = find_format_descriptor(ua->intf[INTF_PLAYBACK]); - if (!fmt_capture || !fmt_playback) - return -ENXIO; - - switch (fmt_capture->bSubframeSize) { - case 3: - ua->format_bit = SNDRV_PCM_FMTBIT_S24_3LE; - break; - case 4: - ua->format_bit = SNDRV_PCM_FMTBIT_S32_LE; - break; - default: - dev_err(&ua->dev->dev, "sample width is not 24 or 32 bits\n"); - return -ENXIO; - } - if (fmt_capture->bSubframeSize != fmt_playback->bSubframeSize) { - dev_err(&ua->dev->dev, - "playback/capture sample widths do not match\n"); - return -ENXIO; - } - - if (fmt_capture->bBitResolution != 24 || - fmt_playback->bBitResolution != 24) { - dev_err(&ua->dev->dev, "sample width is not 24 bits\n"); - return -ENXIO; - } - - ua->rate = combine_triple(fmt_capture->tSamFreq[0]); - rate2 = combine_triple(fmt_playback->tSamFreq[0]); - if (ua->rate != rate2) { - dev_err(&ua->dev->dev, - "playback/capture rates do not match: %u/%u\n", - rate2, ua->rate); - return -ENXIO; - } - - switch (ua->dev->speed) { - case USB_SPEED_FULL: - ua->packets_per_second = 1000; - break; - case USB_SPEED_HIGH: - ua->packets_per_second = 8000; - break; - default: - dev_err(&ua->dev->dev, "unknown device speed\n"); - return -ENXIO; - } - - ua->capture.channels = fmt_capture->bNrChannels; - ua->playback.channels = fmt_playback->bNrChannels; - ua->capture.frame_bytes = - fmt_capture->bSubframeSize * ua->capture.channels; - ua->playback.frame_bytes = - fmt_playback->bSubframeSize * ua->playback.channels; - - epd = &ua->intf[INTF_CAPTURE]->altsetting[1].endpoint[0].desc; - if (!usb_endpoint_is_isoc_in(epd)) { - dev_err(&ua->dev->dev, "invalid capture endpoint\n"); - return -ENXIO; - } - ua->capture.usb_pipe = usb_rcvisocpipe(ua->dev, usb_endpoint_num(epd)); - ua->capture.max_packet_bytes = le16_to_cpu(epd->wMaxPacketSize); - - epd = &ua->intf[INTF_PLAYBACK]->altsetting[1].endpoint[0].desc; - if (!usb_endpoint_is_isoc_out(epd)) { - dev_err(&ua->dev->dev, "invalid playback endpoint\n"); - return -ENXIO; - } - ua->playback.usb_pipe = usb_sndisocpipe(ua->dev, usb_endpoint_num(epd)); - ua->playback.max_packet_bytes = le16_to_cpu(epd->wMaxPacketSize); - return 0; -} - -static int alloc_stream_buffers(struct ua101 *ua, struct ua101_stream *stream) -{ - unsigned int remaining_packets, packets, packets_per_page, i; - size_t size; - - stream->queue_length = queue_length; - stream->queue_length = max(stream->queue_length, - (unsigned int)MIN_QUEUE_LENGTH); - stream->queue_length = min(stream->queue_length, - (unsigned int)MAX_QUEUE_LENGTH); - - /* - * The cache pool sizes used by usb_alloc_coherent() (128, 512, 2048) are - * quite bad when used with the packet sizes of this device (e.g. 280, - * 520, 624). Therefore, we allocate and subdivide entire pages, using - * a smaller buffer only for the last chunk. - */ - remaining_packets = stream->queue_length; - packets_per_page = PAGE_SIZE / stream->max_packet_bytes; - for (i = 0; i < ARRAY_SIZE(stream->buffers); ++i) { - packets = min(remaining_packets, packets_per_page); - size = packets * stream->max_packet_bytes; - stream->buffers[i].addr = - usb_alloc_coherent(ua->dev, size, GFP_KERNEL, - &stream->buffers[i].dma); - if (!stream->buffers[i].addr) - return -ENOMEM; - stream->buffers[i].size = size; - remaining_packets -= packets; - if (!remaining_packets) - break; - } - if (remaining_packets) { - dev_err(&ua->dev->dev, "too many packets\n"); - return -ENXIO; - } - return 0; -} - -static void free_stream_buffers(struct ua101 *ua, struct ua101_stream *stream) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(stream->buffers); ++i) - usb_free_coherent(ua->dev, - stream->buffers[i].size, - stream->buffers[i].addr, - stream->buffers[i].dma); -} - -static int alloc_stream_urbs(struct ua101 *ua, struct ua101_stream *stream, - void (*urb_complete)(struct urb *)) -{ - unsigned max_packet_size = stream->max_packet_bytes; - struct ua101_urb *urb; - unsigned int b, u = 0; - - for (b = 0; b < ARRAY_SIZE(stream->buffers); ++b) { - unsigned int size = stream->buffers[b].size; - u8 *addr = stream->buffers[b].addr; - dma_addr_t dma = stream->buffers[b].dma; - - while (size >= max_packet_size) { - if (u >= stream->queue_length) - goto bufsize_error; - urb = kmalloc(sizeof(*urb), GFP_KERNEL); - if (!urb) - return -ENOMEM; - usb_init_urb(&urb->urb); - urb->urb.dev = ua->dev; - urb->urb.pipe = stream->usb_pipe; - urb->urb.transfer_flags = URB_ISO_ASAP | - URB_NO_TRANSFER_DMA_MAP; - urb->urb.transfer_buffer = addr; - urb->urb.transfer_dma = dma; - urb->urb.transfer_buffer_length = max_packet_size; - urb->urb.number_of_packets = 1; - urb->urb.interval = 1; - urb->urb.context = ua; - urb->urb.complete = urb_complete; - urb->urb.iso_frame_desc[0].offset = 0; - urb->urb.iso_frame_desc[0].length = max_packet_size; - stream->urbs[u++] = urb; - size -= max_packet_size; - addr += max_packet_size; - dma += max_packet_size; - } - } - if (u == stream->queue_length) - return 0; -bufsize_error: - dev_err(&ua->dev->dev, "internal buffer size error\n"); - return -ENXIO; -} - -static void free_stream_urbs(struct ua101_stream *stream) -{ - unsigned int i; - - for (i = 0; i < stream->queue_length; ++i) { - kfree(stream->urbs[i]); - stream->urbs[i] = NULL; - } -} - -static void free_usb_related_resources(struct ua101 *ua, - struct usb_interface *interface) -{ - unsigned int i; - struct usb_interface *intf; - - mutex_lock(&ua->mutex); - free_stream_urbs(&ua->capture); - free_stream_urbs(&ua->playback); - mutex_unlock(&ua->mutex); - free_stream_buffers(ua, &ua->capture); - free_stream_buffers(ua, &ua->playback); - - for (i = 0; i < ARRAY_SIZE(ua->intf); ++i) { - mutex_lock(&ua->mutex); - intf = ua->intf[i]; - ua->intf[i] = NULL; - mutex_unlock(&ua->mutex); - if (intf) { - usb_set_intfdata(intf, NULL); - if (intf != interface) - usb_driver_release_interface(&ua101_driver, - intf); - } - } -} - -static void ua101_card_free(struct snd_card *card) -{ - struct ua101 *ua = card->private_data; - - mutex_destroy(&ua->mutex); -} - -static int ua101_probe(struct usb_interface *interface, - const struct usb_device_id *usb_id) -{ - static const struct snd_usb_midi_endpoint_info midi_ep = { - .out_cables = 0x0001, - .in_cables = 0x0001 - }; - static const struct snd_usb_audio_quirk midi_quirk = { - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = &midi_ep - }; - static const int intf_numbers[2][3] = { - { /* UA-101 */ - [INTF_PLAYBACK] = 0, - [INTF_CAPTURE] = 1, - [INTF_MIDI] = 2, - }, - { /* UA-1000 */ - [INTF_CAPTURE] = 1, - [INTF_PLAYBACK] = 2, - [INTF_MIDI] = 3, - }, - }; - struct snd_card *card; - struct ua101 *ua; - unsigned int card_index, i; - int is_ua1000; - const char *name; - char usb_path[32]; - int err; - - is_ua1000 = usb_id->idProduct == 0x0044; - - if (interface->altsetting->desc.bInterfaceNumber != - intf_numbers[is_ua1000][0]) - return -ENODEV; - - mutex_lock(&devices_mutex); - - for (card_index = 0; card_index < SNDRV_CARDS; ++card_index) - if (enable[card_index] && !(devices_used & (1 << card_index))) - break; - if (card_index >= SNDRV_CARDS) { - mutex_unlock(&devices_mutex); - return -ENOENT; - } - err = snd_card_create(index[card_index], id[card_index], THIS_MODULE, - sizeof(*ua), &card); - if (err < 0) { - mutex_unlock(&devices_mutex); - return err; - } - card->private_free = ua101_card_free; - ua = card->private_data; - ua->dev = interface_to_usbdev(interface); - ua->card = card; - ua->card_index = card_index; - INIT_LIST_HEAD(&ua->midi_list); - spin_lock_init(&ua->lock); - mutex_init(&ua->mutex); - INIT_LIST_HEAD(&ua->ready_playback_urbs); - tasklet_init(&ua->playback_tasklet, - playback_tasklet, (unsigned long)ua); - init_waitqueue_head(&ua->alsa_capture_wait); - init_waitqueue_head(&ua->rate_feedback_wait); - init_waitqueue_head(&ua->alsa_playback_wait); - - ua->intf[0] = interface; - for (i = 1; i < ARRAY_SIZE(ua->intf); ++i) { - ua->intf[i] = usb_ifnum_to_if(ua->dev, - intf_numbers[is_ua1000][i]); - if (!ua->intf[i]) { - dev_err(&ua->dev->dev, "interface %u not found\n", - intf_numbers[is_ua1000][i]); - err = -ENXIO; - goto probe_error; - } - err = usb_driver_claim_interface(&ua101_driver, - ua->intf[i], ua); - if (err < 0) { - ua->intf[i] = NULL; - err = -EBUSY; - goto probe_error; - } - } - - snd_card_set_dev(card, &interface->dev); - - err = detect_usb_format(ua); - if (err < 0) - goto probe_error; - - name = usb_id->idProduct == 0x0044 ? "UA-1000" : "UA-101"; - strcpy(card->driver, "UA-101"); - strcpy(card->shortname, name); - usb_make_path(ua->dev, usb_path, sizeof(usb_path)); - snprintf(ua->card->longname, sizeof(ua->card->longname), - "EDIROL %s (serial %s), %u Hz at %s, %s speed", name, - ua->dev->serial ? ua->dev->serial : "?", ua->rate, usb_path, - ua->dev->speed == USB_SPEED_HIGH ? "high" : "full"); - - err = alloc_stream_buffers(ua, &ua->capture); - if (err < 0) - goto probe_error; - err = alloc_stream_buffers(ua, &ua->playback); - if (err < 0) - goto probe_error; - - err = alloc_stream_urbs(ua, &ua->capture, capture_urb_complete); - if (err < 0) - goto probe_error; - err = alloc_stream_urbs(ua, &ua->playback, playback_urb_complete); - if (err < 0) - goto probe_error; - - err = snd_pcm_new(card, name, 0, 1, 1, &ua->pcm); - if (err < 0) - goto probe_error; - ua->pcm->private_data = ua; - strcpy(ua->pcm->name, name); - snd_pcm_set_ops(ua->pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_pcm_ops); - snd_pcm_set_ops(ua->pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_pcm_ops); - - err = snd_usbmidi_create(card, ua->intf[INTF_MIDI], - &ua->midi_list, &midi_quirk); - if (err < 0) - goto probe_error; - - err = snd_card_register(card); - if (err < 0) - goto probe_error; - - usb_set_intfdata(interface, ua); - devices_used |= 1 << card_index; - - mutex_unlock(&devices_mutex); - return 0; - -probe_error: - free_usb_related_resources(ua, interface); - snd_card_free(card); - mutex_unlock(&devices_mutex); - return err; -} - -static void ua101_disconnect(struct usb_interface *interface) -{ - struct ua101 *ua = usb_get_intfdata(interface); - struct list_head *midi; - - if (!ua) - return; - - mutex_lock(&devices_mutex); - - set_bit(DISCONNECTED, &ua->states); - wake_up(&ua->rate_feedback_wait); - - /* make sure that userspace cannot create new requests */ - snd_card_disconnect(ua->card); - - /* make sure that there are no pending USB requests */ - __list_for_each(midi, &ua->midi_list) - snd_usbmidi_disconnect(midi); - abort_alsa_playback(ua); - abort_alsa_capture(ua); - mutex_lock(&ua->mutex); - stop_usb_playback(ua); - stop_usb_capture(ua); - mutex_unlock(&ua->mutex); - - free_usb_related_resources(ua, interface); - - devices_used &= ~(1 << ua->card_index); - - snd_card_free_when_closed(ua->card); - - mutex_unlock(&devices_mutex); -} - -static struct usb_device_id ua101_ids[] = { - { USB_DEVICE(0x0582, 0x0044) }, /* UA-1000 high speed */ - { USB_DEVICE(0x0582, 0x007d) }, /* UA-101 high speed */ - { USB_DEVICE(0x0582, 0x008d) }, /* UA-101 full speed */ - { } -}; -MODULE_DEVICE_TABLE(usb, ua101_ids); - -static struct usb_driver ua101_driver = { - .name = "snd-ua101", - .id_table = ua101_ids, - .probe = ua101_probe, - .disconnect = ua101_disconnect, -#if 0 - .suspend = ua101_suspend, - .resume = ua101_resume, -#endif -}; - -module_usb_driver(ua101_driver); diff --git a/ANDROID_3.4.5/sound/usb/mixer.c b/ANDROID_3.4.5/sound/usb/mixer.c deleted file mode 100644 index ab23869c..00000000 --- a/ANDROID_3.4.5/sound/usb/mixer.c +++ /dev/null @@ -1,2283 +0,0 @@ -/* - * (Tentative) USB Audio Driver for ALSA - * - * Mixer control part - * - * Copyright (c) 2002 by Takashi Iwai - * - * Many codes borrowed from audio.c by - * Alan Cox (alan@lxorguk.ukuu.org.uk) - * Thomas Sailer (sailer@ife.ee.ethz.ch) - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* - * TODOs, for both the mixer and the streaming interfaces: - * - * - support for UAC2 effect units - * - support for graphical equalizers - * - RANGE and MEM set commands (UAC2) - * - RANGE and MEM interrupt dispatchers (UAC2) - * - audio channel clustering (UAC2) - * - audio sample rate converter units (UAC2) - * - proper handling of clock multipliers (UAC2) - * - dispatch clock change notifications (UAC2) - * - stop PCM streams which use a clock that became invalid - * - stop PCM streams which use a clock selector that has changed - * - parse available sample rates again when clock sources changed - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "usbaudio.h" -#include "mixer.h" -#include "helper.h" -#include "mixer_quirks.h" -#include "power.h" - -#define MAX_ID_ELEMS 256 - -struct usb_audio_term { - int id; - int type; - int channels; - unsigned int chconfig; - int name; -}; - -struct usbmix_name_map; - -struct mixer_build { - struct snd_usb_audio *chip; - struct usb_mixer_interface *mixer; - unsigned char *buffer; - unsigned int buflen; - DECLARE_BITMAP(unitbitmap, MAX_ID_ELEMS); - struct usb_audio_term oterm; - const struct usbmix_name_map *map; - const struct usbmix_selector_map *selector_map; -}; - -/*E-mu 0202/0404/0204 eXtension Unit(XU) control*/ -enum { - USB_XU_CLOCK_RATE = 0xe301, - USB_XU_CLOCK_SOURCE = 0xe302, - USB_XU_DIGITAL_IO_STATUS = 0xe303, - USB_XU_DEVICE_OPTIONS = 0xe304, - USB_XU_DIRECT_MONITORING = 0xe305, - USB_XU_METERING = 0xe306 -}; -enum { - USB_XU_CLOCK_SOURCE_SELECTOR = 0x02, /* clock source*/ - USB_XU_CLOCK_RATE_SELECTOR = 0x03, /* clock rate */ - USB_XU_DIGITAL_FORMAT_SELECTOR = 0x01, /* the spdif format */ - USB_XU_SOFT_LIMIT_SELECTOR = 0x03 /* soft limiter */ -}; - -/* - * manual mapping of mixer names - * if the mixer topology is too complicated and the parsed names are - * ambiguous, add the entries in usbmixer_maps.c. - */ -#include "mixer_maps.c" - -static const struct usbmix_name_map * -find_map(struct mixer_build *state, int unitid, int control) -{ - const struct usbmix_name_map *p = state->map; - - if (!p) - return NULL; - - for (p = state->map; p->id; p++) { - if (p->id == unitid && - (!control || !p->control || control == p->control)) - return p; - } - return NULL; -} - -/* get the mapped name if the unit matches */ -static int -check_mapped_name(const struct usbmix_name_map *p, char *buf, int buflen) -{ - if (!p || !p->name) - return 0; - - buflen--; - return strlcpy(buf, p->name, buflen); -} - -/* check whether the control should be ignored */ -static inline int -check_ignored_ctl(const struct usbmix_name_map *p) -{ - if (!p || p->name || p->dB) - return 0; - return 1; -} - -/* dB mapping */ -static inline void check_mapped_dB(const struct usbmix_name_map *p, - struct usb_mixer_elem_info *cval) -{ - if (p && p->dB) { - cval->dBmin = p->dB->min; - cval->dBmax = p->dB->max; - cval->initialized = 1; - } -} - -/* get the mapped selector source name */ -static int check_mapped_selector_name(struct mixer_build *state, int unitid, - int index, char *buf, int buflen) -{ - const struct usbmix_selector_map *p; - - if (! state->selector_map) - return 0; - for (p = state->selector_map; p->id; p++) { - if (p->id == unitid && index < p->count) - return strlcpy(buf, p->names[index], buflen); - } - return 0; -} - -/* - * find an audio control unit with the given unit id - */ -static void *find_audio_control_unit(struct mixer_build *state, unsigned char unit) -{ - /* we just parse the header */ - struct uac_feature_unit_descriptor *hdr = NULL; - - while ((hdr = snd_usb_find_desc(state->buffer, state->buflen, hdr, - USB_DT_CS_INTERFACE)) != NULL) { - if (hdr->bLength >= 4 && - hdr->bDescriptorSubtype >= UAC_INPUT_TERMINAL && - hdr->bDescriptorSubtype <= UAC2_SAMPLE_RATE_CONVERTER && - hdr->bUnitID == unit) - return hdr; - } - - return NULL; -} - -/* - * copy a string with the given id - */ -static int snd_usb_copy_string_desc(struct mixer_build *state, int index, char *buf, int maxlen) -{ - int len = usb_string(state->chip->dev, index, buf, maxlen - 1); - buf[len] = 0; - return len; -} - -/* - * convert from the byte/word on usb descriptor to the zero-based integer - */ -static int convert_signed_value(struct usb_mixer_elem_info *cval, int val) -{ - switch (cval->val_type) { - case USB_MIXER_BOOLEAN: - return !!val; - case USB_MIXER_INV_BOOLEAN: - return !val; - case USB_MIXER_U8: - val &= 0xff; - break; - case USB_MIXER_S8: - val &= 0xff; - if (val >= 0x80) - val -= 0x100; - break; - case USB_MIXER_U16: - val &= 0xffff; - break; - case USB_MIXER_S16: - val &= 0xffff; - if (val >= 0x8000) - val -= 0x10000; - break; - } - return val; -} - -/* - * convert from the zero-based int to the byte/word for usb descriptor - */ -static int convert_bytes_value(struct usb_mixer_elem_info *cval, int val) -{ - switch (cval->val_type) { - case USB_MIXER_BOOLEAN: - return !!val; - case USB_MIXER_INV_BOOLEAN: - return !val; - case USB_MIXER_S8: - case USB_MIXER_U8: - return val & 0xff; - case USB_MIXER_S16: - case USB_MIXER_U16: - return val & 0xffff; - } - return 0; /* not reached */ -} - -static int get_relative_value(struct usb_mixer_elem_info *cval, int val) -{ - if (! cval->res) - cval->res = 1; - if (val < cval->min) - return 0; - else if (val >= cval->max) - return (cval->max - cval->min + cval->res - 1) / cval->res; - else - return (val - cval->min) / cval->res; -} - -static int get_abs_value(struct usb_mixer_elem_info *cval, int val) -{ - if (val < 0) - return cval->min; - if (! cval->res) - cval->res = 1; - val *= cval->res; - val += cval->min; - if (val > cval->max) - return cval->max; - return val; -} - - -/* - * retrieve a mixer value - */ - -static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) -{ - struct snd_usb_audio *chip = cval->mixer->chip; - unsigned char buf[2]; - int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; - int timeout = 10; - int err; - - err = snd_usb_autoresume(cval->mixer->chip); - if (err < 0) - return -EIO; - while (timeout-- > 0) { - if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request, - USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, - validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), - buf, val_len) >= val_len) { - *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); - snd_usb_autosuspend(cval->mixer->chip); - return 0; - } - } - snd_usb_autosuspend(cval->mixer->chip); - snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", - request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); - return -EINVAL; -} - -static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) -{ - struct snd_usb_audio *chip = cval->mixer->chip; - unsigned char buf[2 + 3*sizeof(__u16)]; /* enough space for one range */ - unsigned char *val; - int ret, size; - __u8 bRequest; - - if (request == UAC_GET_CUR) { - bRequest = UAC2_CS_CUR; - size = sizeof(__u16); - } else { - bRequest = UAC2_CS_RANGE; - size = sizeof(buf); - } - - memset(buf, 0, sizeof(buf)); - - ret = snd_usb_autoresume(chip) ? -EIO : 0; - if (ret) - goto error; - - ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, - USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, - validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), - buf, size); - snd_usb_autosuspend(chip); - - if (ret < 0) { -error: - snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", - request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); - return ret; - } - - /* FIXME: how should we handle multiple triplets here? */ - - switch (request) { - case UAC_GET_CUR: - val = buf; - break; - case UAC_GET_MIN: - val = buf + sizeof(__u16); - break; - case UAC_GET_MAX: - val = buf + sizeof(__u16) * 2; - break; - case UAC_GET_RES: - val = buf + sizeof(__u16) * 3; - break; - default: - return -EINVAL; - } - - *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(val, sizeof(__u16))); - - return 0; -} - -static int get_ctl_value(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) -{ - return (cval->mixer->protocol == UAC_VERSION_1) ? - get_ctl_value_v1(cval, request, validx, value_ret) : - get_ctl_value_v2(cval, request, validx, value_ret); -} - -static int get_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int *value) -{ - return get_ctl_value(cval, UAC_GET_CUR, validx, value); -} - -/* channel = 0: master, 1 = first channel */ -static inline int get_cur_mix_raw(struct usb_mixer_elem_info *cval, - int channel, int *value) -{ - return get_ctl_value(cval, UAC_GET_CUR, (cval->control << 8) | channel, value); -} - -static int get_cur_mix_value(struct usb_mixer_elem_info *cval, - int channel, int index, int *value) -{ - int err; - - if (cval->cached & (1 << channel)) { - *value = cval->cache_val[index]; - return 0; - } - err = get_cur_mix_raw(cval, channel, value); - if (err < 0) { - if (!cval->mixer->ignore_ctl_error) - snd_printd(KERN_ERR "cannot get current value for control %d ch %d: err = %d\n", - cval->control, channel, err); - return err; - } - cval->cached |= 1 << channel; - cval->cache_val[index] = *value; - return 0; -} - - -/* - * set a mixer value - */ - -int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, - int request, int validx, int value_set) -{ - struct snd_usb_audio *chip = cval->mixer->chip; - unsigned char buf[2]; - int val_len, err, timeout = 10; - - if (cval->mixer->protocol == UAC_VERSION_1) { - val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; - } else { /* UAC_VERSION_2 */ - /* audio class v2 controls are always 2 bytes in size */ - val_len = sizeof(__u16); - - /* FIXME */ - if (request != UAC_SET_CUR) { - snd_printdd(KERN_WARNING "RANGE setting not yet supported\n"); - return -EINVAL; - } - - request = UAC2_CS_CUR; - } - - value_set = convert_bytes_value(cval, value_set); - buf[0] = value_set & 0xff; - buf[1] = (value_set >> 8) & 0xff; - err = snd_usb_autoresume(chip); - if (err < 0) - return -EIO; - while (timeout-- > 0) - if (snd_usb_ctl_msg(chip->dev, - usb_sndctrlpipe(chip->dev, 0), request, - USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, - validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), - buf, val_len) >= 0) { - snd_usb_autosuspend(chip); - return 0; - } - snd_usb_autosuspend(chip); - snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", - request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type, buf[0], buf[1]); - return -EINVAL; -} - -static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int value) -{ - return snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR, validx, value); -} - -static int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, - int index, int value) -{ - int err; - unsigned int read_only = (channel == 0) ? - cval->master_readonly : - cval->ch_readonly & (1 << (channel - 1)); - - if (read_only) { - snd_printdd(KERN_INFO "%s(): channel %d of control %d is read_only\n", - __func__, channel, cval->control); - return 0; - } - - err = snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR, (cval->control << 8) | channel, - value); - if (err < 0) - return err; - cval->cached |= 1 << channel; - cval->cache_val[index] = value; - return 0; -} - -/* - * TLV callback for mixer volume controls - */ -static int mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag, - unsigned int size, unsigned int __user *_tlv) -{ - struct usb_mixer_elem_info *cval = kcontrol->private_data; - DECLARE_TLV_DB_MINMAX(scale, 0, 0); - - if (size < sizeof(scale)) - return -ENOMEM; - scale[2] = cval->dBmin; - scale[3] = cval->dBmax; - if (copy_to_user(_tlv, scale, sizeof(scale))) - return -EFAULT; - return 0; -} - -/* - * parser routines begin here... - */ - -static int parse_audio_unit(struct mixer_build *state, int unitid); - - -/* - * check if the input/output channel routing is enabled on the given bitmap. - * used for mixer unit parser - */ -static int check_matrix_bitmap(unsigned char *bmap, int ich, int och, int num_outs) -{ - int idx = ich * num_outs + och; - return bmap[idx >> 3] & (0x80 >> (idx & 7)); -} - - -/* - * add an alsa control element - * search and increment the index until an empty slot is found. - * - * if failed, give up and free the control instance. - */ - -int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer, - struct snd_kcontrol *kctl) -{ - struct usb_mixer_elem_info *cval = kctl->private_data; - int err; - - while (snd_ctl_find_id(mixer->chip->card, &kctl->id)) - kctl->id.index++; - if ((err = snd_ctl_add(mixer->chip->card, kctl)) < 0) { - snd_printd(KERN_ERR "cannot add control (err = %d)\n", err); - return err; - } - cval->elem_id = &kctl->id; - cval->next_id_elem = mixer->id_elems[cval->id]; - mixer->id_elems[cval->id] = cval; - return 0; -} - - -/* - * get a terminal name string - */ - -static struct iterm_name_combo { - int type; - char *name; -} iterm_names[] = { - { 0x0300, "Output" }, - { 0x0301, "Speaker" }, - { 0x0302, "Headphone" }, - { 0x0303, "HMD Audio" }, - { 0x0304, "Desktop Speaker" }, - { 0x0305, "Room Speaker" }, - { 0x0306, "Com Speaker" }, - { 0x0307, "LFE" }, - { 0x0600, "External In" }, - { 0x0601, "Analog In" }, - { 0x0602, "Digital In" }, - { 0x0603, "Line" }, - { 0x0604, "Legacy In" }, - { 0x0605, "IEC958 In" }, - { 0x0606, "1394 DA Stream" }, - { 0x0607, "1394 DV Stream" }, - { 0x0700, "Embedded" }, - { 0x0701, "Noise Source" }, - { 0x0702, "Equalization Noise" }, - { 0x0703, "CD" }, - { 0x0704, "DAT" }, - { 0x0705, "DCC" }, - { 0x0706, "MiniDisk" }, - { 0x0707, "Analog Tape" }, - { 0x0708, "Phonograph" }, - { 0x0709, "VCR Audio" }, - { 0x070a, "Video Disk Audio" }, - { 0x070b, "DVD Audio" }, - { 0x070c, "TV Tuner Audio" }, - { 0x070d, "Satellite Rec Audio" }, - { 0x070e, "Cable Tuner Audio" }, - { 0x070f, "DSS Audio" }, - { 0x0710, "Radio Receiver" }, - { 0x0711, "Radio Transmitter" }, - { 0x0712, "Multi-Track Recorder" }, - { 0x0713, "Synthesizer" }, - { 0 }, -}; - -static int get_term_name(struct mixer_build *state, struct usb_audio_term *iterm, - unsigned char *name, int maxlen, int term_only) -{ - struct iterm_name_combo *names; - - if (iterm->name) - return snd_usb_copy_string_desc(state, iterm->name, name, maxlen); - - /* virtual type - not a real terminal */ - if (iterm->type >> 16) { - if (term_only) - return 0; - switch (iterm->type >> 16) { - case UAC_SELECTOR_UNIT: - strcpy(name, "Selector"); return 8; - case UAC1_PROCESSING_UNIT: - strcpy(name, "Process Unit"); return 12; - case UAC1_EXTENSION_UNIT: - strcpy(name, "Ext Unit"); return 8; - case UAC_MIXER_UNIT: - strcpy(name, "Mixer"); return 5; - default: - return sprintf(name, "Unit %d", iterm->id); - } - } - - switch (iterm->type & 0xff00) { - case 0x0100: - strcpy(name, "PCM"); return 3; - case 0x0200: - strcpy(name, "Mic"); return 3; - case 0x0400: - strcpy(name, "Headset"); return 7; - case 0x0500: - strcpy(name, "Phone"); return 5; - } - - for (names = iterm_names; names->type; names++) - if (names->type == iterm->type) { - strcpy(name, names->name); - return strlen(names->name); - } - return 0; -} - - -/* - * parse the source unit recursively until it reaches to a terminal - * or a branched unit. - */ -static int check_input_term(struct mixer_build *state, int id, struct usb_audio_term *term) -{ - int err; - void *p1; - - memset(term, 0, sizeof(*term)); - while ((p1 = find_audio_control_unit(state, id)) != NULL) { - unsigned char *hdr = p1; - term->id = id; - switch (hdr[2]) { - case UAC_INPUT_TERMINAL: - if (state->mixer->protocol == UAC_VERSION_1) { - struct uac_input_terminal_descriptor *d = p1; - term->type = le16_to_cpu(d->wTerminalType); - term->channels = d->bNrChannels; - term->chconfig = le16_to_cpu(d->wChannelConfig); - term->name = d->iTerminal; - } else { /* UAC_VERSION_2 */ - struct uac2_input_terminal_descriptor *d = p1; - term->type = le16_to_cpu(d->wTerminalType); - term->channels = d->bNrChannels; - term->chconfig = le32_to_cpu(d->bmChannelConfig); - term->name = d->iTerminal; - - /* call recursively to get the clock selectors */ - err = check_input_term(state, d->bCSourceID, term); - if (err < 0) - return err; - } - return 0; - case UAC_FEATURE_UNIT: { - /* the header is the same for v1 and v2 */ - struct uac_feature_unit_descriptor *d = p1; - id = d->bSourceID; - break; /* continue to parse */ - } - case UAC_MIXER_UNIT: { - struct uac_mixer_unit_descriptor *d = p1; - term->type = d->bDescriptorSubtype << 16; /* virtual type */ - term->channels = uac_mixer_unit_bNrChannels(d); - term->chconfig = uac_mixer_unit_wChannelConfig(d, state->mixer->protocol); - term->name = uac_mixer_unit_iMixer(d); - return 0; - } - case UAC_SELECTOR_UNIT: - case UAC2_CLOCK_SELECTOR: { - struct uac_selector_unit_descriptor *d = p1; - /* call recursively to retrieve the channel info */ - if (check_input_term(state, d->baSourceID[0], term) < 0) - return -ENODEV; - term->type = d->bDescriptorSubtype << 16; /* virtual type */ - term->id = id; - term->name = uac_selector_unit_iSelector(d); - return 0; - } - case UAC1_PROCESSING_UNIT: - case UAC1_EXTENSION_UNIT: { - struct uac_processing_unit_descriptor *d = p1; - if (d->bNrInPins) { - id = d->baSourceID[0]; - break; /* continue to parse */ - } - term->type = d->bDescriptorSubtype << 16; /* virtual type */ - term->channels = uac_processing_unit_bNrChannels(d); - term->chconfig = uac_processing_unit_wChannelConfig(d, state->mixer->protocol); - term->name = uac_processing_unit_iProcessing(d, state->mixer->protocol); - return 0; - } - case UAC2_CLOCK_SOURCE: { - struct uac_clock_source_descriptor *d = p1; - term->type = d->bDescriptorSubtype << 16; /* virtual type */ - term->id = id; - term->name = d->iClockSource; - return 0; - } - default: - return -ENODEV; - } - } - return -ENODEV; -} - - -/* - * Feature Unit - */ - -/* feature unit control information */ -struct usb_feature_control_info { - const char *name; - unsigned int type; /* control type (mute, volume, etc.) */ -}; - -static struct usb_feature_control_info audio_feature_info[] = { - { "Mute", USB_MIXER_INV_BOOLEAN }, - { "Volume", USB_MIXER_S16 }, - { "Tone Control - Bass", USB_MIXER_S8 }, - { "Tone Control - Mid", USB_MIXER_S8 }, - { "Tone Control - Treble", USB_MIXER_S8 }, - { "Graphic Equalizer", USB_MIXER_S8 }, /* FIXME: not implemeted yet */ - { "Auto Gain Control", USB_MIXER_BOOLEAN }, - { "Delay Control", USB_MIXER_U16 }, - { "Bass Boost", USB_MIXER_BOOLEAN }, - { "Loudness", USB_MIXER_BOOLEAN }, - /* UAC2 specific */ - { "Input Gain Control", USB_MIXER_U16 }, - { "Input Gain Pad Control", USB_MIXER_BOOLEAN }, - { "Phase Inverter Control", USB_MIXER_BOOLEAN }, -}; - - -/* private_free callback */ -static void usb_mixer_elem_free(struct snd_kcontrol *kctl) -{ - kfree(kctl->private_data); - kctl->private_data = NULL; -} - - -/* - * interface to ALSA control for feature/mixer units - */ - -/* volume control quirks */ -static void volume_control_quirks(struct usb_mixer_elem_info *cval, - struct snd_kcontrol *kctl) -{ - switch (cval->mixer->chip->usb_id) { - case USB_ID(0x0471, 0x0101): - case USB_ID(0x0471, 0x0104): - case USB_ID(0x0471, 0x0105): - case USB_ID(0x0672, 0x1041): - /* quirk for UDA1321/N101. - * note that detection between firmware 2.1.1.7 (N101) - * and later 2.1.1.21 is not very clear from datasheets. - * I hope that the min value is -15360 for newer firmware --jk - */ - if (!strcmp(kctl->id.name, "PCM Playback Volume") && - cval->min == -15616) { - snd_printk(KERN_INFO - "set volume quirk for UDA1321/N101 chip\n"); - cval->max = -256; - } - break; - - case USB_ID(0x046d, 0x09a4): - if (!strcmp(kctl->id.name, "Mic Capture Volume")) { - snd_printk(KERN_INFO - "set volume quirk for QuickCam E3500\n"); - cval->min = 6080; - cval->max = 8768; - cval->res = 192; - } - break; - - case USB_ID(0x046d, 0x0808): - case USB_ID(0x046d, 0x0809): - case USB_ID(0x046d, 0x081d): /* HD Webcam c510 */ - case USB_ID(0x046d, 0x0991): - /* Most audio usb devices lie about volume resolution. - * Most Logitech webcams have res = 384. - * Proboly there is some logitech magic behind this number --fishor - */ - if (!strcmp(kctl->id.name, "Mic Capture Volume")) { - snd_printk(KERN_INFO - "set resolution quirk: cval->res = 384\n"); - cval->res = 384; - } - break; - - } -} - -/* - * retrieve the minimum and maximum values for the specified control - */ -static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval, - int default_min, struct snd_kcontrol *kctl) -{ - /* for failsafe */ - cval->min = default_min; - cval->max = cval->min + 1; - cval->res = 1; - cval->dBmin = cval->dBmax = 0; - - if (cval->val_type == USB_MIXER_BOOLEAN || - cval->val_type == USB_MIXER_INV_BOOLEAN) { - cval->initialized = 1; - } else { - int minchn = 0; - if (cval->cmask) { - int i; - for (i = 0; i < MAX_CHANNELS; i++) - if (cval->cmask & (1 << i)) { - minchn = i + 1; - break; - } - } - if (get_ctl_value(cval, UAC_GET_MAX, (cval->control << 8) | minchn, &cval->max) < 0 || - get_ctl_value(cval, UAC_GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) { - snd_printd(KERN_ERR "%d:%d: cannot get min/max values for control %d (id %d)\n", - cval->id, snd_usb_ctrl_intf(cval->mixer->chip), cval->control, cval->id); - return -EINVAL; - } - if (get_ctl_value(cval, UAC_GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) { - cval->res = 1; - } else { - int last_valid_res = cval->res; - - while (cval->res > 1) { - if (snd_usb_mixer_set_ctl_value(cval, UAC_SET_RES, - (cval->control << 8) | minchn, cval->res / 2) < 0) - break; - cval->res /= 2; - } - if (get_ctl_value(cval, UAC_GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) - cval->res = last_valid_res; - } - if (cval->res == 0) - cval->res = 1; - - /* Additional checks for the proper resolution - * - * Some devices report smaller resolutions than actually - * reacting. They don't return errors but simply clip - * to the lower aligned value. - */ - if (cval->min + cval->res < cval->max) { - int last_valid_res = cval->res; - int saved, test, check; - get_cur_mix_raw(cval, minchn, &saved); - for (;;) { - test = saved; - if (test < cval->max) - test += cval->res; - else - test -= cval->res; - if (test < cval->min || test > cval->max || - set_cur_mix_value(cval, minchn, 0, test) || - get_cur_mix_raw(cval, minchn, &check)) { - cval->res = last_valid_res; - break; - } - if (test == check) - break; - cval->res *= 2; - } - set_cur_mix_value(cval, minchn, 0, saved); - } - - cval->initialized = 1; - } - - if (kctl) - volume_control_quirks(cval, kctl); - - /* USB descriptions contain the dB scale in 1/256 dB unit - * while ALSA TLV contains in 1/100 dB unit - */ - cval->dBmin = (convert_signed_value(cval, cval->min) * 100) / 256; - cval->dBmax = (convert_signed_value(cval, cval->max) * 100) / 256; - if (cval->dBmin > cval->dBmax) { - /* something is wrong; assume it's either from/to 0dB */ - if (cval->dBmin < 0) - cval->dBmax = 0; - else if (cval->dBmin > 0) - cval->dBmin = 0; - if (cval->dBmin > cval->dBmax) { - /* totally crap, return an error */ - return -EINVAL; - } - } - - return 0; -} - -#define get_min_max(cval, def) get_min_max_with_quirks(cval, def, NULL) - -/* get a feature/mixer unit info */ -static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - struct usb_mixer_elem_info *cval = kcontrol->private_data; - - if (cval->val_type == USB_MIXER_BOOLEAN || - cval->val_type == USB_MIXER_INV_BOOLEAN) - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - else - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = cval->channels; - if (cval->val_type == USB_MIXER_BOOLEAN || - cval->val_type == USB_MIXER_INV_BOOLEAN) { - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - } else { - if (!cval->initialized) { - get_min_max_with_quirks(cval, 0, kcontrol); - if (cval->initialized && cval->dBmin >= cval->dBmax) { - kcontrol->vd[0].access &= - ~(SNDRV_CTL_ELEM_ACCESS_TLV_READ | - SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK); - snd_ctl_notify(cval->mixer->chip->card, - SNDRV_CTL_EVENT_MASK_INFO, - &kcontrol->id); - } - } - uinfo->value.integer.min = 0; - uinfo->value.integer.max = - (cval->max - cval->min + cval->res - 1) / cval->res; - } - return 0; -} - -/* get the current value from feature/mixer unit */ -static int mixer_ctl_feature_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct usb_mixer_elem_info *cval = kcontrol->private_data; - int c, cnt, val, err; - - ucontrol->value.integer.value[0] = cval->min; - if (cval->cmask) { - cnt = 0; - for (c = 0; c < MAX_CHANNELS; c++) { - if (!(cval->cmask & (1 << c))) - continue; - err = get_cur_mix_value(cval, c + 1, cnt, &val); - if (err < 0) - return cval->mixer->ignore_ctl_error ? 0 : err; - val = get_relative_value(cval, val); - ucontrol->value.integer.value[cnt] = val; - cnt++; - } - return 0; - } else { - /* master channel */ - err = get_cur_mix_value(cval, 0, 0, &val); - if (err < 0) - return cval->mixer->ignore_ctl_error ? 0 : err; - val = get_relative_value(cval, val); - ucontrol->value.integer.value[0] = val; - } - return 0; -} - -/* put the current value to feature/mixer unit */ -static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct usb_mixer_elem_info *cval = kcontrol->private_data; - int c, cnt, val, oval, err; - int changed = 0; - - if (cval->cmask) { - cnt = 0; - for (c = 0; c < MAX_CHANNELS; c++) { - if (!(cval->cmask & (1 << c))) - continue; - err = get_cur_mix_value(cval, c + 1, cnt, &oval); - if (err < 0) - return cval->mixer->ignore_ctl_error ? 0 : err; - val = ucontrol->value.integer.value[cnt]; - val = get_abs_value(cval, val); - if (oval != val) { - set_cur_mix_value(cval, c + 1, cnt, val); - changed = 1; - } - cnt++; - } - } else { - /* master channel */ - err = get_cur_mix_value(cval, 0, 0, &oval); - if (err < 0) - return cval->mixer->ignore_ctl_error ? 0 : err; - val = ucontrol->value.integer.value[0]; - val = get_abs_value(cval, val); - if (val != oval) { - set_cur_mix_value(cval, 0, 0, val); - changed = 1; - } - } - return changed; -} - -static struct snd_kcontrol_new usb_feature_unit_ctl = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "", /* will be filled later manually */ - .info = mixer_ctl_feature_info, - .get = mixer_ctl_feature_get, - .put = mixer_ctl_feature_put, -}; - -/* the read-only variant */ -static struct snd_kcontrol_new usb_feature_unit_ctl_ro = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "", /* will be filled later manually */ - .info = mixer_ctl_feature_info, - .get = mixer_ctl_feature_get, - .put = NULL, -}; - -/* This symbol is exported in order to allow the mixer quirks to - * hook up to the standard feature unit control mechanism */ -struct snd_kcontrol_new *snd_usb_feature_unit_ctl = &usb_feature_unit_ctl; - -/* - * build a feature control - */ - -static size_t append_ctl_name(struct snd_kcontrol *kctl, const char *str) -{ - return strlcat(kctl->id.name, str, sizeof(kctl->id.name)); -} - -static void build_feature_ctl(struct mixer_build *state, void *raw_desc, - unsigned int ctl_mask, int control, - struct usb_audio_term *iterm, int unitid, - int readonly_mask) -{ - struct uac_feature_unit_descriptor *desc = raw_desc; - unsigned int len = 0; - int mapped_name = 0; - int nameid = uac_feature_unit_iFeature(desc); - struct snd_kcontrol *kctl; - struct usb_mixer_elem_info *cval; - const struct usbmix_name_map *map; - unsigned int range; - - control++; /* change from zero-based to 1-based value */ - - if (control == UAC_FU_GRAPHIC_EQUALIZER) { - /* FIXME: not supported yet */ - return; - } - - map = find_map(state, unitid, control); - if (check_ignored_ctl(map)) - return; - - cval = kzalloc(sizeof(*cval), GFP_KERNEL); - if (! cval) { - snd_printk(KERN_ERR "cannot malloc kcontrol\n"); - return; - } - cval->mixer = state->mixer; - cval->id = unitid; - cval->control = control; - cval->cmask = ctl_mask; - cval->val_type = audio_feature_info[control-1].type; - if (ctl_mask == 0) { - cval->channels = 1; /* master channel */ - cval->master_readonly = readonly_mask; - } else { - int i, c = 0; - for (i = 0; i < 16; i++) - if (ctl_mask & (1 << i)) - c++; - cval->channels = c; - cval->ch_readonly = readonly_mask; - } - - /* if all channels in the mask are marked read-only, make the control - * read-only. set_cur_mix_value() will check the mask again and won't - * issue write commands to read-only channels. */ - if (cval->channels == readonly_mask) - kctl = snd_ctl_new1(&usb_feature_unit_ctl_ro, cval); - else - kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval); - - if (! kctl) { - snd_printk(KERN_ERR "cannot malloc kcontrol\n"); - kfree(cval); - return; - } - kctl->private_free = usb_mixer_elem_free; - - len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name)); - mapped_name = len != 0; - if (! len && nameid) - len = snd_usb_copy_string_desc(state, nameid, - kctl->id.name, sizeof(kctl->id.name)); - - /* get min/max values */ - get_min_max_with_quirks(cval, 0, kctl); - - switch (control) { - case UAC_FU_MUTE: - case UAC_FU_VOLUME: - /* determine the control name. the rule is: - * - if a name id is given in descriptor, use it. - * - if the connected input can be determined, then use the name - * of terminal type. - * - if the connected output can be determined, use it. - * - otherwise, anonymous name. - */ - if (! len) { - len = get_term_name(state, iterm, kctl->id.name, sizeof(kctl->id.name), 1); - if (! len) - len = get_term_name(state, &state->oterm, kctl->id.name, sizeof(kctl->id.name), 1); - if (! len) - len = snprintf(kctl->id.name, sizeof(kctl->id.name), - "Feature %d", unitid); - } - /* determine the stream direction: - * if the connected output is USB stream, then it's likely a - * capture stream. otherwise it should be playback (hopefully :) - */ - if (! mapped_name && ! (state->oterm.type >> 16)) { - if ((state->oterm.type & 0xff00) == 0x0100) { - len = append_ctl_name(kctl, " Capture"); - } else { - len = append_ctl_name(kctl, " Playback"); - } - } - append_ctl_name(kctl, control == UAC_FU_MUTE ? - " Switch" : " Volume"); - if (control == UAC_FU_VOLUME) { - check_mapped_dB(map, cval); - if (cval->dBmin < cval->dBmax || !cval->initialized) { - kctl->tlv.c = mixer_vol_tlv; - kctl->vd[0].access |= - SNDRV_CTL_ELEM_ACCESS_TLV_READ | - SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK; - } - } - break; - - default: - if (! len) - strlcpy(kctl->id.name, audio_feature_info[control-1].name, - sizeof(kctl->id.name)); - break; - } - - range = (cval->max - cval->min) / cval->res; - /* Are there devices with volume range more than 255? I use a bit more - * to be sure. 384 is a resolution magic number found on Logitech - * devices. It will definitively catch all buggy Logitech devices. - */ - if (range > 384) { - snd_printk(KERN_WARNING "usb_audio: Warning! Unlikely big " - "volume range (=%u), cval->res is probably wrong.", - range); - snd_printk(KERN_WARNING "usb_audio: [%d] FU [%s] ch = %d, " - "val = %d/%d/%d", cval->id, - kctl->id.name, cval->channels, - cval->min, cval->max, cval->res); - } - - snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n", - cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res); - snd_usb_mixer_add_control(state->mixer, kctl); -} - - - -/* - * parse a feature unit - * - * most of controls are defined here. - */ -static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void *_ftr) -{ - int channels, i, j; - struct usb_audio_term iterm; - unsigned int master_bits, first_ch_bits; - int err, csize; - struct uac_feature_unit_descriptor *hdr = _ftr; - __u8 *bmaControls; - - if (state->mixer->protocol == UAC_VERSION_1) { - csize = hdr->bControlSize; - if (!csize) { - snd_printdd(KERN_ERR "usbaudio: unit %u: " - "invalid bControlSize == 0\n", unitid); - return -EINVAL; - } - channels = (hdr->bLength - 7) / csize - 1; - bmaControls = hdr->bmaControls; - } else { - struct uac2_feature_unit_descriptor *ftr = _ftr; - csize = 4; - channels = (hdr->bLength - 6) / 4 - 1; - bmaControls = ftr->bmaControls; - } - - if (hdr->bLength < 7 || !csize || hdr->bLength < 7 + csize) { - snd_printk(KERN_ERR "usbaudio: unit %u: invalid UAC_FEATURE_UNIT descriptor\n", unitid); - return -EINVAL; - } - - /* parse the source unit */ - if ((err = parse_audio_unit(state, hdr->bSourceID)) < 0) - return err; - - /* determine the input source type and name */ - if (check_input_term(state, hdr->bSourceID, &iterm) < 0) - return -EINVAL; - - master_bits = snd_usb_combine_bytes(bmaControls, csize); - /* master configuration quirks */ - switch (state->chip->usb_id) { - case USB_ID(0x08bb, 0x2702): - snd_printk(KERN_INFO - "usbmixer: master volume quirk for PCM2702 chip\n"); - /* disable non-functional volume control */ - master_bits &= ~UAC_CONTROL_BIT(UAC_FU_VOLUME); - break; - } - if (channels > 0) - first_ch_bits = snd_usb_combine_bytes(bmaControls + csize, csize); - else - first_ch_bits = 0; - - if (state->mixer->protocol == UAC_VERSION_1) { - /* check all control types */ - for (i = 0; i < 10; i++) { - unsigned int ch_bits = 0; - for (j = 0; j < channels; j++) { - unsigned int mask = snd_usb_combine_bytes(bmaControls + csize * (j+1), csize); - if (mask & (1 << i)) - ch_bits |= (1 << j); - } - /* audio class v1 controls are never read-only */ - if (ch_bits & 1) /* the first channel must be set (for ease of programming) */ - build_feature_ctl(state, _ftr, ch_bits, i, &iterm, unitid, 0); - if (master_bits & (1 << i)) - build_feature_ctl(state, _ftr, 0, i, &iterm, unitid, 0); - } - } else { /* UAC_VERSION_2 */ - for (i = 0; i < ARRAY_SIZE(audio_feature_info); i++) { - unsigned int ch_bits = 0; - unsigned int ch_read_only = 0; - - for (j = 0; j < channels; j++) { - unsigned int mask = snd_usb_combine_bytes(bmaControls + csize * (j+1), csize); - if (uac2_control_is_readable(mask, i)) { - ch_bits |= (1 << j); - if (!uac2_control_is_writeable(mask, i)) - ch_read_only |= (1 << j); - } - } - - /* NOTE: build_feature_ctl() will mark the control read-only if all channels - * are marked read-only in the descriptors. Otherwise, the control will be - * reported as writeable, but the driver will not actually issue a write - * command for read-only channels */ - if (ch_bits & 1) /* the first channel must be set (for ease of programming) */ - build_feature_ctl(state, _ftr, ch_bits, i, &iterm, unitid, ch_read_only); - if (uac2_control_is_readable(master_bits, i)) - build_feature_ctl(state, _ftr, 0, i, &iterm, unitid, - !uac2_control_is_writeable(master_bits, i)); - } - } - - return 0; -} - - -/* - * Mixer Unit - */ - -/* - * build a mixer unit control - * - * the callbacks are identical with feature unit. - * input channel number (zero based) is given in control field instead. - */ - -static void build_mixer_unit_ctl(struct mixer_build *state, - struct uac_mixer_unit_descriptor *desc, - int in_pin, int in_ch, int unitid, - struct usb_audio_term *iterm) -{ - struct usb_mixer_elem_info *cval; - unsigned int num_outs = uac_mixer_unit_bNrChannels(desc); - unsigned int i, len; - struct snd_kcontrol *kctl; - const struct usbmix_name_map *map; - - map = find_map(state, unitid, 0); - if (check_ignored_ctl(map)) - return; - - cval = kzalloc(sizeof(*cval), GFP_KERNEL); - if (! cval) - return; - - cval->mixer = state->mixer; - cval->id = unitid; - cval->control = in_ch + 1; /* based on 1 */ - cval->val_type = USB_MIXER_S16; - for (i = 0; i < num_outs; i++) { - if (check_matrix_bitmap(uac_mixer_unit_bmControls(desc, state->mixer->protocol), in_ch, i, num_outs)) { - cval->cmask |= (1 << i); - cval->channels++; - } - } - - /* get min/max values */ - get_min_max(cval, 0); - - kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval); - if (! kctl) { - snd_printk(KERN_ERR "cannot malloc kcontrol\n"); - kfree(cval); - return; - } - kctl->private_free = usb_mixer_elem_free; - - len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name)); - if (! len) - len = get_term_name(state, iterm, kctl->id.name, sizeof(kctl->id.name), 0); - if (! len) - len = sprintf(kctl->id.name, "Mixer Source %d", in_ch + 1); - append_ctl_name(kctl, " Volume"); - - snd_printdd(KERN_INFO "[%d] MU [%s] ch = %d, val = %d/%d\n", - cval->id, kctl->id.name, cval->channels, cval->min, cval->max); - snd_usb_mixer_add_control(state->mixer, kctl); -} - - -/* - * parse a mixer unit - */ -static int parse_audio_mixer_unit(struct mixer_build *state, int unitid, void *raw_desc) -{ - struct uac_mixer_unit_descriptor *desc = raw_desc; - struct usb_audio_term iterm; - int input_pins, num_ins, num_outs; - int pin, ich, err; - - if (desc->bLength < 11 || ! (input_pins = desc->bNrInPins) || ! (num_outs = uac_mixer_unit_bNrChannels(desc))) { - snd_printk(KERN_ERR "invalid MIXER UNIT descriptor %d\n", unitid); - return -EINVAL; - } - /* no bmControls field (e.g. Maya44) -> ignore */ - if (desc->bLength <= 10 + input_pins) { - snd_printdd(KERN_INFO "MU %d has no bmControls field\n", unitid); - return 0; - } - - num_ins = 0; - ich = 0; - for (pin = 0; pin < input_pins; pin++) { - err = parse_audio_unit(state, desc->baSourceID[pin]); - if (err < 0) - return err; - err = check_input_term(state, desc->baSourceID[pin], &iterm); - if (err < 0) - return err; - num_ins += iterm.channels; - for (; ich < num_ins; ++ich) { - int och, ich_has_controls = 0; - - for (och = 0; och < num_outs; ++och) { - if (check_matrix_bitmap(uac_mixer_unit_bmControls(desc, state->mixer->protocol), - ich, och, num_outs)) { - ich_has_controls = 1; - break; - } - } - if (ich_has_controls) - build_mixer_unit_ctl(state, desc, pin, ich, - unitid, &iterm); - } - } - return 0; -} - - -/* - * Processing Unit / Extension Unit - */ - -/* get callback for processing/extension unit */ -static int mixer_ctl_procunit_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct usb_mixer_elem_info *cval = kcontrol->private_data; - int err, val; - - err = get_cur_ctl_value(cval, cval->control << 8, &val); - if (err < 0 && cval->mixer->ignore_ctl_error) { - ucontrol->value.integer.value[0] = cval->min; - return 0; - } - if (err < 0) - return err; - val = get_relative_value(cval, val); - ucontrol->value.integer.value[0] = val; - return 0; -} - -/* put callback for processing/extension unit */ -static int mixer_ctl_procunit_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct usb_mixer_elem_info *cval = kcontrol->private_data; - int val, oval, err; - - err = get_cur_ctl_value(cval, cval->control << 8, &oval); - if (err < 0) { - if (cval->mixer->ignore_ctl_error) - return 0; - return err; - } - val = ucontrol->value.integer.value[0]; - val = get_abs_value(cval, val); - if (val != oval) { - set_cur_ctl_value(cval, cval->control << 8, val); - return 1; - } - return 0; -} - -/* alsa control interface for processing/extension unit */ -static struct snd_kcontrol_new mixer_procunit_ctl = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "", /* will be filled later */ - .info = mixer_ctl_feature_info, - .get = mixer_ctl_procunit_get, - .put = mixer_ctl_procunit_put, -}; - - -/* - * predefined data for processing units - */ -struct procunit_value_info { - int control; - char *suffix; - int val_type; - int min_value; -}; - -struct procunit_info { - int type; - char *name; - struct procunit_value_info *values; -}; - -static struct procunit_value_info updown_proc_info[] = { - { UAC_UD_ENABLE, "Switch", USB_MIXER_BOOLEAN }, - { UAC_UD_MODE_SELECT, "Mode Select", USB_MIXER_U8, 1 }, - { 0 } -}; -static struct procunit_value_info prologic_proc_info[] = { - { UAC_DP_ENABLE, "Switch", USB_MIXER_BOOLEAN }, - { UAC_DP_MODE_SELECT, "Mode Select", USB_MIXER_U8, 1 }, - { 0 } -}; -static struct procunit_value_info threed_enh_proc_info[] = { - { UAC_3D_ENABLE, "Switch", USB_MIXER_BOOLEAN }, - { UAC_3D_SPACE, "Spaciousness", USB_MIXER_U8 }, - { 0 } -}; -static struct procunit_value_info reverb_proc_info[] = { - { UAC_REVERB_ENABLE, "Switch", USB_MIXER_BOOLEAN }, - { UAC_REVERB_LEVEL, "Level", USB_MIXER_U8 }, - { UAC_REVERB_TIME, "Time", USB_MIXER_U16 }, - { UAC_REVERB_FEEDBACK, "Feedback", USB_MIXER_U8 }, - { 0 } -}; -static struct procunit_value_info chorus_proc_info[] = { - { UAC_CHORUS_ENABLE, "Switch", USB_MIXER_BOOLEAN }, - { UAC_CHORUS_LEVEL, "Level", USB_MIXER_U8 }, - { UAC_CHORUS_RATE, "Rate", USB_MIXER_U16 }, - { UAC_CHORUS_DEPTH, "Depth", USB_MIXER_U16 }, - { 0 } -}; -static struct procunit_value_info dcr_proc_info[] = { - { UAC_DCR_ENABLE, "Switch", USB_MIXER_BOOLEAN }, - { UAC_DCR_RATE, "Ratio", USB_MIXER_U16 }, - { UAC_DCR_MAXAMPL, "Max Amp", USB_MIXER_S16 }, - { UAC_DCR_THRESHOLD, "Threshold", USB_MIXER_S16 }, - { UAC_DCR_ATTACK_TIME, "Attack Time", USB_MIXER_U16 }, - { UAC_DCR_RELEASE_TIME, "Release Time", USB_MIXER_U16 }, - { 0 } -}; - -static struct procunit_info procunits[] = { - { UAC_PROCESS_UP_DOWNMIX, "Up Down", updown_proc_info }, - { UAC_PROCESS_DOLBY_PROLOGIC, "Dolby Prologic", prologic_proc_info }, - { UAC_PROCESS_STEREO_EXTENDER, "3D Stereo Extender", threed_enh_proc_info }, - { UAC_PROCESS_REVERB, "Reverb", reverb_proc_info }, - { UAC_PROCESS_CHORUS, "Chorus", chorus_proc_info }, - { UAC_PROCESS_DYN_RANGE_COMP, "DCR", dcr_proc_info }, - { 0 }, -}; -/* - * predefined data for extension units - */ -static struct procunit_value_info clock_rate_xu_info[] = { - { USB_XU_CLOCK_RATE_SELECTOR, "Selector", USB_MIXER_U8, 0 }, - { 0 } -}; -static struct procunit_value_info clock_source_xu_info[] = { - { USB_XU_CLOCK_SOURCE_SELECTOR, "External", USB_MIXER_BOOLEAN }, - { 0 } -}; -static struct procunit_value_info spdif_format_xu_info[] = { - { USB_XU_DIGITAL_FORMAT_SELECTOR, "SPDIF/AC3", USB_MIXER_BOOLEAN }, - { 0 } -}; -static struct procunit_value_info soft_limit_xu_info[] = { - { USB_XU_SOFT_LIMIT_SELECTOR, " ", USB_MIXER_BOOLEAN }, - { 0 } -}; -static struct procunit_info extunits[] = { - { USB_XU_CLOCK_RATE, "Clock rate", clock_rate_xu_info }, - { USB_XU_CLOCK_SOURCE, "DigitalIn CLK source", clock_source_xu_info }, - { USB_XU_DIGITAL_IO_STATUS, "DigitalOut format:", spdif_format_xu_info }, - { USB_XU_DEVICE_OPTIONS, "AnalogueIn Soft Limit", soft_limit_xu_info }, - { 0 } -}; -/* - * build a processing/extension unit - */ -static int build_audio_procunit(struct mixer_build *state, int unitid, void *raw_desc, struct procunit_info *list, char *name) -{ - struct uac_processing_unit_descriptor *desc = raw_desc; - int num_ins = desc->bNrInPins; - struct usb_mixer_elem_info *cval; - struct snd_kcontrol *kctl; - int i, err, nameid, type, len; - struct procunit_info *info; - struct procunit_value_info *valinfo; - const struct usbmix_name_map *map; - static struct procunit_value_info default_value_info[] = { - { 0x01, "Switch", USB_MIXER_BOOLEAN }, - { 0 } - }; - static struct procunit_info default_info = { - 0, NULL, default_value_info - }; - - if (desc->bLength < 13 || desc->bLength < 13 + num_ins || - desc->bLength < num_ins + uac_processing_unit_bControlSize(desc, state->mixer->protocol)) { - snd_printk(KERN_ERR "invalid %s descriptor (id %d)\n", name, unitid); - return -EINVAL; - } - - for (i = 0; i < num_ins; i++) { - if ((err = parse_audio_unit(state, desc->baSourceID[i])) < 0) - return err; - } - - type = le16_to_cpu(desc->wProcessType); - for (info = list; info && info->type; info++) - if (info->type == type) - break; - if (! info || ! info->type) - info = &default_info; - - for (valinfo = info->values; valinfo->control; valinfo++) { - __u8 *controls = uac_processing_unit_bmControls(desc, state->mixer->protocol); - - if (! (controls[valinfo->control / 8] & (1 << ((valinfo->control % 8) - 1)))) - continue; - map = find_map(state, unitid, valinfo->control); - if (check_ignored_ctl(map)) - continue; - cval = kzalloc(sizeof(*cval), GFP_KERNEL); - if (! cval) { - snd_printk(KERN_ERR "cannot malloc kcontrol\n"); - return -ENOMEM; - } - cval->mixer = state->mixer; - cval->id = unitid; - cval->control = valinfo->control; - cval->val_type = valinfo->val_type; - cval->channels = 1; - - /* get min/max values */ - if (type == UAC_PROCESS_UP_DOWNMIX && cval->control == UAC_UD_MODE_SELECT) { - __u8 *control_spec = uac_processing_unit_specific(desc, state->mixer->protocol); - /* FIXME: hard-coded */ - cval->min = 1; - cval->max = control_spec[0]; - cval->res = 1; - cval->initialized = 1; - } else { - if (type == USB_XU_CLOCK_RATE) { - /* E-Mu USB 0404/0202/TrackerPre/0204 - * samplerate control quirk - */ - cval->min = 0; - cval->max = 5; - cval->res = 1; - cval->initialized = 1; - } else - get_min_max(cval, valinfo->min_value); - } - - kctl = snd_ctl_new1(&mixer_procunit_ctl, cval); - if (! kctl) { - snd_printk(KERN_ERR "cannot malloc kcontrol\n"); - kfree(cval); - return -ENOMEM; - } - kctl->private_free = usb_mixer_elem_free; - - if (check_mapped_name(map, kctl->id.name, - sizeof(kctl->id.name))) - /* nothing */ ; - else if (info->name) - strlcpy(kctl->id.name, info->name, sizeof(kctl->id.name)); - else { - nameid = uac_processing_unit_iProcessing(desc, state->mixer->protocol); - len = 0; - if (nameid) - len = snd_usb_copy_string_desc(state, nameid, kctl->id.name, sizeof(kctl->id.name)); - if (! len) - strlcpy(kctl->id.name, name, sizeof(kctl->id.name)); - } - append_ctl_name(kctl, " "); - append_ctl_name(kctl, valinfo->suffix); - - snd_printdd(KERN_INFO "[%d] PU [%s] ch = %d, val = %d/%d\n", - cval->id, kctl->id.name, cval->channels, cval->min, cval->max); - if ((err = snd_usb_mixer_add_control(state->mixer, kctl)) < 0) - return err; - } - return 0; -} - - -static int parse_audio_processing_unit(struct mixer_build *state, int unitid, void *raw_desc) -{ - return build_audio_procunit(state, unitid, raw_desc, procunits, "Processing Unit"); -} - -static int parse_audio_extension_unit(struct mixer_build *state, int unitid, void *raw_desc) -{ - /* Note that we parse extension units with processing unit descriptors. - * That's ok as the layout is the same */ - return build_audio_procunit(state, unitid, raw_desc, extunits, "Extension Unit"); -} - - -/* - * Selector Unit - */ - -/* info callback for selector unit - * use an enumerator type for routing - */ -static int mixer_ctl_selector_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - struct usb_mixer_elem_info *cval = kcontrol->private_data; - const char **itemlist = (const char **)kcontrol->private_value; - - if (snd_BUG_ON(!itemlist)) - return -EINVAL; - return snd_ctl_enum_info(uinfo, 1, cval->max, itemlist); -} - -/* get callback for selector unit */ -static int mixer_ctl_selector_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct usb_mixer_elem_info *cval = kcontrol->private_data; - int val, err; - - err = get_cur_ctl_value(cval, cval->control << 8, &val); - if (err < 0) { - if (cval->mixer->ignore_ctl_error) { - ucontrol->value.enumerated.item[0] = 0; - return 0; - } - return err; - } - val = get_relative_value(cval, val); - ucontrol->value.enumerated.item[0] = val; - return 0; -} - -/* put callback for selector unit */ -static int mixer_ctl_selector_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct usb_mixer_elem_info *cval = kcontrol->private_data; - int val, oval, err; - - err = get_cur_ctl_value(cval, cval->control << 8, &oval); - if (err < 0) { - if (cval->mixer->ignore_ctl_error) - return 0; - return err; - } - val = ucontrol->value.enumerated.item[0]; - val = get_abs_value(cval, val); - if (val != oval) { - set_cur_ctl_value(cval, cval->control << 8, val); - return 1; - } - return 0; -} - -/* alsa control interface for selector unit */ -static struct snd_kcontrol_new mixer_selectunit_ctl = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "", /* will be filled later */ - .info = mixer_ctl_selector_info, - .get = mixer_ctl_selector_get, - .put = mixer_ctl_selector_put, -}; - - -/* private free callback. - * free both private_data and private_value - */ -static void usb_mixer_selector_elem_free(struct snd_kcontrol *kctl) -{ - int i, num_ins = 0; - - if (kctl->private_data) { - struct usb_mixer_elem_info *cval = kctl->private_data; - num_ins = cval->max; - kfree(cval); - kctl->private_data = NULL; - } - if (kctl->private_value) { - char **itemlist = (char **)kctl->private_value; - for (i = 0; i < num_ins; i++) - kfree(itemlist[i]); - kfree(itemlist); - kctl->private_value = 0; - } -} - -/* - * parse a selector unit - */ -static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void *raw_desc) -{ - struct uac_selector_unit_descriptor *desc = raw_desc; - unsigned int i, nameid, len; - int err; - struct usb_mixer_elem_info *cval; - struct snd_kcontrol *kctl; - const struct usbmix_name_map *map; - char **namelist; - - if (!desc->bNrInPins || desc->bLength < 5 + desc->bNrInPins) { - snd_printk(KERN_ERR "invalid SELECTOR UNIT descriptor %d\n", unitid); - return -EINVAL; - } - - for (i = 0; i < desc->bNrInPins; i++) { - if ((err = parse_audio_unit(state, desc->baSourceID[i])) < 0) - return err; - } - - if (desc->bNrInPins == 1) /* only one ? nonsense! */ - return 0; - - map = find_map(state, unitid, 0); - if (check_ignored_ctl(map)) - return 0; - - cval = kzalloc(sizeof(*cval), GFP_KERNEL); - if (! cval) { - snd_printk(KERN_ERR "cannot malloc kcontrol\n"); - return -ENOMEM; - } - cval->mixer = state->mixer; - cval->id = unitid; - cval->val_type = USB_MIXER_U8; - cval->channels = 1; - cval->min = 1; - cval->max = desc->bNrInPins; - cval->res = 1; - cval->initialized = 1; - - if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR) - cval->control = UAC2_CX_CLOCK_SELECTOR; - else - cval->control = 0; - - namelist = kmalloc(sizeof(char *) * desc->bNrInPins, GFP_KERNEL); - if (! namelist) { - snd_printk(KERN_ERR "cannot malloc\n"); - kfree(cval); - return -ENOMEM; - } -#define MAX_ITEM_NAME_LEN 64 - for (i = 0; i < desc->bNrInPins; i++) { - struct usb_audio_term iterm; - len = 0; - namelist[i] = kmalloc(MAX_ITEM_NAME_LEN, GFP_KERNEL); - if (! namelist[i]) { - snd_printk(KERN_ERR "cannot malloc\n"); - while (i--) - kfree(namelist[i]); - kfree(namelist); - kfree(cval); - return -ENOMEM; - } - len = check_mapped_selector_name(state, unitid, i, namelist[i], - MAX_ITEM_NAME_LEN); - if (! len && check_input_term(state, desc->baSourceID[i], &iterm) >= 0) - len = get_term_name(state, &iterm, namelist[i], MAX_ITEM_NAME_LEN, 0); - if (! len) - sprintf(namelist[i], "Input %d", i); - } - - kctl = snd_ctl_new1(&mixer_selectunit_ctl, cval); - if (! kctl) { - snd_printk(KERN_ERR "cannot malloc kcontrol\n"); - kfree(namelist); - kfree(cval); - return -ENOMEM; - } - kctl->private_value = (unsigned long)namelist; - kctl->private_free = usb_mixer_selector_elem_free; - - nameid = uac_selector_unit_iSelector(desc); - len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name)); - if (len) - ; - else if (nameid) - snd_usb_copy_string_desc(state, nameid, kctl->id.name, sizeof(kctl->id.name)); - else { - len = get_term_name(state, &state->oterm, - kctl->id.name, sizeof(kctl->id.name), 0); - if (! len) - strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name)); - - if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR) - append_ctl_name(kctl, " Clock Source"); - else if ((state->oterm.type & 0xff00) == 0x0100) - append_ctl_name(kctl, " Capture Source"); - else - append_ctl_name(kctl, " Playback Source"); - } - - snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n", - cval->id, kctl->id.name, desc->bNrInPins); - if ((err = snd_usb_mixer_add_control(state->mixer, kctl)) < 0) - return err; - - return 0; -} - - -/* - * parse an audio unit recursively - */ - -static int parse_audio_unit(struct mixer_build *state, int unitid) -{ - unsigned char *p1; - - if (test_and_set_bit(unitid, state->unitbitmap)) - return 0; /* the unit already visited */ - - p1 = find_audio_control_unit(state, unitid); - if (!p1) { - snd_printk(KERN_ERR "usbaudio: unit %d not found!\n", unitid); - return -EINVAL; - } - - switch (p1[2]) { - case UAC_INPUT_TERMINAL: - case UAC2_CLOCK_SOURCE: - return 0; /* NOP */ - case UAC_MIXER_UNIT: - return parse_audio_mixer_unit(state, unitid, p1); - case UAC_SELECTOR_UNIT: - case UAC2_CLOCK_SELECTOR: - return parse_audio_selector_unit(state, unitid, p1); - case UAC_FEATURE_UNIT: - return parse_audio_feature_unit(state, unitid, p1); - case UAC1_PROCESSING_UNIT: - /* UAC2_EFFECT_UNIT has the same value */ - if (state->mixer->protocol == UAC_VERSION_1) - return parse_audio_processing_unit(state, unitid, p1); - else - return 0; /* FIXME - effect units not implemented yet */ - case UAC1_EXTENSION_UNIT: - /* UAC2_PROCESSING_UNIT_V2 has the same value */ - if (state->mixer->protocol == UAC_VERSION_1) - return parse_audio_extension_unit(state, unitid, p1); - else /* UAC_VERSION_2 */ - return parse_audio_processing_unit(state, unitid, p1); - default: - snd_printk(KERN_ERR "usbaudio: unit %u: unexpected type 0x%02x\n", unitid, p1[2]); - return -EINVAL; - } -} - -static void snd_usb_mixer_free(struct usb_mixer_interface *mixer) -{ - kfree(mixer->id_elems); - if (mixer->urb) { - kfree(mixer->urb->transfer_buffer); - usb_free_urb(mixer->urb); - } - usb_free_urb(mixer->rc_urb); - kfree(mixer->rc_setup_packet); - kfree(mixer); -} - -static int snd_usb_mixer_dev_free(struct snd_device *device) -{ - struct usb_mixer_interface *mixer = device->device_data; - snd_usb_mixer_free(mixer); - return 0; -} - -/* - * create mixer controls - * - * walk through all UAC_OUTPUT_TERMINAL descriptors to search for mixers - */ -static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) -{ - struct mixer_build state; - int err; - const struct usbmix_ctl_map *map; - void *p; - - memset(&state, 0, sizeof(state)); - state.chip = mixer->chip; - state.mixer = mixer; - state.buffer = mixer->hostif->extra; - state.buflen = mixer->hostif->extralen; - - /* check the mapping table */ - for (map = usbmix_ctl_maps; map->id; map++) { - if (map->id == state.chip->usb_id) { - state.map = map->map; - state.selector_map = map->selector_map; - mixer->ignore_ctl_error = map->ignore_ctl_error; - break; - } - } - - p = NULL; - while ((p = snd_usb_find_csint_desc(mixer->hostif->extra, mixer->hostif->extralen, - p, UAC_OUTPUT_TERMINAL)) != NULL) { - if (mixer->protocol == UAC_VERSION_1) { - struct uac1_output_terminal_descriptor *desc = p; - - if (desc->bLength < sizeof(*desc)) - continue; /* invalid descriptor? */ - set_bit(desc->bTerminalID, state.unitbitmap); /* mark terminal ID as visited */ - state.oterm.id = desc->bTerminalID; - state.oterm.type = le16_to_cpu(desc->wTerminalType); - state.oterm.name = desc->iTerminal; - err = parse_audio_unit(&state, desc->bSourceID); - if (err < 0) - return err; - } else { /* UAC_VERSION_2 */ - struct uac2_output_terminal_descriptor *desc = p; - - if (desc->bLength < sizeof(*desc)) - continue; /* invalid descriptor? */ - set_bit(desc->bTerminalID, state.unitbitmap); /* mark terminal ID as visited */ - state.oterm.id = desc->bTerminalID; - state.oterm.type = le16_to_cpu(desc->wTerminalType); - state.oterm.name = desc->iTerminal; - err = parse_audio_unit(&state, desc->bSourceID); - if (err < 0) - return err; - - /* for UAC2, use the same approach to also add the clock selectors */ - err = parse_audio_unit(&state, desc->bCSourceID); - if (err < 0) - return err; - } - } - - return 0; -} - -void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid) -{ - struct usb_mixer_elem_info *info; - - for (info = mixer->id_elems[unitid]; info; info = info->next_id_elem) - snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - info->elem_id); -} - -static void snd_usb_mixer_dump_cval(struct snd_info_buffer *buffer, - int unitid, - struct usb_mixer_elem_info *cval) -{ - static char *val_types[] = {"BOOLEAN", "INV_BOOLEAN", - "S8", "U8", "S16", "U16"}; - snd_iprintf(buffer, " Unit: %i\n", unitid); - if (cval->elem_id) - snd_iprintf(buffer, " Control: name=\"%s\", index=%i\n", - cval->elem_id->name, cval->elem_id->index); - snd_iprintf(buffer, " Info: id=%i, control=%i, cmask=0x%x, " - "channels=%i, type=\"%s\"\n", cval->id, - cval->control, cval->cmask, cval->channels, - val_types[cval->val_type]); - snd_iprintf(buffer, " Volume: min=%i, max=%i, dBmin=%i, dBmax=%i\n", - cval->min, cval->max, cval->dBmin, cval->dBmax); -} - -static void snd_usb_mixer_proc_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_usb_audio *chip = entry->private_data; - struct usb_mixer_interface *mixer; - struct usb_mixer_elem_info *cval; - int unitid; - - list_for_each_entry(mixer, &chip->mixer_list, list) { - snd_iprintf(buffer, - "USB Mixer: usb_id=0x%08x, ctrlif=%i, ctlerr=%i\n", - chip->usb_id, snd_usb_ctrl_intf(chip), - mixer->ignore_ctl_error); - snd_iprintf(buffer, "Card: %s\n", chip->card->longname); - for (unitid = 0; unitid < MAX_ID_ELEMS; unitid++) { - for (cval = mixer->id_elems[unitid]; cval; - cval = cval->next_id_elem) - snd_usb_mixer_dump_cval(buffer, unitid, cval); - } - } -} - -static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer, - int attribute, int value, int index) -{ - struct usb_mixer_elem_info *info; - __u8 unitid = (index >> 8) & 0xff; - __u8 control = (value >> 8) & 0xff; - __u8 channel = value & 0xff; - - if (channel >= MAX_CHANNELS) { - snd_printk(KERN_DEBUG "%s(): bogus channel number %d\n", - __func__, channel); - return; - } - - for (info = mixer->id_elems[unitid]; info; info = info->next_id_elem) { - if (info->control != control) - continue; - - switch (attribute) { - case UAC2_CS_CUR: - /* invalidate cache, so the value is read from the device */ - if (channel) - info->cached &= ~(1 << channel); - else /* master channel */ - info->cached = 0; - - snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - info->elem_id); - break; - - case UAC2_CS_RANGE: - /* TODO */ - break; - - case UAC2_CS_MEM: - /* TODO */ - break; - - default: - snd_printk(KERN_DEBUG "unknown attribute %d in interrupt\n", - attribute); - break; - } /* switch */ - } -} - -static void snd_usb_mixer_interrupt(struct urb *urb) -{ - struct usb_mixer_interface *mixer = urb->context; - int len = urb->actual_length; - int ustatus = urb->status; - - if (ustatus != 0) - goto requeue; - - if (mixer->protocol == UAC_VERSION_1) { - struct uac1_status_word *status; - - for (status = urb->transfer_buffer; - len >= sizeof(*status); - len -= sizeof(*status), status++) { - snd_printd(KERN_DEBUG "status interrupt: %02x %02x\n", - status->bStatusType, - status->bOriginator); - - /* ignore any notifications not from the control interface */ - if ((status->bStatusType & UAC1_STATUS_TYPE_ORIG_MASK) != - UAC1_STATUS_TYPE_ORIG_AUDIO_CONTROL_IF) - continue; - - if (status->bStatusType & UAC1_STATUS_TYPE_MEM_CHANGED) - snd_usb_mixer_rc_memory_change(mixer, status->bOriginator); - else - snd_usb_mixer_notify_id(mixer, status->bOriginator); - } - } else { /* UAC_VERSION_2 */ - struct uac2_interrupt_data_msg *msg; - - for (msg = urb->transfer_buffer; - len >= sizeof(*msg); - len -= sizeof(*msg), msg++) { - /* drop vendor specific and endpoint requests */ - if ((msg->bInfo & UAC2_INTERRUPT_DATA_MSG_VENDOR) || - (msg->bInfo & UAC2_INTERRUPT_DATA_MSG_EP)) - continue; - - snd_usb_mixer_interrupt_v2(mixer, msg->bAttribute, - le16_to_cpu(msg->wValue), - le16_to_cpu(msg->wIndex)); - } - } - -requeue: - if (ustatus != -ENOENT && ustatus != -ECONNRESET && ustatus != -ESHUTDOWN) { - urb->dev = mixer->chip->dev; - usb_submit_urb(urb, GFP_ATOMIC); - } -} - -/* stop any bus activity of a mixer */ -void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer) -{ - usb_kill_urb(mixer->urb); - usb_kill_urb(mixer->rc_urb); -} - -int snd_usb_mixer_activate(struct usb_mixer_interface *mixer) -{ - int err; - - if (mixer->urb) { - err = usb_submit_urb(mixer->urb, GFP_NOIO); - if (err < 0) - return err; - } - - return 0; -} - -/* create the handler for the optional status interrupt endpoint */ -static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer) -{ - struct usb_endpoint_descriptor *ep; - void *transfer_buffer; - int buffer_length; - unsigned int epnum; - - /* we need one interrupt input endpoint */ - if (get_iface_desc(mixer->hostif)->bNumEndpoints < 1) - return 0; - ep = get_endpoint(mixer->hostif, 0); - if (!usb_endpoint_dir_in(ep) || !usb_endpoint_xfer_int(ep)) - return 0; - - epnum = usb_endpoint_num(ep); - buffer_length = le16_to_cpu(ep->wMaxPacketSize); - transfer_buffer = kmalloc(buffer_length, GFP_KERNEL); - if (!transfer_buffer) - return -ENOMEM; - mixer->urb = usb_alloc_urb(0, GFP_KERNEL); - if (!mixer->urb) { - kfree(transfer_buffer); - return -ENOMEM; - } - usb_fill_int_urb(mixer->urb, mixer->chip->dev, - usb_rcvintpipe(mixer->chip->dev, epnum), - transfer_buffer, buffer_length, - snd_usb_mixer_interrupt, mixer, ep->bInterval); - usb_submit_urb(mixer->urb, GFP_KERNEL); - return 0; -} - -int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, - int ignore_error) -{ - static struct snd_device_ops dev_ops = { - .dev_free = snd_usb_mixer_dev_free - }; - struct usb_mixer_interface *mixer; - struct snd_info_entry *entry; - int err; - - strcpy(chip->card->mixername, "USB Mixer"); - - mixer = kzalloc(sizeof(*mixer), GFP_KERNEL); - if (!mixer) - return -ENOMEM; - mixer->chip = chip; - mixer->ignore_ctl_error = ignore_error; - mixer->id_elems = kcalloc(MAX_ID_ELEMS, sizeof(*mixer->id_elems), - GFP_KERNEL); - if (!mixer->id_elems) { - kfree(mixer); - return -ENOMEM; - } - - mixer->hostif = &usb_ifnum_to_if(chip->dev, ctrlif)->altsetting[0]; - switch (get_iface_desc(mixer->hostif)->bInterfaceProtocol) { - case UAC_VERSION_1: - default: - mixer->protocol = UAC_VERSION_1; - break; - case UAC_VERSION_2: - mixer->protocol = UAC_VERSION_2; - break; - } - - if ((err = snd_usb_mixer_controls(mixer)) < 0 || - (err = snd_usb_mixer_status_create(mixer)) < 0) - goto _error; - - snd_usb_mixer_apply_create_quirk(mixer); - - err = snd_device_new(chip->card, SNDRV_DEV_LOWLEVEL, mixer, &dev_ops); - if (err < 0) - goto _error; - - if (list_empty(&chip->mixer_list) && - !snd_card_proc_new(chip->card, "usbmixer", &entry)) - snd_info_set_text_ops(entry, chip, snd_usb_mixer_proc_read); - - list_add(&mixer->list, &chip->mixer_list); - return 0; - -_error: - snd_usb_mixer_free(mixer); - return err; -} - -void snd_usb_mixer_disconnect(struct list_head *p) -{ - struct usb_mixer_interface *mixer; - - mixer = list_entry(p, struct usb_mixer_interface, list); - usb_kill_urb(mixer->urb); - usb_kill_urb(mixer->rc_urb); -} diff --git a/ANDROID_3.4.5/sound/usb/mixer.h b/ANDROID_3.4.5/sound/usb/mixer.h deleted file mode 100644 index 81b2d8a3..00000000 --- a/ANDROID_3.4.5/sound/usb/mixer.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef __USBMIXER_H -#define __USBMIXER_H - -struct usb_mixer_interface { - struct snd_usb_audio *chip; - struct usb_host_interface *hostif; - struct list_head list; - unsigned int ignore_ctl_error; - struct urb *urb; - /* array[MAX_ID_ELEMS], indexed by unit id */ - struct usb_mixer_elem_info **id_elems; - - /* the usb audio specification version this interface complies to */ - int protocol; - - /* Sound Blaster remote control stuff */ - const struct rc_config *rc_cfg; - u32 rc_code; - wait_queue_head_t rc_waitq; - struct urb *rc_urb; - struct usb_ctrlrequest *rc_setup_packet; - u8 rc_buffer[6]; - - u8 audigy2nx_leds[3]; - u8 xonar_u1_status; -}; - -#define MAX_CHANNELS 16 /* max logical channels */ - -enum { - USB_MIXER_BOOLEAN, - USB_MIXER_INV_BOOLEAN, - USB_MIXER_S8, - USB_MIXER_U8, - USB_MIXER_S16, - USB_MIXER_U16, -}; - -struct usb_mixer_elem_info { - struct usb_mixer_interface *mixer; - struct usb_mixer_elem_info *next_id_elem; /* list of controls with same id */ - struct snd_ctl_elem_id *elem_id; - unsigned int id; - unsigned int control; /* CS or ICN (high byte) */ - unsigned int cmask; /* channel mask bitmap: 0 = master */ - unsigned int ch_readonly; - unsigned int master_readonly; - int channels; - int val_type; - int min, max, res; - int dBmin, dBmax; - int cached; - int cache_val[MAX_CHANNELS]; - u8 initialized; -}; - -int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, - int ignore_error); -void snd_usb_mixer_disconnect(struct list_head *p); - -void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid); - -int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, - int request, int validx, int value_set); -void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer); -int snd_usb_mixer_activate(struct usb_mixer_interface *mixer); - -int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer, - struct snd_kcontrol *kctl); - -#endif /* __USBMIXER_H */ diff --git a/ANDROID_3.4.5/sound/usb/mixer_maps.c b/ANDROID_3.4.5/sound/usb/mixer_maps.c deleted file mode 100644 index f1324c42..00000000 --- a/ANDROID_3.4.5/sound/usb/mixer_maps.c +++ /dev/null @@ -1,376 +0,0 @@ -/* - * Additional mixer mapping - * - * Copyright (c) 2002 by Takashi Iwai - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -struct usbmix_dB_map { - u32 min; - u32 max; -}; - -struct usbmix_name_map { - int id; - const char *name; - int control; - struct usbmix_dB_map *dB; -}; - -struct usbmix_selector_map { - int id; - int count; - const char **names; -}; - -struct usbmix_ctl_map { - u32 id; - const struct usbmix_name_map *map; - const struct usbmix_selector_map *selector_map; - int ignore_ctl_error; -}; - -/* - * USB control mappers for SB Exitigy - */ - -/* - * Topology of SB Extigy (see on the wide screen :) - -USB_IN[1] --->FU[2]------------------------------+->MU[16]-->PU[17]-+->FU[18]--+->EU[27]--+->EU[21]-->FU[22]--+->FU[23] > Dig_OUT[24] - ^ | | | | -USB_IN[3] -+->SU[5]-->FU[6]--+->MU[14] ->PU[15]->+ | | | +->FU[25] > Dig_OUT[26] - ^ ^ | | | | -Dig_IN[4] -+ | | | | +->FU[28]---------------------> Spk_OUT[19] - | | | | -Lin-IN[7] -+-->FU[8]---------+ | | +----------------------------------------> Hph_OUT[20] - | | | -Mic-IN[9] --+->FU[10]----------------------------+ | - || | - || +----------------------------------------------------+ - VV V - ++--+->SU[11]-->FU[12] --------------------------------------------------------------------------------------> USB_OUT[13] -*/ - -static struct usbmix_name_map extigy_map[] = { - /* 1: IT pcm */ - { 2, "PCM Playback" }, /* FU */ - /* 3: IT pcm */ - /* 4: IT digital in */ - { 5, NULL }, /* DISABLED: this seems to be bogus on some firmware */ - { 6, "Digital In" }, /* FU */ - /* 7: IT line */ - { 8, "Line Playback" }, /* FU */ - /* 9: IT mic */ - { 10, "Mic Playback" }, /* FU */ - { 11, "Capture Source" }, /* SU */ - { 12, "Capture" }, /* FU */ - /* 13: OT pcm capture */ - /* 14: MU (w/o controls) */ - /* 15: PU (3D enh) */ - /* 16: MU (w/o controls) */ - { 17, NULL, 1 }, /* DISABLED: PU-switch (any effect?) */ - { 17, "Channel Routing", 2 }, /* PU: mode select */ - { 18, "Tone Control - Bass", UAC_FU_BASS }, /* FU */ - { 18, "Tone Control - Treble", UAC_FU_TREBLE }, /* FU */ - { 18, "Master Playback" }, /* FU; others */ - /* 19: OT speaker */ - /* 20: OT headphone */ - { 21, NULL }, /* DISABLED: EU (for what?) */ - { 22, "Digital Out Playback" }, /* FU */ - { 23, "Digital Out1 Playback" }, /* FU */ /* FIXME: corresponds to 24 */ - /* 24: OT digital out */ - { 25, "IEC958 Optical Playback" }, /* FU */ - { 26, "IEC958 Optical Playback" }, /* OT */ - { 27, NULL }, /* DISABLED: EU (for what?) */ - /* 28: FU speaker (mute) */ - { 29, NULL }, /* Digital Input Playback Source? */ - { 0 } /* terminator */ -}; - -/* Sound Blaster MP3+ controls mapping - * The default mixer channels have totally misleading names, - * e.g. no Master and fake PCM volume - * Pavel Mihaylov - */ -static struct usbmix_dB_map mp3plus_dB_1 = {-4781, 0}; /* just guess */ -static struct usbmix_dB_map mp3plus_dB_2 = {-1781, 618}; /* just guess */ - -static struct usbmix_name_map mp3plus_map[] = { - /* 1: IT pcm */ - /* 2: IT mic */ - /* 3: IT line */ - /* 4: IT digital in */ - /* 5: OT digital out */ - /* 6: OT speaker */ - /* 7: OT pcm capture */ - { 8, "Capture Source" }, /* FU, default PCM Capture Source */ - /* (Mic, Input 1 = Line input, Input 2 = Optical input) */ - { 9, "Master Playback" }, /* FU, default Speaker 1 */ - /* { 10, "Mic Capture", 1 }, */ /* FU, Mic Capture */ - { 10, /* "Mic Capture", */ NULL, 2, .dB = &mp3plus_dB_2 }, - /* FU, Mic Capture */ - { 10, "Mic Boost", 7 }, /* FU, default Auto Gain Input */ - { 11, "Line Capture", .dB = &mp3plus_dB_2 }, - /* FU, default PCM Capture */ - { 12, "Digital In Playback" }, /* FU, default PCM 1 */ - { 13, /* "Mic Playback", */ .dB = &mp3plus_dB_1 }, - /* FU, default Mic Playback */ - { 14, "Line Playback", .dB = &mp3plus_dB_1 }, /* FU, default Speaker */ - /* 15: MU */ - { 0 } /* terminator */ -}; - -/* Topology of SB Audigy 2 NX - - +----------------------------->EU[27]--+ - | v - | +----------------------------------->SU[29]---->FU[22]-->Dig_OUT[24] - | | ^ -USB_IN[1]-+------------+ +->EU[17]->+->FU[11]-+ - | v | v | -Dig_IN[4]---+->FU[6]-->MU[16]->FU[18]-+->EU[21]->SU[31]----->FU[30]->Hph_OUT[20] - | ^ | | -Lin_IN[7]-+--->FU[8]---+ +->EU[23]->FU[28]------------->Spk_OUT[19] - | | v - +--->FU[12]------------------------------------->SU[14]--->USB_OUT[15] - | ^ - +->FU[13]--------------------------------------+ -*/ -static struct usbmix_name_map audigy2nx_map[] = { - /* 1: IT pcm playback */ - /* 4: IT digital in */ - { 6, "Digital In Playback" }, /* FU */ - /* 7: IT line in */ - { 8, "Line Playback" }, /* FU */ - { 11, "What-U-Hear Capture" }, /* FU */ - { 12, "Line Capture" }, /* FU */ - { 13, "Digital In Capture" }, /* FU */ - { 14, "Capture Source" }, /* SU */ - /* 15: OT pcm capture */ - /* 16: MU w/o controls */ - { 17, NULL }, /* DISABLED: EU (for what?) */ - { 18, "Master Playback" }, /* FU */ - /* 19: OT speaker */ - /* 20: OT headphone */ - { 21, NULL }, /* DISABLED: EU (for what?) */ - { 22, "Digital Out Playback" }, /* FU */ - { 23, NULL }, /* DISABLED: EU (for what?) */ - /* 24: OT digital out */ - { 27, NULL }, /* DISABLED: EU (for what?) */ - { 28, "Speaker Playback" }, /* FU */ - { 29, "Digital Out Source" }, /* SU */ - { 30, "Headphone Playback" }, /* FU */ - { 31, "Headphone Source" }, /* SU */ - { 0 } /* terminator */ -}; - -static struct usbmix_selector_map audigy2nx_selectors[] = { - { - .id = 14, /* Capture Source */ - .count = 3, - .names = (const char*[]) {"Line", "Digital In", "What-U-Hear"} - }, - { - .id = 29, /* Digital Out Source */ - .count = 3, - .names = (const char*[]) {"Front", "PCM", "Digital In"} - }, - { - .id = 31, /* Headphone Source */ - .count = 2, - .names = (const char*[]) {"Front", "Side"} - }, - { 0 } /* terminator */ -}; - -/* Creative SoundBlaster Live! 24-bit External */ -static struct usbmix_name_map live24ext_map[] = { - /* 2: PCM Playback Volume */ - { 5, "Mic Capture" }, /* FU, default PCM Capture Volume */ - { 0 } /* terminator */ -}; - -/* LineX FM Transmitter entry - needed to bypass controls bug */ -static struct usbmix_name_map linex_map[] = { - /* 1: IT pcm */ - /* 2: OT Speaker */ - { 3, "Master" }, /* FU: master volume - left / right / mute */ - { 0 } /* terminator */ -}; - -static struct usbmix_name_map maya44_map[] = { - /* 1: IT line */ - { 2, "Line Playback" }, /* FU */ - /* 3: IT line */ - { 4, "Line Playback" }, /* FU */ - /* 5: IT pcm playback */ - /* 6: MU */ - { 7, "Master Playback" }, /* FU */ - /* 8: OT speaker */ - /* 9: IT line */ - { 10, "Line Capture" }, /* FU */ - /* 11: MU */ - /* 12: OT pcm capture */ - { } -}; - -/* Section "justlink_map" below added by James Courtier-Dutton - * sourced from Maplin Electronics (http://www.maplin.co.uk), part number A56AK - * Part has 2 connectors that act as a single output. (TOSLINK Optical for digital out, and 3.5mm Jack for Analogue out.) - * The USB Mixer publishes a Microphone and extra Volume controls for it, but none exist on the device, - * so this map removes all unwanted sliders from alsamixer - */ - -static struct usbmix_name_map justlink_map[] = { - /* 1: IT pcm playback */ - /* 2: Not present */ - { 3, NULL}, /* IT mic (No mic input on device) */ - /* 4: Not present */ - /* 5: OT speacker */ - /* 6: OT pcm capture */ - { 7, "Master Playback" }, /* Mute/volume for speaker */ - { 8, NULL }, /* Capture Switch (No capture inputs on device) */ - { 9, NULL }, /* Capture Mute/volume (No capture inputs on device */ - /* 0xa: Not present */ - /* 0xb: MU (w/o controls) */ - { 0xc, NULL }, /* Mic feedback Mute/volume (No capture inputs on device) */ - { 0 } /* terminator */ -}; - -/* TerraTec Aureon 5.1 MkII USB */ -static struct usbmix_name_map aureon_51_2_map[] = { - /* 1: IT USB */ - /* 2: IT Mic */ - /* 3: IT Line */ - /* 4: IT SPDIF */ - /* 5: OT SPDIF */ - /* 6: OT Speaker */ - /* 7: OT USB */ - { 8, "Capture Source" }, /* SU */ - { 9, "Master Playback" }, /* FU */ - { 10, "Mic Capture" }, /* FU */ - { 11, "Line Capture" }, /* FU */ - { 12, "IEC958 In Capture" }, /* FU */ - { 13, "Mic Playback" }, /* FU */ - { 14, "Line Playback" }, /* FU */ - /* 15: MU */ - {} /* terminator */ -}; - -static struct usbmix_name_map scratch_live_map[] = { - /* 1: IT Line 1 (USB streaming) */ - /* 2: OT Line 1 (Speaker) */ - /* 3: IT Line 1 (Line connector) */ - { 4, "Line 1 In" }, /* FU */ - /* 5: OT Line 1 (USB streaming) */ - /* 6: IT Line 2 (USB streaming) */ - /* 7: OT Line 2 (Speaker) */ - /* 8: IT Line 2 (Line connector) */ - { 9, "Line 2 In" }, /* FU */ - /* 10: OT Line 2 (USB streaming) */ - /* 11: IT Mic (Line connector) */ - /* 12: OT Mic (USB streaming) */ - { 0 } /* terminator */ -}; - -/* "Gamesurround Muse Pocket LT" looks same like "Sound Blaster MP3+" - * most importand difference is SU[8], it should be set to "Capture Source" - * to make alsamixer and PA working properly. - * FIXME: or mp3plus_map should use "Capture Source" too, - * so this maps can be merget - */ -static struct usbmix_name_map hercules_usb51_map[] = { - { 8, "Capture Source" }, /* SU, default "PCM Capture Source" */ - { 9, "Master Playback" }, /* FU, default "Speaker Playback" */ - { 10, "Mic Boost", 7 }, /* FU, default "Auto Gain Input" */ - { 11, "Line Capture" }, /* FU, default "PCM Capture" */ - { 13, "Mic Bypass Playback" }, /* FU, default "Mic Playback" */ - { 14, "Line Bypass Playback" }, /* FU, default "Line Playback" */ - { 0 } /* terminator */ -}; - -/* - * Control map entries - */ - -static struct usbmix_ctl_map usbmix_ctl_maps[] = { - { - .id = USB_ID(0x041e, 0x3000), - .map = extigy_map, - .ignore_ctl_error = 1, - }, - { - .id = USB_ID(0x041e, 0x3010), - .map = mp3plus_map, - }, - { - .id = USB_ID(0x041e, 0x3020), - .map = audigy2nx_map, - .selector_map = audigy2nx_selectors, - }, - { - .id = USB_ID(0x041e, 0x3040), - .map = live24ext_map, - }, - { - .id = USB_ID(0x041e, 0x3048), - .map = audigy2nx_map, - .selector_map = audigy2nx_selectors, - }, - { - /* Hercules DJ Console (Windows Edition) */ - .id = USB_ID(0x06f8, 0xb000), - .ignore_ctl_error = 1, - }, - { - /* Hercules DJ Console (Macintosh Edition) */ - .id = USB_ID(0x06f8, 0xd002), - .ignore_ctl_error = 1, - }, - { - /* Hercules Gamesurround Muse Pocket LT - * (USB 5.1 Channel Audio Adapter) - */ - .id = USB_ID(0x06f8, 0xc000), - .map = hercules_usb51_map, - }, - { - .id = USB_ID(0x08bb, 0x2702), - .map = linex_map, - .ignore_ctl_error = 1, - }, - { - .id = USB_ID(0x0a92, 0x0091), - .map = maya44_map, - }, - { - .id = USB_ID(0x0c45, 0x1158), - .map = justlink_map, - }, - { - .id = USB_ID(0x0ccd, 0x0028), - .map = aureon_51_2_map, - }, - { - .id = USB_ID(0x13e5, 0x0001), - .map = scratch_live_map, - .ignore_ctl_error = 1, - }, - { 0 } /* terminator */ -}; - diff --git a/ANDROID_3.4.5/sound/usb/mixer_quirks.c b/ANDROID_3.4.5/sound/usb/mixer_quirks.c deleted file mode 100644 index ab125ee0..00000000 --- a/ANDROID_3.4.5/sound/usb/mixer_quirks.c +++ /dev/null @@ -1,654 +0,0 @@ -/* - * USB Audio Driver for ALSA - * - * Quirks and vendor-specific extensions for mixer interfaces - * - * Copyright (c) 2002 by Takashi Iwai - * - * Many codes borrowed from audio.c by - * Alan Cox (alan@lxorguk.ukuu.org.uk) - * Thomas Sailer (sailer@ife.ee.ethz.ch) - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "usbaudio.h" -#include "mixer.h" -#include "mixer_quirks.h" -#include "helper.h" - -extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl; - -/* - * Sound Blaster remote control configuration - * - * format of remote control data: - * Extigy: xx 00 - * Audigy 2 NX: 06 80 xx 00 00 00 - * Live! 24-bit: 06 80 xx yy 22 83 - */ -static const struct rc_config { - u32 usb_id; - u8 offset; - u8 length; - u8 packet_length; - u8 min_packet_length; /* minimum accepted length of the URB result */ - u8 mute_mixer_id; - u32 mute_code; -} rc_configs[] = { - { USB_ID(0x041e, 0x3000), 0, 1, 2, 1, 18, 0x0013 }, /* Extigy */ - { USB_ID(0x041e, 0x3020), 2, 1, 6, 6, 18, 0x0013 }, /* Audigy 2 NX */ - { USB_ID(0x041e, 0x3040), 2, 2, 6, 6, 2, 0x6e91 }, /* Live! 24-bit */ - { USB_ID(0x041e, 0x3042), 0, 1, 1, 1, 1, 0x000d }, /* Usb X-Fi S51 */ - { USB_ID(0x041e, 0x30df), 0, 1, 1, 1, 1, 0x000d }, /* Usb X-Fi S51 Pro */ - { USB_ID(0x041e, 0x3048), 2, 2, 6, 6, 2, 0x6e91 }, /* Toshiba SB0500 */ -}; - -static void snd_usb_soundblaster_remote_complete(struct urb *urb) -{ - struct usb_mixer_interface *mixer = urb->context; - const struct rc_config *rc = mixer->rc_cfg; - u32 code; - - if (urb->status < 0 || urb->actual_length < rc->min_packet_length) - return; - - code = mixer->rc_buffer[rc->offset]; - if (rc->length == 2) - code |= mixer->rc_buffer[rc->offset + 1] << 8; - - /* the Mute button actually changes the mixer control */ - if (code == rc->mute_code) - snd_usb_mixer_notify_id(mixer, rc->mute_mixer_id); - mixer->rc_code = code; - wmb(); - wake_up(&mixer->rc_waitq); -} - -static long snd_usb_sbrc_hwdep_read(struct snd_hwdep *hw, char __user *buf, - long count, loff_t *offset) -{ - struct usb_mixer_interface *mixer = hw->private_data; - int err; - u32 rc_code; - - if (count != 1 && count != 4) - return -EINVAL; - err = wait_event_interruptible(mixer->rc_waitq, - (rc_code = xchg(&mixer->rc_code, 0)) != 0); - if (err == 0) { - if (count == 1) - err = put_user(rc_code, buf); - else - err = put_user(rc_code, (u32 __user *)buf); - } - return err < 0 ? err : count; -} - -static unsigned int snd_usb_sbrc_hwdep_poll(struct snd_hwdep *hw, struct file *file, - poll_table *wait) -{ - struct usb_mixer_interface *mixer = hw->private_data; - - poll_wait(file, &mixer->rc_waitq, wait); - return mixer->rc_code ? POLLIN | POLLRDNORM : 0; -} - -static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer) -{ - struct snd_hwdep *hwdep; - int err, len, i; - - for (i = 0; i < ARRAY_SIZE(rc_configs); ++i) - if (rc_configs[i].usb_id == mixer->chip->usb_id) - break; - if (i >= ARRAY_SIZE(rc_configs)) - return 0; - mixer->rc_cfg = &rc_configs[i]; - - len = mixer->rc_cfg->packet_length; - - init_waitqueue_head(&mixer->rc_waitq); - err = snd_hwdep_new(mixer->chip->card, "SB remote control", 0, &hwdep); - if (err < 0) - return err; - snprintf(hwdep->name, sizeof(hwdep->name), - "%s remote control", mixer->chip->card->shortname); - hwdep->iface = SNDRV_HWDEP_IFACE_SB_RC; - hwdep->private_data = mixer; - hwdep->ops.read = snd_usb_sbrc_hwdep_read; - hwdep->ops.poll = snd_usb_sbrc_hwdep_poll; - hwdep->exclusive = 1; - - mixer->rc_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!mixer->rc_urb) - return -ENOMEM; - mixer->rc_setup_packet = kmalloc(sizeof(*mixer->rc_setup_packet), GFP_KERNEL); - if (!mixer->rc_setup_packet) { - usb_free_urb(mixer->rc_urb); - mixer->rc_urb = NULL; - return -ENOMEM; - } - mixer->rc_setup_packet->bRequestType = - USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE; - mixer->rc_setup_packet->bRequest = UAC_GET_MEM; - mixer->rc_setup_packet->wValue = cpu_to_le16(0); - mixer->rc_setup_packet->wIndex = cpu_to_le16(0); - mixer->rc_setup_packet->wLength = cpu_to_le16(len); - usb_fill_control_urb(mixer->rc_urb, mixer->chip->dev, - usb_rcvctrlpipe(mixer->chip->dev, 0), - (u8*)mixer->rc_setup_packet, mixer->rc_buffer, len, - snd_usb_soundblaster_remote_complete, mixer); - return 0; -} - -#define snd_audigy2nx_led_info snd_ctl_boolean_mono_info - -static int snd_audigy2nx_led_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); - int index = kcontrol->private_value; - - ucontrol->value.integer.value[0] = mixer->audigy2nx_leds[index]; - return 0; -} - -static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); - int index = kcontrol->private_value; - int value = ucontrol->value.integer.value[0]; - int err, changed; - - if (value > 1) - return -EINVAL; - changed = value != mixer->audigy2nx_leds[index]; - if (mixer->chip->usb_id == USB_ID(0x041e, 0x3042)) - err = snd_usb_ctl_msg(mixer->chip->dev, - usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, - !value, 0, NULL, 0); - /* USB X-Fi S51 Pro */ - if (mixer->chip->usb_id == USB_ID(0x041e, 0x30df)) - err = snd_usb_ctl_msg(mixer->chip->dev, - usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, - !value, 0, NULL, 0); - else - err = snd_usb_ctl_msg(mixer->chip->dev, - usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, - value, index + 2, NULL, 0); - if (err < 0) - return err; - mixer->audigy2nx_leds[index] = value; - return changed; -} - -static struct snd_kcontrol_new snd_audigy2nx_controls[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "CMSS LED Switch", - .info = snd_audigy2nx_led_info, - .get = snd_audigy2nx_led_get, - .put = snd_audigy2nx_led_put, - .private_value = 0, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Power LED Switch", - .info = snd_audigy2nx_led_info, - .get = snd_audigy2nx_led_get, - .put = snd_audigy2nx_led_put, - .private_value = 1, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Dolby Digital LED Switch", - .info = snd_audigy2nx_led_info, - .get = snd_audigy2nx_led_get, - .put = snd_audigy2nx_led_put, - .private_value = 2, - }, -}; - -static int snd_audigy2nx_controls_create(struct usb_mixer_interface *mixer) -{ - int i, err; - - for (i = 0; i < ARRAY_SIZE(snd_audigy2nx_controls); ++i) { - /* USB X-Fi S51 doesn't have a CMSS LED */ - if ((mixer->chip->usb_id == USB_ID(0x041e, 0x3042)) && i == 0) - continue; - /* USB X-Fi S51 Pro doesn't have one either */ - if ((mixer->chip->usb_id == USB_ID(0x041e, 0x30df)) && i == 0) - continue; - if (i > 1 && /* Live24ext has 2 LEDs only */ - (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) || - mixer->chip->usb_id == USB_ID(0x041e, 0x3042) || - mixer->chip->usb_id == USB_ID(0x041e, 0x30df) || - mixer->chip->usb_id == USB_ID(0x041e, 0x3048))) - break; - err = snd_ctl_add(mixer->chip->card, - snd_ctl_new1(&snd_audigy2nx_controls[i], mixer)); - if (err < 0) - return err; - } - mixer->audigy2nx_leds[1] = 1; /* Power LED is on by default */ - return 0; -} - -static void snd_audigy2nx_proc_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - static const struct sb_jack { - int unitid; - const char *name; - } jacks_audigy2nx[] = { - {4, "dig in "}, - {7, "line in"}, - {19, "spk out"}, - {20, "hph out"}, - {-1, NULL} - }, jacks_live24ext[] = { - {4, "line in"}, /* &1=Line, &2=Mic*/ - {3, "hph out"}, /* headphones */ - {0, "RC "}, /* last command, 6 bytes see rc_config above */ - {-1, NULL} - }; - const struct sb_jack *jacks; - struct usb_mixer_interface *mixer = entry->private_data; - int i, err; - u8 buf[3]; - - snd_iprintf(buffer, "%s jacks\n\n", mixer->chip->card->shortname); - if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020)) - jacks = jacks_audigy2nx; - else if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) || - mixer->chip->usb_id == USB_ID(0x041e, 0x3048)) - jacks = jacks_live24ext; - else - return; - - for (i = 0; jacks[i].name; ++i) { - snd_iprintf(buffer, "%s: ", jacks[i].name); - err = snd_usb_ctl_msg(mixer->chip->dev, - usb_rcvctrlpipe(mixer->chip->dev, 0), - UAC_GET_MEM, USB_DIR_IN | USB_TYPE_CLASS | - USB_RECIP_INTERFACE, 0, - jacks[i].unitid << 8, buf, 3); - if (err == 3 && (buf[0] == 3 || buf[0] == 6)) - snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]); - else - snd_iprintf(buffer, "?\n"); - } -} - -static int snd_xonar_u1_switch_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = !!(mixer->xonar_u1_status & 0x02); - return 0; -} - -static int snd_xonar_u1_switch_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); - u8 old_status, new_status; - int err, changed; - - old_status = mixer->xonar_u1_status; - if (ucontrol->value.integer.value[0]) - new_status = old_status | 0x02; - else - new_status = old_status & ~0x02; - changed = new_status != old_status; - err = snd_usb_ctl_msg(mixer->chip->dev, - usb_sndctrlpipe(mixer->chip->dev, 0), 0x08, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, - 50, 0, &new_status, 1); - if (err < 0) - return err; - mixer->xonar_u1_status = new_status; - return changed; -} - -static struct snd_kcontrol_new snd_xonar_u1_output_switch = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Digital Playback Switch", - .info = snd_ctl_boolean_mono_info, - .get = snd_xonar_u1_switch_get, - .put = snd_xonar_u1_switch_put, -}; - -static int snd_xonar_u1_controls_create(struct usb_mixer_interface *mixer) -{ - int err; - - err = snd_ctl_add(mixer->chip->card, - snd_ctl_new1(&snd_xonar_u1_output_switch, mixer)); - if (err < 0) - return err; - mixer->xonar_u1_status = 0x05; - return 0; -} - -/* Native Instruments device quirks */ - -#define _MAKE_NI_CONTROL(bRequest,wIndex) ((bRequest) << 16 | (wIndex)) - -static int snd_nativeinstruments_control_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); - struct usb_device *dev = mixer->chip->dev; - u8 bRequest = (kcontrol->private_value >> 16) & 0xff; - u16 wIndex = kcontrol->private_value & 0xffff; - u8 tmp; - - int ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest, - USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - 0, cpu_to_le16(wIndex), - &tmp, sizeof(tmp), 1000); - - if (ret < 0) { - snd_printk(KERN_ERR - "unable to issue vendor read request (ret = %d)", ret); - return ret; - } - - ucontrol->value.integer.value[0] = tmp; - - return 0; -} - -static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); - struct usb_device *dev = mixer->chip->dev; - u8 bRequest = (kcontrol->private_value >> 16) & 0xff; - u16 wIndex = kcontrol->private_value & 0xffff; - u16 wValue = ucontrol->value.integer.value[0]; - - int ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest, - USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, - cpu_to_le16(wValue), cpu_to_le16(wIndex), - NULL, 0, 1000); - - if (ret < 0) { - snd_printk(KERN_ERR - "unable to issue vendor write request (ret = %d)", ret); - return ret; - } - - return 0; -} - -static struct snd_kcontrol_new snd_nativeinstruments_ta6_mixers[] = { - { - .name = "Direct Thru Channel A", - .private_value = _MAKE_NI_CONTROL(0x01, 0x03), - }, - { - .name = "Direct Thru Channel B", - .private_value = _MAKE_NI_CONTROL(0x01, 0x05), - }, - { - .name = "Phono Input Channel A", - .private_value = _MAKE_NI_CONTROL(0x02, 0x03), - }, - { - .name = "Phono Input Channel B", - .private_value = _MAKE_NI_CONTROL(0x02, 0x05), - }, -}; - -static struct snd_kcontrol_new snd_nativeinstruments_ta10_mixers[] = { - { - .name = "Direct Thru Channel A", - .private_value = _MAKE_NI_CONTROL(0x01, 0x03), - }, - { - .name = "Direct Thru Channel B", - .private_value = _MAKE_NI_CONTROL(0x01, 0x05), - }, - { - .name = "Direct Thru Channel C", - .private_value = _MAKE_NI_CONTROL(0x01, 0x07), - }, - { - .name = "Direct Thru Channel D", - .private_value = _MAKE_NI_CONTROL(0x01, 0x09), - }, - { - .name = "Phono Input Channel A", - .private_value = _MAKE_NI_CONTROL(0x02, 0x03), - }, - { - .name = "Phono Input Channel B", - .private_value = _MAKE_NI_CONTROL(0x02, 0x05), - }, - { - .name = "Phono Input Channel C", - .private_value = _MAKE_NI_CONTROL(0x02, 0x07), - }, - { - .name = "Phono Input Channel D", - .private_value = _MAKE_NI_CONTROL(0x02, 0x09), - }, -}; - -static int snd_nativeinstruments_create_mixer(struct usb_mixer_interface *mixer, - const struct snd_kcontrol_new *kc, - unsigned int count) -{ - int i, err = 0; - struct snd_kcontrol_new template = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .get = snd_nativeinstruments_control_get, - .put = snd_nativeinstruments_control_put, - .info = snd_ctl_boolean_mono_info, - }; - - for (i = 0; i < count; i++) { - struct snd_kcontrol *c; - - template.name = kc[i].name; - template.private_value = kc[i].private_value; - - c = snd_ctl_new1(&template, mixer); - err = snd_ctl_add(mixer->chip->card, c); - - if (err < 0) - break; - } - - return err; -} - -/* M-Audio FastTrack Ultra quirks */ - -/* private_free callback */ -static void usb_mixer_elem_free(struct snd_kcontrol *kctl) -{ - kfree(kctl->private_data); - kctl->private_data = NULL; -} - -static int snd_maudio_ftu_create_ctl(struct usb_mixer_interface *mixer, - int in, int out, const char *name) -{ - struct usb_mixer_elem_info *cval; - struct snd_kcontrol *kctl; - - cval = kzalloc(sizeof(*cval), GFP_KERNEL); - if (!cval) - return -ENOMEM; - - cval->id = 5; - cval->mixer = mixer; - cval->val_type = USB_MIXER_S16; - cval->channels = 1; - cval->control = out + 1; - cval->cmask = 1 << in; - - kctl = snd_ctl_new1(snd_usb_feature_unit_ctl, cval); - if (!kctl) { - kfree(cval); - return -ENOMEM; - } - - snprintf(kctl->id.name, sizeof(kctl->id.name), name); - kctl->private_free = usb_mixer_elem_free; - return snd_usb_mixer_add_control(mixer, kctl); -} - -static int snd_maudio_ftu_create_mixer(struct usb_mixer_interface *mixer) -{ - char name[64]; - int in, out, err; - - for (out = 0; out < 8; out++) { - for (in = 0; in < 8; in++) { - snprintf(name, sizeof(name), - "AIn%d - Out%d Capture Volume", in + 1, out + 1); - err = snd_maudio_ftu_create_ctl(mixer, in, out, name); - if (err < 0) - return err; - } - - for (in = 8; in < 16; in++) { - snprintf(name, sizeof(name), - "DIn%d - Out%d Playback Volume", in - 7, out + 1); - err = snd_maudio_ftu_create_ctl(mixer, in, out, name); - if (err < 0) - return err; - } - } - - return 0; -} - -void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, - unsigned char samplerate_id) -{ - struct usb_mixer_interface *mixer; - struct usb_mixer_elem_info *cval; - int unitid = 12; /* SamleRate ExtensionUnit ID */ - - list_for_each_entry(mixer, &chip->mixer_list, list) { - cval = mixer->id_elems[unitid]; - if (cval) { - snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR, - cval->control << 8, - samplerate_id); - snd_usb_mixer_notify_id(mixer, unitid); - } - break; - } -} - -int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) -{ - int err = 0; - struct snd_info_entry *entry; - - if ((err = snd_usb_soundblaster_remote_init(mixer)) < 0) - return err; - - switch (mixer->chip->usb_id) { - case USB_ID(0x041e, 0x3020): - case USB_ID(0x041e, 0x3040): - case USB_ID(0x041e, 0x3042): - case USB_ID(0x041e, 0x30df): - case USB_ID(0x041e, 0x3048): - err = snd_audigy2nx_controls_create(mixer); - if (err < 0) - break; - if (!snd_card_proc_new(mixer->chip->card, "audigy2nx", &entry)) - snd_info_set_text_ops(entry, mixer, - snd_audigy2nx_proc_read); - break; - - case USB_ID(0x0763, 0x2080): /* M-Audio Fast Track Ultra */ - case USB_ID(0x0763, 0x2081): /* M-Audio Fast Track Ultra 8R */ - err = snd_maudio_ftu_create_mixer(mixer); - break; - - case USB_ID(0x0b05, 0x1739): - case USB_ID(0x0b05, 0x1743): - err = snd_xonar_u1_controls_create(mixer); - break; - - case USB_ID(0x17cc, 0x1011): /* Traktor Audio 6 */ - err = snd_nativeinstruments_create_mixer(mixer, - snd_nativeinstruments_ta6_mixers, - ARRAY_SIZE(snd_nativeinstruments_ta6_mixers)); - break; - - case USB_ID(0x17cc, 0x1021): /* Traktor Audio 10 */ - err = snd_nativeinstruments_create_mixer(mixer, - snd_nativeinstruments_ta10_mixers, - ARRAY_SIZE(snd_nativeinstruments_ta10_mixers)); - break; - } - - return err; -} - -void snd_usb_mixer_rc_memory_change(struct usb_mixer_interface *mixer, - int unitid) -{ - if (!mixer->rc_cfg) - return; - /* unit ids specific to Extigy/Audigy 2 NX: */ - switch (unitid) { - case 0: /* remote control */ - mixer->rc_urb->dev = mixer->chip->dev; - usb_submit_urb(mixer->rc_urb, GFP_ATOMIC); - break; - case 4: /* digital in jack */ - case 7: /* line in jacks */ - case 19: /* speaker out jacks */ - case 20: /* headphones out jack */ - break; - /* live24ext: 4 = line-in jack */ - case 3: /* hp-out jack (may actuate Mute) */ - if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) || - mixer->chip->usb_id == USB_ID(0x041e, 0x3048)) - snd_usb_mixer_notify_id(mixer, mixer->rc_cfg->mute_mixer_id); - break; - default: - snd_printd(KERN_DEBUG "memory change in unknown unit %d\n", unitid); - break; - } -} - diff --git a/ANDROID_3.4.5/sound/usb/mixer_quirks.h b/ANDROID_3.4.5/sound/usb/mixer_quirks.h deleted file mode 100644 index bdbfab09..00000000 --- a/ANDROID_3.4.5/sound/usb/mixer_quirks.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SND_USB_MIXER_QUIRKS_H -#define SND_USB_MIXER_QUIRKS_H - -int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer); - -void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, - unsigned char samplerate_id); - -void snd_usb_mixer_rc_memory_change(struct usb_mixer_interface *mixer, - int unitid); - -#endif /* SND_USB_MIXER_QUIRKS_H */ - diff --git a/ANDROID_3.4.5/sound/usb/pcm.c b/ANDROID_3.4.5/sound/usb/pcm.c deleted file mode 100644 index 67a4d6db..00000000 --- a/ANDROID_3.4.5/sound/usb/pcm.c +++ /dev/null @@ -1,911 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "usbaudio.h" -#include "card.h" -#include "quirks.h" -#include "debug.h" -#include "endpoint.h" -#include "helper.h" -#include "pcm.h" -#include "clock.h" -#include "power.h" - -/* return the estimated delay based on USB frame counters */ -snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs, - unsigned int rate) -{ - int current_frame_number; - int frame_diff; - int est_delay; - - current_frame_number = usb_get_current_frame_number(subs->dev); - /* - * HCD implementations use different widths, use lower 8 bits. - * The delay will be managed up to 256ms, which is more than - * enough - */ - frame_diff = (current_frame_number - subs->last_frame_number) & 0xff; - - /* Approximation based on number of samples per USB frame (ms), - some truncation for 44.1 but the estimate is good enough */ - est_delay = subs->last_delay - (frame_diff * rate / 1000); - if (est_delay < 0) - est_delay = 0; - return est_delay; -} - -/* - * return the current pcm pointer. just based on the hwptr_done value. - */ -static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct snd_usb_substream *subs; - unsigned int hwptr_done; - - subs = (struct snd_usb_substream *)substream->runtime->private_data; - spin_lock(&subs->lock); - hwptr_done = subs->hwptr_done; - substream->runtime->delay = snd_usb_pcm_delay(subs, - substream->runtime->rate); - spin_unlock(&subs->lock); - return hwptr_done / (substream->runtime->frame_bits >> 3); -} - -/* - * find a matching audio format - */ -static struct audioformat *find_format(struct snd_usb_substream *subs, unsigned int format, - unsigned int rate, unsigned int channels) -{ - struct list_head *p; - struct audioformat *found = NULL; - int cur_attr = 0, attr; - - list_for_each(p, &subs->fmt_list) { - struct audioformat *fp; - fp = list_entry(p, struct audioformat, list); - if (!(fp->formats & (1uLL << format))) - continue; - if (fp->channels != channels) - continue; - if (rate < fp->rate_min || rate > fp->rate_max) - continue; - if (! (fp->rates & SNDRV_PCM_RATE_CONTINUOUS)) { - unsigned int i; - for (i = 0; i < fp->nr_rates; i++) - if (fp->rate_table[i] == rate) - break; - if (i >= fp->nr_rates) - continue; - } - attr = fp->ep_attr & USB_ENDPOINT_SYNCTYPE; - if (! found) { - found = fp; - cur_attr = attr; - continue; - } - /* avoid async out and adaptive in if the other method - * supports the same format. - * this is a workaround for the case like - * M-audio audiophile USB. - */ - if (attr != cur_attr) { - if ((attr == USB_ENDPOINT_SYNC_ASYNC && - subs->direction == SNDRV_PCM_STREAM_PLAYBACK) || - (attr == USB_ENDPOINT_SYNC_ADAPTIVE && - subs->direction == SNDRV_PCM_STREAM_CAPTURE)) - continue; - if ((cur_attr == USB_ENDPOINT_SYNC_ASYNC && - subs->direction == SNDRV_PCM_STREAM_PLAYBACK) || - (cur_attr == USB_ENDPOINT_SYNC_ADAPTIVE && - subs->direction == SNDRV_PCM_STREAM_CAPTURE)) { - found = fp; - cur_attr = attr; - continue; - } - } - /* find the format with the largest max. packet size */ - if (fp->maxpacksize > found->maxpacksize) { - found = fp; - cur_attr = attr; - } - } - return found; -} - -static int init_pitch_v1(struct snd_usb_audio *chip, int iface, - struct usb_host_interface *alts, - struct audioformat *fmt) -{ - struct usb_device *dev = chip->dev; - unsigned int ep; - unsigned char data[1]; - int err; - - ep = get_endpoint(alts, 0)->bEndpointAddress; - - data[0] = 1; - if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR, - USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, - UAC_EP_CS_ATTR_PITCH_CONTROL << 8, ep, - data, sizeof(data))) < 0) { - snd_printk(KERN_ERR "%d:%d:%d: cannot set enable PITCH\n", - dev->devnum, iface, ep); - return err; - } - - return 0; -} - -static int init_pitch_v2(struct snd_usb_audio *chip, int iface, - struct usb_host_interface *alts, - struct audioformat *fmt) -{ - struct usb_device *dev = chip->dev; - unsigned char data[1]; - unsigned int ep; - int err; - - ep = get_endpoint(alts, 0)->bEndpointAddress; - - data[0] = 1; - if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR, - USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT, - UAC2_EP_CS_PITCH << 8, 0, - data, sizeof(data))) < 0) { - snd_printk(KERN_ERR "%d:%d:%d: cannot set enable PITCH (v2)\n", - dev->devnum, iface, fmt->altsetting); - return err; - } - - return 0; -} - -/* - * initialize the pitch control and sample rate - */ -int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface, - struct usb_host_interface *alts, - struct audioformat *fmt) -{ - struct usb_interface_descriptor *altsd = get_iface_desc(alts); - - /* if endpoint doesn't have pitch control, bail out */ - if (!(fmt->attributes & UAC_EP_CS_ATTR_PITCH_CONTROL)) - return 0; - - switch (altsd->bInterfaceProtocol) { - case UAC_VERSION_1: - default: - return init_pitch_v1(chip, iface, alts, fmt); - - case UAC_VERSION_2: - return init_pitch_v2(chip, iface, alts, fmt); - } -} - -/* - * find a matching format and set up the interface - */ -static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) -{ - struct usb_device *dev = subs->dev; - struct usb_host_interface *alts; - struct usb_interface_descriptor *altsd; - struct usb_interface *iface; - unsigned int ep, attr; - int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK; - int err; - - iface = usb_ifnum_to_if(dev, fmt->iface); - if (WARN_ON(!iface)) - return -EINVAL; - alts = &iface->altsetting[fmt->altset_idx]; - altsd = get_iface_desc(alts); - if (WARN_ON(altsd->bAlternateSetting != fmt->altsetting)) - return -EINVAL; - - if (fmt == subs->cur_audiofmt) - return 0; - - /* close the old interface */ - if (subs->interface >= 0 && subs->interface != fmt->iface) { - if (usb_set_interface(subs->dev, subs->interface, 0) < 0) { - snd_printk(KERN_ERR "%d:%d:%d: return to setting 0 failed\n", - dev->devnum, fmt->iface, fmt->altsetting); - return -EIO; - } - subs->interface = -1; - subs->altset_idx = 0; - } - - /* set interface */ - if (subs->interface != fmt->iface || subs->altset_idx != fmt->altset_idx) { - if (usb_set_interface(dev, fmt->iface, fmt->altsetting) < 0) { - snd_printk(KERN_ERR "%d:%d:%d: usb_set_interface failed\n", - dev->devnum, fmt->iface, fmt->altsetting); - return -EIO; - } - snd_printdd(KERN_INFO "setting usb interface %d:%d\n", fmt->iface, fmt->altsetting); - subs->interface = fmt->iface; - subs->altset_idx = fmt->altset_idx; - } - - /* create a data pipe */ - ep = fmt->endpoint & USB_ENDPOINT_NUMBER_MASK; - if (is_playback) - subs->datapipe = usb_sndisocpipe(dev, ep); - else - subs->datapipe = usb_rcvisocpipe(dev, ep); - subs->datainterval = fmt->datainterval; - subs->syncpipe = subs->syncinterval = 0; - subs->maxpacksize = fmt->maxpacksize; - subs->syncmaxsize = 0; - subs->fill_max = 0; - - /* we need a sync pipe in async OUT or adaptive IN mode */ - /* check the number of EP, since some devices have broken - * descriptors which fool us. if it has only one EP, - * assume it as adaptive-out or sync-in. - */ - attr = fmt->ep_attr & USB_ENDPOINT_SYNCTYPE; - if (((is_playback && attr == USB_ENDPOINT_SYNC_ASYNC) || - (! is_playback && attr == USB_ENDPOINT_SYNC_ADAPTIVE)) && - altsd->bNumEndpoints >= 2) { - /* check sync-pipe endpoint */ - /* ... and check descriptor size before accessing bSynchAddress - because there is a version of the SB Audigy 2 NX firmware lacking - the audio fields in the endpoint descriptors */ - if ((get_endpoint(alts, 1)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != 0x01 || - (get_endpoint(alts, 1)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE && - get_endpoint(alts, 1)->bSynchAddress != 0)) { - snd_printk(KERN_ERR "%d:%d:%d : invalid synch pipe\n", - dev->devnum, fmt->iface, fmt->altsetting); - return -EINVAL; - } - ep = get_endpoint(alts, 1)->bEndpointAddress; - if (get_endpoint(alts, 0)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE && - (( is_playback && ep != (unsigned int)(get_endpoint(alts, 0)->bSynchAddress | USB_DIR_IN)) || - (!is_playback && ep != (unsigned int)(get_endpoint(alts, 0)->bSynchAddress & ~USB_DIR_IN)))) { - snd_printk(KERN_ERR "%d:%d:%d : invalid synch pipe\n", - dev->devnum, fmt->iface, fmt->altsetting); - return -EINVAL; - } - ep &= USB_ENDPOINT_NUMBER_MASK; - if (is_playback) - subs->syncpipe = usb_rcvisocpipe(dev, ep); - else - subs->syncpipe = usb_sndisocpipe(dev, ep); - if (get_endpoint(alts, 1)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE && - get_endpoint(alts, 1)->bRefresh >= 1 && - get_endpoint(alts, 1)->bRefresh <= 9) - subs->syncinterval = get_endpoint(alts, 1)->bRefresh; - else if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) - subs->syncinterval = 1; - else if (get_endpoint(alts, 1)->bInterval >= 1 && - get_endpoint(alts, 1)->bInterval <= 16) - subs->syncinterval = get_endpoint(alts, 1)->bInterval - 1; - else - subs->syncinterval = 3; - subs->syncmaxsize = le16_to_cpu(get_endpoint(alts, 1)->wMaxPacketSize); - } - - /* always fill max packet size */ - if (fmt->attributes & UAC_EP_CS_ATTR_FILL_MAX) - subs->fill_max = 1; - - if ((err = snd_usb_init_pitch(subs->stream->chip, subs->interface, alts, fmt)) < 0) - return err; - - subs->cur_audiofmt = fmt; - - snd_usb_set_format_quirk(subs, fmt); - -#if 0 - printk(KERN_DEBUG - "setting done: format = %d, rate = %d..%d, channels = %d\n", - fmt->format, fmt->rate_min, fmt->rate_max, fmt->channels); - printk(KERN_DEBUG - " datapipe = 0x%0x, syncpipe = 0x%0x\n", - subs->datapipe, subs->syncpipe); -#endif - - return 0; -} - -/* - * hw_params callback - * - * allocate a buffer and set the given audio format. - * - * so far we use a physically linear buffer although packetize transfer - * doesn't need a continuous area. - * if sg buffer is supported on the later version of alsa, we'll follow - * that. - */ -static int snd_usb_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_usb_substream *subs = substream->runtime->private_data; - struct audioformat *fmt; - unsigned int channels, rate, format; - int ret, changed; - - ret = snd_pcm_lib_alloc_vmalloc_buffer(substream, - params_buffer_bytes(hw_params)); - if (ret < 0) - return ret; - - format = params_format(hw_params); - rate = params_rate(hw_params); - channels = params_channels(hw_params); - fmt = find_format(subs, format, rate, channels); - if (!fmt) { - snd_printd(KERN_DEBUG "cannot set format: format = %#x, rate = %d, channels = %d\n", - format, rate, channels); - return -EINVAL; - } - - changed = subs->cur_audiofmt != fmt || - subs->period_bytes != params_period_bytes(hw_params) || - subs->cur_rate != rate; - if ((ret = set_format(subs, fmt)) < 0) - return ret; - - if (subs->cur_rate != rate) { - struct usb_host_interface *alts; - struct usb_interface *iface; - iface = usb_ifnum_to_if(subs->dev, fmt->iface); - alts = &iface->altsetting[fmt->altset_idx]; - ret = snd_usb_init_sample_rate(subs->stream->chip, subs->interface, alts, fmt, rate); - if (ret < 0) - return ret; - subs->cur_rate = rate; - } - - if (changed) { - mutex_lock(&subs->stream->chip->shutdown_mutex); - /* format changed */ - snd_usb_release_substream_urbs(subs, 0); - /* influenced: period_bytes, channels, rate, format, */ - ret = snd_usb_init_substream_urbs(subs, params_period_bytes(hw_params), - params_rate(hw_params), - snd_pcm_format_physical_width(params_format(hw_params)) * - params_channels(hw_params)); - mutex_unlock(&subs->stream->chip->shutdown_mutex); - } - - return ret; -} - -/* - * hw_free callback - * - * reset the audio format and release the buffer - */ -static int snd_usb_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_usb_substream *subs = substream->runtime->private_data; - - subs->cur_audiofmt = NULL; - subs->cur_rate = 0; - subs->period_bytes = 0; - mutex_lock(&subs->stream->chip->shutdown_mutex); - snd_usb_release_substream_urbs(subs, 0); - mutex_unlock(&subs->stream->chip->shutdown_mutex); - return snd_pcm_lib_free_vmalloc_buffer(substream); -} - -/* - * prepare callback - * - * only a few subtle things... - */ -static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_usb_substream *subs = runtime->private_data; - - if (! subs->cur_audiofmt) { - snd_printk(KERN_ERR "usbaudio: no format is specified!\n"); - return -ENXIO; - } - - /* some unit conversions in runtime */ - subs->maxframesize = bytes_to_frames(runtime, subs->maxpacksize); - subs->curframesize = bytes_to_frames(runtime, subs->curpacksize); - - /* reset the pointer */ - subs->hwptr_done = 0; - subs->transfer_done = 0; - subs->phase = 0; - subs->last_delay = 0; - subs->last_frame_number = 0; - runtime->delay = 0; - - return snd_usb_substream_prepare(subs, runtime); -} - -static struct snd_pcm_hardware snd_usb_hardware = -{ - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_BATCH | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_PAUSE, - .buffer_bytes_max = 1024 * 1024, - .period_bytes_min = 64, - .period_bytes_max = 512 * 1024, - .periods_min = 2, - .periods_max = 1024, -}; - -static int hw_check_valid_format(struct snd_usb_substream *subs, - struct snd_pcm_hw_params *params, - struct audioformat *fp) -{ - struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); - struct snd_interval *ct = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); - struct snd_mask *fmts = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); - struct snd_interval *pt = hw_param_interval(params, SNDRV_PCM_HW_PARAM_PERIOD_TIME); - struct snd_mask check_fmts; - unsigned int ptime; - - /* check the format */ - snd_mask_none(&check_fmts); - check_fmts.bits[0] = (u32)fp->formats; - check_fmts.bits[1] = (u32)(fp->formats >> 32); - snd_mask_intersect(&check_fmts, fmts); - if (snd_mask_empty(&check_fmts)) { - hwc_debug(" > check: no supported format %d\n", fp->format); - return 0; - } - /* check the channels */ - if (fp->channels < ct->min || fp->channels > ct->max) { - hwc_debug(" > check: no valid channels %d (%d/%d)\n", fp->channels, ct->min, ct->max); - return 0; - } - /* check the rate is within the range */ - if (fp->rate_min > it->max || (fp->rate_min == it->max && it->openmax)) { - hwc_debug(" > check: rate_min %d > max %d\n", fp->rate_min, it->max); - return 0; - } - if (fp->rate_max < it->min || (fp->rate_max == it->min && it->openmin)) { - hwc_debug(" > check: rate_max %d < min %d\n", fp->rate_max, it->min); - return 0; - } - /* check whether the period time is >= the data packet interval */ - if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) { - ptime = 125 * (1 << fp->datainterval); - if (ptime > pt->max || (ptime == pt->max && pt->openmax)) { - hwc_debug(" > check: ptime %u > max %u\n", ptime, pt->max); - return 0; - } - } - return 1; -} - -static int hw_rule_rate(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_usb_substream *subs = rule->private; - struct list_head *p; - struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); - unsigned int rmin, rmax; - int changed; - - hwc_debug("hw_rule_rate: (%d,%d)\n", it->min, it->max); - changed = 0; - rmin = rmax = 0; - list_for_each(p, &subs->fmt_list) { - struct audioformat *fp; - fp = list_entry(p, struct audioformat, list); - if (!hw_check_valid_format(subs, params, fp)) - continue; - if (changed++) { - if (rmin > fp->rate_min) - rmin = fp->rate_min; - if (rmax < fp->rate_max) - rmax = fp->rate_max; - } else { - rmin = fp->rate_min; - rmax = fp->rate_max; - } - } - - if (!changed) { - hwc_debug(" --> get empty\n"); - it->empty = 1; - return -EINVAL; - } - - changed = 0; - if (it->min < rmin) { - it->min = rmin; - it->openmin = 0; - changed = 1; - } - if (it->max > rmax) { - it->max = rmax; - it->openmax = 0; - changed = 1; - } - if (snd_interval_checkempty(it)) { - it->empty = 1; - return -EINVAL; - } - hwc_debug(" --> (%d, %d) (changed = %d)\n", it->min, it->max, changed); - return changed; -} - - -static int hw_rule_channels(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_usb_substream *subs = rule->private; - struct list_head *p; - struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); - unsigned int rmin, rmax; - int changed; - - hwc_debug("hw_rule_channels: (%d,%d)\n", it->min, it->max); - changed = 0; - rmin = rmax = 0; - list_for_each(p, &subs->fmt_list) { - struct audioformat *fp; - fp = list_entry(p, struct audioformat, list); - if (!hw_check_valid_format(subs, params, fp)) - continue; - if (changed++) { - if (rmin > fp->channels) - rmin = fp->channels; - if (rmax < fp->channels) - rmax = fp->channels; - } else { - rmin = fp->channels; - rmax = fp->channels; - } - } - - if (!changed) { - hwc_debug(" --> get empty\n"); - it->empty = 1; - return -EINVAL; - } - - changed = 0; - if (it->min < rmin) { - it->min = rmin; - it->openmin = 0; - changed = 1; - } - if (it->max > rmax) { - it->max = rmax; - it->openmax = 0; - changed = 1; - } - if (snd_interval_checkempty(it)) { - it->empty = 1; - return -EINVAL; - } - hwc_debug(" --> (%d, %d) (changed = %d)\n", it->min, it->max, changed); - return changed; -} - -static int hw_rule_format(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_usb_substream *subs = rule->private; - struct list_head *p; - struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); - u64 fbits; - u32 oldbits[2]; - int changed; - - hwc_debug("hw_rule_format: %x:%x\n", fmt->bits[0], fmt->bits[1]); - fbits = 0; - list_for_each(p, &subs->fmt_list) { - struct audioformat *fp; - fp = list_entry(p, struct audioformat, list); - if (!hw_check_valid_format(subs, params, fp)) - continue; - fbits |= fp->formats; - } - - oldbits[0] = fmt->bits[0]; - oldbits[1] = fmt->bits[1]; - fmt->bits[0] &= (u32)fbits; - fmt->bits[1] &= (u32)(fbits >> 32); - if (!fmt->bits[0] && !fmt->bits[1]) { - hwc_debug(" --> get empty\n"); - return -EINVAL; - } - changed = (oldbits[0] != fmt->bits[0] || oldbits[1] != fmt->bits[1]); - hwc_debug(" --> %x:%x (changed = %d)\n", fmt->bits[0], fmt->bits[1], changed); - return changed; -} - -static int hw_rule_period_time(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_usb_substream *subs = rule->private; - struct audioformat *fp; - struct snd_interval *it; - unsigned char min_datainterval; - unsigned int pmin; - int changed; - - it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_PERIOD_TIME); - hwc_debug("hw_rule_period_time: (%u,%u)\n", it->min, it->max); - min_datainterval = 0xff; - list_for_each_entry(fp, &subs->fmt_list, list) { - if (!hw_check_valid_format(subs, params, fp)) - continue; - min_datainterval = min(min_datainterval, fp->datainterval); - } - if (min_datainterval == 0xff) { - hwc_debug(" --> get empty\n"); - it->empty = 1; - return -EINVAL; - } - pmin = 125 * (1 << min_datainterval); - changed = 0; - if (it->min < pmin) { - it->min = pmin; - it->openmin = 0; - changed = 1; - } - if (snd_interval_checkempty(it)) { - it->empty = 1; - return -EINVAL; - } - hwc_debug(" --> (%u,%u) (changed = %d)\n", it->min, it->max, changed); - return changed; -} - -/* - * If the device supports unusual bit rates, does the request meet these? - */ -static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime, - struct snd_usb_substream *subs) -{ - struct audioformat *fp; - int *rate_list; - int count = 0, needs_knot = 0; - int err; - - kfree(subs->rate_list.list); - subs->rate_list.list = NULL; - - list_for_each_entry(fp, &subs->fmt_list, list) { - if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS) - return 0; - count += fp->nr_rates; - if (fp->rates & SNDRV_PCM_RATE_KNOT) - needs_knot = 1; - } - if (!needs_knot) - return 0; - - subs->rate_list.list = rate_list = - kmalloc(sizeof(int) * count, GFP_KERNEL); - if (!subs->rate_list.list) - return -ENOMEM; - subs->rate_list.count = count; - subs->rate_list.mask = 0; - count = 0; - list_for_each_entry(fp, &subs->fmt_list, list) { - int i; - for (i = 0; i < fp->nr_rates; i++) - rate_list[count++] = fp->rate_table[i]; - } - err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - &subs->rate_list); - if (err < 0) - return err; - - return 0; -} - - -/* - * set up the runtime hardware information. - */ - -static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substream *subs) -{ - struct list_head *p; - unsigned int pt, ptmin; - int param_period_time_if_needed; - int err; - - runtime->hw.formats = subs->formats; - - runtime->hw.rate_min = 0x7fffffff; - runtime->hw.rate_max = 0; - runtime->hw.channels_min = 256; - runtime->hw.channels_max = 0; - runtime->hw.rates = 0; - ptmin = UINT_MAX; - /* check min/max rates and channels */ - list_for_each(p, &subs->fmt_list) { - struct audioformat *fp; - fp = list_entry(p, struct audioformat, list); - runtime->hw.rates |= fp->rates; - if (runtime->hw.rate_min > fp->rate_min) - runtime->hw.rate_min = fp->rate_min; - if (runtime->hw.rate_max < fp->rate_max) - runtime->hw.rate_max = fp->rate_max; - if (runtime->hw.channels_min > fp->channels) - runtime->hw.channels_min = fp->channels; - if (runtime->hw.channels_max < fp->channels) - runtime->hw.channels_max = fp->channels; - if (fp->fmt_type == UAC_FORMAT_TYPE_II && fp->frame_size > 0) { - /* FIXME: there might be more than one audio formats... */ - runtime->hw.period_bytes_min = runtime->hw.period_bytes_max = - fp->frame_size; - } - pt = 125 * (1 << fp->datainterval); - ptmin = min(ptmin, pt); - } - err = snd_usb_autoresume(subs->stream->chip); - if (err < 0) - return err; - - param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME; - if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) - /* full speed devices have fixed data packet interval */ - ptmin = 1000; - if (ptmin == 1000) - /* if period time doesn't go below 1 ms, no rules needed */ - param_period_time_if_needed = -1; - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, - ptmin, UINT_MAX); - - if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - hw_rule_rate, subs, - SNDRV_PCM_HW_PARAM_FORMAT, - SNDRV_PCM_HW_PARAM_CHANNELS, - param_period_time_if_needed, - -1)) < 0) - goto rep_err; - if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - hw_rule_channels, subs, - SNDRV_PCM_HW_PARAM_FORMAT, - SNDRV_PCM_HW_PARAM_RATE, - param_period_time_if_needed, - -1)) < 0) - goto rep_err; - if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT, - hw_rule_format, subs, - SNDRV_PCM_HW_PARAM_RATE, - SNDRV_PCM_HW_PARAM_CHANNELS, - param_period_time_if_needed, - -1)) < 0) - goto rep_err; - if (param_period_time_if_needed >= 0) { - err = snd_pcm_hw_rule_add(runtime, 0, - SNDRV_PCM_HW_PARAM_PERIOD_TIME, - hw_rule_period_time, subs, - SNDRV_PCM_HW_PARAM_FORMAT, - SNDRV_PCM_HW_PARAM_CHANNELS, - SNDRV_PCM_HW_PARAM_RATE, - -1); - if (err < 0) - goto rep_err; - } - if ((err = snd_usb_pcm_check_knot(runtime, subs)) < 0) - goto rep_err; - return 0; - -rep_err: - snd_usb_autosuspend(subs->stream->chip); - return err; -} - -static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction) -{ - struct snd_usb_stream *as = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_usb_substream *subs = &as->substream[direction]; - - subs->interface = -1; - subs->altset_idx = 0; - runtime->hw = snd_usb_hardware; - runtime->private_data = subs; - subs->pcm_substream = substream; - /* runtime PM is also done there */ - return setup_hw_info(runtime, subs); -} - -static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction) -{ - struct snd_usb_stream *as = snd_pcm_substream_chip(substream); - struct snd_usb_substream *subs = &as->substream[direction]; - - if (!as->chip->shutdown && subs->interface >= 0) { - usb_set_interface(subs->dev, subs->interface, 0); - subs->interface = -1; - } - subs->pcm_substream = NULL; - snd_usb_autosuspend(subs->stream->chip); - return 0; -} - -static int snd_usb_playback_open(struct snd_pcm_substream *substream) -{ - return snd_usb_pcm_open(substream, SNDRV_PCM_STREAM_PLAYBACK); -} - -static int snd_usb_playback_close(struct snd_pcm_substream *substream) -{ - return snd_usb_pcm_close(substream, SNDRV_PCM_STREAM_PLAYBACK); -} - -static int snd_usb_capture_open(struct snd_pcm_substream *substream) -{ - return snd_usb_pcm_open(substream, SNDRV_PCM_STREAM_CAPTURE); -} - -static int snd_usb_capture_close(struct snd_pcm_substream *substream) -{ - return snd_usb_pcm_close(substream, SNDRV_PCM_STREAM_CAPTURE); -} - -static struct snd_pcm_ops snd_usb_playback_ops = { - .open = snd_usb_playback_open, - .close = snd_usb_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_usb_hw_params, - .hw_free = snd_usb_hw_free, - .prepare = snd_usb_pcm_prepare, - .trigger = snd_usb_substream_playback_trigger, - .pointer = snd_usb_pcm_pointer, - .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, -}; - -static struct snd_pcm_ops snd_usb_capture_ops = { - .open = snd_usb_capture_open, - .close = snd_usb_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_usb_hw_params, - .hw_free = snd_usb_hw_free, - .prepare = snd_usb_pcm_prepare, - .trigger = snd_usb_substream_capture_trigger, - .pointer = snd_usb_pcm_pointer, - .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, -}; - -void snd_usb_set_pcm_ops(struct snd_pcm *pcm, int stream) -{ - snd_pcm_set_ops(pcm, stream, - stream == SNDRV_PCM_STREAM_PLAYBACK ? - &snd_usb_playback_ops : &snd_usb_capture_ops); -} diff --git a/ANDROID_3.4.5/sound/usb/pcm.h b/ANDROID_3.4.5/sound/usb/pcm.h deleted file mode 100644 index df7a0036..00000000 --- a/ANDROID_3.4.5/sound/usb/pcm.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef __USBAUDIO_PCM_H -#define __USBAUDIO_PCM_H - -snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs, - unsigned int rate); - -void snd_usb_set_pcm_ops(struct snd_pcm *pcm, int stream); - -int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface, - struct usb_host_interface *alts, - struct audioformat *fmt); - - -#endif /* __USBAUDIO_PCM_H */ diff --git a/ANDROID_3.4.5/sound/usb/power.h b/ANDROID_3.4.5/sound/usb/power.h deleted file mode 100644 index 48ee51dc..00000000 --- a/ANDROID_3.4.5/sound/usb/power.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef __USBAUDIO_POWER_H -#define __USBAUDIO_POWER_H - -#ifdef CONFIG_PM -int snd_usb_autoresume(struct snd_usb_audio *chip); -void snd_usb_autosuspend(struct snd_usb_audio *chip); -#else -static inline int snd_usb_autoresume(struct snd_usb_audio *chip) -{ - return 0; -} -static inline void snd_usb_autosuspend(struct snd_usb_audio *chip) -{ -} -#endif - -#endif /* __USBAUDIO_POWER_H */ diff --git a/ANDROID_3.4.5/sound/usb/proc.c b/ANDROID_3.4.5/sound/usb/proc.c deleted file mode 100644 index 961c9a25..00000000 --- a/ANDROID_3.4.5/sound/usb/proc.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include - -#include -#include -#include - -#include "usbaudio.h" -#include "helper.h" -#include "card.h" -#include "proc.h" - -/* convert our full speed USB rate into sampling rate in Hz */ -static inline unsigned get_full_speed_hz(unsigned int usb_rate) -{ - return (usb_rate * 125 + (1 << 12)) >> 13; -} - -/* convert our high speed USB rate into sampling rate in Hz */ -static inline unsigned get_high_speed_hz(unsigned int usb_rate) -{ - return (usb_rate * 125 + (1 << 9)) >> 10; -} - -/* - * common proc files to show the usb device info - */ -static void proc_audio_usbbus_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) -{ - struct snd_usb_audio *chip = entry->private_data; - if (!chip->shutdown) - snd_iprintf(buffer, "%03d/%03d\n", chip->dev->bus->busnum, chip->dev->devnum); -} - -static void proc_audio_usbid_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) -{ - struct snd_usb_audio *chip = entry->private_data; - if (!chip->shutdown) - snd_iprintf(buffer, "%04x:%04x\n", - USB_ID_VENDOR(chip->usb_id), - USB_ID_PRODUCT(chip->usb_id)); -} - -void snd_usb_audio_create_proc(struct snd_usb_audio *chip) -{ - struct snd_info_entry *entry; - if (!snd_card_proc_new(chip->card, "usbbus", &entry)) - snd_info_set_text_ops(entry, chip, proc_audio_usbbus_read); - if (!snd_card_proc_new(chip->card, "usbid", &entry)) - snd_info_set_text_ops(entry, chip, proc_audio_usbid_read); -} - -/* - * proc interface for list the supported pcm formats - */ -static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct snd_info_buffer *buffer) -{ - struct list_head *p; - static char *sync_types[4] = { - "NONE", "ASYNC", "ADAPTIVE", "SYNC" - }; - - list_for_each(p, &subs->fmt_list) { - struct audioformat *fp; - snd_pcm_format_t fmt; - fp = list_entry(p, struct audioformat, list); - snd_iprintf(buffer, " Interface %d\n", fp->iface); - snd_iprintf(buffer, " Altset %d\n", fp->altsetting); - snd_iprintf(buffer, " Format:"); - for (fmt = 0; fmt <= SNDRV_PCM_FORMAT_LAST; ++fmt) - if (fp->formats & (1uLL << fmt)) - snd_iprintf(buffer, " %s", - snd_pcm_format_name(fmt)); - snd_iprintf(buffer, "\n"); - snd_iprintf(buffer, " Channels: %d\n", fp->channels); - snd_iprintf(buffer, " Endpoint: %d %s (%s)\n", - fp->endpoint & USB_ENDPOINT_NUMBER_MASK, - fp->endpoint & USB_DIR_IN ? "IN" : "OUT", - sync_types[(fp->ep_attr & USB_ENDPOINT_SYNCTYPE) >> 2]); - if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS) { - snd_iprintf(buffer, " Rates: %d - %d (continuous)\n", - fp->rate_min, fp->rate_max); - } else { - unsigned int i; - snd_iprintf(buffer, " Rates: "); - for (i = 0; i < fp->nr_rates; i++) { - if (i > 0) - snd_iprintf(buffer, ", "); - snd_iprintf(buffer, "%d", fp->rate_table[i]); - } - snd_iprintf(buffer, "\n"); - } - if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) - snd_iprintf(buffer, " Data packet interval: %d us\n", - 125 * (1 << fp->datainterval)); - // snd_iprintf(buffer, " Max Packet Size = %d\n", fp->maxpacksize); - // snd_iprintf(buffer, " EP Attribute = %#x\n", fp->attributes); - } -} - -static void proc_dump_substream_status(struct snd_usb_substream *subs, struct snd_info_buffer *buffer) -{ - if (subs->running) { - unsigned int i; - snd_iprintf(buffer, " Status: Running\n"); - snd_iprintf(buffer, " Interface = %d\n", subs->interface); - snd_iprintf(buffer, " Altset = %d\n", subs->altset_idx); - snd_iprintf(buffer, " URBs = %d [ ", subs->nurbs); - for (i = 0; i < subs->nurbs; i++) - snd_iprintf(buffer, "%d ", subs->dataurb[i].packets); - snd_iprintf(buffer, "]\n"); - snd_iprintf(buffer, " Packet Size = %d\n", subs->curpacksize); - snd_iprintf(buffer, " Momentary freq = %u Hz (%#x.%04x)\n", - snd_usb_get_speed(subs->dev) == USB_SPEED_FULL - ? get_full_speed_hz(subs->freqm) - : get_high_speed_hz(subs->freqm), - subs->freqm >> 16, subs->freqm & 0xffff); - if (subs->freqshift != INT_MIN) - snd_iprintf(buffer, " Feedback Format = %d.%d\n", - (subs->syncmaxsize > 3 ? 32 : 24) - - (16 - subs->freqshift), - 16 - subs->freqshift); - } else { - snd_iprintf(buffer, " Status: Stop\n"); - } -} - -static void proc_pcm_format_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) -{ - struct snd_usb_stream *stream = entry->private_data; - - snd_iprintf(buffer, "%s : %s\n", stream->chip->card->longname, stream->pcm->name); - - if (stream->substream[SNDRV_PCM_STREAM_PLAYBACK].num_formats) { - snd_iprintf(buffer, "\nPlayback:\n"); - proc_dump_substream_status(&stream->substream[SNDRV_PCM_STREAM_PLAYBACK], buffer); - proc_dump_substream_formats(&stream->substream[SNDRV_PCM_STREAM_PLAYBACK], buffer); - } - if (stream->substream[SNDRV_PCM_STREAM_CAPTURE].num_formats) { - snd_iprintf(buffer, "\nCapture:\n"); - proc_dump_substream_status(&stream->substream[SNDRV_PCM_STREAM_CAPTURE], buffer); - proc_dump_substream_formats(&stream->substream[SNDRV_PCM_STREAM_CAPTURE], buffer); - } -} - -void snd_usb_proc_pcm_format_add(struct snd_usb_stream *stream) -{ - struct snd_info_entry *entry; - char name[32]; - struct snd_card *card = stream->chip->card; - - sprintf(name, "stream%d", stream->pcm_index); - if (!snd_card_proc_new(card, name, &entry)) - snd_info_set_text_ops(entry, stream, proc_pcm_format_read); -} - diff --git a/ANDROID_3.4.5/sound/usb/proc.h b/ANDROID_3.4.5/sound/usb/proc.h deleted file mode 100644 index a45b765e..00000000 --- a/ANDROID_3.4.5/sound/usb/proc.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __USBAUDIO_PROC_H -#define __USBAUDIO_PROC_H - -void snd_usb_audio_create_proc(struct snd_usb_audio *chip); -void snd_usb_proc_pcm_format_add(struct snd_usb_stream *stream); - -#endif /* __USBAUDIO_PROC_H */ - diff --git a/ANDROID_3.4.5/sound/usb/quirks-table.h b/ANDROID_3.4.5/sound/usb/quirks-table.h deleted file mode 100644 index d89ab4c7..00000000 --- a/ANDROID_3.4.5/sound/usb/quirks-table.h +++ /dev/null @@ -1,2769 +0,0 @@ -/* - * ALSA USB Audio Driver - * - * Copyright (c) 2002 by Takashi Iwai , - * Clemens Ladisch - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * The contents of this file are part of the driver's id_table. - * - * In a perfect world, this file would be empty. - */ - -/* - * Use this for devices where other interfaces are standard compliant, - * to prevent the quirk being applied to those interfaces. (To work with - * hotplugging, bDeviceClass must be set to USB_CLASS_PER_INTERFACE.) - */ -#define USB_DEVICE_VENDOR_SPEC(vend, prod) \ - .match_flags = USB_DEVICE_ID_MATCH_VENDOR | \ - USB_DEVICE_ID_MATCH_PRODUCT | \ - USB_DEVICE_ID_MATCH_INT_CLASS, \ - .idVendor = vend, \ - .idProduct = prod, \ - .bInterfaceClass = USB_CLASS_VENDOR_SPEC - -/* FTDI devices */ -{ - USB_DEVICE(0x0403, 0xb8d8), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - /* .vendor_name = "STARR LABS", */ - /* .product_name = "Starr Labs MIDI USB device", */ - .ifnum = 0, - .type = QUIRK_MIDI_FTDI - } -}, - -/* Creative/Toshiba Multimedia Center SB-0500 */ -{ - USB_DEVICE(0x041e, 0x3048), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Toshiba", - .product_name = "SB-0500", - .ifnum = QUIRK_NO_INTERFACE - } -}, - -/* Creative/E-Mu devices */ -{ - USB_DEVICE(0x041e, 0x3010), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Creative Labs", - .product_name = "Sound Blaster MP3+", - .ifnum = QUIRK_NO_INTERFACE - } -}, -{ - /* E-Mu 0202 USB */ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x041e, - .idProduct = 0x3f02, - .bInterfaceClass = USB_CLASS_AUDIO, -}, -{ - /* E-Mu 0404 USB */ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x041e, - .idProduct = 0x3f04, - .bInterfaceClass = USB_CLASS_AUDIO, -}, -{ - /* E-Mu Tracker Pre */ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x041e, - .idProduct = 0x3f0a, - .bInterfaceClass = USB_CLASS_AUDIO, -}, -{ - /* E-Mu 0204 USB */ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x041e, - .idProduct = 0x3f19, - .bInterfaceClass = USB_CLASS_AUDIO, -}, - -/* - * Logitech QuickCam: bDeviceClass is vendor-specific, so generic interface - * class matches do not take effect without an explicit ID match. - */ -{ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | - USB_DEVICE_ID_MATCH_INT_CLASS | - USB_DEVICE_ID_MATCH_INT_SUBCLASS, - .idVendor = 0x046d, - .idProduct = 0x0850, - .bInterfaceClass = USB_CLASS_AUDIO, - .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL -}, -{ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | - USB_DEVICE_ID_MATCH_INT_CLASS | - USB_DEVICE_ID_MATCH_INT_SUBCLASS, - .idVendor = 0x046d, - .idProduct = 0x08ae, - .bInterfaceClass = USB_CLASS_AUDIO, - .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL -}, -{ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | - USB_DEVICE_ID_MATCH_INT_CLASS | - USB_DEVICE_ID_MATCH_INT_SUBCLASS, - .idVendor = 0x046d, - .idProduct = 0x08c6, - .bInterfaceClass = USB_CLASS_AUDIO, - .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL -}, -{ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | - USB_DEVICE_ID_MATCH_INT_CLASS | - USB_DEVICE_ID_MATCH_INT_SUBCLASS, - .idVendor = 0x046d, - .idProduct = 0x08f0, - .bInterfaceClass = USB_CLASS_AUDIO, - .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL -}, -{ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | - USB_DEVICE_ID_MATCH_INT_CLASS | - USB_DEVICE_ID_MATCH_INT_SUBCLASS, - .idVendor = 0x046d, - .idProduct = 0x08f5, - .bInterfaceClass = USB_CLASS_AUDIO, - .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL -}, -{ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | - USB_DEVICE_ID_MATCH_INT_CLASS | - USB_DEVICE_ID_MATCH_INT_SUBCLASS, - .idVendor = 0x046d, - .idProduct = 0x08f6, - .bInterfaceClass = USB_CLASS_AUDIO, - .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL -}, -{ - USB_DEVICE(0x046d, 0x0990), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Logitech, Inc.", - .product_name = "QuickCam Pro 9000", - .ifnum = QUIRK_NO_INTERFACE - } -}, - -/* - * Yamaha devices - */ - -#define YAMAHA_DEVICE(id, name) { \ - USB_DEVICE(0x0499, id), \ - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { \ - .vendor_name = "Yamaha", \ - .product_name = name, \ - .ifnum = QUIRK_ANY_INTERFACE, \ - .type = QUIRK_MIDI_YAMAHA \ - } \ -} -#define YAMAHA_INTERFACE(id, intf, name) { \ - USB_DEVICE_VENDOR_SPEC(0x0499, id), \ - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { \ - .vendor_name = "Yamaha", \ - .product_name = name, \ - .ifnum = intf, \ - .type = QUIRK_MIDI_YAMAHA \ - } \ -} -YAMAHA_DEVICE(0x1000, "UX256"), -YAMAHA_DEVICE(0x1001, "MU1000"), -YAMAHA_DEVICE(0x1002, "MU2000"), -YAMAHA_DEVICE(0x1003, "MU500"), -YAMAHA_INTERFACE(0x1004, 3, "UW500"), -YAMAHA_DEVICE(0x1005, "MOTIF6"), -YAMAHA_DEVICE(0x1006, "MOTIF7"), -YAMAHA_DEVICE(0x1007, "MOTIF8"), -YAMAHA_DEVICE(0x1008, "UX96"), -YAMAHA_DEVICE(0x1009, "UX16"), -YAMAHA_INTERFACE(0x100a, 3, "EOS BX"), -YAMAHA_DEVICE(0x100c, "UC-MX"), -YAMAHA_DEVICE(0x100d, "UC-KX"), -YAMAHA_DEVICE(0x100e, "S08"), -YAMAHA_DEVICE(0x100f, "CLP-150"), -YAMAHA_DEVICE(0x1010, "CLP-170"), -YAMAHA_DEVICE(0x1011, "P-250"), -YAMAHA_DEVICE(0x1012, "TYROS"), -YAMAHA_DEVICE(0x1013, "PF-500"), -YAMAHA_DEVICE(0x1014, "S90"), -YAMAHA_DEVICE(0x1015, "MOTIF-R"), -YAMAHA_DEVICE(0x1016, "MDP-5"), -YAMAHA_DEVICE(0x1017, "CVP-204"), -YAMAHA_DEVICE(0x1018, "CVP-206"), -YAMAHA_DEVICE(0x1019, "CVP-208"), -YAMAHA_DEVICE(0x101a, "CVP-210"), -YAMAHA_DEVICE(0x101b, "PSR-1100"), -YAMAHA_DEVICE(0x101c, "PSR-2100"), -YAMAHA_DEVICE(0x101d, "CLP-175"), -YAMAHA_DEVICE(0x101e, "PSR-K1"), -YAMAHA_DEVICE(0x101f, "EZ-J24"), -YAMAHA_DEVICE(0x1020, "EZ-250i"), -YAMAHA_DEVICE(0x1021, "MOTIF ES 6"), -YAMAHA_DEVICE(0x1022, "MOTIF ES 7"), -YAMAHA_DEVICE(0x1023, "MOTIF ES 8"), -YAMAHA_DEVICE(0x1024, "CVP-301"), -YAMAHA_DEVICE(0x1025, "CVP-303"), -YAMAHA_DEVICE(0x1026, "CVP-305"), -YAMAHA_DEVICE(0x1027, "CVP-307"), -YAMAHA_DEVICE(0x1028, "CVP-309"), -YAMAHA_DEVICE(0x1029, "CVP-309GP"), -YAMAHA_DEVICE(0x102a, "PSR-1500"), -YAMAHA_DEVICE(0x102b, "PSR-3000"), -YAMAHA_DEVICE(0x102e, "ELS-01/01C"), -YAMAHA_DEVICE(0x1030, "PSR-295/293"), -YAMAHA_DEVICE(0x1031, "DGX-205/203"), -YAMAHA_DEVICE(0x1032, "DGX-305"), -YAMAHA_DEVICE(0x1033, "DGX-505"), -YAMAHA_DEVICE(0x1034, NULL), -YAMAHA_DEVICE(0x1035, NULL), -YAMAHA_DEVICE(0x1036, NULL), -YAMAHA_DEVICE(0x1037, NULL), -YAMAHA_DEVICE(0x1038, NULL), -YAMAHA_DEVICE(0x1039, NULL), -YAMAHA_DEVICE(0x103a, NULL), -YAMAHA_DEVICE(0x103b, NULL), -YAMAHA_DEVICE(0x103c, NULL), -YAMAHA_DEVICE(0x103d, NULL), -YAMAHA_DEVICE(0x103e, NULL), -YAMAHA_DEVICE(0x103f, NULL), -YAMAHA_DEVICE(0x1040, NULL), -YAMAHA_DEVICE(0x1041, NULL), -YAMAHA_DEVICE(0x1042, NULL), -YAMAHA_DEVICE(0x1043, NULL), -YAMAHA_DEVICE(0x1044, NULL), -YAMAHA_DEVICE(0x1045, NULL), -YAMAHA_INTERFACE(0x104e, 0, NULL), -YAMAHA_DEVICE(0x104f, NULL), -YAMAHA_DEVICE(0x1050, NULL), -YAMAHA_DEVICE(0x1051, NULL), -YAMAHA_DEVICE(0x1052, NULL), -YAMAHA_INTERFACE(0x1053, 0, NULL), -YAMAHA_INTERFACE(0x1054, 0, NULL), -YAMAHA_DEVICE(0x1055, NULL), -YAMAHA_DEVICE(0x1056, NULL), -YAMAHA_DEVICE(0x1057, NULL), -YAMAHA_DEVICE(0x1058, NULL), -YAMAHA_DEVICE(0x1059, NULL), -YAMAHA_DEVICE(0x105a, NULL), -YAMAHA_DEVICE(0x105b, NULL), -YAMAHA_DEVICE(0x105c, NULL), -YAMAHA_DEVICE(0x105d, NULL), -{ - USB_DEVICE(0x0499, 0x1503), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - /* .vendor_name = "Yamaha", */ - /* .product_name = "MOX6/MOX8", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 3, - .type = QUIRK_MIDI_YAMAHA - }, - { - .ifnum = -1 - } - } - } -}, -YAMAHA_DEVICE(0x2000, "DGP-7"), -YAMAHA_DEVICE(0x2001, "DGP-5"), -YAMAHA_DEVICE(0x2002, NULL), -YAMAHA_DEVICE(0x2003, NULL), -YAMAHA_DEVICE(0x5000, "CS1D"), -YAMAHA_DEVICE(0x5001, "DSP1D"), -YAMAHA_DEVICE(0x5002, "DME32"), -YAMAHA_DEVICE(0x5003, "DM2000"), -YAMAHA_DEVICE(0x5004, "02R96"), -YAMAHA_DEVICE(0x5005, "ACU16-C"), -YAMAHA_DEVICE(0x5006, "NHB32-C"), -YAMAHA_DEVICE(0x5007, "DM1000"), -YAMAHA_DEVICE(0x5008, "01V96"), -YAMAHA_DEVICE(0x5009, "SPX2000"), -YAMAHA_DEVICE(0x500a, "PM5D"), -YAMAHA_DEVICE(0x500b, "DME64N"), -YAMAHA_DEVICE(0x500c, "DME24N"), -YAMAHA_DEVICE(0x500d, NULL), -YAMAHA_DEVICE(0x500e, NULL), -YAMAHA_DEVICE(0x500f, NULL), -YAMAHA_DEVICE(0x7000, "DTX"), -YAMAHA_DEVICE(0x7010, "UB99"), -#undef YAMAHA_DEVICE -#undef YAMAHA_INTERFACE - -/* - * Roland/RolandED/Edirol/BOSS devices - */ -{ - USB_DEVICE(0x0582, 0x0000), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Roland", - .product_name = "UA-100", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = & (const struct audioformat) { - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .channels = 4, - .iface = 0, - .altsetting = 1, - .altset_idx = 1, - .attributes = 0, - .endpoint = 0x01, - .ep_attr = 0x09, - .rates = SNDRV_PCM_RATE_CONTINUOUS, - .rate_min = 44100, - .rate_max = 44100, - } - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = & (const struct audioformat) { - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .channels = 2, - .iface = 1, - .altsetting = 1, - .altset_idx = 1, - .attributes = UAC_EP_CS_ATTR_FILL_MAX, - .endpoint = 0x81, - .ep_attr = 0x05, - .rates = SNDRV_PCM_RATE_CONTINUOUS, - .rate_min = 44100, - .rate_max = 44100, - } - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0007, - .in_cables = 0x0007 - } - }, - { - .ifnum = -1 - } - } - } -}, -{ - USB_DEVICE(0x0582, 0x0002), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "EDIROL", - .product_name = "UM-4", - .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_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x000f, - .in_cables = 0x000f - } - }, - { - .ifnum = -1 - } - } - } -}, -{ - USB_DEVICE(0x0582, 0x0003), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Roland", - .product_name = "SC-8850", - .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_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x003f, - .in_cables = 0x003f - } - }, - { - .ifnum = -1 - } - } - } -}, -{ - USB_DEVICE(0x0582, 0x0004), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Roland", - .product_name = "U-8", - .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_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0005, - .in_cables = 0x0005 - } - }, - { - .ifnum = -1 - } - } - } -}, -{ - /* Has ID 0x0099 when not in "Advanced Driver" mode. - * The UM-2EX has only one input, but we cannot detect this. */ - USB_DEVICE(0x0582, 0x0005), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "EDIROL", - .product_name = "UM-2", - .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_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0003, - .in_cables = 0x0003 - } - }, - { - .ifnum = -1 - } - } - } -}, -{ - USB_DEVICE(0x0582, 0x0007), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Roland", - .product_name = "SC-8820", - .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_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0013, - .in_cables = 0x0013 - } - }, - { - .ifnum = -1 - } - } - } -}, -{ - USB_DEVICE(0x0582, 0x0008), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Roland", - .product_name = "PC-300", - .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_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } - }, - { - .ifnum = -1 - } - } - } -}, -{ - /* has ID 0x009d when not in "Advanced Driver" mode */ - USB_DEVICE(0x0582, 0x0009), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "EDIROL", - .product_name = "UM-1", - .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_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } - }, - { - .ifnum = -1 - } - } - } -}, -{ - USB_DEVICE(0x0582, 0x000b), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Roland", - .product_name = "SK-500", - .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_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0013, - .in_cables = 0x0013 - } - }, - { - .ifnum = -1 - } - } - } -}, -{ - /* thanks to Emiliano Grilli - * for helping researching this data */ - USB_DEVICE(0x0582, 0x000c), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Roland", - .product_name = "SC-D70", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = & (const struct audioformat) { - .formats = SNDRV_PCM_FMTBIT_S24_3LE, - .channels = 2, - .iface = 0, - .altsetting = 1, - .altset_idx = 1, - .attributes = 0, - .endpoint = 0x01, - .ep_attr = 0x01, - .rates = SNDRV_PCM_RATE_CONTINUOUS, - .rate_min = 44100, - .rate_max = 44100, - } - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = & (const struct audioformat) { - .formats = SNDRV_PCM_FMTBIT_S24_3LE, - .channels = 2, - .iface = 1, - .altsetting = 1, - .altset_idx = 1, - .attributes = 0, - .endpoint = 0x81, - .ep_attr = 0x01, - .rates = SNDRV_PCM_RATE_CONTINUOUS, - .rate_min = 44100, - .rate_max = 44100, - } - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0007, - .in_cables = 0x0007 - } - }, - { - .ifnum = -1 - } - } - } -}, -{ /* - * This quirk is for the "Advanced Driver" mode of the Edirol UA-5. - * If the advanced mode switch at the back of the unit is off, the - * UA-5 has ID 0x0582/0x0011 and is standard compliant (no quirks), - * but offers only 16-bit PCM. - * In advanced mode, the UA-5 will output S24_3LE samples (two - * channels) at the rate indicated on the front switch, including - * the 96kHz sample rate. - */ - USB_DEVICE(0x0582, 0x0010), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "EDIROL", - .product_name = "UA-5", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = -1 - } - } - } -}, -{ - /* has ID 0x0013 when not in "Advanced Driver" mode */ - USB_DEVICE(0x0582, 0x0012), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Roland", - .product_name = "XV-5050", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } - } -}, -{ - /* has ID 0x0015 when not in "Advanced Driver" mode */ - USB_DEVICE(0x0582, 0x0014), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "EDIROL", - .product_name = "UM-880", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x01ff, - .in_cables = 0x01ff - } - } -}, -{ - /* has ID 0x0017 when not in "Advanced Driver" mode */ - USB_DEVICE(0x0582, 0x0016), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "EDIROL", - .product_name = "SD-90", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x000f, - .in_cables = 0x000f - } - }, - { - .ifnum = -1 - } - } - } -}, -{ - /* has ID 0x001c when not in "Advanced Driver" mode */ - USB_DEVICE(0x0582, 0x001b), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Roland", - .product_name = "MMP-2", - .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_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } - }, - { - .ifnum = -1 - } - } - } -}, -{ - /* has ID 0x001e when not in "Advanced Driver" mode */ - USB_DEVICE(0x0582, 0x001d), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Roland", - .product_name = "V-SYNTH", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } - } -}, -{ - /* has ID 0x0024 when not in "Advanced Driver" mode */ - USB_DEVICE(0x0582, 0x0023), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "EDIROL", - .product_name = "UM-550", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x003f, - .in_cables = 0x003f - } - } -}, -{ - /* - * This quirk is for the "Advanced Driver" mode. If off, the UA-20 - * has ID 0x0026 and is standard compliant, but has only 16-bit PCM - * and no MIDI. - */ - USB_DEVICE(0x0582, 0x0025), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "EDIROL", - .product_name = "UA-20", - .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) { - .formats = SNDRV_PCM_FMTBIT_S24_3LE, - .channels = 2, - .iface = 1, - .altsetting = 1, - .altset_idx = 1, - .attributes = 0, - .endpoint = 0x01, - .ep_attr = 0x01, - .rates = SNDRV_PCM_RATE_CONTINUOUS, - .rate_min = 44100, - .rate_max = 44100, - } - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = & (const struct audioformat) { - .formats = SNDRV_PCM_FMTBIT_S24_3LE, - .channels = 2, - .iface = 2, - .altsetting = 1, - .altset_idx = 1, - .attributes = 0, - .endpoint = 0x82, - .ep_attr = 0x01, - .rates = SNDRV_PCM_RATE_CONTINUOUS, - .rate_min = 44100, - .rate_max = 44100, - } - }, - { - .ifnum = 3, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } - }, - { - .ifnum = -1 - } - } - } -}, -{ - /* has ID 0x0028 when not in "Advanced Driver" mode */ - USB_DEVICE(0x0582, 0x0027), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "EDIROL", - .product_name = "SD-20", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0003, - .in_cables = 0x0007 - } - } -}, -{ - /* has ID 0x002a when not in "Advanced Driver" mode */ - USB_DEVICE(0x0582, 0x0029), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "EDIROL", - .product_name = "SD-80", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x000f, - .in_cables = 0x000f - } - } -}, -{ /* - * This quirk is for the "Advanced" modes of the Edirol UA-700. - * If the sample format switch is not in an advanced setting, the - * UA-700 has ID 0x0582/0x002c and is standard compliant (no quirks), - * but offers only 16-bit PCM and no MIDI. - */ - USB_DEVICE_VENDOR_SPEC(0x0582, 0x002b), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "EDIROL", - .product_name = "UA-700", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_EDIROL_UAXX - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_EDIROL_UAXX - }, - { - .ifnum = 3, - .type = QUIRK_AUDIO_EDIROL_UAXX - }, - { - .ifnum = -1 - } - } - } -}, -{ - /* has ID 0x002e when not in "Advanced Driver" mode */ - USB_DEVICE(0x0582, 0x002d), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Roland", - .product_name = "XV-2020", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } - } -}, -{ - /* has ID 0x0030 when not in "Advanced Driver" mode */ - USB_DEVICE(0x0582, 0x002f), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Roland", - .product_name = "VariOS", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0007, - .in_cables = 0x0007 - } - } -}, -{ - /* has ID 0x0034 when not in "Advanced Driver" mode */ - USB_DEVICE(0x0582, 0x0033), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "EDIROL", - .product_name = "PCR", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0003, - .in_cables = 0x0007 - } - } -}, - /* TODO: add Roland M-1000 support */ -{ - /* - * Has ID 0x0038 when not in "Advanced Driver" mode; - * later revisions use IDs 0x0054 and 0x00a2. - */ - USB_DEVICE(0x0582, 0x0037), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Roland", - .product_name = "Digital Piano", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } - } -}, -{ - /* - * This quirk is for the "Advanced Driver" mode. If off, the GS-10 - * has ID 0x003c and is standard compliant, but has only 16-bit PCM - * and no MIDI. - */ - USB_DEVICE_VENDOR_SPEC(0x0582, 0x003b), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "BOSS", - .product_name = "GS-10", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = & (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 3, - .type = QUIRK_MIDI_STANDARD_INTERFACE - }, - { - .ifnum = -1 - } - } - } -}, -{ - /* has ID 0x0041 when not in "Advanced Driver" mode */ - USB_DEVICE(0x0582, 0x0040), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Roland", - .product_name = "GI-20", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } - } -}, -{ - /* has ID 0x0043 when not in "Advanced Driver" mode */ - USB_DEVICE(0x0582, 0x0042), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Roland", - .product_name = "RS-70", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } - } -}, -{ - /* has ID 0x0049 when not in "Advanced Driver" mode */ - USB_DEVICE(0x0582, 0x0047), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - /* .vendor_name = "EDIROL", */ - /* .product_name = "UR-80", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - /* in the 96 kHz modes, only interface 1 is there */ - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = -1 - } - } - } -}, -{ - /* has ID 0x004a when not in "Advanced Driver" mode */ - USB_DEVICE(0x0582, 0x0048), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - /* .vendor_name = "EDIROL", */ - /* .product_name = "UR-80", */ - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0003, - .in_cables = 0x0007 - } - } -}, - /* TODO: add Edirol M-100FX support */ -{ - /* has ID 0x004e when not in "Advanced Driver" mode */ - USB_DEVICE(0x0582, 0x004c), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "EDIROL", - .product_name = "PCR-A", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = -1 - } - } - } -}, -{ - /* has ID 0x004f when not in "Advanced Driver" mode */ - USB_DEVICE(0x0582, 0x004d), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "EDIROL", - .product_name = "PCR-A", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0003, - .in_cables = 0x0007 - } - } -}, -{ - /* - * This quirk is for the "Advanced Driver" mode. If off, the UA-3FX - * is standard compliant, but has only 16-bit PCM. - */ - USB_DEVICE(0x0582, 0x0050), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "EDIROL", - .product_name = "UA-3FX", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = -1 - } - } - } -}, -{ - USB_DEVICE(0x0582, 0x0052), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "EDIROL", - .product_name = "UM-1SX", - .ifnum = 0, - .type = QUIRK_MIDI_STANDARD_INTERFACE - } -}, -{ - USB_DEVICE(0x0582, 0x0060), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Roland", - .product_name = "EXR Series", - .ifnum = 0, - .type = QUIRK_MIDI_STANDARD_INTERFACE - } -}, -{ - /* has ID 0x0066 when not in "Advanced Driver" mode */ - USB_DEVICE(0x0582, 0x0064), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - /* .vendor_name = "EDIROL", */ - /* .product_name = "PCR-1", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = -1 - } - } - } -}, -{ - /* has ID 0x0067 when not in "Advanced Driver" mode */ - USB_DEVICE(0x0582, 0x0065), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - /* .vendor_name = "EDIROL", */ - /* .product_name = "PCR-1", */ - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0001, - .in_cables = 0x0003 - } - } -}, -{ - /* has ID 0x006b when not in "Advanced Driver" mode */ - USB_DEVICE_VENDOR_SPEC(0x0582, 0x006a), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Roland", - .product_name = "SP-606", - .ifnum = 3, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } - } -}, -{ - /* has ID 0x006e when not in "Advanced Driver" mode */ - USB_DEVICE(0x0582, 0x006d), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Roland", - .product_name = "FANTOM-X", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } - } -}, -{ /* - * This quirk is for the "Advanced" modes of the Edirol UA-25. - * If the switch is not in an advanced setting, the UA-25 has - * ID 0x0582/0x0073 and is standard compliant (no quirks), but - * offers only 16-bit PCM at 44.1 kHz and no MIDI. - */ - USB_DEVICE_VENDOR_SPEC(0x0582, 0x0074), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "EDIROL", - .product_name = "UA-25", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_EDIROL_UAXX - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_EDIROL_UAXX - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_EDIROL_UAXX - }, - { - .ifnum = -1 - } - } - } -}, -{ - /* has ID 0x0076 when not in "Advanced Driver" mode */ - USB_DEVICE(0x0582, 0x0075), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "BOSS", - .product_name = "DR-880", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } - } -}, -{ - /* has ID 0x007b when not in "Advanced Driver" mode */ - USB_DEVICE_VENDOR_SPEC(0x0582, 0x007a), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Roland", - /* "RD" or "RD-700SX"? */ - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0003, - .in_cables = 0x0003 - } - } -}, -{ - /* has ID 0x0081 when not in "Advanced Driver" mode */ - USB_DEVICE(0x0582, 0x0080), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Roland", - .product_name = "G-70", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } - } -}, - /* TODO: add Roland V-SYNTH XT support */ - /* TODO: add BOSS GT-PRO support */ -{ - /* has ID 0x008c when not in "Advanced Driver" mode */ - USB_DEVICE(0x0582, 0x008b), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "EDIROL", - .product_name = "PC-50", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } - } -}, - /* TODO: add Edirol PC-80 support */ -{ - USB_DEVICE(0x0582, 0x0096), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "EDIROL", - .product_name = "UA-1EX", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = -1 - } - } - } -}, -{ - USB_DEVICE(0x0582, 0x009a), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "EDIROL", - .product_name = "UM-3EX", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x000f, - .in_cables = 0x000f - } - } -}, -{ - /* - * This quirk is for the "Advanced Driver" mode. If off, the UA-4FX - * is standard compliant, but has only 16-bit PCM and no MIDI. - */ - USB_DEVICE(0x0582, 0x00a3), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "EDIROL", - .product_name = "UA-4FX", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_EDIROL_UAXX - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_EDIROL_UAXX - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_EDIROL_UAXX - }, - { - .ifnum = -1 - } - } - } -}, - /* TODO: add Edirol MD-P1 support */ -{ - USB_DEVICE(0x582, 0x00a6), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Roland", - .product_name = "Juno-G", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } - } -}, -{ - /* Roland SH-201 */ - USB_DEVICE(0x0582, 0x00ad), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Roland", - .product_name = "SH-201", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } - }, - { - .ifnum = -1 - } - } - } -}, -{ - /* Roland SonicCell */ - USB_DEVICE(0x0582, 0x00c2), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Roland", - .product_name = "SonicCell", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } - }, - { - .ifnum = -1 - } - } - } -}, -{ - /* Edirol M-16DX */ - /* FIXME: This quirk gives a good-working capture stream but the - * playback seems problematic because of lacking of sync - * with capture stream. It needs to sync with the capture - * clock. As now, you'll get frequent sound distortions - * via the playback. - */ - USB_DEVICE(0x0582, 0x00c4), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } - }, - { - .ifnum = -1 - } - } - } -}, -{ - /* BOSS GT-10 */ - USB_DEVICE(0x0582, 0x00da), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } - }, - { - .ifnum = -1 - } - } - } -}, -{ - /* Advanced modes of the Edirol UA-25EX. - * For the standard mode, UA-25EX has ID 0582:00e7, which - * offers only 16-bit PCM at 44.1 kHz and no MIDI. - */ - USB_DEVICE_VENDOR_SPEC(0x0582, 0x00e6), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "EDIROL", - .product_name = "UA-25EX", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_EDIROL_UAXX - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_EDIROL_UAXX - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_EDIROL_UAXX - }, - { - .ifnum = -1 - } - } - } -}, -{ - /* has ID 0x00ea when not in Advanced Driver mode */ - USB_DEVICE_VENDOR_SPEC(0x0582, 0x00e9), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - /* .vendor_name = "Roland", */ - /* .product_name = "UA-1G", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = -1 - } - } - } -}, -{ - USB_DEVICE_VENDOR_SPEC(0x0582, 0x0104), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - /* .vendor_name = "Roland", */ - /* .product_name = "UM-1G", */ - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } - } -}, -{ - /* Edirol UM-3G */ - USB_DEVICE_VENDOR_SPEC(0x0582, 0x0108), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .ifnum = 0, - .type = QUIRK_MIDI_STANDARD_INTERFACE - } -}, -{ - /* Boss JS-8 Jam Station */ - USB_DEVICE(0x0582, 0x0109), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - /* .vendor_name = "BOSS", */ - /* .product_name = "JS-8", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_STANDARD_INTERFACE - }, - { - .ifnum = -1 - } - } - } -}, -{ - /* has ID 0x0110 when not in Advanced Driver mode */ - USB_DEVICE_VENDOR_SPEC(0x0582, 0x010f), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - /* .vendor_name = "Roland", */ - /* .product_name = "A-PRO", */ - .ifnum = 1, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0003, - .in_cables = 0x0007 - } - } -}, -{ - /* Roland GAIA SH-01 */ - USB_DEVICE(0x0582, 0x0111), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .vendor_name = "Roland", - .product_name = "GAIA", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = &(const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0003, - .in_cables = 0x0003 - } - }, - { - .ifnum = -1 - } - } - } -}, -{ - USB_DEVICE(0x0582, 0x0113), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - /* .vendor_name = "BOSS", */ - /* .product_name = "ME-25", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } - }, - { - .ifnum = -1 - } - } - } -}, -{ - USB_DEVICE(0x0582, 0x0127), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - /* .vendor_name = "Roland", */ - /* .product_name = "GR-55", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_STANDARD_INTERFACE - }, - { - .ifnum = -1 - } - } - } -}, -{ - /* Added support for Roland UM-ONE which differs from UM-1 */ - USB_DEVICE(0x0582, 0x012a), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - /* .vendor_name = "ROLAND", */ - /* .product_name = "UM-ONE", */ - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0001, - .in_cables = 0x0003 - } - } -}, -{ - USB_DEVICE(0x0582, 0x011e), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - /* .vendor_name = "BOSS", */ - /* .product_name = "BR-800", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } - }, - { - .ifnum = -1 - } - } - } -}, -{ - USB_DEVICE(0x0582, 0x0130), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - /* .vendor_name = "BOSS", */ - /* .product_name = "MICRO BR-80", */ - .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_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 3, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } - }, - { - .ifnum = -1 - } - } - } -}, - -/* Guillemot devices */ -{ - /* - * This is for the "Windows Edition" where the external MIDI ports are - * the only MIDI ports; the control data is reported through HID - * interfaces. The "Macintosh Edition" has ID 0xd002 and uses standard - * compliant USB MIDI ports for external MIDI and controls. - */ - USB_DEVICE_VENDOR_SPEC(0x06f8, 0xb000), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Hercules", - .product_name = "DJ Console (WE)", - .ifnum = 4, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } - } -}, - -/* Midiman/M-Audio devices */ -{ - USB_DEVICE_VENDOR_SPEC(0x0763, 0x1002), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "M-Audio", - .product_name = "MidiSport 2x2", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_MIDI_MIDIMAN, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0003, - .in_cables = 0x0003 - } - } -}, -{ - USB_DEVICE_VENDOR_SPEC(0x0763, 0x1011), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "M-Audio", - .product_name = "MidiSport 1x1", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_MIDI_MIDIMAN, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } - } -}, -{ - USB_DEVICE_VENDOR_SPEC(0x0763, 0x1015), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "M-Audio", - .product_name = "Keystation", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_MIDI_MIDIMAN, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } - } -}, -{ - USB_DEVICE_VENDOR_SPEC(0x0763, 0x1021), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "M-Audio", - .product_name = "MidiSport 4x4", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_MIDI_MIDIMAN, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x000f, - .in_cables = 0x000f - } - } -}, -{ - /* - * For hardware revision 1.05; in the later revisions (1.10 and - * 1.21), 0x1031 is the ID for the device without firmware. - * Thanks to Olaf Giesbrecht - */ - USB_DEVICE_VER(0x0763, 0x1031, 0x0100, 0x0109), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "M-Audio", - .product_name = "MidiSport 8x8", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_MIDI_MIDIMAN, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x01ff, - .in_cables = 0x01ff - } - } -}, -{ - USB_DEVICE_VENDOR_SPEC(0x0763, 0x1033), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "M-Audio", - .product_name = "MidiSport 8x8", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_MIDI_MIDIMAN, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x01ff, - .in_cables = 0x01ff - } - } -}, -{ - USB_DEVICE_VENDOR_SPEC(0x0763, 0x1041), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "M-Audio", - .product_name = "MidiSport 2x4", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_MIDI_MIDIMAN, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x000f, - .in_cables = 0x0003 - } - } -}, -{ - USB_DEVICE_VENDOR_SPEC(0x0763, 0x2001), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "M-Audio", - .product_name = "Quattro", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = & (const struct snd_usb_audio_quirk[]) { - /* - * Interfaces 0-2 are "Windows-compatible", 16-bit only, - * and share endpoints with the other interfaces. - * Ignore them. The other interfaces can do 24 bits, - * but captured samples are big-endian (see usbaudio.c). - */ - { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 3, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 4, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 5, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 6, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 7, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 8, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 9, - .type = QUIRK_MIDI_MIDIMAN, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } - }, - { - .ifnum = -1 - } - } - } -}, -{ - USB_DEVICE_VENDOR_SPEC(0x0763, 0x2003), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "M-Audio", - .product_name = "AudioPhile", - .ifnum = 6, - .type = QUIRK_MIDI_MIDIMAN, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } - } -}, -{ - USB_DEVICE_VENDOR_SPEC(0x0763, 0x2008), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "M-Audio", - .product_name = "Ozone", - .ifnum = 3, - .type = QUIRK_MIDI_MIDIMAN, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } - } -}, -{ - USB_DEVICE_VENDOR_SPEC(0x0763, 0x200d), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "M-Audio", - .product_name = "OmniStudio", - .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_IGNORE_INTERFACE - }, - { - .ifnum = 3, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 4, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 5, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 6, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 7, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 8, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 9, - .type = QUIRK_MIDI_MIDIMAN, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } - }, - { - .ifnum = -1 - } - } - } -}, -{ - USB_DEVICE(0x0763, 0x2019), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - /* .vendor_name = "M-Audio", */ - /* .product_name = "Ozone Academic", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = & (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 3, - .type = QUIRK_MIDI_MIDIMAN, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0001, - .in_cables = 0x0001 - } - }, - { - .ifnum = -1 - } - } - } -}, -{ - USB_DEVICE_VENDOR_SPEC(0x0763, 0x2080), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - /* .vendor_name = "M-Audio", */ - /* .product_name = "Fast Track Ultra", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = & (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_MIXER, - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = & (const struct audioformat) { - .formats = SNDRV_PCM_FMTBIT_S24_3LE, - .channels = 8, - .iface = 1, - .altsetting = 1, - .altset_idx = 1, - .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE, - .endpoint = 0x01, - .ep_attr = 0x09, - .rates = SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000, - .rate_min = 44100, - .rate_max = 96000, - .nr_rates = 4, - .rate_table = (unsigned int[]) { - 44100, 48000, 88200, 96000 - } - } - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = & (const struct audioformat) { - .formats = SNDRV_PCM_FMTBIT_S24_3LE, - .channels = 8, - .iface = 2, - .altsetting = 1, - .altset_idx = 1, - .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE, - .endpoint = 0x81, - .ep_attr = 0x05, - .rates = SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000, - .rate_min = 44100, - .rate_max = 96000, - .nr_rates = 4, - .rate_table = (unsigned int[]) { - 44100, 48000, 88200, 96000 - } - } - }, - /* interface 3 (MIDI) is standard compliant */ - { - .ifnum = -1 - } - } - } -}, -{ - USB_DEVICE_VENDOR_SPEC(0x0763, 0x2081), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - /* .vendor_name = "M-Audio", */ - /* .product_name = "Fast Track Ultra 8R", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = & (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_MIXER, - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = & (const struct audioformat) { - .formats = SNDRV_PCM_FMTBIT_S24_3LE, - .channels = 8, - .iface = 1, - .altsetting = 1, - .altset_idx = 1, - .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE, - .endpoint = 0x01, - .ep_attr = 0x09, - .rates = SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000, - .rate_min = 44100, - .rate_max = 96000, - .nr_rates = 4, - .rate_table = (unsigned int[]) { - 44100, 48000, 88200, 96000 - } - } - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = & (const struct audioformat) { - .formats = SNDRV_PCM_FMTBIT_S24_3LE, - .channels = 8, - .iface = 2, - .altsetting = 1, - .altset_idx = 1, - .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE, - .endpoint = 0x81, - .ep_attr = 0x05, - .rates = SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000, - .rate_min = 44100, - .rate_max = 96000, - .nr_rates = 4, - .rate_table = (unsigned int[]) { - 44100, 48000, 88200, 96000 - } - } - }, - /* interface 3 (MIDI) is standard compliant */ - { - .ifnum = -1 - } - } - } -}, - -/* Casio devices */ -{ - USB_DEVICE(0x07cf, 0x6801), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Casio", - .product_name = "PL-40R", - .ifnum = 0, - .type = QUIRK_MIDI_YAMAHA - } -}, -{ - /* this ID is used by several devices without a product ID */ - USB_DEVICE(0x07cf, 0x6802), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Casio", - .product_name = "Keyboard", - .ifnum = 0, - .type = QUIRK_MIDI_YAMAHA - } -}, - -/* Mark of the Unicorn devices */ -{ - /* thanks to Robert A. Lerche */ - .match_flags = USB_DEVICE_ID_MATCH_VENDOR | - USB_DEVICE_ID_MATCH_PRODUCT | - USB_DEVICE_ID_MATCH_DEV_SUBCLASS, - .idVendor = 0x07fd, - .idProduct = 0x0001, - .bDeviceSubClass = 2, - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "MOTU", - .product_name = "Fastlane", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = & (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_MIDI_RAW_BYTES - }, - { - .ifnum = 1, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = -1 - } - } - } -}, - -/* Emagic devices */ -{ - USB_DEVICE(0x086a, 0x0001), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Emagic", - /* .product_name = "Unitor8", */ - .ifnum = 2, - .type = QUIRK_MIDI_EMAGIC, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x80ff, - .in_cables = 0x80ff - } - } -}, -{ - USB_DEVICE(0x086a, 0x0002), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Emagic", - /* .product_name = "AMT8", */ - .ifnum = 2, - .type = QUIRK_MIDI_EMAGIC, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x80ff, - .in_cables = 0x80ff - } - } -}, -{ - USB_DEVICE(0x086a, 0x0003), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Emagic", - /* .product_name = "MT4", */ - .ifnum = 2, - .type = QUIRK_MIDI_EMAGIC, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x800f, - .in_cables = 0x8003 - } - } -}, - -/* KORG devices */ -{ - USB_DEVICE_VENDOR_SPEC(0x0944, 0x0200), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "KORG, Inc.", - /* .product_name = "PANDORA PX5D", */ - .ifnum = 3, - .type = QUIRK_MIDI_STANDARD_INTERFACE, - } -}, - -{ - USB_DEVICE_VENDOR_SPEC(0x0944, 0x0201), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "KORG, Inc.", - /* .product_name = "ToneLab ST", */ - .ifnum = 3, - .type = QUIRK_MIDI_STANDARD_INTERFACE, - } -}, - -/* AKAI devices */ -{ - USB_DEVICE(0x09e8, 0x0062), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "AKAI", - .product_name = "MPD16", - .ifnum = 0, - .type = QUIRK_MIDI_AKAI, - } -}, - -/* TerraTec devices */ -{ - USB_DEVICE_VENDOR_SPEC(0x0ccd, 0x0012), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "TerraTec", - .product_name = "PHASE 26", - .ifnum = 3, - .type = QUIRK_MIDI_STANDARD_INTERFACE - } -}, -{ - USB_DEVICE_VENDOR_SPEC(0x0ccd, 0x0013), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "TerraTec", - .product_name = "PHASE 26", - .ifnum = 3, - .type = QUIRK_MIDI_STANDARD_INTERFACE - } -}, -{ - USB_DEVICE_VENDOR_SPEC(0x0ccd, 0x0014), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "TerraTec", - .product_name = "PHASE 26", - .ifnum = 3, - .type = QUIRK_MIDI_STANDARD_INTERFACE - } -}, -{ - USB_DEVICE(0x0ccd, 0x0028), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "TerraTec", - .product_name = "Aureon5.1MkII", - .ifnum = QUIRK_NO_INTERFACE - } -}, -{ - USB_DEVICE(0x0ccd, 0x0035), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Miditech", - .product_name = "Play'n Roll", - .ifnum = 0, - .type = QUIRK_MIDI_CME - } -}, - -/* Stanton/N2IT Final Scratch v1 device ('Scratchamp') */ -{ - USB_DEVICE(0x103d, 0x0100), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Stanton", - .product_name = "ScratchAmp", - .ifnum = QUIRK_NO_INTERFACE - } -}, -{ - USB_DEVICE(0x103d, 0x0101), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Stanton", - .product_name = "ScratchAmp", - .ifnum = QUIRK_NO_INTERFACE - } -}, - -/* Novation EMS devices */ -{ - USB_DEVICE_VENDOR_SPEC(0x1235, 0x0001), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Novation", - .product_name = "ReMOTE Audio/XStation", - .ifnum = 4, - .type = QUIRK_MIDI_NOVATION - } -}, -{ - USB_DEVICE_VENDOR_SPEC(0x1235, 0x0002), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Novation", - .product_name = "Speedio", - .ifnum = 3, - .type = QUIRK_MIDI_NOVATION - } -}, -{ - USB_DEVICE(0x1235, 0x000e), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - /* .vendor_name = "Novation", */ - /* .product_name = "Launchpad", */ - .ifnum = 0, - .type = QUIRK_MIDI_RAW_BYTES - } -}, -{ - USB_DEVICE_VENDOR_SPEC(0x1235, 0x4661), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Novation", - .product_name = "ReMOTE25", - .ifnum = 0, - .type = QUIRK_MIDI_NOVATION - } -}, - -/* Access Music devices */ -{ - /* VirusTI Desktop */ - USB_DEVICE_VENDOR_SPEC(0x133e, 0x0815), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = &(const struct snd_usb_audio_quirk[]) { - { - .ifnum = 3, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = &(const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0003, - .in_cables = 0x0003 - } - }, - { - .ifnum = 4, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = -1 - } - } - } -}, - -/* */ -{ - /* aka. Serato Scratch Live DJ Box */ - USB_DEVICE(0x13e5, 0x0001), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Rane", - .product_name = "SL-1", - .ifnum = QUIRK_NO_INTERFACE - } -}, - -/* Native Instruments MK2 series */ -{ - /* Komplete Audio 6 */ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x17cc, - .idProduct = 0x1000, -}, -{ - /* Traktor Audio 6 */ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x17cc, - .idProduct = 0x1010, -}, -{ - /* Traktor Audio 10 */ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x17cc, - .idProduct = 0x1020, -}, - -/* KeithMcMillen Stringport */ -{ - USB_DEVICE(0x1f38, 0x0001), - .bInterfaceClass = USB_CLASS_AUDIO, -}, - -/* Miditech devices */ -{ - USB_DEVICE(0x4752, 0x0011), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Miditech", - .product_name = "Midistart-2", - .ifnum = 0, - .type = QUIRK_MIDI_CME - } -}, - -/* Central Music devices */ -{ - /* this ID used by both Miditech MidiStudio-2 and CME UF-x */ - USB_DEVICE(0x7104, 0x2202), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .ifnum = 0, - .type = QUIRK_MIDI_CME - } -}, - -/* Hauppauge HVR-950Q and HVR-850 */ -{ - USB_DEVICE_VENDOR_SPEC(0x2040, 0x7200), - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | - USB_DEVICE_ID_MATCH_INT_CLASS | - USB_DEVICE_ID_MATCH_INT_SUBCLASS, - .bInterfaceClass = USB_CLASS_AUDIO, - .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .vendor_name = "Hauppauge", - .product_name = "HVR-950Q", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_AUDIO_ALIGN_TRANSFER, - } -}, -{ - USB_DEVICE_VENDOR_SPEC(0x2040, 0x7240), - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | - USB_DEVICE_ID_MATCH_INT_CLASS | - USB_DEVICE_ID_MATCH_INT_SUBCLASS, - .bInterfaceClass = USB_CLASS_AUDIO, - .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .vendor_name = "Hauppauge", - .product_name = "HVR-850", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_AUDIO_ALIGN_TRANSFER, - } -}, -{ - USB_DEVICE_VENDOR_SPEC(0x2040, 0x7210), - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | - USB_DEVICE_ID_MATCH_INT_CLASS | - USB_DEVICE_ID_MATCH_INT_SUBCLASS, - .bInterfaceClass = USB_CLASS_AUDIO, - .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .vendor_name = "Hauppauge", - .product_name = "HVR-950Q", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_AUDIO_ALIGN_TRANSFER, - } -}, -{ - USB_DEVICE_VENDOR_SPEC(0x2040, 0x7217), - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | - USB_DEVICE_ID_MATCH_INT_CLASS | - USB_DEVICE_ID_MATCH_INT_SUBCLASS, - .bInterfaceClass = USB_CLASS_AUDIO, - .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .vendor_name = "Hauppauge", - .product_name = "HVR-950Q", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_AUDIO_ALIGN_TRANSFER, - } -}, -{ - USB_DEVICE_VENDOR_SPEC(0x2040, 0x721b), - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | - USB_DEVICE_ID_MATCH_INT_CLASS | - USB_DEVICE_ID_MATCH_INT_SUBCLASS, - .bInterfaceClass = USB_CLASS_AUDIO, - .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .vendor_name = "Hauppauge", - .product_name = "HVR-950Q", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_AUDIO_ALIGN_TRANSFER, - } -}, -{ - USB_DEVICE_VENDOR_SPEC(0x2040, 0x721e), - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | - USB_DEVICE_ID_MATCH_INT_CLASS | - USB_DEVICE_ID_MATCH_INT_SUBCLASS, - .bInterfaceClass = USB_CLASS_AUDIO, - .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .vendor_name = "Hauppauge", - .product_name = "HVR-950Q", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_AUDIO_ALIGN_TRANSFER, - } -}, -{ - USB_DEVICE_VENDOR_SPEC(0x2040, 0x721f), - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | - USB_DEVICE_ID_MATCH_INT_CLASS | - USB_DEVICE_ID_MATCH_INT_SUBCLASS, - .bInterfaceClass = USB_CLASS_AUDIO, - .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .vendor_name = "Hauppauge", - .product_name = "HVR-950Q", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_AUDIO_ALIGN_TRANSFER, - } -}, -{ - USB_DEVICE_VENDOR_SPEC(0x2040, 0x7280), - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | - USB_DEVICE_ID_MATCH_INT_CLASS | - USB_DEVICE_ID_MATCH_INT_SUBCLASS, - .bInterfaceClass = USB_CLASS_AUDIO, - .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .vendor_name = "Hauppauge", - .product_name = "HVR-950Q", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_AUDIO_ALIGN_TRANSFER, - } -}, -{ - USB_DEVICE_VENDOR_SPEC(0x0fd9, 0x0008), - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | - USB_DEVICE_ID_MATCH_INT_CLASS | - USB_DEVICE_ID_MATCH_INT_SUBCLASS, - .bInterfaceClass = USB_CLASS_AUDIO, - .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .vendor_name = "Hauppauge", - .product_name = "HVR-950Q", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_AUDIO_ALIGN_TRANSFER, - } -}, - -/* Digidesign Mbox */ -{ - /* Thanks to Clemens Ladisch */ - USB_DEVICE(0x0dba, 0x1000), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .vendor_name = "Digidesign", - .product_name = "MBox", - .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) { - .formats = SNDRV_PCM_FMTBIT_S24_3BE, - .channels = 2, - .iface = 1, - .altsetting = 1, - .altset_idx = 1, - .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE, - .endpoint = 0x02, - .ep_attr = 0x01, - .maxpacksize = 0x130, - .rates = SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000, - .rate_min = 44100, - .rate_max = 48000, - .nr_rates = 2, - .rate_table = (unsigned int[]) { - 44100, 48000 - } - } - }, - { - .ifnum = -1 - } - } - - } -}, - -{ - /* - * Some USB MIDI devices don't have an audio control interface, - * so we have to grab MIDI streaming interfaces here. - */ - .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS | - USB_DEVICE_ID_MATCH_INT_SUBCLASS, - .bInterfaceClass = USB_CLASS_AUDIO, - .bInterfaceSubClass = USB_SUBCLASS_MIDISTREAMING, - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_MIDI_STANDARD_INTERFACE - } -}, - -#undef USB_DEVICE_VENDOR_SPEC diff --git a/ANDROID_3.4.5/sound/usb/quirks.c b/ANDROID_3.4.5/sound/usb/quirks.c deleted file mode 100644 index 27817266..00000000 --- a/ANDROID_3.4.5/sound/usb/quirks.c +++ /dev/null @@ -1,763 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "usbaudio.h" -#include "card.h" -#include "mixer.h" -#include "mixer_quirks.h" -#include "midi.h" -#include "quirks.h" -#include "helper.h" -#include "endpoint.h" -#include "pcm.h" -#include "clock.h" -#include "stream.h" - -/* - * handle the quirks for the contained interfaces - */ -static int create_composite_quirk(struct snd_usb_audio *chip, - struct usb_interface *iface, - struct usb_driver *driver, - const struct snd_usb_audio_quirk *quirk) -{ - int probed_ifnum = get_iface_desc(iface->altsetting)->bInterfaceNumber; - int err; - - for (quirk = quirk->data; quirk->ifnum >= 0; ++quirk) { - iface = usb_ifnum_to_if(chip->dev, quirk->ifnum); - if (!iface) - continue; - if (quirk->ifnum != probed_ifnum && - usb_interface_claimed(iface)) - continue; - err = snd_usb_create_quirk(chip, iface, driver, quirk); - if (err < 0) - return err; - if (quirk->ifnum != probed_ifnum) - usb_driver_claim_interface(driver, iface, (void *)-1L); - } - return 0; -} - -static int ignore_interface_quirk(struct snd_usb_audio *chip, - struct usb_interface *iface, - struct usb_driver *driver, - const struct snd_usb_audio_quirk *quirk) -{ - return 0; -} - - -/* - * Allow alignment on audio sub-slot (channel samples) rather than - * on audio slots (audio frames) - */ -static int create_align_transfer_quirk(struct snd_usb_audio *chip, - struct usb_interface *iface, - struct usb_driver *driver, - const struct snd_usb_audio_quirk *quirk) -{ - chip->txfr_quirk = 1; - return 1; /* Continue with creating streams and mixer */ -} - -static int create_any_midi_quirk(struct snd_usb_audio *chip, - struct usb_interface *intf, - struct usb_driver *driver, - const struct snd_usb_audio_quirk *quirk) -{ - return snd_usbmidi_create(chip->card, intf, &chip->midi_list, quirk); -} - -/* - * create a stream for an interface with proper descriptors - */ -static int create_standard_audio_quirk(struct snd_usb_audio *chip, - struct usb_interface *iface, - struct usb_driver *driver, - const struct snd_usb_audio_quirk *quirk) -{ - struct usb_host_interface *alts; - struct usb_interface_descriptor *altsd; - int err; - - alts = &iface->altsetting[0]; - altsd = get_iface_desc(alts); - err = snd_usb_parse_audio_interface(chip, altsd->bInterfaceNumber); - if (err < 0) { - snd_printk(KERN_ERR "cannot setup if %d: error %d\n", - altsd->bInterfaceNumber, err); - return err; - } - /* reset the current interface */ - usb_set_interface(chip->dev, altsd->bInterfaceNumber, 0); - return 0; -} - -/* - * create a stream for an endpoint/altsetting without proper descriptors - */ -static int create_fixed_stream_quirk(struct snd_usb_audio *chip, - struct usb_interface *iface, - struct usb_driver *driver, - const struct snd_usb_audio_quirk *quirk) -{ - struct audioformat *fp; - struct usb_host_interface *alts; - int stream, err; - unsigned *rate_table = NULL; - - fp = kmemdup(quirk->data, sizeof(*fp), GFP_KERNEL); - if (!fp) { - snd_printk(KERN_ERR "cannot memdup\n"); - return -ENOMEM; - } - if (fp->nr_rates > MAX_NR_RATES) { - kfree(fp); - return -EINVAL; - } - if (fp->nr_rates > 0) { - rate_table = kmemdup(fp->rate_table, - sizeof(int) * fp->nr_rates, GFP_KERNEL); - if (!rate_table) { - kfree(fp); - return -ENOMEM; - } - fp->rate_table = rate_table; - } - - stream = (fp->endpoint & USB_DIR_IN) - ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; - err = snd_usb_add_audio_stream(chip, stream, fp); - if (err < 0) { - kfree(fp); - kfree(rate_table); - return err; - } - if (fp->iface != get_iface_desc(&iface->altsetting[0])->bInterfaceNumber || - fp->altset_idx >= iface->num_altsetting) { - kfree(fp); - kfree(rate_table); - return -EINVAL; - } - alts = &iface->altsetting[fp->altset_idx]; - fp->datainterval = snd_usb_parse_datainterval(chip, alts); - fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); - usb_set_interface(chip->dev, fp->iface, 0); - snd_usb_init_pitch(chip, fp->iface, alts, fp); - snd_usb_init_sample_rate(chip, fp->iface, alts, fp, fp->rate_max); - return 0; -} - -/* - * Create a stream for an Edirol UA-700/UA-25/UA-4FX interface. - * The only way to detect the sample rate is by looking at wMaxPacketSize. - */ -static int create_uaxx_quirk(struct snd_usb_audio *chip, - struct usb_interface *iface, - struct usb_driver *driver, - const struct snd_usb_audio_quirk *quirk) -{ - static const struct audioformat ua_format = { - .formats = SNDRV_PCM_FMTBIT_S24_3LE, - .channels = 2, - .fmt_type = UAC_FORMAT_TYPE_I, - .altsetting = 1, - .altset_idx = 1, - .rates = SNDRV_PCM_RATE_CONTINUOUS, - }; - struct usb_host_interface *alts; - struct usb_interface_descriptor *altsd; - struct audioformat *fp; - int stream, err; - - /* both PCM and MIDI interfaces have 2 or more altsettings */ - if (iface->num_altsetting < 2) - return -ENXIO; - alts = &iface->altsetting[1]; - altsd = get_iface_desc(alts); - - if (altsd->bNumEndpoints == 2) { - static const struct snd_usb_midi_endpoint_info ua700_ep = { - .out_cables = 0x0003, - .in_cables = 0x0003 - }; - static const struct snd_usb_audio_quirk ua700_quirk = { - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = &ua700_ep - }; - static const struct snd_usb_midi_endpoint_info uaxx_ep = { - .out_cables = 0x0001, - .in_cables = 0x0001 - }; - static const struct snd_usb_audio_quirk uaxx_quirk = { - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = &uaxx_ep - }; - const struct snd_usb_audio_quirk *quirk = - chip->usb_id == USB_ID(0x0582, 0x002b) - ? &ua700_quirk : &uaxx_quirk; - return snd_usbmidi_create(chip->card, iface, - &chip->midi_list, quirk); - } - - if (altsd->bNumEndpoints != 1) - return -ENXIO; - - fp = kmemdup(&ua_format, sizeof(*fp), GFP_KERNEL); - if (!fp) - return -ENOMEM; - - fp->iface = altsd->bInterfaceNumber; - fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; - fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; - fp->datainterval = 0; - fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); - - switch (fp->maxpacksize) { - case 0x120: - fp->rate_max = fp->rate_min = 44100; - break; - case 0x138: - case 0x140: - fp->rate_max = fp->rate_min = 48000; - break; - case 0x258: - case 0x260: - fp->rate_max = fp->rate_min = 96000; - break; - default: - snd_printk(KERN_ERR "unknown sample rate\n"); - kfree(fp); - return -ENXIO; - } - - stream = (fp->endpoint & USB_DIR_IN) - ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; - err = snd_usb_add_audio_stream(chip, stream, fp); - if (err < 0) { - kfree(fp); - return err; - } - usb_set_interface(chip->dev, fp->iface, 0); - return 0; -} - -/* - * Create a standard mixer for the specified interface. - */ -static int create_standard_mixer_quirk(struct snd_usb_audio *chip, - struct usb_interface *iface, - struct usb_driver *driver, - const struct snd_usb_audio_quirk *quirk) -{ - if (quirk->ifnum < 0) - return 0; - - return snd_usb_create_mixer(chip, quirk->ifnum, 0); -} - -/* - * audio-interface quirks - * - * returns zero if no standard audio/MIDI parsing is needed. - * returns a positive value if standard audio/midi interfaces are parsed - * after this. - * returns a negative value at error. - */ -int snd_usb_create_quirk(struct snd_usb_audio *chip, - struct usb_interface *iface, - struct usb_driver *driver, - const struct snd_usb_audio_quirk *quirk) -{ - typedef int (*quirk_func_t)(struct snd_usb_audio *, - struct usb_interface *, - struct usb_driver *, - const struct snd_usb_audio_quirk *); - static const quirk_func_t quirk_funcs[] = { - [QUIRK_IGNORE_INTERFACE] = ignore_interface_quirk, - [QUIRK_COMPOSITE] = create_composite_quirk, - [QUIRK_MIDI_STANDARD_INTERFACE] = create_any_midi_quirk, - [QUIRK_MIDI_FIXED_ENDPOINT] = create_any_midi_quirk, - [QUIRK_MIDI_YAMAHA] = create_any_midi_quirk, - [QUIRK_MIDI_MIDIMAN] = create_any_midi_quirk, - [QUIRK_MIDI_NOVATION] = create_any_midi_quirk, - [QUIRK_MIDI_RAW_BYTES] = create_any_midi_quirk, - [QUIRK_MIDI_EMAGIC] = create_any_midi_quirk, - [QUIRK_MIDI_CME] = create_any_midi_quirk, - [QUIRK_MIDI_AKAI] = create_any_midi_quirk, - [QUIRK_MIDI_FTDI] = create_any_midi_quirk, - [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk, - [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk, - [QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk, - [QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk, - [QUIRK_AUDIO_STANDARD_MIXER] = create_standard_mixer_quirk, - }; - - if (quirk->type < QUIRK_TYPE_COUNT) { - return quirk_funcs[quirk->type](chip, iface, driver, quirk); - } else { - snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type); - return -ENXIO; - } -} - -/* - * boot quirks - */ - -#define EXTIGY_FIRMWARE_SIZE_OLD 794 -#define EXTIGY_FIRMWARE_SIZE_NEW 483 - -static int snd_usb_extigy_boot_quirk(struct usb_device *dev, struct usb_interface *intf) -{ - struct usb_host_config *config = dev->actconfig; - int err; - - if (le16_to_cpu(get_cfg_desc(config)->wTotalLength) == EXTIGY_FIRMWARE_SIZE_OLD || - le16_to_cpu(get_cfg_desc(config)->wTotalLength) == EXTIGY_FIRMWARE_SIZE_NEW) { - snd_printdd("sending Extigy boot sequence...\n"); - /* Send message to force it to reconnect with full interface. */ - err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev,0), - 0x10, 0x43, 0x0001, 0x000a, NULL, 0); - if (err < 0) snd_printdd("error sending boot message: %d\n", err); - err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, - &dev->descriptor, sizeof(dev->descriptor)); - config = dev->actconfig; - if (err < 0) snd_printdd("error usb_get_descriptor: %d\n", err); - err = usb_reset_configuration(dev); - if (err < 0) snd_printdd("error usb_reset_configuration: %d\n", err); - snd_printdd("extigy_boot: new boot length = %d\n", - le16_to_cpu(get_cfg_desc(config)->wTotalLength)); - return -ENODEV; /* quit this anyway */ - } - return 0; -} - -static int snd_usb_audigy2nx_boot_quirk(struct usb_device *dev) -{ - u8 buf = 1; - - snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), 0x2a, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER, - 0, 0, &buf, 1); - if (buf == 0) { - snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 0x29, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, - 1, 2000, NULL, 0); - return -ENODEV; - } - return 0; -} - -static int snd_usb_fasttrackpro_boot_quirk(struct usb_device *dev) -{ - int err; - - if (dev->actconfig->desc.bConfigurationValue == 1) { - snd_printk(KERN_INFO "usb-audio: " - "Fast Track Pro switching to config #2\n"); - /* This function has to be available by the usb core module. - * if it is not avialable the boot quirk has to be left out - * and the configuration has to be set by udev or hotplug - * rules - */ - err = usb_driver_set_configuration(dev, 2); - if (err < 0) { - snd_printdd("error usb_driver_set_configuration: %d\n", - err); - return -ENODEV; - } - } else - snd_printk(KERN_INFO "usb-audio: Fast Track Pro config OK\n"); - - return 0; -} - -/* - * C-Media CM106/CM106+ have four 16-bit internal registers that are nicely - * documented in the device's data sheet. - */ -static int snd_usb_cm106_write_int_reg(struct usb_device *dev, int reg, u16 value) -{ - u8 buf[4]; - buf[0] = 0x20; - buf[1] = value & 0xff; - buf[2] = (value >> 8) & 0xff; - buf[3] = reg; - return snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_CONFIGURATION, - USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_ENDPOINT, - 0, 0, &buf, 4); -} - -static int snd_usb_cm106_boot_quirk(struct usb_device *dev) -{ - /* - * Enable line-out driver mode, set headphone source to front - * channels, enable stereo mic. - */ - return snd_usb_cm106_write_int_reg(dev, 2, 0x8004); -} - -/* - * C-Media CM6206 is based on CM106 with two additional - * registers that are not documented in the data sheet. - * Values here are chosen based on sniffing USB traffic - * under Windows. - */ -static int snd_usb_cm6206_boot_quirk(struct usb_device *dev) -{ - int err = 0, reg; - int val[] = {0x2004, 0x3000, 0xf800, 0x143f, 0x0000, 0x3000}; - - for (reg = 0; reg < ARRAY_SIZE(val); reg++) { - err = snd_usb_cm106_write_int_reg(dev, reg, val[reg]); - if (err < 0) - return err; - } - - return err; -} - -/* - * This call will put the synth in "USB send" mode, i.e it will send MIDI - * messages through USB (this is disabled at startup). The synth will - * acknowledge by sending a sysex on endpoint 0x85 and by displaying a USB - * sign on its LCD. Values here are chosen based on sniffing USB traffic - * under Windows. - */ -static int snd_usb_accessmusic_boot_quirk(struct usb_device *dev) -{ - int err, actual_length; - - /* "midi send" enable */ - static const u8 seq[] = { 0x4e, 0x73, 0x52, 0x01 }; - - void *buf = kmemdup(seq, ARRAY_SIZE(seq), GFP_KERNEL); - if (!buf) - return -ENOMEM; - err = usb_interrupt_msg(dev, usb_sndintpipe(dev, 0x05), buf, - ARRAY_SIZE(seq), &actual_length, 1000); - kfree(buf); - if (err < 0) - return err; - - return 0; -} - -/* - * Some sound cards from Native Instruments are in fact compliant to the USB - * audio standard of version 2 and other approved USB standards, even though - * they come up as vendor-specific device when first connected. - * - * However, they can be told to come up with a new set of descriptors - * upon their next enumeration, and the interfaces announced by the new - * descriptors will then be handled by the kernel's class drivers. As the - * product ID will also change, no further checks are required. - */ - -static int snd_usb_nativeinstruments_boot_quirk(struct usb_device *dev) -{ - int ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - 0xaf, USB_TYPE_VENDOR | USB_RECIP_DEVICE, - cpu_to_le16(1), 0, NULL, 0, 1000); - - if (ret < 0) - return ret; - - usb_reset_device(dev); - - /* return -EAGAIN, so the creation of an audio interface for this - * temporary device is aborted. The device will reconnect with a - * new product ID */ - return -EAGAIN; -} - -/* - * Setup quirks - */ -#define MAUDIO_SET 0x01 /* parse device_setup */ -#define MAUDIO_SET_COMPATIBLE 0x80 /* use only "win-compatible" interfaces */ -#define MAUDIO_SET_DTS 0x02 /* enable DTS Digital Output */ -#define MAUDIO_SET_96K 0x04 /* 48-96KHz rate if set, 8-48KHz otherwise */ -#define MAUDIO_SET_24B 0x08 /* 24bits sample if set, 16bits otherwise */ -#define MAUDIO_SET_DI 0x10 /* enable Digital Input */ -#define MAUDIO_SET_MASK 0x1f /* bit mask for setup value */ -#define MAUDIO_SET_24B_48K_DI 0x19 /* 24bits+48KHz+Digital Input */ -#define MAUDIO_SET_24B_48K_NOTDI 0x09 /* 24bits+48KHz+No Digital Input */ -#define MAUDIO_SET_16B_48K_DI 0x11 /* 16bits+48KHz+Digital Input */ -#define MAUDIO_SET_16B_48K_NOTDI 0x01 /* 16bits+48KHz+No Digital Input */ - -static int quattro_skip_setting_quirk(struct snd_usb_audio *chip, - int iface, int altno) -{ - /* Reset ALL ifaces to 0 altsetting. - * Call it for every possible altsetting of every interface. - */ - usb_set_interface(chip->dev, iface, 0); - if (chip->setup & MAUDIO_SET) { - if (chip->setup & MAUDIO_SET_COMPATIBLE) { - if (iface != 1 && iface != 2) - return 1; /* skip all interfaces but 1 and 2 */ - } else { - unsigned int mask; - if (iface == 1 || iface == 2) - return 1; /* skip interfaces 1 and 2 */ - if ((chip->setup & MAUDIO_SET_96K) && altno != 1) - return 1; /* skip this altsetting */ - mask = chip->setup & MAUDIO_SET_MASK; - if (mask == MAUDIO_SET_24B_48K_DI && altno != 2) - return 1; /* skip this altsetting */ - if (mask == MAUDIO_SET_24B_48K_NOTDI && altno != 3) - return 1; /* skip this altsetting */ - if (mask == MAUDIO_SET_16B_48K_NOTDI && altno != 4) - return 1; /* skip this altsetting */ - } - } - snd_printdd(KERN_INFO - "using altsetting %d for interface %d config %d\n", - altno, iface, chip->setup); - return 0; /* keep this altsetting */ -} - -static int audiophile_skip_setting_quirk(struct snd_usb_audio *chip, - int iface, - int altno) -{ - /* Reset ALL ifaces to 0 altsetting. - * Call it for every possible altsetting of every interface. - */ - usb_set_interface(chip->dev, iface, 0); - - if (chip->setup & MAUDIO_SET) { - unsigned int mask; - if ((chip->setup & MAUDIO_SET_DTS) && altno != 6) - return 1; /* skip this altsetting */ - if ((chip->setup & MAUDIO_SET_96K) && altno != 1) - return 1; /* skip this altsetting */ - mask = chip->setup & MAUDIO_SET_MASK; - if (mask == MAUDIO_SET_24B_48K_DI && altno != 2) - return 1; /* skip this altsetting */ - if (mask == MAUDIO_SET_24B_48K_NOTDI && altno != 3) - return 1; /* skip this altsetting */ - if (mask == MAUDIO_SET_16B_48K_DI && altno != 4) - return 1; /* skip this altsetting */ - if (mask == MAUDIO_SET_16B_48K_NOTDI && altno != 5) - return 1; /* skip this altsetting */ - } - - return 0; /* keep this altsetting */ -} - - -static int fasttrackpro_skip_setting_quirk(struct snd_usb_audio *chip, - int iface, int altno) -{ - /* Reset ALL ifaces to 0 altsetting. - * Call it for every possible altsetting of every interface. - */ - usb_set_interface(chip->dev, iface, 0); - - /* possible configuration where both inputs and only one output is - *used is not supported by the current setup - */ - if (chip->setup & (MAUDIO_SET | MAUDIO_SET_24B)) { - if (chip->setup & MAUDIO_SET_96K) { - if (altno != 3 && altno != 6) - return 1; - } else if (chip->setup & MAUDIO_SET_DI) { - if (iface == 4) - return 1; /* no analog input */ - if (altno != 2 && altno != 5) - return 1; /* enable only altsets 2 and 5 */ - } else { - if (iface == 5) - return 1; /* disable digialt input */ - if (altno != 2 && altno != 5) - return 1; /* enalbe only altsets 2 and 5 */ - } - } else { - /* keep only 16-Bit mode */ - if (altno != 1) - return 1; - } - - snd_printdd(KERN_INFO - "using altsetting %d for interface %d config %d\n", - altno, iface, chip->setup); - return 0; /* keep this altsetting */ -} - -int snd_usb_apply_interface_quirk(struct snd_usb_audio *chip, - int iface, - int altno) -{ - /* audiophile usb: skip altsets incompatible with device_setup */ - if (chip->usb_id == USB_ID(0x0763, 0x2003)) - return audiophile_skip_setting_quirk(chip, iface, altno); - /* quattro usb: skip altsets incompatible with device_setup */ - if (chip->usb_id == USB_ID(0x0763, 0x2001)) - return quattro_skip_setting_quirk(chip, iface, altno); - /* fasttrackpro usb: skip altsets incompatible with device_setup */ - if (chip->usb_id == USB_ID(0x0763, 0x2012)) - return fasttrackpro_skip_setting_quirk(chip, iface, altno); - - return 0; -} - -int snd_usb_apply_boot_quirk(struct usb_device *dev, - struct usb_interface *intf, - const struct snd_usb_audio_quirk *quirk) -{ - u32 id = USB_ID(le16_to_cpu(dev->descriptor.idVendor), - le16_to_cpu(dev->descriptor.idProduct)); - - switch (id) { - case USB_ID(0x041e, 0x3000): - /* SB Extigy needs special boot-up sequence */ - /* if more models come, this will go to the quirk list. */ - return snd_usb_extigy_boot_quirk(dev, intf); - - case USB_ID(0x041e, 0x3020): - /* SB Audigy 2 NX needs its own boot-up magic, too */ - return snd_usb_audigy2nx_boot_quirk(dev); - - case USB_ID(0x10f5, 0x0200): - /* C-Media CM106 / Turtle Beach Audio Advantage Roadie */ - return snd_usb_cm106_boot_quirk(dev); - - case USB_ID(0x0d8c, 0x0102): - /* C-Media CM6206 / CM106-Like Sound Device */ - case USB_ID(0x0ccd, 0x00b1): /* Terratec Aureon 7.1 USB */ - return snd_usb_cm6206_boot_quirk(dev); - - case USB_ID(0x133e, 0x0815): - /* Access Music VirusTI Desktop */ - return snd_usb_accessmusic_boot_quirk(dev); - - case USB_ID(0x17cc, 0x1000): /* Komplete Audio 6 */ - case USB_ID(0x17cc, 0x1010): /* Traktor Audio 6 */ - case USB_ID(0x17cc, 0x1020): /* Traktor Audio 10 */ - return snd_usb_nativeinstruments_boot_quirk(dev); - case USB_ID(0x0763, 0x2012): /* M-Audio Fast Track Pro USB */ - return snd_usb_fasttrackpro_boot_quirk(dev); - } - - return 0; -} - -/* - * check if the device uses big-endian samples - */ -int snd_usb_is_big_endian_format(struct snd_usb_audio *chip, struct audioformat *fp) -{ - /* it depends on altsetting wether the device is big-endian or not */ - switch (chip->usb_id) { - case USB_ID(0x0763, 0x2001): /* M-Audio Quattro: captured data only */ - if (fp->altsetting == 2 || fp->altsetting == 3 || - fp->altsetting == 5 || fp->altsetting == 6) - return 1; - break; - case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */ - if (chip->setup == 0x00 || - fp->altsetting == 1 || fp->altsetting == 2 || - fp->altsetting == 3) - return 1; - break; - case USB_ID(0x0763, 0x2012): /* M-Audio Fast Track Pro */ - if (fp->altsetting == 2 || fp->altsetting == 3 || - fp->altsetting == 5 || fp->altsetting == 6) - return 1; - break; - } - return 0; -} - -/* - * For E-Mu 0404USB/0202USB/TrackerPre/0204 sample rate should be set for device, - * not for interface. - */ - -enum { - EMU_QUIRK_SR_44100HZ = 0, - EMU_QUIRK_SR_48000HZ, - EMU_QUIRK_SR_88200HZ, - EMU_QUIRK_SR_96000HZ, - EMU_QUIRK_SR_176400HZ, - EMU_QUIRK_SR_192000HZ -}; - -static void set_format_emu_quirk(struct snd_usb_substream *subs, - struct audioformat *fmt) -{ - unsigned char emu_samplerate_id = 0; - - /* When capture is active - * sample rate shouldn't be changed - * by playback substream - */ - if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) { - if (subs->stream->substream[SNDRV_PCM_STREAM_CAPTURE].interface != -1) - return; - } - - switch (fmt->rate_min) { - case 48000: - emu_samplerate_id = EMU_QUIRK_SR_48000HZ; - break; - case 88200: - emu_samplerate_id = EMU_QUIRK_SR_88200HZ; - break; - case 96000: - emu_samplerate_id = EMU_QUIRK_SR_96000HZ; - break; - case 176400: - emu_samplerate_id = EMU_QUIRK_SR_176400HZ; - break; - case 192000: - emu_samplerate_id = EMU_QUIRK_SR_192000HZ; - break; - default: - emu_samplerate_id = EMU_QUIRK_SR_44100HZ; - break; - } - snd_emuusb_set_samplerate(subs->stream->chip, emu_samplerate_id); -} - -void snd_usb_set_format_quirk(struct snd_usb_substream *subs, - struct audioformat *fmt) -{ - switch (subs->stream->chip->usb_id) { - case USB_ID(0x041e, 0x3f02): /* E-Mu 0202 USB */ - case USB_ID(0x041e, 0x3f04): /* E-Mu 0404 USB */ - case USB_ID(0x041e, 0x3f0a): /* E-Mu Tracker Pre */ - case USB_ID(0x041e, 0x3f19): /* E-Mu 0204 USB */ - set_format_emu_quirk(subs, fmt); - break; - } -} - diff --git a/ANDROID_3.4.5/sound/usb/quirks.h b/ANDROID_3.4.5/sound/usb/quirks.h deleted file mode 100644 index 03e5e940..00000000 --- a/ANDROID_3.4.5/sound/usb/quirks.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef __USBAUDIO_QUIRKS_H -#define __USBAUDIO_QUIRKS_H - -int snd_usb_create_quirk(struct snd_usb_audio *chip, - struct usb_interface *iface, - struct usb_driver *driver, - const struct snd_usb_audio_quirk *quirk); - -int snd_usb_apply_interface_quirk(struct snd_usb_audio *chip, - int iface, - int altno); - -int snd_usb_apply_boot_quirk(struct usb_device *dev, - struct usb_interface *intf, - const struct snd_usb_audio_quirk *quirk); - -void snd_usb_set_format_quirk(struct snd_usb_substream *subs, - struct audioformat *fmt); - -int snd_usb_is_big_endian_format(struct snd_usb_audio *chip, - struct audioformat *fp); - -#endif /* __USBAUDIO_QUIRKS_H */ diff --git a/ANDROID_3.4.5/sound/usb/stream.c b/ANDROID_3.4.5/sound/usb/stream.c deleted file mode 100644 index 5ff8010b..00000000 --- a/ANDROID_3.4.5/sound/usb/stream.c +++ /dev/null @@ -1,452 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -#include -#include -#include -#include -#include - -#include -#include - -#include "usbaudio.h" -#include "card.h" -#include "proc.h" -#include "quirks.h" -#include "endpoint.h" -#include "pcm.h" -#include "helper.h" -#include "format.h" -#include "clock.h" -#include "stream.h" - -/* - * free a substream - */ -static void free_substream(struct snd_usb_substream *subs) -{ - struct list_head *p, *n; - - if (!subs->num_formats) - return; /* not initialized */ - list_for_each_safe(p, n, &subs->fmt_list) { - struct audioformat *fp = list_entry(p, struct audioformat, list); - kfree(fp->rate_table); - kfree(fp); - } - kfree(subs->rate_list.list); -} - - -/* - * free a usb stream instance - */ -static void snd_usb_audio_stream_free(struct snd_usb_stream *stream) -{ - free_substream(&stream->substream[0]); - free_substream(&stream->substream[1]); - list_del(&stream->list); - kfree(stream); -} - -static void snd_usb_audio_pcm_free(struct snd_pcm *pcm) -{ - struct snd_usb_stream *stream = pcm->private_data; - if (stream) { - stream->pcm = NULL; - snd_usb_audio_stream_free(stream); - } -} - - -/* - * add this endpoint to the chip instance. - * if a stream with the same endpoint already exists, append to it. - * if not, create a new pcm stream. - */ -int snd_usb_add_audio_stream(struct snd_usb_audio *chip, - int stream, - struct audioformat *fp) -{ - struct list_head *p; - struct snd_usb_stream *as; - struct snd_usb_substream *subs; - struct snd_pcm *pcm; - int err; - - list_for_each(p, &chip->pcm_list) { - as = list_entry(p, struct snd_usb_stream, list); - if (as->fmt_type != fp->fmt_type) - continue; - subs = &as->substream[stream]; - if (!subs->endpoint) - continue; - if (subs->endpoint == fp->endpoint) { - list_add_tail(&fp->list, &subs->fmt_list); - subs->num_formats++; - subs->formats |= fp->formats; - return 0; - } - } - /* look for an empty stream */ - list_for_each(p, &chip->pcm_list) { - as = list_entry(p, struct snd_usb_stream, list); - if (as->fmt_type != fp->fmt_type) - continue; - subs = &as->substream[stream]; - if (subs->endpoint) - continue; - err = snd_pcm_new_stream(as->pcm, stream, 1); - if (err < 0) - return err; - snd_usb_init_substream(as, stream, fp); - return 0; - } - - /* create a new pcm */ - as = kzalloc(sizeof(*as), GFP_KERNEL); - if (!as) - return -ENOMEM; - as->pcm_index = chip->pcm_devs; - as->chip = chip; - as->fmt_type = fp->fmt_type; - err = snd_pcm_new(chip->card, "USB Audio", chip->pcm_devs, - stream == SNDRV_PCM_STREAM_PLAYBACK ? 1 : 0, - stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1, - &pcm); - if (err < 0) { - kfree(as); - return err; - } - as->pcm = pcm; - pcm->private_data = as; - pcm->private_free = snd_usb_audio_pcm_free; - pcm->info_flags = 0; - if (chip->pcm_devs > 0) - sprintf(pcm->name, "USB Audio #%d", chip->pcm_devs); - else - strcpy(pcm->name, "USB Audio"); - - snd_usb_init_substream(as, stream, fp); - - list_add(&as->list, &chip->pcm_list); - chip->pcm_devs++; - - snd_usb_proc_pcm_format_add(as); - - return 0; -} - -static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip, - struct usb_host_interface *alts, - int protocol, int iface_no) -{ - /* parsed with a v1 header here. that's ok as we only look at the - * header first which is the same for both versions */ - struct uac_iso_endpoint_descriptor *csep; - struct usb_interface_descriptor *altsd = get_iface_desc(alts); - int attributes = 0; - - csep = snd_usb_find_desc(alts->endpoint[0].extra, alts->endpoint[0].extralen, NULL, USB_DT_CS_ENDPOINT); - - /* Creamware Noah has this descriptor after the 2nd endpoint */ - if (!csep && altsd->bNumEndpoints >= 2) - csep = snd_usb_find_desc(alts->endpoint[1].extra, alts->endpoint[1].extralen, NULL, USB_DT_CS_ENDPOINT); - - if (!csep || csep->bLength < 7 || - csep->bDescriptorSubtype != UAC_EP_GENERAL) { - snd_printk(KERN_WARNING "%d:%u:%d : no or invalid" - " class specific endpoint descriptor\n", - chip->dev->devnum, iface_no, - altsd->bAlternateSetting); - return 0; - } - - if (protocol == UAC_VERSION_1) { - attributes = csep->bmAttributes; - } else { - struct uac2_iso_endpoint_descriptor *csep2 = - (struct uac2_iso_endpoint_descriptor *) csep; - - attributes = csep->bmAttributes & UAC_EP_CS_ATTR_FILL_MAX; - - /* emulate the endpoint attributes of a v1 device */ - if (csep2->bmControls & UAC2_CONTROL_PITCH) - attributes |= UAC_EP_CS_ATTR_PITCH_CONTROL; - } - - return attributes; -} - -static struct uac2_input_terminal_descriptor * - snd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface, - int terminal_id) -{ - struct uac2_input_terminal_descriptor *term = NULL; - - while ((term = snd_usb_find_csint_desc(ctrl_iface->extra, - ctrl_iface->extralen, - term, UAC_INPUT_TERMINAL))) { - if (term->bTerminalID == terminal_id) - return term; - } - - return NULL; -} - -static struct uac2_output_terminal_descriptor * - snd_usb_find_output_terminal_descriptor(struct usb_host_interface *ctrl_iface, - int terminal_id) -{ - struct uac2_output_terminal_descriptor *term = NULL; - - while ((term = snd_usb_find_csint_desc(ctrl_iface->extra, - ctrl_iface->extralen, - term, UAC_OUTPUT_TERMINAL))) { - if (term->bTerminalID == terminal_id) - return term; - } - - return NULL; -} - -int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) -{ - struct usb_device *dev; - struct usb_interface *iface; - struct usb_host_interface *alts; - struct usb_interface_descriptor *altsd; - int i, altno, err, stream; - int format = 0, num_channels = 0; - struct audioformat *fp = NULL; - int num, protocol, clock = 0; - struct uac_format_type_i_continuous_descriptor *fmt; - - dev = chip->dev; - - /* parse the interface's altsettings */ - iface = usb_ifnum_to_if(dev, iface_no); - - num = iface->num_altsetting; - - /* - * Dallas DS4201 workaround: It presents 5 altsettings, but the last - * one misses syncpipe, and does not produce any sound. - */ - if (chip->usb_id == USB_ID(0x04fa, 0x4201)) - num = 4; - - for (i = 0; i < num; i++) { - alts = &iface->altsetting[i]; - altsd = get_iface_desc(alts); - protocol = altsd->bInterfaceProtocol; - /* skip invalid one */ - if ((altsd->bInterfaceClass != USB_CLASS_AUDIO && - altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC) || - (altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIOSTREAMING && - altsd->bInterfaceSubClass != USB_SUBCLASS_VENDOR_SPEC) || - altsd->bNumEndpoints < 1 || - le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) == 0) - continue; - /* must be isochronous */ - if ((get_endpoint(alts, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != - USB_ENDPOINT_XFER_ISOC) - continue; - /* check direction */ - stream = (get_endpoint(alts, 0)->bEndpointAddress & USB_DIR_IN) ? - SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; - altno = altsd->bAlternateSetting; - - if (snd_usb_apply_interface_quirk(chip, iface_no, altno)) - continue; - - /* get audio formats */ - switch (protocol) { - default: - snd_printdd(KERN_WARNING "%d:%u:%d: unknown interface protocol %#02x, assuming v1\n", - dev->devnum, iface_no, altno, protocol); - protocol = UAC_VERSION_1; - /* fall through */ - - case UAC_VERSION_1: { - struct uac1_as_header_descriptor *as = - snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL); - - if (!as) { - snd_printk(KERN_ERR "%d:%u:%d : UAC_AS_GENERAL descriptor not found\n", - dev->devnum, iface_no, altno); - continue; - } - - if (as->bLength < sizeof(*as)) { - snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_AS_GENERAL desc\n", - dev->devnum, iface_no, altno); - continue; - } - - format = le16_to_cpu(as->wFormatTag); /* remember the format value */ - break; - } - - case UAC_VERSION_2: { - struct uac2_input_terminal_descriptor *input_term; - struct uac2_output_terminal_descriptor *output_term; - struct uac2_as_header_descriptor *as = - snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL); - - if (!as) { - snd_printk(KERN_ERR "%d:%u:%d : UAC_AS_GENERAL descriptor not found\n", - dev->devnum, iface_no, altno); - continue; - } - - if (as->bLength < sizeof(*as)) { - snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_AS_GENERAL desc\n", - dev->devnum, iface_no, altno); - continue; - } - - num_channels = as->bNrChannels; - format = le32_to_cpu(as->bmFormats); - - /* lookup the terminal associated to this interface - * to extract the clock */ - input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf, - as->bTerminalLink); - if (input_term) { - clock = input_term->bCSourceID; - break; - } - - output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf, - as->bTerminalLink); - if (output_term) { - clock = output_term->bCSourceID; - break; - } - - snd_printk(KERN_ERR "%d:%u:%d : bogus bTerminalLink %d\n", - dev->devnum, iface_no, altno, as->bTerminalLink); - continue; - } - } - - /* get format type */ - fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_FORMAT_TYPE); - if (!fmt) { - snd_printk(KERN_ERR "%d:%u:%d : no UAC_FORMAT_TYPE desc\n", - dev->devnum, iface_no, altno); - continue; - } - if (((protocol == UAC_VERSION_1) && (fmt->bLength < 8)) || - ((protocol == UAC_VERSION_2) && (fmt->bLength < 6))) { - snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_FORMAT_TYPE desc\n", - dev->devnum, iface_no, altno); - continue; - } - - /* - * Blue Microphones workaround: The last altsetting is identical - * with the previous one, except for a larger packet size, but - * is actually a mislabeled two-channel setting; ignore it. - */ - if (fmt->bNrChannels == 1 && - fmt->bSubframeSize == 2 && - altno == 2 && num == 3 && - fp && fp->altsetting == 1 && fp->channels == 1 && - fp->formats == SNDRV_PCM_FMTBIT_S16_LE && - protocol == UAC_VERSION_1 && - le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) == - fp->maxpacksize * 2) - continue; - - fp = kzalloc(sizeof(*fp), GFP_KERNEL); - if (! fp) { - snd_printk(KERN_ERR "cannot malloc\n"); - return -ENOMEM; - } - - fp->iface = iface_no; - fp->altsetting = altno; - fp->altset_idx = i; - fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; - fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; - fp->datainterval = snd_usb_parse_datainterval(chip, alts); - fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); - /* num_channels is only set for v2 interfaces */ - fp->channels = num_channels; - if (snd_usb_get_speed(dev) == USB_SPEED_HIGH) - fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1) - * (fp->maxpacksize & 0x7ff); - fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no); - fp->clock = clock; - - /* some quirks for attributes here */ - - switch (chip->usb_id) { - case USB_ID(0x0a92, 0x0053): /* AudioTrak Optoplay */ - /* Optoplay sets the sample rate attribute although - * it seems not supporting it in fact. - */ - fp->attributes &= ~UAC_EP_CS_ATTR_SAMPLE_RATE; - break; - case USB_ID(0x041e, 0x3020): /* Creative SB Audigy 2 NX */ - case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */ - /* doesn't set the sample rate attribute, but supports it */ - fp->attributes |= UAC_EP_CS_ATTR_SAMPLE_RATE; - break; - case USB_ID(0x0763, 0x2001): /* M-Audio Quattro USB */ - case USB_ID(0x0763, 0x2012): /* M-Audio Fast Track Pro USB */ - case USB_ID(0x047f, 0x0ca1): /* plantronics headset */ - case USB_ID(0x077d, 0x07af): /* Griffin iMic (note that there is - an older model 77d:223) */ - /* - * plantronics headset and Griffin iMic have set adaptive-in - * although it's really not... - */ - fp->ep_attr &= ~USB_ENDPOINT_SYNCTYPE; - if (stream == SNDRV_PCM_STREAM_PLAYBACK) - fp->ep_attr |= USB_ENDPOINT_SYNC_ADAPTIVE; - else - fp->ep_attr |= USB_ENDPOINT_SYNC_SYNC; - break; - } - - /* ok, let's parse further... */ - if (snd_usb_parse_audio_format(chip, fp, format, fmt, stream, alts) < 0) { - kfree(fp->rate_table); - kfree(fp); - fp = NULL; - continue; - } - - snd_printdd(KERN_INFO "%d:%u:%d: add audio endpoint %#x\n", dev->devnum, iface_no, altno, fp->endpoint); - err = snd_usb_add_audio_stream(chip, stream, fp); - if (err < 0) { - kfree(fp->rate_table); - kfree(fp); - return err; - } - /* try to set the interface... */ - usb_set_interface(chip->dev, iface_no, altno); - snd_usb_init_pitch(chip, iface_no, alts, fp); - snd_usb_init_sample_rate(chip, iface_no, alts, fp, fp->rate_max); - } - return 0; -} - diff --git a/ANDROID_3.4.5/sound/usb/stream.h b/ANDROID_3.4.5/sound/usb/stream.h deleted file mode 100644 index c97f679f..00000000 --- a/ANDROID_3.4.5/sound/usb/stream.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef __USBAUDIO_STREAM_H -#define __USBAUDIO_STREAM_H - -int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, - int iface_no); - -int snd_usb_add_audio_stream(struct snd_usb_audio *chip, - int stream, - struct audioformat *fp); - -#endif /* __USBAUDIO_STREAM_H */ - diff --git a/ANDROID_3.4.5/sound/usb/usbaudio.h b/ANDROID_3.4.5/sound/usb/usbaudio.h deleted file mode 100644 index 3e2b0357..00000000 --- a/ANDROID_3.4.5/sound/usb/usbaudio.h +++ /dev/null @@ -1,105 +0,0 @@ -#ifndef __USBAUDIO_H -#define __USBAUDIO_H -/* - * (Tentative) USB Audio Driver for ALSA - * - * Copyright (c) 2002 by Takashi Iwai - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* handling of USB vendor/product ID pairs as 32-bit numbers */ -#define USB_ID(vendor, product) (((vendor) << 16) | (product)) -#define USB_ID_VENDOR(id) ((id) >> 16) -#define USB_ID_PRODUCT(id) ((u16)(id)) - -/* - * - */ - -struct snd_usb_audio { - int index; - struct usb_device *dev; - struct snd_card *card; - struct usb_interface *pm_intf; - u32 usb_id; - struct mutex shutdown_mutex; - unsigned int shutdown:1; - unsigned int probing:1; - unsigned int autosuspended:1; - unsigned int txfr_quirk:1; /* Subframe boundaries on transfers */ - - int num_interfaces; - int num_suspended_intf; - - struct list_head pcm_list; /* list of pcm streams */ - int pcm_devs; - - struct list_head midi_list; /* list of midi interfaces */ - - struct list_head mixer_list; /* list of mixer interfaces */ - - int setup; /* from the 'device_setup' module param */ - int nrpacks; /* from the 'nrpacks' module param */ - int async_unlink; /* from the 'async_unlink' module param */ - - struct usb_host_interface *ctrl_intf; /* the audio control interface */ -}; - -/* - * Information about devices with broken descriptors - */ - -/* special values for .ifnum */ -#define QUIRK_NO_INTERFACE -2 -#define QUIRK_ANY_INTERFACE -1 - -enum quirk_type { - QUIRK_IGNORE_INTERFACE, - QUIRK_COMPOSITE, - QUIRK_MIDI_STANDARD_INTERFACE, - QUIRK_MIDI_FIXED_ENDPOINT, - QUIRK_MIDI_YAMAHA, - QUIRK_MIDI_MIDIMAN, - QUIRK_MIDI_NOVATION, - QUIRK_MIDI_RAW_BYTES, - QUIRK_MIDI_EMAGIC, - QUIRK_MIDI_CME, - QUIRK_MIDI_AKAI, - QUIRK_MIDI_US122L, - QUIRK_MIDI_FTDI, - QUIRK_AUDIO_STANDARD_INTERFACE, - QUIRK_AUDIO_FIXED_ENDPOINT, - QUIRK_AUDIO_EDIROL_UAXX, - QUIRK_AUDIO_ALIGN_TRANSFER, - QUIRK_AUDIO_STANDARD_MIXER, - - QUIRK_TYPE_COUNT -}; - -struct snd_usb_audio_quirk { - const char *vendor_name; - const char *product_name; - int16_t ifnum; - uint16_t type; - const void *data; -}; - -#define combine_word(s) ((*(s)) | ((unsigned int)(s)[1] << 8)) -#define combine_triple(s) (combine_word(s) | ((unsigned int)(s)[2] << 16)) -#define combine_quad(s) (combine_triple(s) | ((unsigned int)(s)[3] << 24)) - -#endif /* __USBAUDIO_H */ diff --git a/ANDROID_3.4.5/sound/usb/usx2y/Makefile b/ANDROID_3.4.5/sound/usb/usx2y/Makefile deleted file mode 100644 index 74893305..00000000 --- a/ANDROID_3.4.5/sound/usb/usx2y/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -snd-usb-usx2y-objs := usbusx2y.o usX2Yhwdep.o usx2yhwdeppcm.o -snd-usb-us122l-objs := us122l.o - -obj-$(CONFIG_SND_USB_USX2Y) += snd-usb-usx2y.o -obj-$(CONFIG_SND_USB_US122L) += snd-usb-us122l.o diff --git a/ANDROID_3.4.5/sound/usb/usx2y/us122l.c b/ANDROID_3.4.5/sound/usb/usx2y/us122l.c deleted file mode 100644 index c4fd3b1d..00000000 --- a/ANDROID_3.4.5/sound/usb/usx2y/us122l.c +++ /dev/null @@ -1,775 +0,0 @@ -/* - * Copyright (C) 2007, 2008 Karsten Wiese - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#define MODNAME "US122L" -#include "usb_stream.c" -#include "../usbaudio.h" -#include "../midi.h" -#include "us122l.h" - -MODULE_AUTHOR("Karsten Wiese "); -MODULE_DESCRIPTION("TASCAM "NAME_ALLCAPS" Version 0.5"); -MODULE_LICENSE("GPL"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */ - /* Enable this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for "NAME_ALLCAPS"."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for "NAME_ALLCAPS"."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable "NAME_ALLCAPS"."); - -static int snd_us122l_card_used[SNDRV_CARDS]; - - -static int us122l_create_usbmidi(struct snd_card *card) -{ - static struct snd_usb_midi_endpoint_info quirk_data = { - .out_ep = 4, - .in_ep = 3, - .out_cables = 0x001, - .in_cables = 0x001 - }; - static struct snd_usb_audio_quirk quirk = { - .vendor_name = "US122L", - .product_name = NAME_ALLCAPS, - .ifnum = 1, - .type = QUIRK_MIDI_US122L, - .data = &quirk_data - }; - struct usb_device *dev = US122L(card)->dev; - struct usb_interface *iface = usb_ifnum_to_if(dev, 1); - - return snd_usbmidi_create(card, iface, - &US122L(card)->midi_list, &quirk); -} - -static int us144_create_usbmidi(struct snd_card *card) -{ - static struct snd_usb_midi_endpoint_info quirk_data = { - .out_ep = 4, - .in_ep = 3, - .out_cables = 0x001, - .in_cables = 0x001 - }; - static struct snd_usb_audio_quirk quirk = { - .vendor_name = "US144", - .product_name = NAME_ALLCAPS, - .ifnum = 0, - .type = QUIRK_MIDI_US122L, - .data = &quirk_data - }; - struct usb_device *dev = US122L(card)->dev; - struct usb_interface *iface = usb_ifnum_to_if(dev, 0); - - return snd_usbmidi_create(card, iface, - &US122L(card)->midi_list, &quirk); -} - -/* - * Wrapper for usb_control_msg(). - * Allocates a temp buffer to prevent dmaing from/to the stack. - */ -static int us122l_ctl_msg(struct usb_device *dev, unsigned int pipe, - __u8 request, __u8 requesttype, - __u16 value, __u16 index, void *data, - __u16 size, int timeout) -{ - int err; - void *buf = NULL; - - if (size > 0) { - buf = kmemdup(data, size, GFP_KERNEL); - if (!buf) - return -ENOMEM; - } - err = usb_control_msg(dev, pipe, request, requesttype, - value, index, buf, size, timeout); - if (size > 0) { - memcpy(data, buf, size); - kfree(buf); - } - return err; -} - -static void pt_info_set(struct usb_device *dev, u8 v) -{ - int ret; - - ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - 'I', - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - v, 0, NULL, 0, 1000); - snd_printdd(KERN_DEBUG "%i\n", ret); -} - -static void usb_stream_hwdep_vm_open(struct vm_area_struct *area) -{ - struct us122l *us122l = area->vm_private_data; - atomic_inc(&us122l->mmap_count); - snd_printdd(KERN_DEBUG "%i\n", atomic_read(&us122l->mmap_count)); -} - -static int usb_stream_hwdep_vm_fault(struct vm_area_struct *area, - struct vm_fault *vmf) -{ - unsigned long offset; - struct page *page; - void *vaddr; - struct us122l *us122l = area->vm_private_data; - struct usb_stream *s; - - mutex_lock(&us122l->mutex); - s = us122l->sk.s; - if (!s) - goto unlock; - - offset = vmf->pgoff << PAGE_SHIFT; - if (offset < PAGE_ALIGN(s->read_size)) - vaddr = (char *)s + offset; - else { - offset -= PAGE_ALIGN(s->read_size); - if (offset >= PAGE_ALIGN(s->write_size)) - goto unlock; - - vaddr = us122l->sk.write_page + offset; - } - page = virt_to_page(vaddr); - - get_page(page); - mutex_unlock(&us122l->mutex); - - vmf->page = page; - - return 0; -unlock: - mutex_unlock(&us122l->mutex); - return VM_FAULT_SIGBUS; -} - -static void usb_stream_hwdep_vm_close(struct vm_area_struct *area) -{ - struct us122l *us122l = area->vm_private_data; - atomic_dec(&us122l->mmap_count); - snd_printdd(KERN_DEBUG "%i\n", atomic_read(&us122l->mmap_count)); -} - -static const struct vm_operations_struct usb_stream_hwdep_vm_ops = { - .open = usb_stream_hwdep_vm_open, - .fault = usb_stream_hwdep_vm_fault, - .close = usb_stream_hwdep_vm_close, -}; - - -static int usb_stream_hwdep_open(struct snd_hwdep *hw, struct file *file) -{ - struct us122l *us122l = hw->private_data; - struct usb_interface *iface; - snd_printdd(KERN_DEBUG "%p %p\n", hw, file); - if (hw->used >= 2) - return -EBUSY; - - if (!us122l->first) - us122l->first = file; - - if (us122l->dev->descriptor.idProduct == USB_ID_US144 || - us122l->dev->descriptor.idProduct == USB_ID_US144MKII) { - iface = usb_ifnum_to_if(us122l->dev, 0); - usb_autopm_get_interface(iface); - } - iface = usb_ifnum_to_if(us122l->dev, 1); - usb_autopm_get_interface(iface); - return 0; -} - -static int usb_stream_hwdep_release(struct snd_hwdep *hw, struct file *file) -{ - struct us122l *us122l = hw->private_data; - struct usb_interface *iface; - snd_printdd(KERN_DEBUG "%p %p\n", hw, file); - - if (us122l->dev->descriptor.idProduct == USB_ID_US144 || - us122l->dev->descriptor.idProduct == USB_ID_US144MKII) { - iface = usb_ifnum_to_if(us122l->dev, 0); - usb_autopm_put_interface(iface); - } - iface = usb_ifnum_to_if(us122l->dev, 1); - usb_autopm_put_interface(iface); - if (us122l->first == file) - us122l->first = NULL; - mutex_lock(&us122l->mutex); - if (us122l->master == file) - us122l->master = us122l->slave; - - us122l->slave = NULL; - mutex_unlock(&us122l->mutex); - return 0; -} - -static int usb_stream_hwdep_mmap(struct snd_hwdep *hw, - struct file *filp, struct vm_area_struct *area) -{ - unsigned long size = area->vm_end - area->vm_start; - struct us122l *us122l = hw->private_data; - unsigned long offset; - struct usb_stream *s; - int err = 0; - bool read; - - offset = area->vm_pgoff << PAGE_SHIFT; - mutex_lock(&us122l->mutex); - s = us122l->sk.s; - read = offset < s->read_size; - if (read && area->vm_flags & VM_WRITE) { - err = -EPERM; - goto out; - } - snd_printdd(KERN_DEBUG "%lu %u\n", size, - read ? s->read_size : s->write_size); - /* if userspace tries to mmap beyond end of our buffer, fail */ - if (size > PAGE_ALIGN(read ? s->read_size : s->write_size)) { - snd_printk(KERN_WARNING "%lu > %u\n", size, - read ? s->read_size : s->write_size); - err = -EINVAL; - goto out; - } - - area->vm_ops = &usb_stream_hwdep_vm_ops; - area->vm_flags |= VM_RESERVED; - area->vm_private_data = us122l; - atomic_inc(&us122l->mmap_count); -out: - mutex_unlock(&us122l->mutex); - return err; -} - -static unsigned int usb_stream_hwdep_poll(struct snd_hwdep *hw, - struct file *file, poll_table *wait) -{ - struct us122l *us122l = hw->private_data; - unsigned *polled; - unsigned int mask; - - poll_wait(file, &us122l->sk.sleep, wait); - - mask = POLLIN | POLLOUT | POLLWRNORM | POLLERR; - if (mutex_trylock(&us122l->mutex)) { - struct usb_stream *s = us122l->sk.s; - if (s && s->state == usb_stream_ready) { - if (us122l->first == file) - polled = &s->periods_polled; - else - polled = &us122l->second_periods_polled; - if (*polled != s->periods_done) { - *polled = s->periods_done; - mask = POLLIN | POLLOUT | POLLWRNORM; - } else - mask = 0; - } - mutex_unlock(&us122l->mutex); - } - return mask; -} - -static void us122l_stop(struct us122l *us122l) -{ - struct list_head *p; - list_for_each(p, &us122l->midi_list) - snd_usbmidi_input_stop(p); - - usb_stream_stop(&us122l->sk); - usb_stream_free(&us122l->sk); -} - -static int us122l_set_sample_rate(struct usb_device *dev, int rate) -{ - unsigned int ep = 0x81; - unsigned char data[3]; - int err; - - data[0] = rate; - data[1] = rate >> 8; - data[2] = rate >> 16; - err = us122l_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR, - USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, - UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep, data, 3, 1000); - if (err < 0) - snd_printk(KERN_ERR "%d: cannot set freq %d to ep 0x%x\n", - dev->devnum, rate, ep); - return err; -} - -static bool us122l_start(struct us122l *us122l, - unsigned rate, unsigned period_frames) -{ - struct list_head *p; - int err; - unsigned use_packsize = 0; - bool success = false; - - if (us122l->dev->speed == USB_SPEED_HIGH) { - /* The us-122l's descriptor defaults to iso max_packsize 78, - which isn't needed for samplerates <= 48000. - Lets save some memory: - */ - switch (rate) { - case 44100: - use_packsize = 36; - break; - case 48000: - use_packsize = 42; - break; - case 88200: - use_packsize = 72; - break; - } - } - if (!usb_stream_new(&us122l->sk, us122l->dev, 1, 2, - rate, use_packsize, period_frames, 6)) - goto out; - - err = us122l_set_sample_rate(us122l->dev, rate); - if (err < 0) { - us122l_stop(us122l); - snd_printk(KERN_ERR "us122l_set_sample_rate error \n"); - goto out; - } - err = usb_stream_start(&us122l->sk); - if (err < 0) { - us122l_stop(us122l); - snd_printk(KERN_ERR "us122l_start error %i \n", err); - goto out; - } - list_for_each(p, &us122l->midi_list) - snd_usbmidi_input_start(p); - success = true; -out: - return success; -} - -static int usb_stream_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, - unsigned cmd, unsigned long arg) -{ - struct usb_stream_config *cfg; - struct us122l *us122l = hw->private_data; - struct usb_stream *s; - unsigned min_period_frames; - int err = 0; - bool high_speed; - - if (cmd != SNDRV_USB_STREAM_IOCTL_SET_PARAMS) - return -ENOTTY; - - cfg = memdup_user((void *)arg, sizeof(*cfg)); - if (IS_ERR(cfg)) - return PTR_ERR(cfg); - - if (cfg->version != USB_STREAM_INTERFACE_VERSION) { - err = -ENXIO; - goto free; - } - high_speed = us122l->dev->speed == USB_SPEED_HIGH; - if ((cfg->sample_rate != 44100 && cfg->sample_rate != 48000 && - (!high_speed || - (cfg->sample_rate != 88200 && cfg->sample_rate != 96000))) || - cfg->frame_size != 6 || - cfg->period_frames > 0x3000) { - err = -EINVAL; - goto free; - } - switch (cfg->sample_rate) { - case 44100: - min_period_frames = 48; - break; - case 48000: - min_period_frames = 52; - break; - default: - min_period_frames = 104; - break; - } - if (!high_speed) - min_period_frames <<= 1; - if (cfg->period_frames < min_period_frames) { - err = -EINVAL; - goto free; - } - - snd_power_wait(hw->card, SNDRV_CTL_POWER_D0); - - mutex_lock(&us122l->mutex); - s = us122l->sk.s; - if (!us122l->master) - us122l->master = file; - else if (us122l->master != file) { - if (!s || memcmp(cfg, &s->cfg, sizeof(*cfg))) { - err = -EIO; - goto unlock; - } - us122l->slave = file; - } - if (!s || memcmp(cfg, &s->cfg, sizeof(*cfg)) || - s->state == usb_stream_xrun) { - us122l_stop(us122l); - if (!us122l_start(us122l, cfg->sample_rate, cfg->period_frames)) - err = -EIO; - else - err = 1; - } -unlock: - mutex_unlock(&us122l->mutex); -free: - kfree(cfg); - wake_up_all(&us122l->sk.sleep); - return err; -} - -#define SND_USB_STREAM_ID "USB STREAM" -static int usb_stream_hwdep_new(struct snd_card *card) -{ - int err; - struct snd_hwdep *hw; - struct usb_device *dev = US122L(card)->dev; - - err = snd_hwdep_new(card, SND_USB_STREAM_ID, 0, &hw); - if (err < 0) - return err; - - hw->iface = SNDRV_HWDEP_IFACE_USB_STREAM; - hw->private_data = US122L(card); - hw->ops.open = usb_stream_hwdep_open; - hw->ops.release = usb_stream_hwdep_release; - hw->ops.ioctl = usb_stream_hwdep_ioctl; - hw->ops.ioctl_compat = usb_stream_hwdep_ioctl; - hw->ops.mmap = usb_stream_hwdep_mmap; - hw->ops.poll = usb_stream_hwdep_poll; - - sprintf(hw->name, "/proc/bus/usb/%03d/%03d/hwdeppcm", - dev->bus->busnum, dev->devnum); - return 0; -} - - -static bool us122l_create_card(struct snd_card *card) -{ - int err; - struct us122l *us122l = US122L(card); - - if (us122l->dev->descriptor.idProduct == USB_ID_US144 || - us122l->dev->descriptor.idProduct == USB_ID_US144MKII) { - err = usb_set_interface(us122l->dev, 0, 1); - if (err) { - snd_printk(KERN_ERR "usb_set_interface error \n"); - return false; - } - } - err = usb_set_interface(us122l->dev, 1, 1); - if (err) { - snd_printk(KERN_ERR "usb_set_interface error \n"); - return false; - } - - pt_info_set(us122l->dev, 0x11); - pt_info_set(us122l->dev, 0x10); - - if (!us122l_start(us122l, 44100, 256)) - return false; - - if (us122l->dev->descriptor.idProduct == USB_ID_US144 || - us122l->dev->descriptor.idProduct == USB_ID_US144MKII) - err = us144_create_usbmidi(card); - else - err = us122l_create_usbmidi(card); - if (err < 0) { - snd_printk(KERN_ERR "us122l_create_usbmidi error %i \n", err); - us122l_stop(us122l); - return false; - } - err = usb_stream_hwdep_new(card); - if (err < 0) { -/* release the midi resources */ - struct list_head *p; - list_for_each(p, &us122l->midi_list) - snd_usbmidi_disconnect(p); - - us122l_stop(us122l); - return false; - } - return true; -} - -static void snd_us122l_free(struct snd_card *card) -{ - struct us122l *us122l = US122L(card); - int index = us122l->card_index; - if (index >= 0 && index < SNDRV_CARDS) - snd_us122l_card_used[index] = 0; -} - -static int usx2y_create_card(struct usb_device *device, struct snd_card **cardp) -{ - int dev; - struct snd_card *card; - int err; - - for (dev = 0; dev < SNDRV_CARDS; ++dev) - if (enable[dev] && !snd_us122l_card_used[dev]) - break; - if (dev >= SNDRV_CARDS) - return -ENODEV; - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct us122l), &card); - if (err < 0) - return err; - snd_us122l_card_used[US122L(card)->card_index = dev] = 1; - card->private_free = snd_us122l_free; - US122L(card)->dev = device; - mutex_init(&US122L(card)->mutex); - init_waitqueue_head(&US122L(card)->sk.sleep); - INIT_LIST_HEAD(&US122L(card)->midi_list); - strcpy(card->driver, "USB "NAME_ALLCAPS""); - sprintf(card->shortname, "TASCAM "NAME_ALLCAPS""); - sprintf(card->longname, "%s (%x:%x if %d at %03d/%03d)", - card->shortname, - le16_to_cpu(device->descriptor.idVendor), - le16_to_cpu(device->descriptor.idProduct), - 0, - US122L(card)->dev->bus->busnum, - US122L(card)->dev->devnum - ); - *cardp = card; - return 0; -} - -static int us122l_usb_probe(struct usb_interface *intf, - const struct usb_device_id *device_id, - struct snd_card **cardp) -{ - struct usb_device *device = interface_to_usbdev(intf); - struct snd_card *card; - int err; - - err = usx2y_create_card(device, &card); - if (err < 0) - return err; - - snd_card_set_dev(card, &intf->dev); - if (!us122l_create_card(card)) { - snd_card_free(card); - return -EINVAL; - } - - err = snd_card_register(card); - if (err < 0) { - snd_card_free(card); - return err; - } - - usb_get_intf(usb_ifnum_to_if(device, 0)); - usb_get_dev(device); - *cardp = card; - return 0; -} - -static int snd_us122l_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *device = interface_to_usbdev(intf); - struct snd_card *card; - int err; - - if ((device->descriptor.idProduct == USB_ID_US144 || - device->descriptor.idProduct == USB_ID_US144MKII) - && device->speed == USB_SPEED_HIGH) { - snd_printk(KERN_ERR "disable ehci-hcd to run US-144 \n"); - return -ENODEV; - } - - snd_printdd(KERN_DEBUG"%p:%i\n", - intf, intf->cur_altsetting->desc.bInterfaceNumber); - if (intf->cur_altsetting->desc.bInterfaceNumber != 1) - return 0; - - err = us122l_usb_probe(usb_get_intf(intf), id, &card); - if (err < 0) { - usb_put_intf(intf); - return err; - } - - usb_set_intfdata(intf, card); - return 0; -} - -static void snd_us122l_disconnect(struct usb_interface *intf) -{ - struct snd_card *card; - struct us122l *us122l; - struct list_head *p; - - card = usb_get_intfdata(intf); - if (!card) - return; - - snd_card_disconnect(card); - - us122l = US122L(card); - mutex_lock(&us122l->mutex); - us122l_stop(us122l); - mutex_unlock(&us122l->mutex); - -/* release the midi resources */ - list_for_each(p, &us122l->midi_list) { - snd_usbmidi_disconnect(p); - } - - usb_put_intf(usb_ifnum_to_if(us122l->dev, 0)); - usb_put_intf(usb_ifnum_to_if(us122l->dev, 1)); - usb_put_dev(us122l->dev); - - while (atomic_read(&us122l->mmap_count)) - msleep(500); - - snd_card_free(card); -} - -static int snd_us122l_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct snd_card *card; - struct us122l *us122l; - struct list_head *p; - - card = usb_get_intfdata(intf); - if (!card) - return 0; - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - - us122l = US122L(card); - if (!us122l) - return 0; - - list_for_each(p, &us122l->midi_list) - snd_usbmidi_input_stop(p); - - mutex_lock(&us122l->mutex); - usb_stream_stop(&us122l->sk); - mutex_unlock(&us122l->mutex); - - return 0; -} - -static int snd_us122l_resume(struct usb_interface *intf) -{ - struct snd_card *card; - struct us122l *us122l; - struct list_head *p; - int err; - - card = usb_get_intfdata(intf); - if (!card) - return 0; - - us122l = US122L(card); - if (!us122l) - return 0; - - mutex_lock(&us122l->mutex); - /* needed, doesn't restart without: */ - if (us122l->dev->descriptor.idProduct == USB_ID_US144 || - us122l->dev->descriptor.idProduct == USB_ID_US144MKII) { - err = usb_set_interface(us122l->dev, 0, 1); - if (err) { - snd_printk(KERN_ERR "usb_set_interface error \n"); - goto unlock; - } - } - err = usb_set_interface(us122l->dev, 1, 1); - if (err) { - snd_printk(KERN_ERR "usb_set_interface error \n"); - goto unlock; - } - - pt_info_set(us122l->dev, 0x11); - pt_info_set(us122l->dev, 0x10); - - err = us122l_set_sample_rate(us122l->dev, - us122l->sk.s->cfg.sample_rate); - if (err < 0) { - snd_printk(KERN_ERR "us122l_set_sample_rate error \n"); - goto unlock; - } - err = usb_stream_start(&us122l->sk); - if (err) - goto unlock; - - list_for_each(p, &us122l->midi_list) - snd_usbmidi_input_start(p); -unlock: - mutex_unlock(&us122l->mutex); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return err; -} - -static struct usb_device_id snd_us122l_usb_id_table[] = { - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x0644, - .idProduct = USB_ID_US122L - }, - { /* US-144 only works at USB1.1! Disable module ehci-hcd. */ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x0644, - .idProduct = USB_ID_US144 - }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x0644, - .idProduct = USB_ID_US122MKII - }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x0644, - .idProduct = USB_ID_US144MKII - }, - { /* terminator */ } -}; - -MODULE_DEVICE_TABLE(usb, snd_us122l_usb_id_table); -static struct usb_driver snd_us122l_usb_driver = { - .name = "snd-usb-us122l", - .probe = snd_us122l_probe, - .disconnect = snd_us122l_disconnect, - .suspend = snd_us122l_suspend, - .resume = snd_us122l_resume, - .reset_resume = snd_us122l_resume, - .id_table = snd_us122l_usb_id_table, - .supports_autosuspend = 1 -}; - -module_usb_driver(snd_us122l_usb_driver); diff --git a/ANDROID_3.4.5/sound/usb/usx2y/us122l.h b/ANDROID_3.4.5/sound/usb/usx2y/us122l.h deleted file mode 100644 index f263b3f9..00000000 --- a/ANDROID_3.4.5/sound/usb/usx2y/us122l.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef US122L_H -#define US122L_H - - -struct us122l { - struct usb_device *dev; - int card_index; - int stride; - struct usb_stream_kernel sk; - - struct mutex mutex; - struct file *first; - unsigned second_periods_polled; - struct file *master; - struct file *slave; - struct list_head midi_list; - - atomic_t mmap_count; -}; - - -#define US122L(c) ((struct us122l *)(c)->private_data) - -#define NAME_ALLCAPS "US-122L" - -#define USB_ID_US122L 0x800E -#define USB_ID_US144 0x800F -#define USB_ID_US122MKII 0x8021 -#define USB_ID_US144MKII 0x8020 - -#endif diff --git a/ANDROID_3.4.5/sound/usb/usx2y/usX2Yhwdep.c b/ANDROID_3.4.5/sound/usb/usx2y/usX2Yhwdep.c deleted file mode 100644 index 04aafb43..00000000 --- a/ANDROID_3.4.5/sound/usb/usx2y/usX2Yhwdep.c +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Driver for Tascam US-X2Y USB soundcards - * - * FPGA Loader + ALSA Startup - * - * Copyright (c) 2003 by Karsten Wiese - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include "usx2y.h" -#include "usbusx2y.h" -#include "usX2Yhwdep.h" - -static int snd_us428ctls_vm_fault(struct vm_area_struct *area, - struct vm_fault *vmf) -{ - unsigned long offset; - struct page * page; - void *vaddr; - - snd_printdd("ENTER, start %lXh, pgoff %ld\n", - area->vm_start, - vmf->pgoff); - - offset = vmf->pgoff << PAGE_SHIFT; - vaddr = (char*)((struct usX2Ydev *)area->vm_private_data)->us428ctls_sharedmem + offset; - page = virt_to_page(vaddr); - get_page(page); - vmf->page = page; - - snd_printdd("vaddr=%p made us428ctls_vm_fault() page %p\n", - vaddr, page); - - return 0; -} - -static const struct vm_operations_struct us428ctls_vm_ops = { - .fault = snd_us428ctls_vm_fault, -}; - -static int snd_us428ctls_mmap(struct snd_hwdep * hw, struct file *filp, struct vm_area_struct *area) -{ - unsigned long size = (unsigned long)(area->vm_end - area->vm_start); - struct usX2Ydev *us428 = hw->private_data; - - // FIXME this hwdep interface is used twice: fpga download and mmap for controlling Lights etc. Maybe better using 2 hwdep devs? - // so as long as the device isn't fully initialised yet we return -EBUSY here. - if (!(us428->chip_status & USX2Y_STAT_CHIP_INIT)) - return -EBUSY; - - /* if userspace tries to mmap beyond end of our buffer, fail */ - if (size > PAGE_ALIGN(sizeof(struct us428ctls_sharedmem))) { - snd_printd( "%lu > %lu\n", size, (unsigned long)sizeof(struct us428ctls_sharedmem)); - return -EINVAL; - } - - if (!us428->us428ctls_sharedmem) { - init_waitqueue_head(&us428->us428ctls_wait_queue_head); - if(!(us428->us428ctls_sharedmem = snd_malloc_pages(sizeof(struct us428ctls_sharedmem), GFP_KERNEL))) - return -ENOMEM; - memset(us428->us428ctls_sharedmem, -1, sizeof(struct us428ctls_sharedmem)); - us428->us428ctls_sharedmem->CtlSnapShotLast = -2; - } - area->vm_ops = &us428ctls_vm_ops; - area->vm_flags |= VM_RESERVED | VM_DONTEXPAND; - area->vm_private_data = hw->private_data; - return 0; -} - -static unsigned int snd_us428ctls_poll(struct snd_hwdep *hw, struct file *file, poll_table *wait) -{ - unsigned int mask = 0; - struct usX2Ydev *us428 = hw->private_data; - struct us428ctls_sharedmem *shm = us428->us428ctls_sharedmem; - if (us428->chip_status & USX2Y_STAT_CHIP_HUP) - return POLLHUP; - - poll_wait(file, &us428->us428ctls_wait_queue_head, wait); - - if (shm != NULL && shm->CtlSnapShotLast != shm->CtlSnapShotRed) - mask |= POLLIN; - - return mask; -} - - -static int snd_usX2Y_hwdep_dsp_status(struct snd_hwdep *hw, - struct snd_hwdep_dsp_status *info) -{ - static char *type_ids[USX2Y_TYPE_NUMS] = { - [USX2Y_TYPE_122] = "us122", - [USX2Y_TYPE_224] = "us224", - [USX2Y_TYPE_428] = "us428", - }; - struct usX2Ydev *us428 = hw->private_data; - int id = -1; - - switch (le16_to_cpu(us428->dev->descriptor.idProduct)) { - case USB_ID_US122: - id = USX2Y_TYPE_122; - break; - case USB_ID_US224: - id = USX2Y_TYPE_224; - break; - case USB_ID_US428: - id = USX2Y_TYPE_428; - break; - } - if (0 > id) - return -ENODEV; - strcpy(info->id, type_ids[id]); - info->num_dsps = 2; // 0: Prepad Data, 1: FPGA Code - if (us428->chip_status & USX2Y_STAT_CHIP_INIT) - info->chip_ready = 1; - info->version = USX2Y_DRIVER_VERSION; - return 0; -} - - -static int usX2Y_create_usbmidi(struct snd_card *card) -{ - static struct snd_usb_midi_endpoint_info quirk_data_1 = { - .out_ep = 0x06, - .in_ep = 0x06, - .out_cables = 0x001, - .in_cables = 0x001 - }; - static struct snd_usb_audio_quirk quirk_1 = { - .vendor_name = "TASCAM", - .product_name = NAME_ALLCAPS, - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = &quirk_data_1 - }; - static struct snd_usb_midi_endpoint_info quirk_data_2 = { - .out_ep = 0x06, - .in_ep = 0x06, - .out_cables = 0x003, - .in_cables = 0x003 - }; - static struct snd_usb_audio_quirk quirk_2 = { - .vendor_name = "TASCAM", - .product_name = "US428", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = &quirk_data_2 - }; - struct usb_device *dev = usX2Y(card)->dev; - struct usb_interface *iface = usb_ifnum_to_if(dev, 0); - struct snd_usb_audio_quirk *quirk = - le16_to_cpu(dev->descriptor.idProduct) == USB_ID_US428 ? - &quirk_2 : &quirk_1; - - snd_printdd("usX2Y_create_usbmidi \n"); - return snd_usbmidi_create(card, iface, &usX2Y(card)->midi_list, quirk); -} - -static int usX2Y_create_alsa_devices(struct snd_card *card) -{ - int err; - - do { - if ((err = usX2Y_create_usbmidi(card)) < 0) { - snd_printk(KERN_ERR "usX2Y_create_alsa_devices: usX2Y_create_usbmidi error %i \n", err); - break; - } - if ((err = usX2Y_audio_create(card)) < 0) - break; - if ((err = usX2Y_hwdep_pcm_new(card)) < 0) - break; - if ((err = snd_card_register(card)) < 0) - break; - } while (0); - - return err; -} - -static int snd_usX2Y_hwdep_dsp_load(struct snd_hwdep *hw, - struct snd_hwdep_dsp_image *dsp) -{ - struct usX2Ydev *priv = hw->private_data; - int lret, err = -EINVAL; - snd_printdd( "dsp_load %s\n", dsp->name); - - if (access_ok(VERIFY_READ, dsp->image, dsp->length)) { - struct usb_device* dev = priv->dev; - char *buf; - - buf = memdup_user(dsp->image, dsp->length); - if (IS_ERR(buf)) - return PTR_ERR(buf); - - err = usb_set_interface(dev, 0, 1); - if (err) - snd_printk(KERN_ERR "usb_set_interface error \n"); - else - err = usb_bulk_msg(dev, usb_sndbulkpipe(dev, 2), buf, dsp->length, &lret, 6000); - kfree(buf); - } - if (err) - return err; - if (dsp->index == 1) { - msleep(250); // give the device some time - err = usX2Y_AsyncSeq04_init(priv); - if (err) { - snd_printk(KERN_ERR "usX2Y_AsyncSeq04_init error \n"); - return err; - } - err = usX2Y_In04_init(priv); - if (err) { - snd_printk(KERN_ERR "usX2Y_In04_init error \n"); - return err; - } - err = usX2Y_create_alsa_devices(hw->card); - if (err) { - snd_printk(KERN_ERR "usX2Y_create_alsa_devices error %i \n", err); - snd_card_free(hw->card); - return err; - } - priv->chip_status |= USX2Y_STAT_CHIP_INIT; - snd_printdd("%s: alsa all started\n", hw->name); - } - return err; -} - - -int usX2Y_hwdep_new(struct snd_card *card, struct usb_device* device) -{ - int err; - struct snd_hwdep *hw; - - if ((err = snd_hwdep_new(card, SND_USX2Y_LOADER_ID, 0, &hw)) < 0) - return err; - - hw->iface = SNDRV_HWDEP_IFACE_USX2Y; - hw->private_data = usX2Y(card); - hw->ops.dsp_status = snd_usX2Y_hwdep_dsp_status; - hw->ops.dsp_load = snd_usX2Y_hwdep_dsp_load; - hw->ops.mmap = snd_us428ctls_mmap; - hw->ops.poll = snd_us428ctls_poll; - hw->exclusive = 1; - sprintf(hw->name, "/proc/bus/usb/%03d/%03d", device->bus->busnum, device->devnum); - return 0; -} - diff --git a/ANDROID_3.4.5/sound/usb/usx2y/usX2Yhwdep.h b/ANDROID_3.4.5/sound/usb/usx2y/usX2Yhwdep.h deleted file mode 100644 index c095d5bf..00000000 --- a/ANDROID_3.4.5/sound/usb/usx2y/usX2Yhwdep.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef USX2YHWDEP_H -#define USX2YHWDEP_H - -int usX2Y_hwdep_new(struct snd_card *card, struct usb_device* device); - -#endif diff --git a/ANDROID_3.4.5/sound/usb/usx2y/usb_stream.c b/ANDROID_3.4.5/sound/usb/usx2y/usb_stream.c deleted file mode 100644 index 1e7a47a8..00000000 --- a/ANDROID_3.4.5/sound/usb/usx2y/usb_stream.c +++ /dev/null @@ -1,754 +0,0 @@ -/* - * Copyright (C) 2007, 2008 Karsten Wiese - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include - -#include "usb_stream.h" - - -/* setup */ - -static unsigned usb_stream_next_packet_size(struct usb_stream_kernel *sk) -{ - struct usb_stream *s = sk->s; - sk->out_phase_peeked = (sk->out_phase & 0xffff) + sk->freqn; - return (sk->out_phase_peeked >> 16) * s->cfg.frame_size; -} - -static void playback_prep_freqn(struct usb_stream_kernel *sk, struct urb *urb) -{ - struct usb_stream *s = sk->s; - int pack, lb = 0; - - for (pack = 0; pack < sk->n_o_ps; pack++) { - int l = usb_stream_next_packet_size(sk); - if (s->idle_outsize + lb + l > s->period_size) - goto check; - - sk->out_phase = sk->out_phase_peeked; - urb->iso_frame_desc[pack].offset = lb; - urb->iso_frame_desc[pack].length = l; - lb += l; - } - snd_printdd(KERN_DEBUG "%i\n", lb); - -check: - urb->number_of_packets = pack; - urb->transfer_buffer_length = lb; - s->idle_outsize += lb - s->period_size; - snd_printdd(KERN_DEBUG "idle=%i ul=%i ps=%i\n", s->idle_outsize, - lb, s->period_size); -} - -static void init_pipe_urbs(struct usb_stream_kernel *sk, unsigned use_packsize, - struct urb **urbs, char *transfer, - struct usb_device *dev, int pipe) -{ - int u, p; - int maxpacket = use_packsize ? - use_packsize : usb_maxpacket(dev, pipe, usb_pipeout(pipe)); - int transfer_length = maxpacket * sk->n_o_ps; - - for (u = 0; u < USB_STREAM_NURBS; - ++u, transfer += transfer_length) { - struct urb *urb = urbs[u]; - struct usb_iso_packet_descriptor *desc; - urb->transfer_flags = URB_ISO_ASAP; - urb->transfer_buffer = transfer; - urb->dev = dev; - urb->pipe = pipe; - urb->number_of_packets = sk->n_o_ps; - urb->context = sk; - urb->interval = 1; - if (usb_pipeout(pipe)) - continue; - - urb->transfer_buffer_length = transfer_length; - desc = urb->iso_frame_desc; - desc->offset = 0; - desc->length = maxpacket; - for (p = 1; p < sk->n_o_ps; ++p) { - desc[p].offset = desc[p - 1].offset + maxpacket; - desc[p].length = maxpacket; - } - } -} - -static void init_urbs(struct usb_stream_kernel *sk, unsigned use_packsize, - struct usb_device *dev, int in_pipe, int out_pipe) -{ - struct usb_stream *s = sk->s; - char *indata = (char *)s + sizeof(*s) + - sizeof(struct usb_stream_packet) * - s->inpackets; - int u; - - for (u = 0; u < USB_STREAM_NURBS; ++u) { - sk->inurb[u] = usb_alloc_urb(sk->n_o_ps, GFP_KERNEL); - sk->outurb[u] = usb_alloc_urb(sk->n_o_ps, GFP_KERNEL); - } - - init_pipe_urbs(sk, use_packsize, sk->inurb, indata, dev, in_pipe); - init_pipe_urbs(sk, use_packsize, sk->outurb, sk->write_page, dev, - out_pipe); -} - - -/* - * convert a sampling rate into our full speed format (fs/1000 in Q16.16) - * this will overflow at approx 524 kHz - */ -static inline unsigned get_usb_full_speed_rate(unsigned rate) -{ - return ((rate << 13) + 62) / 125; -} - -/* - * convert a sampling rate into USB high speed format (fs/8000 in Q16.16) - * this will overflow at approx 4 MHz - */ -static inline unsigned get_usb_high_speed_rate(unsigned rate) -{ - return ((rate << 10) + 62) / 125; -} - -void usb_stream_free(struct usb_stream_kernel *sk) -{ - struct usb_stream *s; - unsigned u; - - for (u = 0; u < USB_STREAM_NURBS; ++u) { - usb_free_urb(sk->inurb[u]); - sk->inurb[u] = NULL; - usb_free_urb(sk->outurb[u]); - sk->outurb[u] = NULL; - } - - s = sk->s; - if (!s) - return; - - free_pages((unsigned long)sk->write_page, get_order(s->write_size)); - sk->write_page = NULL; - free_pages((unsigned long)s, get_order(s->read_size)); - sk->s = NULL; -} - -struct usb_stream *usb_stream_new(struct usb_stream_kernel *sk, - struct usb_device *dev, - unsigned in_endpoint, unsigned out_endpoint, - unsigned sample_rate, unsigned use_packsize, - unsigned period_frames, unsigned frame_size) -{ - int packets, max_packsize; - int in_pipe, out_pipe; - int read_size = sizeof(struct usb_stream); - int write_size; - int usb_frames = dev->speed == USB_SPEED_HIGH ? 8000 : 1000; - int pg; - - in_pipe = usb_rcvisocpipe(dev, in_endpoint); - out_pipe = usb_sndisocpipe(dev, out_endpoint); - - max_packsize = use_packsize ? - use_packsize : usb_maxpacket(dev, in_pipe, 0); - - /* - t_period = period_frames / sample_rate - iso_packs = t_period / t_iso_frame - = (period_frames / sample_rate) * (1 / t_iso_frame) - */ - - packets = period_frames * usb_frames / sample_rate + 1; - - if (dev->speed == USB_SPEED_HIGH) - packets = (packets + 7) & ~7; - - read_size += packets * USB_STREAM_URBDEPTH * - (max_packsize + sizeof(struct usb_stream_packet)); - - max_packsize = usb_maxpacket(dev, out_pipe, 1); - write_size = max_packsize * packets * USB_STREAM_URBDEPTH; - - if (read_size >= 256*PAGE_SIZE || write_size >= 256*PAGE_SIZE) { - snd_printk(KERN_WARNING "a size exceeds 128*PAGE_SIZE\n"); - goto out; - } - - pg = get_order(read_size); - sk->s = (void *) __get_free_pages(GFP_KERNEL|__GFP_COMP|__GFP_ZERO, pg); - if (!sk->s) { - snd_printk(KERN_WARNING "couldn't __get_free_pages()\n"); - goto out; - } - sk->s->cfg.version = USB_STREAM_INTERFACE_VERSION; - - sk->s->read_size = read_size; - - sk->s->cfg.sample_rate = sample_rate; - sk->s->cfg.frame_size = frame_size; - sk->n_o_ps = packets; - sk->s->inpackets = packets * USB_STREAM_URBDEPTH; - sk->s->cfg.period_frames = period_frames; - sk->s->period_size = frame_size * period_frames; - - sk->s->write_size = write_size; - pg = get_order(write_size); - - sk->write_page = - (void *)__get_free_pages(GFP_KERNEL|__GFP_COMP|__GFP_ZERO, pg); - if (!sk->write_page) { - snd_printk(KERN_WARNING "couldn't __get_free_pages()\n"); - usb_stream_free(sk); - return NULL; - } - - /* calculate the frequency in 16.16 format */ - if (dev->speed == USB_SPEED_FULL) - sk->freqn = get_usb_full_speed_rate(sample_rate); - else - sk->freqn = get_usb_high_speed_rate(sample_rate); - - init_urbs(sk, use_packsize, dev, in_pipe, out_pipe); - sk->s->state = usb_stream_stopped; -out: - return sk->s; -} - - -/* start */ - -static bool balance_check(struct usb_stream_kernel *sk, struct urb *urb) -{ - bool r; - if (unlikely(urb->status)) { - if (urb->status != -ESHUTDOWN && urb->status != -ENOENT) - snd_printk(KERN_WARNING "status=%i\n", urb->status); - sk->iso_frame_balance = 0x7FFFFFFF; - return false; - } - r = sk->iso_frame_balance == 0; - if (!r) - sk->i_urb = urb; - return r; -} - -static bool balance_playback(struct usb_stream_kernel *sk, struct urb *urb) -{ - sk->iso_frame_balance += urb->number_of_packets; - return balance_check(sk, urb); -} - -static bool balance_capture(struct usb_stream_kernel *sk, struct urb *urb) -{ - sk->iso_frame_balance -= urb->number_of_packets; - return balance_check(sk, urb); -} - -static void subs_set_complete(struct urb **urbs, void (*complete)(struct urb *)) -{ - int u; - - for (u = 0; u < USB_STREAM_NURBS; u++) { - struct urb *urb = urbs[u]; - urb->complete = complete; - } -} - -static int usb_stream_prepare_playback(struct usb_stream_kernel *sk, - struct urb *inurb) -{ - struct usb_stream *s = sk->s; - struct urb *io; - struct usb_iso_packet_descriptor *id, *od; - int p = 0, lb = 0, l = 0; - - io = sk->idle_outurb; - od = io->iso_frame_desc; - - for (; s->sync_packet < 0; ++p, ++s->sync_packet) { - struct urb *ii = sk->completed_inurb; - id = ii->iso_frame_desc + - ii->number_of_packets + s->sync_packet; - l = id->actual_length; - - od[p].length = l; - od[p].offset = lb; - lb += l; - } - - for (; - s->sync_packet < inurb->number_of_packets && p < sk->n_o_ps; - ++p, ++s->sync_packet) { - l = inurb->iso_frame_desc[s->sync_packet].actual_length; - - if (s->idle_outsize + lb + l > s->period_size) - goto check_ok; - - od[p].length = l; - od[p].offset = lb; - lb += l; - } - -check_ok: - s->sync_packet -= inurb->number_of_packets; - if (unlikely(s->sync_packet < -2 || s->sync_packet > 0)) { - snd_printk(KERN_WARNING "invalid sync_packet = %i;" - " p=%i nop=%i %i %x %x %x > %x\n", - s->sync_packet, p, inurb->number_of_packets, - s->idle_outsize + lb + l, - s->idle_outsize, lb, l, - s->period_size); - return -1; - } - if (unlikely(lb % s->cfg.frame_size)) { - snd_printk(KERN_WARNING"invalid outsize = %i\n", - lb); - return -1; - } - s->idle_outsize += lb - s->period_size; - io->number_of_packets = p; - io->transfer_buffer_length = lb; - if (s->idle_outsize <= 0) - return 0; - - snd_printk(KERN_WARNING "idle=%i\n", s->idle_outsize); - return -1; -} - -static void prepare_inurb(int number_of_packets, struct urb *iu) -{ - struct usb_iso_packet_descriptor *id; - int p; - - iu->number_of_packets = number_of_packets; - id = iu->iso_frame_desc; - id->offset = 0; - for (p = 0; p < iu->number_of_packets - 1; ++p) - id[p + 1].offset = id[p].offset + id[p].length; - - iu->transfer_buffer_length = - id[0].length * iu->number_of_packets; -} - -static int submit_urbs(struct usb_stream_kernel *sk, - struct urb *inurb, struct urb *outurb) -{ - int err; - prepare_inurb(sk->idle_outurb->number_of_packets, sk->idle_inurb); - err = usb_submit_urb(sk->idle_inurb, GFP_ATOMIC); - if (err < 0) { - snd_printk(KERN_ERR "%i\n", err); - return err; - } - sk->idle_inurb = sk->completed_inurb; - sk->completed_inurb = inurb; - err = usb_submit_urb(sk->idle_outurb, GFP_ATOMIC); - if (err < 0) { - snd_printk(KERN_ERR "%i\n", err); - return err; - } - sk->idle_outurb = sk->completed_outurb; - sk->completed_outurb = outurb; - return 0; -} - -#ifdef DEBUG_LOOP_BACK -/* - This loop_back() shows how to read/write the period data. - */ -static void loop_back(struct usb_stream *s) -{ - char *i, *o; - int il, ol, l, p; - struct urb *iu; - struct usb_iso_packet_descriptor *id; - - o = s->playback1st_to; - ol = s->playback1st_size; - l = 0; - - if (s->insplit_pack >= 0) { - iu = sk->idle_inurb; - id = iu->iso_frame_desc; - p = s->insplit_pack; - } else - goto second; -loop: - for (; p < iu->number_of_packets && l < s->period_size; ++p) { - i = iu->transfer_buffer + id[p].offset; - il = id[p].actual_length; - if (l + il > s->period_size) - il = s->period_size - l; - if (il <= ol) { - memcpy(o, i, il); - o += il; - ol -= il; - } else { - memcpy(o, i, ol); - singen_6pack(o, ol); - o = s->playback_to; - memcpy(o, i + ol, il - ol); - o += il - ol; - ol = s->period_size - s->playback1st_size; - } - l += il; - } - if (iu == sk->completed_inurb) { - if (l != s->period_size) - printk(KERN_DEBUG"%s:%i %i\n", __func__, __LINE__, - l/(int)s->cfg.frame_size); - - return; - } -second: - iu = sk->completed_inurb; - id = iu->iso_frame_desc; - p = 0; - goto loop; - -} -#else -static void loop_back(struct usb_stream *s) -{ -} -#endif - -static void stream_idle(struct usb_stream_kernel *sk, - struct urb *inurb, struct urb *outurb) -{ - struct usb_stream *s = sk->s; - int l, p; - int insize = s->idle_insize; - int urb_size = 0; - - s->inpacket_split = s->next_inpacket_split; - s->inpacket_split_at = s->next_inpacket_split_at; - s->next_inpacket_split = -1; - s->next_inpacket_split_at = 0; - - for (p = 0; p < inurb->number_of_packets; ++p) { - struct usb_iso_packet_descriptor *id = inurb->iso_frame_desc; - l = id[p].actual_length; - if (unlikely(l == 0 || id[p].status)) { - snd_printk(KERN_WARNING "underrun, status=%u\n", - id[p].status); - goto err_out; - } - s->inpacket_head++; - s->inpacket_head %= s->inpackets; - if (s->inpacket_split == -1) - s->inpacket_split = s->inpacket_head; - - s->inpacket[s->inpacket_head].offset = - id[p].offset + (inurb->transfer_buffer - (void *)s); - s->inpacket[s->inpacket_head].length = l; - if (insize + l > s->period_size && - s->next_inpacket_split == -1) { - s->next_inpacket_split = s->inpacket_head; - s->next_inpacket_split_at = s->period_size - insize; - } - insize += l; - urb_size += l; - } - s->idle_insize += urb_size - s->period_size; - if (s->idle_insize < 0) { - snd_printk(KERN_WARNING "%i\n", - (s->idle_insize)/(int)s->cfg.frame_size); - goto err_out; - } - s->insize_done += urb_size; - - l = s->idle_outsize; - s->outpacket[0].offset = (sk->idle_outurb->transfer_buffer - - sk->write_page) - l; - - if (usb_stream_prepare_playback(sk, inurb) < 0) - goto err_out; - - s->outpacket[0].length = sk->idle_outurb->transfer_buffer_length + l; - s->outpacket[1].offset = sk->completed_outurb->transfer_buffer - - sk->write_page; - - if (submit_urbs(sk, inurb, outurb) < 0) - goto err_out; - - loop_back(s); - s->periods_done++; - wake_up_all(&sk->sleep); - return; -err_out: - s->state = usb_stream_xrun; - wake_up_all(&sk->sleep); -} - -static void i_capture_idle(struct urb *urb) -{ - struct usb_stream_kernel *sk = urb->context; - if (balance_capture(sk, urb)) - stream_idle(sk, urb, sk->i_urb); -} - -static void i_playback_idle(struct urb *urb) -{ - struct usb_stream_kernel *sk = urb->context; - if (balance_playback(sk, urb)) - stream_idle(sk, sk->i_urb, urb); -} - -static void stream_start(struct usb_stream_kernel *sk, - struct urb *inurb, struct urb *outurb) -{ - struct usb_stream *s = sk->s; - if (s->state >= usb_stream_sync1) { - int l, p, max_diff, max_diff_0; - int urb_size = 0; - unsigned frames_per_packet, min_frames = 0; - frames_per_packet = (s->period_size - s->idle_insize); - frames_per_packet <<= 8; - frames_per_packet /= - s->cfg.frame_size * inurb->number_of_packets; - frames_per_packet++; - - max_diff_0 = s->cfg.frame_size; - if (s->cfg.period_frames >= 256) - max_diff_0 <<= 1; - if (s->cfg.period_frames >= 1024) - max_diff_0 <<= 1; - max_diff = max_diff_0; - for (p = 0; p < inurb->number_of_packets; ++p) { - int diff; - l = inurb->iso_frame_desc[p].actual_length; - urb_size += l; - - min_frames += frames_per_packet; - diff = urb_size - - (min_frames >> 8) * s->cfg.frame_size; - if (diff < max_diff) { - snd_printdd(KERN_DEBUG "%i %i %i %i\n", - s->insize_done, - urb_size / (int)s->cfg.frame_size, - inurb->number_of_packets, diff); - max_diff = diff; - } - } - s->idle_insize -= max_diff - max_diff_0; - s->idle_insize += urb_size - s->period_size; - if (s->idle_insize < 0) { - snd_printk(KERN_WARNING "%i %i %i\n", - s->idle_insize, urb_size, s->period_size); - return; - } else if (s->idle_insize == 0) { - s->next_inpacket_split = - (s->inpacket_head + 1) % s->inpackets; - s->next_inpacket_split_at = 0; - } else { - unsigned split = s->inpacket_head; - l = s->idle_insize; - while (l > s->inpacket[split].length) { - l -= s->inpacket[split].length; - if (split == 0) - split = s->inpackets - 1; - else - split--; - } - s->next_inpacket_split = split; - s->next_inpacket_split_at = - s->inpacket[split].length - l; - } - - s->insize_done += urb_size; - - if (usb_stream_prepare_playback(sk, inurb) < 0) - return; - - } else - playback_prep_freqn(sk, sk->idle_outurb); - - if (submit_urbs(sk, inurb, outurb) < 0) - return; - - if (s->state == usb_stream_sync1 && s->insize_done > 360000) { - /* just guesswork ^^^^^^ */ - s->state = usb_stream_ready; - subs_set_complete(sk->inurb, i_capture_idle); - subs_set_complete(sk->outurb, i_playback_idle); - } -} - -static void i_capture_start(struct urb *urb) -{ - struct usb_iso_packet_descriptor *id = urb->iso_frame_desc; - struct usb_stream_kernel *sk = urb->context; - struct usb_stream *s = sk->s; - int p; - int empty = 0; - - if (urb->status) { - snd_printk(KERN_WARNING "status=%i\n", urb->status); - return; - } - - for (p = 0; p < urb->number_of_packets; ++p) { - int l = id[p].actual_length; - if (l < s->cfg.frame_size) { - ++empty; - if (s->state >= usb_stream_sync0) { - snd_printk(KERN_WARNING "%i\n", l); - return; - } - } - s->inpacket_head++; - s->inpacket_head %= s->inpackets; - s->inpacket[s->inpacket_head].offset = - id[p].offset + (urb->transfer_buffer - (void *)s); - s->inpacket[s->inpacket_head].length = l; - } -#ifdef SHOW_EMPTY - if (empty) { - printk(KERN_DEBUG"%s:%i: %i", __func__, __LINE__, - urb->iso_frame_desc[0].actual_length); - for (pack = 1; pack < urb->number_of_packets; ++pack) { - int l = urb->iso_frame_desc[pack].actual_length; - printk(" %i", l); - } - printk("\n"); - } -#endif - if (!empty && s->state < usb_stream_sync1) - ++s->state; - - if (balance_capture(sk, urb)) - stream_start(sk, urb, sk->i_urb); -} - -static void i_playback_start(struct urb *urb) -{ - struct usb_stream_kernel *sk = urb->context; - if (balance_playback(sk, urb)) - stream_start(sk, sk->i_urb, urb); -} - -int usb_stream_start(struct usb_stream_kernel *sk) -{ - struct usb_stream *s = sk->s; - int frame = 0, iters = 0; - int u, err; - int try = 0; - - if (s->state != usb_stream_stopped) - return -EAGAIN; - - subs_set_complete(sk->inurb, i_capture_start); - subs_set_complete(sk->outurb, i_playback_start); - memset(sk->write_page, 0, s->write_size); -dotry: - s->insize_done = 0; - s->idle_insize = 0; - s->idle_outsize = 0; - s->sync_packet = -1; - s->inpacket_head = -1; - sk->iso_frame_balance = 0; - ++try; - for (u = 0; u < 2; u++) { - struct urb *inurb = sk->inurb[u]; - struct urb *outurb = sk->outurb[u]; - playback_prep_freqn(sk, outurb); - inurb->number_of_packets = outurb->number_of_packets; - inurb->transfer_buffer_length = - inurb->number_of_packets * - inurb->iso_frame_desc[0].length; - - if (u == 0) { - int now; - struct usb_device *dev = inurb->dev; - frame = usb_get_current_frame_number(dev); - do { - now = usb_get_current_frame_number(dev); - ++iters; - } while (now > -1 && now == frame); - } - err = usb_submit_urb(inurb, GFP_ATOMIC); - if (err < 0) { - snd_printk(KERN_ERR"usb_submit_urb(sk->inurb[%i])" - " returned %i\n", u, err); - return err; - } - err = usb_submit_urb(outurb, GFP_ATOMIC); - if (err < 0) { - snd_printk(KERN_ERR"usb_submit_urb(sk->outurb[%i])" - " returned %i\n", u, err); - return err; - } - - if (inurb->start_frame != outurb->start_frame) { - snd_printd(KERN_DEBUG - "u[%i] start_frames differ in:%u out:%u\n", - u, inurb->start_frame, outurb->start_frame); - goto check_retry; - } - } - snd_printdd(KERN_DEBUG "%i %i\n", frame, iters); - try = 0; -check_retry: - if (try) { - usb_stream_stop(sk); - if (try < 5) { - msleep(1500); - snd_printd(KERN_DEBUG "goto dotry;\n"); - goto dotry; - } - snd_printk(KERN_WARNING"couldn't start" - " all urbs on the same start_frame.\n"); - return -EFAULT; - } - - sk->idle_inurb = sk->inurb[USB_STREAM_NURBS - 2]; - sk->idle_outurb = sk->outurb[USB_STREAM_NURBS - 2]; - sk->completed_inurb = sk->inurb[USB_STREAM_NURBS - 1]; - sk->completed_outurb = sk->outurb[USB_STREAM_NURBS - 1]; - -/* wait, check */ - { - int wait_ms = 3000; - while (s->state != usb_stream_ready && wait_ms > 0) { - snd_printdd(KERN_DEBUG "%i\n", s->state); - msleep(200); - wait_ms -= 200; - } - } - - return s->state == usb_stream_ready ? 0 : -EFAULT; -} - - -/* stop */ - -void usb_stream_stop(struct usb_stream_kernel *sk) -{ - int u; - if (!sk->s) - return; - for (u = 0; u < USB_STREAM_NURBS; ++u) { - usb_kill_urb(sk->inurb[u]); - usb_kill_urb(sk->outurb[u]); - } - sk->s->state = usb_stream_stopped; - msleep(400); -} diff --git a/ANDROID_3.4.5/sound/usb/usx2y/usb_stream.h b/ANDROID_3.4.5/sound/usb/usx2y/usb_stream.h deleted file mode 100644 index 4dd74ab1..00000000 --- a/ANDROID_3.4.5/sound/usb/usx2y/usb_stream.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2007, 2008 Karsten Wiese - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#define USB_STREAM_INTERFACE_VERSION 2 - -#define SNDRV_USB_STREAM_IOCTL_SET_PARAMS \ - _IOW('H', 0x90, struct usb_stream_config) - -struct usb_stream_packet { - unsigned offset; - unsigned length; -}; - - -struct usb_stream_config { - unsigned version; - unsigned sample_rate; - unsigned period_frames; - unsigned frame_size; -}; - -struct usb_stream { - struct usb_stream_config cfg; - unsigned read_size; - unsigned write_size; - - int period_size; - - unsigned state; - - int idle_insize; - int idle_outsize; - int sync_packet; - unsigned insize_done; - unsigned periods_done; - unsigned periods_polled; - - struct usb_stream_packet outpacket[2]; - unsigned inpackets; - unsigned inpacket_head; - unsigned inpacket_split; - unsigned inpacket_split_at; - unsigned next_inpacket_split; - unsigned next_inpacket_split_at; - struct usb_stream_packet inpacket[0]; -}; - -enum usb_stream_state { - usb_stream_invalid, - usb_stream_stopped, - usb_stream_sync0, - usb_stream_sync1, - usb_stream_ready, - usb_stream_running, - usb_stream_xrun, -}; - -#if __KERNEL__ - -#define USB_STREAM_NURBS 4 -#define USB_STREAM_URBDEPTH 4 - -struct usb_stream_kernel { - struct usb_stream *s; - - void *write_page; - - unsigned n_o_ps; - - struct urb *inurb[USB_STREAM_NURBS]; - struct urb *idle_inurb; - struct urb *completed_inurb; - struct urb *outurb[USB_STREAM_NURBS]; - struct urb *idle_outurb; - struct urb *completed_outurb; - struct urb *i_urb; - - int iso_frame_balance; - - wait_queue_head_t sleep; - - unsigned out_phase; - unsigned out_phase_peeked; - unsigned freqn; -}; - -struct usb_stream *usb_stream_new(struct usb_stream_kernel *sk, - struct usb_device *dev, - unsigned in_endpoint, unsigned out_endpoint, - unsigned sample_rate, unsigned use_packsize, - unsigned period_frames, unsigned frame_size); -void usb_stream_free(struct usb_stream_kernel *); -int usb_stream_start(struct usb_stream_kernel *); -void usb_stream_stop(struct usb_stream_kernel *); - - -#endif diff --git a/ANDROID_3.4.5/sound/usb/usx2y/usbus428ctldefs.h b/ANDROID_3.4.5/sound/usb/usx2y/usbus428ctldefs.h deleted file mode 100644 index b864e7e2..00000000 --- a/ANDROID_3.4.5/sound/usb/usx2y/usbus428ctldefs.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * - * Copyright (c) 2003 by Karsten Wiese - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -enum E_In84{ - eFader0 = 0, - eFader1, - eFader2, - eFader3, - eFader4, - eFader5, - eFader6, - eFader7, - eFaderM, - eTransport, - eModifier = 10, - eFilterSelect, - eSelect, - eMute, - - eSwitch = 15, - eWheelGain, - eWheelFreq, - eWheelQ, - eWheelPan, - eWheel = 20 -}; - -#define T_RECORD 1 -#define T_PLAY 2 -#define T_STOP 4 -#define T_F_FWD 8 -#define T_REW 0x10 -#define T_SOLO 0x20 -#define T_REC 0x40 -#define T_NULL 0x80 - - -struct us428_ctls { - unsigned char Fader[9]; - unsigned char Transport; - unsigned char Modifier; - unsigned char FilterSelect; - unsigned char Select; - unsigned char Mute; - unsigned char UNKNOWN; - unsigned char Switch; - unsigned char Wheel[5]; -}; - -struct us428_setByte { - unsigned char Offset, - Value; -}; - -enum { - eLT_Volume = 0, - eLT_Light -}; - -struct usX2Y_volume { - unsigned char Channel, - LH, - LL, - RH, - RL; -}; - -struct us428_lights { - struct us428_setByte Light[7]; -}; - -struct us428_p4out { - char type; - union { - struct usX2Y_volume vol; - struct us428_lights lights; - } val; -}; - -#define N_us428_ctl_BUFS 16 -#define N_us428_p4out_BUFS 16 -struct us428ctls_sharedmem{ - struct us428_ctls CtlSnapShot[N_us428_ctl_BUFS]; - int CtlSnapShotDiffersAt[N_us428_ctl_BUFS]; - int CtlSnapShotLast, CtlSnapShotRed; - struct us428_p4out p4out[N_us428_p4out_BUFS]; - int p4outLast, p4outSent; -}; diff --git a/ANDROID_3.4.5/sound/usb/usx2y/usbusx2y.c b/ANDROID_3.4.5/sound/usb/usx2y/usbusx2y.c deleted file mode 100644 index 9af7c1f1..00000000 --- a/ANDROID_3.4.5/sound/usb/usx2y/usbusx2y.c +++ /dev/null @@ -1,462 +0,0 @@ -/* - * usbusy2y.c - ALSA USB US-428 Driver - * -2005-04-14 Karsten Wiese - Version 0.8.7.2: - Call snd_card_free() instead of snd_card_free_in_thread() to prevent oops with dead keyboard symptom. - Tested ok with kernel 2.6.12-rc2. - -2004-12-14 Karsten Wiese - Version 0.8.7.1: - snd_pcm_open for rawusb pcm-devices now returns -EBUSY if called without rawusb's hwdep device being open. - -2004-12-02 Karsten Wiese - Version 0.8.7: - Use macro usb_maxpacket() for portability. - -2004-10-26 Karsten Wiese - Version 0.8.6: - wake_up() process waiting in usX2Y_urbs_start() on error. - -2004-10-21 Karsten Wiese - Version 0.8.5: - nrpacks is runtime or compiletime configurable now with tested values from 1 to 4. - -2004-10-03 Karsten Wiese - Version 0.8.2: - Avoid any possible racing while in prepare callback. - -2004-09-30 Karsten Wiese - Version 0.8.0: - Simplified things and made ohci work again. - -2004-09-20 Karsten Wiese - Version 0.7.3: - Use usb_kill_urb() instead of deprecated (kernel 2.6.9) usb_unlink_urb(). - -2004-07-13 Karsten Wiese - Version 0.7.1: - Don't sleep in START/STOP callbacks anymore. - us428 channels C/D not handled just for this version, sorry. - -2004-06-21 Karsten Wiese - Version 0.6.4: - Temporarely suspend midi input - to sanely call usb_set_interface() when setting format. - -2004-06-12 Karsten Wiese - Version 0.6.3: - Made it thus the following rule is enforced: - "All pcm substreams of one usX2Y have to operate at the same rate & format." - -2004-04-06 Karsten Wiese - Version 0.6.0: - Runs on 2.6.5 kernel without any "--with-debug=" things. - us224 reported running. - -2004-01-14 Karsten Wiese - Version 0.5.1: - Runs with 2.6.1 kernel. - -2003-12-30 Karsten Wiese - Version 0.4.1: - Fix 24Bit 4Channel capturing for the us428. - -2003-11-27 Karsten Wiese, Martin Langer - Version 0.4: - us122 support. - us224 could be tested by uncommenting the sections containing USB_ID_US224 - -2003-11-03 Karsten Wiese - Version 0.3: - 24Bit support. - "arecord -D hw:1 -c 2 -r 48000 -M -f S24_3LE|aplay -D hw:1 -c 2 -r 48000 -M -f S24_3LE" works. - -2003-08-22 Karsten Wiese - Version 0.0.8: - Removed EZUSB Firmware. First Stage Firmwaredownload is now done by tascam-firmware downloader. - See: - http://usb-midi-fw.sourceforge.net/tascam-firmware.tar.gz - -2003-06-18 Karsten Wiese - Version 0.0.5: - changed to compile with kernel 2.4.21 and alsa 0.9.4 - -2002-10-16 Karsten Wiese - Version 0.0.4: - compiles again with alsa-current. - USB_ISO_ASAP not used anymore (most of the time), instead - urb->start_frame is calculated here now, some calls inside usb-driver don't need to happen anymore. - - To get the best out of this: - Disable APM-support in the kernel as APM-BIOS calls (once each second) hard disable interrupt for many precious milliseconds. - This helped me much on my slowish PII 400 & PIII 500. - ACPI yet untested but might cause the same bad behaviour. - Use a kernel with lowlatency and preemptiv patches applied. - To autoload snd-usb-midi append a line - post-install snd-usb-us428 modprobe snd-usb-midi - to /etc/modules.conf. - - known problems: - sliders, knobs, lights not yet handled except MASTER Volume slider. - "pcm -c 2" doesn't work. "pcm -c 2 -m direct_interleaved" does. - KDE3: "Enable full duplex operation" deadlocks. - - -2002-08-31 Karsten Wiese - Version 0.0.3: audio also simplex; - simplifying: iso urbs only 1 packet, melted structs. - ASYNC_UNLINK not used anymore: no more crashes so far..... - for alsa 0.9 rc3. - -2002-08-09 Karsten Wiese - Version 0.0.2: midi works with snd-usb-midi, audio (only fullduplex now) with i.e. bristol. - The firmware has been sniffed from win2k us-428 driver 3.09. - - * Copyright (c) 2002 - 2004 Karsten Wiese - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "usx2y.h" -#include "usbusx2y.h" -#include "usX2Yhwdep.h" - - - -MODULE_AUTHOR("Karsten Wiese "); -MODULE_DESCRIPTION("TASCAM "NAME_ALLCAPS" Version 0.8.7.2"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{TASCAM(0x1604), "NAME_ALLCAPS"(0x8001)(0x8005)(0x8007) }}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */ -static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for "NAME_ALLCAPS"."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for "NAME_ALLCAPS"."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable "NAME_ALLCAPS"."); - - -static int snd_usX2Y_card_used[SNDRV_CARDS]; - -static void usX2Y_usb_disconnect(struct usb_device* usb_device, void* ptr); -static void snd_usX2Y_card_private_free(struct snd_card *card); - -/* - * pipe 4 is used for switching the lamps, setting samplerate, volumes .... - */ -static void i_usX2Y_Out04Int(struct urb *urb) -{ -#ifdef CONFIG_SND_DEBUG - if (urb->status) { - int i; - struct usX2Ydev *usX2Y = urb->context; - for (i = 0; i < 10 && usX2Y->AS04.urb[i] != urb; i++); - snd_printdd("i_usX2Y_Out04Int() urb %i status=%i\n", i, urb->status); - } -#endif -} - -static void i_usX2Y_In04Int(struct urb *urb) -{ - int err = 0; - struct usX2Ydev *usX2Y = urb->context; - struct us428ctls_sharedmem *us428ctls = usX2Y->us428ctls_sharedmem; - - usX2Y->In04IntCalls++; - - if (urb->status) { - snd_printdd("Interrupt Pipe 4 came back with status=%i\n", urb->status); - return; - } - - // printk("%i:0x%02X ", 8, (int)((unsigned char*)usX2Y->In04Buf)[8]); Master volume shows 0 here if fader is at max during boot ?!? - if (us428ctls) { - int diff = -1; - if (-2 == us428ctls->CtlSnapShotLast) { - diff = 0; - memcpy(usX2Y->In04Last, usX2Y->In04Buf, sizeof(usX2Y->In04Last)); - us428ctls->CtlSnapShotLast = -1; - } else { - int i; - for (i = 0; i < 21; i++) { - if (usX2Y->In04Last[i] != ((char*)usX2Y->In04Buf)[i]) { - if (diff < 0) - diff = i; - usX2Y->In04Last[i] = ((char*)usX2Y->In04Buf)[i]; - } - } - } - if (0 <= diff) { - int n = us428ctls->CtlSnapShotLast + 1; - if (n >= N_us428_ctl_BUFS || n < 0) - n = 0; - memcpy(us428ctls->CtlSnapShot + n, usX2Y->In04Buf, sizeof(us428ctls->CtlSnapShot[0])); - us428ctls->CtlSnapShotDiffersAt[n] = diff; - us428ctls->CtlSnapShotLast = n; - wake_up(&usX2Y->us428ctls_wait_queue_head); - } - } - - - if (usX2Y->US04) { - if (0 == usX2Y->US04->submitted) - do { - err = usb_submit_urb(usX2Y->US04->urb[usX2Y->US04->submitted++], GFP_ATOMIC); - } while (!err && usX2Y->US04->submitted < usX2Y->US04->len); - } else - if (us428ctls && us428ctls->p4outLast >= 0 && us428ctls->p4outLast < N_us428_p4out_BUFS) { - if (us428ctls->p4outLast != us428ctls->p4outSent) { - int j, send = us428ctls->p4outSent + 1; - if (send >= N_us428_p4out_BUFS) - send = 0; - for (j = 0; j < URBS_AsyncSeq && !err; ++j) - if (0 == usX2Y->AS04.urb[j]->status) { - struct us428_p4out *p4out = us428ctls->p4out + send; // FIXME if more than 1 p4out is new, 1 gets lost. - usb_fill_bulk_urb(usX2Y->AS04.urb[j], usX2Y->dev, - usb_sndbulkpipe(usX2Y->dev, 0x04), &p4out->val.vol, - p4out->type == eLT_Light ? sizeof(struct us428_lights) : 5, - i_usX2Y_Out04Int, usX2Y); - err = usb_submit_urb(usX2Y->AS04.urb[j], GFP_ATOMIC); - us428ctls->p4outSent = send; - break; - } - } - } - - if (err) - snd_printk(KERN_ERR "In04Int() usb_submit_urb err=%i\n", err); - - urb->dev = usX2Y->dev; - usb_submit_urb(urb, GFP_ATOMIC); -} - -/* - * Prepare some urbs - */ -int usX2Y_AsyncSeq04_init(struct usX2Ydev *usX2Y) -{ - int err = 0, - i; - - if (NULL == (usX2Y->AS04.buffer = kmalloc(URB_DataLen_AsyncSeq*URBS_AsyncSeq, GFP_KERNEL))) { - err = -ENOMEM; - } else - for (i = 0; i < URBS_AsyncSeq; ++i) { - if (NULL == (usX2Y->AS04.urb[i] = usb_alloc_urb(0, GFP_KERNEL))) { - err = -ENOMEM; - break; - } - usb_fill_bulk_urb( usX2Y->AS04.urb[i], usX2Y->dev, - usb_sndbulkpipe(usX2Y->dev, 0x04), - usX2Y->AS04.buffer + URB_DataLen_AsyncSeq*i, 0, - i_usX2Y_Out04Int, usX2Y - ); - } - return err; -} - -int usX2Y_In04_init(struct usX2Ydev *usX2Y) -{ - if (! (usX2Y->In04urb = usb_alloc_urb(0, GFP_KERNEL))) - return -ENOMEM; - - if (! (usX2Y->In04Buf = kmalloc(21, GFP_KERNEL))) { - usb_free_urb(usX2Y->In04urb); - return -ENOMEM; - } - - init_waitqueue_head(&usX2Y->In04WaitQueue); - usb_fill_int_urb(usX2Y->In04urb, usX2Y->dev, usb_rcvintpipe(usX2Y->dev, 0x4), - usX2Y->In04Buf, 21, - i_usX2Y_In04Int, usX2Y, - 10); - return usb_submit_urb(usX2Y->In04urb, GFP_KERNEL); -} - -static void usX2Y_unlinkSeq(struct snd_usX2Y_AsyncSeq *S) -{ - int i; - for (i = 0; i < URBS_AsyncSeq; ++i) { - if (S[i].urb) { - usb_kill_urb(S->urb[i]); - usb_free_urb(S->urb[i]); - S->urb[i] = NULL; - } - } - kfree(S->buffer); -} - - -static struct usb_device_id snd_usX2Y_usb_id_table[] = { - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x1604, - .idProduct = USB_ID_US428 - }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x1604, - .idProduct = USB_ID_US122 - }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x1604, - .idProduct = USB_ID_US224 - }, - { /* terminator */ } -}; - -static int usX2Y_create_card(struct usb_device *device, struct snd_card **cardp) -{ - int dev; - struct snd_card * card; - int err; - - for (dev = 0; dev < SNDRV_CARDS; ++dev) - if (enable[dev] && !snd_usX2Y_card_used[dev]) - break; - if (dev >= SNDRV_CARDS) - return -ENODEV; - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct usX2Ydev), &card); - if (err < 0) - return err; - snd_usX2Y_card_used[usX2Y(card)->card_index = dev] = 1; - card->private_free = snd_usX2Y_card_private_free; - usX2Y(card)->dev = device; - init_waitqueue_head(&usX2Y(card)->prepare_wait_queue); - mutex_init(&usX2Y(card)->prepare_mutex); - INIT_LIST_HEAD(&usX2Y(card)->midi_list); - strcpy(card->driver, "USB "NAME_ALLCAPS""); - sprintf(card->shortname, "TASCAM "NAME_ALLCAPS""); - sprintf(card->longname, "%s (%x:%x if %d at %03d/%03d)", - card->shortname, - le16_to_cpu(device->descriptor.idVendor), - le16_to_cpu(device->descriptor.idProduct), - 0,//us428(card)->usbmidi.ifnum, - usX2Y(card)->dev->bus->busnum, usX2Y(card)->dev->devnum - ); - *cardp = card; - return 0; -} - - -static int usX2Y_usb_probe(struct usb_device *device, - struct usb_interface *intf, - const struct usb_device_id *device_id, - struct snd_card **cardp) -{ - int err; - struct snd_card * card; - - *cardp = NULL; - if (le16_to_cpu(device->descriptor.idVendor) != 0x1604 || - (le16_to_cpu(device->descriptor.idProduct) != USB_ID_US122 && - le16_to_cpu(device->descriptor.idProduct) != USB_ID_US224 && - le16_to_cpu(device->descriptor.idProduct) != USB_ID_US428)) - return -EINVAL; - - err = usX2Y_create_card(device, &card); - if (err < 0) - return err; - snd_card_set_dev(card, &intf->dev); - if ((err = usX2Y_hwdep_new(card, device)) < 0 || - (err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } - *cardp = card; - return 0; -} - -/* - * new 2.5 USB kernel API - */ -static int snd_usX2Y_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct snd_card *card; - int err; - - err = usX2Y_usb_probe(interface_to_usbdev(intf), intf, id, &card); - if (err < 0) - return err; - dev_set_drvdata(&intf->dev, card); - return 0; -} - -static void snd_usX2Y_disconnect(struct usb_interface *intf) -{ - usX2Y_usb_disconnect(interface_to_usbdev(intf), - usb_get_intfdata(intf)); -} - -MODULE_DEVICE_TABLE(usb, snd_usX2Y_usb_id_table); -static struct usb_driver snd_usX2Y_usb_driver = { - .name = "snd-usb-usx2y", - .probe = snd_usX2Y_probe, - .disconnect = snd_usX2Y_disconnect, - .id_table = snd_usX2Y_usb_id_table, -}; - -static void snd_usX2Y_card_private_free(struct snd_card *card) -{ - kfree(usX2Y(card)->In04Buf); - usb_free_urb(usX2Y(card)->In04urb); - if (usX2Y(card)->us428ctls_sharedmem) - snd_free_pages(usX2Y(card)->us428ctls_sharedmem, sizeof(*usX2Y(card)->us428ctls_sharedmem)); - if (usX2Y(card)->card_index >= 0 && usX2Y(card)->card_index < SNDRV_CARDS) - snd_usX2Y_card_used[usX2Y(card)->card_index] = 0; -} - -/* - * Frees the device. - */ -static void usX2Y_usb_disconnect(struct usb_device *device, void* ptr) -{ - if (ptr) { - struct snd_card *card = ptr; - struct usX2Ydev *usX2Y = usX2Y(card); - struct list_head *p; - usX2Y->chip_status = USX2Y_STAT_CHIP_HUP; - usX2Y_unlinkSeq(&usX2Y->AS04); - usb_kill_urb(usX2Y->In04urb); - snd_card_disconnect(card); - /* release the midi resources */ - list_for_each(p, &usX2Y->midi_list) { - snd_usbmidi_disconnect(p); - } - if (usX2Y->us428ctls_sharedmem) - wake_up(&usX2Y->us428ctls_wait_queue_head); - snd_card_free(card); - } -} - -module_usb_driver(snd_usX2Y_usb_driver); diff --git a/ANDROID_3.4.5/sound/usb/usx2y/usbusx2y.h b/ANDROID_3.4.5/sound/usb/usx2y/usbusx2y.h deleted file mode 100644 index e43c0a86..00000000 --- a/ANDROID_3.4.5/sound/usb/usx2y/usbusx2y.h +++ /dev/null @@ -1,88 +0,0 @@ -#ifndef USBUSX2Y_H -#define USBUSX2Y_H -#include "../usbaudio.h" -#include "../midi.h" -#include "usbus428ctldefs.h" - -#define NRURBS 2 - - -#define URBS_AsyncSeq 10 -#define URB_DataLen_AsyncSeq 32 -struct snd_usX2Y_AsyncSeq { - struct urb *urb[URBS_AsyncSeq]; - char *buffer; -}; - -struct snd_usX2Y_urbSeq { - int submitted; - int len; - struct urb *urb[0]; -}; - -#include "usx2yhwdeppcm.h" - -struct usX2Ydev { - struct usb_device *dev; - int card_index; - int stride; - struct urb *In04urb; - void *In04Buf; - char In04Last[24]; - unsigned In04IntCalls; - struct snd_usX2Y_urbSeq *US04; - wait_queue_head_t In04WaitQueue; - struct snd_usX2Y_AsyncSeq AS04; - unsigned int rate, - format; - int chip_status; - struct mutex prepare_mutex; - struct us428ctls_sharedmem *us428ctls_sharedmem; - int wait_iso_frame; - wait_queue_head_t us428ctls_wait_queue_head; - struct snd_usX2Y_hwdep_pcm_shm *hwdep_pcm_shm; - struct snd_usX2Y_substream *subs[4]; - struct snd_usX2Y_substream * volatile prepare_subs; - wait_queue_head_t prepare_wait_queue; - struct list_head midi_list; - struct list_head pcm_list; - int pcm_devs; -}; - - -struct snd_usX2Y_substream { - struct usX2Ydev *usX2Y; - struct snd_pcm_substream *pcm_substream; - - int endpoint; - unsigned int maxpacksize; /* max packet size in bytes */ - - atomic_t state; -#define state_STOPPED 0 -#define state_STARTING1 1 -#define state_STARTING2 2 -#define state_STARTING3 3 -#define state_PREPARED 4 -#define state_PRERUNNING 6 -#define state_RUNNING 8 - - int hwptr; /* free frame position in the buffer (only for playback) */ - int hwptr_done; /* processed frame position in the buffer */ - int transfer_done; /* processed frames since last period update */ - - struct urb *urb[NRURBS]; /* data urb table */ - struct urb *completed_urb; - char *tmpbuf; /* temporary buffer for playback */ -}; - - -#define usX2Y(c) ((struct usX2Ydev *)(c)->private_data) - -int usX2Y_audio_create(struct snd_card *card); - -int usX2Y_AsyncSeq04_init(struct usX2Ydev *usX2Y); -int usX2Y_In04_init(struct usX2Ydev *usX2Y); - -#define NAME_ALLCAPS "US-X2Y" - -#endif diff --git a/ANDROID_3.4.5/sound/usb/usx2y/usbusx2yaudio.c b/ANDROID_3.4.5/sound/usb/usx2y/usbusx2yaudio.c deleted file mode 100644 index 520ef96d..00000000 --- a/ANDROID_3.4.5/sound/usb/usx2y/usbusx2yaudio.c +++ /dev/null @@ -1,1028 +0,0 @@ -/* - * US-X2Y AUDIO - * Copyright (c) 2002-2004 by Karsten Wiese - * - * based on - * - * (Tentative) USB Audio Driver for ALSA - * - * Main and PCM part - * - * Copyright (c) 2002 by Takashi Iwai - * - * Many codes borrowed from audio.c by - * Alan Cox (alan@lxorguk.ukuu.org.uk) - * Thomas Sailer (sailer@ife.ee.ethz.ch) - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include "usx2y.h" -#include "usbusx2y.h" - -#define USX2Y_NRPACKS 4 /* Default value used for nr of packs per urb. - 1 to 4 have been tested ok on uhci. - To use 3 on ohci, you'd need a patch: - look for "0000425-linux-2.6.9-rc4-mm1_ohci-hcd.patch.gz" on - "https://bugtrack.alsa-project.org/alsa-bug/bug_view_page.php?bug_id=0000425" - . - 1, 2 and 4 work out of the box on ohci, if I recall correctly. - Bigger is safer operation, - smaller gives lower latencies. - */ -#define USX2Y_NRPACKS_VARIABLE y /* If your system works ok with this module's parameter - nrpacks set to 1, you might as well comment - this #define out, and thereby produce smaller, faster code. - You'd also set USX2Y_NRPACKS to 1 then. - */ - -#ifdef USX2Y_NRPACKS_VARIABLE - static int nrpacks = USX2Y_NRPACKS; /* number of packets per urb */ - #define nr_of_packs() nrpacks - module_param(nrpacks, int, 0444); - MODULE_PARM_DESC(nrpacks, "Number of packets per URB."); -#else - #define nr_of_packs() USX2Y_NRPACKS -#endif - - -static int usX2Y_urb_capt_retire(struct snd_usX2Y_substream *subs) -{ - struct urb *urb = subs->completed_urb; - struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; - unsigned char *cp; - int i, len, lens = 0, hwptr_done = subs->hwptr_done; - struct usX2Ydev *usX2Y = subs->usX2Y; - - for (i = 0; i < nr_of_packs(); i++) { - cp = (unsigned char*)urb->transfer_buffer + urb->iso_frame_desc[i].offset; - if (urb->iso_frame_desc[i].status) { /* active? hmm, skip this */ - snd_printk(KERN_ERR "active frame status %i. " - "Most probably some hardware problem.\n", - urb->iso_frame_desc[i].status); - return urb->iso_frame_desc[i].status; - } - len = urb->iso_frame_desc[i].actual_length / usX2Y->stride; - if (! len) { - snd_printd("0 == len ERROR!\n"); - continue; - } - - /* copy a data chunk */ - if ((hwptr_done + len) > runtime->buffer_size) { - int cnt = runtime->buffer_size - hwptr_done; - int blen = cnt * usX2Y->stride; - memcpy(runtime->dma_area + hwptr_done * usX2Y->stride, cp, blen); - memcpy(runtime->dma_area, cp + blen, len * usX2Y->stride - blen); - } else { - memcpy(runtime->dma_area + hwptr_done * usX2Y->stride, cp, - len * usX2Y->stride); - } - lens += len; - if ((hwptr_done += len) >= runtime->buffer_size) - hwptr_done -= runtime->buffer_size; - } - - subs->hwptr_done = hwptr_done; - subs->transfer_done += lens; - /* update the pointer, call callback if necessary */ - if (subs->transfer_done >= runtime->period_size) { - subs->transfer_done -= runtime->period_size; - snd_pcm_period_elapsed(subs->pcm_substream); - } - return 0; -} -/* - * prepare urb for playback data pipe - * - * we copy the data directly from the pcm buffer. - * the current position to be copied is held in hwptr field. - * since a urb can handle only a single linear buffer, if the total - * transferred area overflows the buffer boundary, we cannot send - * it directly from the buffer. thus the data is once copied to - * a temporary buffer and urb points to that. - */ -static int usX2Y_urb_play_prepare(struct snd_usX2Y_substream *subs, - struct urb *cap_urb, - struct urb *urb) -{ - int count, counts, pack; - struct usX2Ydev *usX2Y = subs->usX2Y; - struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; - - count = 0; - for (pack = 0; pack < nr_of_packs(); pack++) { - /* calculate the size of a packet */ - counts = cap_urb->iso_frame_desc[pack].actual_length / usX2Y->stride; - count += counts; - if (counts < 43 || counts > 50) { - snd_printk(KERN_ERR "should not be here with counts=%i\n", counts); - return -EPIPE; - } - /* set up descriptor */ - urb->iso_frame_desc[pack].offset = pack ? - urb->iso_frame_desc[pack - 1].offset + - urb->iso_frame_desc[pack - 1].length : - 0; - urb->iso_frame_desc[pack].length = cap_urb->iso_frame_desc[pack].actual_length; - } - if (atomic_read(&subs->state) >= state_PRERUNNING) - if (subs->hwptr + count > runtime->buffer_size) { - /* err, the transferred area goes over buffer boundary. - * copy the data to the temp buffer. - */ - int len; - len = runtime->buffer_size - subs->hwptr; - urb->transfer_buffer = subs->tmpbuf; - memcpy(subs->tmpbuf, runtime->dma_area + - subs->hwptr * usX2Y->stride, len * usX2Y->stride); - memcpy(subs->tmpbuf + len * usX2Y->stride, - runtime->dma_area, (count - len) * usX2Y->stride); - subs->hwptr += count; - subs->hwptr -= runtime->buffer_size; - } else { - /* set the buffer pointer */ - urb->transfer_buffer = runtime->dma_area + subs->hwptr * usX2Y->stride; - if ((subs->hwptr += count) >= runtime->buffer_size) - subs->hwptr -= runtime->buffer_size; - } - else - urb->transfer_buffer = subs->tmpbuf; - urb->transfer_buffer_length = count * usX2Y->stride; - return 0; -} - -/* - * process after playback data complete - * - * update the current position and call callback if a period is processed. - */ -static void usX2Y_urb_play_retire(struct snd_usX2Y_substream *subs, struct urb *urb) -{ - struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; - int len = urb->actual_length / subs->usX2Y->stride; - - subs->transfer_done += len; - subs->hwptr_done += len; - if (subs->hwptr_done >= runtime->buffer_size) - subs->hwptr_done -= runtime->buffer_size; - if (subs->transfer_done >= runtime->period_size) { - subs->transfer_done -= runtime->period_size; - snd_pcm_period_elapsed(subs->pcm_substream); - } -} - -static int usX2Y_urb_submit(struct snd_usX2Y_substream *subs, struct urb *urb, int frame) -{ - int err; - if (!urb) - return -ENODEV; - urb->start_frame = (frame + NRURBS * nr_of_packs()); // let hcd do rollover sanity checks - urb->hcpriv = NULL; - urb->dev = subs->usX2Y->dev; /* we need to set this at each time */ - if ((err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) { - snd_printk(KERN_ERR "usb_submit_urb() returned %i\n", err); - return err; - } - return 0; -} - -static inline int usX2Y_usbframe_complete(struct snd_usX2Y_substream *capsubs, - struct snd_usX2Y_substream *playbacksubs, - int frame) -{ - int err, state; - struct urb *urb = playbacksubs->completed_urb; - - state = atomic_read(&playbacksubs->state); - if (NULL != urb) { - if (state == state_RUNNING) - usX2Y_urb_play_retire(playbacksubs, urb); - else if (state >= state_PRERUNNING) - atomic_inc(&playbacksubs->state); - } else { - switch (state) { - case state_STARTING1: - urb = playbacksubs->urb[0]; - atomic_inc(&playbacksubs->state); - break; - case state_STARTING2: - urb = playbacksubs->urb[1]; - atomic_inc(&playbacksubs->state); - break; - } - } - if (urb) { - if ((err = usX2Y_urb_play_prepare(playbacksubs, capsubs->completed_urb, urb)) || - (err = usX2Y_urb_submit(playbacksubs, urb, frame))) { - return err; - } - } - - playbacksubs->completed_urb = NULL; - - state = atomic_read(&capsubs->state); - if (state >= state_PREPARED) { - if (state == state_RUNNING) { - if ((err = usX2Y_urb_capt_retire(capsubs))) - return err; - } else if (state >= state_PRERUNNING) - atomic_inc(&capsubs->state); - if ((err = usX2Y_urb_submit(capsubs, capsubs->completed_urb, frame))) - return err; - } - capsubs->completed_urb = NULL; - return 0; -} - - -static void usX2Y_clients_stop(struct usX2Ydev *usX2Y) -{ - int s, u; - - for (s = 0; s < 4; s++) { - struct snd_usX2Y_substream *subs = usX2Y->subs[s]; - if (subs) { - snd_printdd("%i %p state=%i\n", s, subs, atomic_read(&subs->state)); - atomic_set(&subs->state, state_STOPPED); - } - } - for (s = 0; s < 4; s++) { - struct snd_usX2Y_substream *subs = usX2Y->subs[s]; - if (subs) { - if (atomic_read(&subs->state) >= state_PRERUNNING) { - snd_pcm_stop(subs->pcm_substream, SNDRV_PCM_STATE_XRUN); - } - for (u = 0; u < NRURBS; u++) { - struct urb *urb = subs->urb[u]; - if (NULL != urb) - snd_printdd("%i status=%i start_frame=%i\n", - u, urb->status, urb->start_frame); - } - } - } - usX2Y->prepare_subs = NULL; - wake_up(&usX2Y->prepare_wait_queue); -} - -static void usX2Y_error_urb_status(struct usX2Ydev *usX2Y, - struct snd_usX2Y_substream *subs, struct urb *urb) -{ - snd_printk(KERN_ERR "ep=%i stalled with status=%i\n", subs->endpoint, urb->status); - urb->status = 0; - usX2Y_clients_stop(usX2Y); -} - -static void usX2Y_error_sequence(struct usX2Ydev *usX2Y, - struct snd_usX2Y_substream *subs, struct urb *urb) -{ - snd_printk(KERN_ERR -"Sequence Error!(hcd_frame=%i ep=%i%s;wait=%i,frame=%i).\n" -"Most probably some urb of usb-frame %i is still missing.\n" -"Cause could be too long delays in usb-hcd interrupt handling.\n", - usb_get_current_frame_number(usX2Y->dev), - subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out", - usX2Y->wait_iso_frame, urb->start_frame, usX2Y->wait_iso_frame); - usX2Y_clients_stop(usX2Y); -} - -static void i_usX2Y_urb_complete(struct urb *urb) -{ - struct snd_usX2Y_substream *subs = urb->context; - struct usX2Ydev *usX2Y = subs->usX2Y; - - if (unlikely(atomic_read(&subs->state) < state_PREPARED)) { - snd_printdd("hcd_frame=%i ep=%i%s status=%i start_frame=%i\n", - usb_get_current_frame_number(usX2Y->dev), - subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out", - urb->status, urb->start_frame); - return; - } - if (unlikely(urb->status)) { - usX2Y_error_urb_status(usX2Y, subs, urb); - return; - } - if (likely((urb->start_frame & 0xFFFF) == (usX2Y->wait_iso_frame & 0xFFFF))) - subs->completed_urb = urb; - else { - usX2Y_error_sequence(usX2Y, subs, urb); - return; - } - { - struct snd_usX2Y_substream *capsubs = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE], - *playbacksubs = usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]; - if (capsubs->completed_urb && - atomic_read(&capsubs->state) >= state_PREPARED && - (playbacksubs->completed_urb || - atomic_read(&playbacksubs->state) < state_PREPARED)) { - if (!usX2Y_usbframe_complete(capsubs, playbacksubs, urb->start_frame)) - usX2Y->wait_iso_frame += nr_of_packs(); - else { - snd_printdd("\n"); - usX2Y_clients_stop(usX2Y); - } - } - } -} - -static void usX2Y_urbs_set_complete(struct usX2Ydev * usX2Y, - void (*complete)(struct urb *)) -{ - int s, u; - for (s = 0; s < 4; s++) { - struct snd_usX2Y_substream *subs = usX2Y->subs[s]; - if (NULL != subs) - for (u = 0; u < NRURBS; u++) { - struct urb * urb = subs->urb[u]; - if (NULL != urb) - urb->complete = complete; - } - } -} - -static void usX2Y_subs_startup_finish(struct usX2Ydev * usX2Y) -{ - usX2Y_urbs_set_complete(usX2Y, i_usX2Y_urb_complete); - usX2Y->prepare_subs = NULL; -} - -static void i_usX2Y_subs_startup(struct urb *urb) -{ - struct snd_usX2Y_substream *subs = urb->context; - struct usX2Ydev *usX2Y = subs->usX2Y; - struct snd_usX2Y_substream *prepare_subs = usX2Y->prepare_subs; - if (NULL != prepare_subs) - if (urb->start_frame == prepare_subs->urb[0]->start_frame) { - usX2Y_subs_startup_finish(usX2Y); - atomic_inc(&prepare_subs->state); - wake_up(&usX2Y->prepare_wait_queue); - } - - i_usX2Y_urb_complete(urb); -} - -static void usX2Y_subs_prepare(struct snd_usX2Y_substream *subs) -{ - snd_printdd("usX2Y_substream_prepare(%p) ep=%i urb0=%p urb1=%p\n", - subs, subs->endpoint, subs->urb[0], subs->urb[1]); - /* reset the pointer */ - subs->hwptr = 0; - subs->hwptr_done = 0; - subs->transfer_done = 0; -} - - -static void usX2Y_urb_release(struct urb **urb, int free_tb) -{ - if (*urb) { - usb_kill_urb(*urb); - if (free_tb) - kfree((*urb)->transfer_buffer); - usb_free_urb(*urb); - *urb = NULL; - } -} -/* - * release a substreams urbs - */ -static void usX2Y_urbs_release(struct snd_usX2Y_substream *subs) -{ - int i; - snd_printdd("usX2Y_urbs_release() %i\n", subs->endpoint); - for (i = 0; i < NRURBS; i++) - usX2Y_urb_release(subs->urb + i, - subs != subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]); - - kfree(subs->tmpbuf); - subs->tmpbuf = NULL; -} -/* - * initialize a substream's urbs - */ -static int usX2Y_urbs_allocate(struct snd_usX2Y_substream *subs) -{ - int i; - unsigned int pipe; - int is_playback = subs == subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]; - struct usb_device *dev = subs->usX2Y->dev; - - pipe = is_playback ? usb_sndisocpipe(dev, subs->endpoint) : - usb_rcvisocpipe(dev, subs->endpoint); - subs->maxpacksize = usb_maxpacket(dev, pipe, is_playback); - if (!subs->maxpacksize) - return -EINVAL; - - if (is_playback && NULL == subs->tmpbuf) { /* allocate a temporary buffer for playback */ - subs->tmpbuf = kcalloc(nr_of_packs(), subs->maxpacksize, GFP_KERNEL); - if (NULL == subs->tmpbuf) { - snd_printk(KERN_ERR "cannot malloc tmpbuf\n"); - return -ENOMEM; - } - } - /* allocate and initialize data urbs */ - for (i = 0; i < NRURBS; i++) { - struct urb **purb = subs->urb + i; - if (*purb) { - usb_kill_urb(*purb); - continue; - } - *purb = usb_alloc_urb(nr_of_packs(), GFP_KERNEL); - if (NULL == *purb) { - usX2Y_urbs_release(subs); - return -ENOMEM; - } - if (!is_playback && !(*purb)->transfer_buffer) { - /* allocate a capture buffer per urb */ - (*purb)->transfer_buffer = kmalloc(subs->maxpacksize * nr_of_packs(), GFP_KERNEL); - if (NULL == (*purb)->transfer_buffer) { - usX2Y_urbs_release(subs); - return -ENOMEM; - } - } - (*purb)->dev = dev; - (*purb)->pipe = pipe; - (*purb)->number_of_packets = nr_of_packs(); - (*purb)->context = subs; - (*purb)->interval = 1; - (*purb)->complete = i_usX2Y_subs_startup; - } - return 0; -} - -static void usX2Y_subs_startup(struct snd_usX2Y_substream *subs) -{ - struct usX2Ydev *usX2Y = subs->usX2Y; - usX2Y->prepare_subs = subs; - subs->urb[0]->start_frame = -1; - wmb(); - usX2Y_urbs_set_complete(usX2Y, i_usX2Y_subs_startup); -} - -static int usX2Y_urbs_start(struct snd_usX2Y_substream *subs) -{ - int i, err; - struct usX2Ydev *usX2Y = subs->usX2Y; - - if ((err = usX2Y_urbs_allocate(subs)) < 0) - return err; - subs->completed_urb = NULL; - for (i = 0; i < 4; i++) { - struct snd_usX2Y_substream *subs = usX2Y->subs[i]; - if (subs != NULL && atomic_read(&subs->state) >= state_PREPARED) - goto start; - } - - start: - usX2Y_subs_startup(subs); - for (i = 0; i < NRURBS; i++) { - struct urb *urb = subs->urb[i]; - if (usb_pipein(urb->pipe)) { - unsigned long pack; - if (0 == i) - atomic_set(&subs->state, state_STARTING3); - urb->dev = usX2Y->dev; - urb->transfer_flags = URB_ISO_ASAP; - for (pack = 0; pack < nr_of_packs(); pack++) { - urb->iso_frame_desc[pack].offset = subs->maxpacksize * pack; - urb->iso_frame_desc[pack].length = subs->maxpacksize; - } - urb->transfer_buffer_length = subs->maxpacksize * nr_of_packs(); - if ((err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) { - snd_printk (KERN_ERR "cannot submit datapipe for urb %d, err = %d\n", i, err); - err = -EPIPE; - goto cleanup; - } else - if (i == 0) - usX2Y->wait_iso_frame = urb->start_frame; - urb->transfer_flags = 0; - } else { - atomic_set(&subs->state, state_STARTING1); - break; - } - } - err = 0; - wait_event(usX2Y->prepare_wait_queue, NULL == usX2Y->prepare_subs); - if (atomic_read(&subs->state) != state_PREPARED) - err = -EPIPE; - - cleanup: - if (err) { - usX2Y_subs_startup_finish(usX2Y); - usX2Y_clients_stop(usX2Y); // something is completely wroong > stop evrything - } - return err; -} - -/* - * return the current pcm pointer. just return the hwptr_done value. - */ -static snd_pcm_uframes_t snd_usX2Y_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct snd_usX2Y_substream *subs = substream->runtime->private_data; - return subs->hwptr_done; -} -/* - * start/stop substream - */ -static int snd_usX2Y_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_usX2Y_substream *subs = substream->runtime->private_data; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - snd_printdd("snd_usX2Y_pcm_trigger(START)\n"); - if (atomic_read(&subs->state) == state_PREPARED && - atomic_read(&subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE]->state) >= state_PREPARED) { - atomic_set(&subs->state, state_PRERUNNING); - } else { - snd_printdd("\n"); - return -EPIPE; - } - break; - case SNDRV_PCM_TRIGGER_STOP: - snd_printdd("snd_usX2Y_pcm_trigger(STOP)\n"); - if (atomic_read(&subs->state) >= state_PRERUNNING) - atomic_set(&subs->state, state_PREPARED); - break; - default: - return -EINVAL; - } - return 0; -} - - -/* - * allocate a buffer, setup samplerate - * - * so far we use a physically linear buffer although packetize transfer - * doesn't need a continuous area. - * if sg buffer is supported on the later version of alsa, we'll follow - * that. - */ -static struct s_c2 -{ - char c1, c2; -} - SetRate44100[] = -{ - { 0x14, 0x08}, // this line sets 44100, well actually a little less - { 0x18, 0x40}, // only tascam / frontier design knows the further lines ....... - { 0x18, 0x42}, - { 0x18, 0x45}, - { 0x18, 0x46}, - { 0x18, 0x48}, - { 0x18, 0x4A}, - { 0x18, 0x4C}, - { 0x18, 0x4E}, - { 0x18, 0x50}, - { 0x18, 0x52}, - { 0x18, 0x54}, - { 0x18, 0x56}, - { 0x18, 0x58}, - { 0x18, 0x5A}, - { 0x18, 0x5C}, - { 0x18, 0x5E}, - { 0x18, 0x60}, - { 0x18, 0x62}, - { 0x18, 0x64}, - { 0x18, 0x66}, - { 0x18, 0x68}, - { 0x18, 0x6A}, - { 0x18, 0x6C}, - { 0x18, 0x6E}, - { 0x18, 0x70}, - { 0x18, 0x72}, - { 0x18, 0x74}, - { 0x18, 0x76}, - { 0x18, 0x78}, - { 0x18, 0x7A}, - { 0x18, 0x7C}, - { 0x18, 0x7E} -}; -static struct s_c2 SetRate48000[] = -{ - { 0x14, 0x09}, // this line sets 48000, well actually a little less - { 0x18, 0x40}, // only tascam / frontier design knows the further lines ....... - { 0x18, 0x42}, - { 0x18, 0x45}, - { 0x18, 0x46}, - { 0x18, 0x48}, - { 0x18, 0x4A}, - { 0x18, 0x4C}, - { 0x18, 0x4E}, - { 0x18, 0x50}, - { 0x18, 0x52}, - { 0x18, 0x54}, - { 0x18, 0x56}, - { 0x18, 0x58}, - { 0x18, 0x5A}, - { 0x18, 0x5C}, - { 0x18, 0x5E}, - { 0x18, 0x60}, - { 0x18, 0x62}, - { 0x18, 0x64}, - { 0x18, 0x66}, - { 0x18, 0x68}, - { 0x18, 0x6A}, - { 0x18, 0x6C}, - { 0x18, 0x6E}, - { 0x18, 0x70}, - { 0x18, 0x73}, - { 0x18, 0x74}, - { 0x18, 0x76}, - { 0x18, 0x78}, - { 0x18, 0x7A}, - { 0x18, 0x7C}, - { 0x18, 0x7E} -}; -#define NOOF_SETRATE_URBS ARRAY_SIZE(SetRate48000) - -static void i_usX2Y_04Int(struct urb *urb) -{ - struct usX2Ydev *usX2Y = urb->context; - - if (urb->status) - snd_printk(KERN_ERR "snd_usX2Y_04Int() urb->status=%i\n", urb->status); - if (0 == --usX2Y->US04->len) - wake_up(&usX2Y->In04WaitQueue); -} - -static int usX2Y_rate_set(struct usX2Ydev *usX2Y, int rate) -{ - int err = 0, i; - struct snd_usX2Y_urbSeq *us = NULL; - int *usbdata = NULL; - struct s_c2 *ra = rate == 48000 ? SetRate48000 : SetRate44100; - - if (usX2Y->rate != rate) { - us = kzalloc(sizeof(*us) + sizeof(struct urb*) * NOOF_SETRATE_URBS, GFP_KERNEL); - if (NULL == us) { - err = -ENOMEM; - goto cleanup; - } - usbdata = kmalloc(sizeof(int) * NOOF_SETRATE_URBS, GFP_KERNEL); - if (NULL == usbdata) { - err = -ENOMEM; - goto cleanup; - } - for (i = 0; i < NOOF_SETRATE_URBS; ++i) { - if (NULL == (us->urb[i] = usb_alloc_urb(0, GFP_KERNEL))) { - err = -ENOMEM; - goto cleanup; - } - ((char*)(usbdata + i))[0] = ra[i].c1; - ((char*)(usbdata + i))[1] = ra[i].c2; - usb_fill_bulk_urb(us->urb[i], usX2Y->dev, usb_sndbulkpipe(usX2Y->dev, 4), - usbdata + i, 2, i_usX2Y_04Int, usX2Y); -#ifdef OLD_USB - us->urb[i]->transfer_flags = USB_QUEUE_BULK; -#endif - } - us->submitted = 0; - us->len = NOOF_SETRATE_URBS; - usX2Y->US04 = us; - wait_event_timeout(usX2Y->In04WaitQueue, 0 == us->len, HZ); - usX2Y->US04 = NULL; - if (us->len) - err = -ENODEV; - cleanup: - if (us) { - us->submitted = 2*NOOF_SETRATE_URBS; - for (i = 0; i < NOOF_SETRATE_URBS; ++i) { - struct urb *urb = us->urb[i]; - if (urb->status) { - if (!err) - err = -ENODEV; - usb_kill_urb(urb); - } - usb_free_urb(urb); - } - usX2Y->US04 = NULL; - kfree(usbdata); - kfree(us); - if (!err) - usX2Y->rate = rate; - } - } - - return err; -} - - -static int usX2Y_format_set(struct usX2Ydev *usX2Y, snd_pcm_format_t format) -{ - int alternate, err; - struct list_head* p; - if (format == SNDRV_PCM_FORMAT_S24_3LE) { - alternate = 2; - usX2Y->stride = 6; - } else { - alternate = 1; - usX2Y->stride = 4; - } - list_for_each(p, &usX2Y->midi_list) { - snd_usbmidi_input_stop(p); - } - usb_kill_urb(usX2Y->In04urb); - if ((err = usb_set_interface(usX2Y->dev, 0, alternate))) { - snd_printk(KERN_ERR "usb_set_interface error \n"); - return err; - } - usX2Y->In04urb->dev = usX2Y->dev; - err = usb_submit_urb(usX2Y->In04urb, GFP_KERNEL); - list_for_each(p, &usX2Y->midi_list) { - snd_usbmidi_input_start(p); - } - usX2Y->format = format; - usX2Y->rate = 0; - return err; -} - - -static int snd_usX2Y_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - int err = 0; - unsigned int rate = params_rate(hw_params); - snd_pcm_format_t format = params_format(hw_params); - struct snd_card *card = substream->pstr->pcm->card; - struct list_head *list; - - snd_printdd("snd_usX2Y_hw_params(%p, %p)\n", substream, hw_params); - // all pcm substreams off one usX2Y have to operate at the same rate & format - list_for_each(list, &card->devices) { - struct snd_device *dev; - struct snd_pcm *pcm; - int s; - dev = snd_device(list); - if (dev->type != SNDRV_DEV_PCM) - continue; - pcm = dev->device_data; - for (s = 0; s < 2; ++s) { - struct snd_pcm_substream *test_substream; - test_substream = pcm->streams[s].substream; - if (test_substream && test_substream != substream && - test_substream->runtime && - ((test_substream->runtime->format && - test_substream->runtime->format != format) || - (test_substream->runtime->rate && - test_substream->runtime->rate != rate))) - return -EINVAL; - } - } - if (0 > (err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)))) { - snd_printk(KERN_ERR "snd_pcm_lib_malloc_pages(%p, %i) returned %i\n", - substream, params_buffer_bytes(hw_params), err); - return err; - } - return 0; -} - -/* - * free the buffer - */ -static int snd_usX2Y_pcm_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_usX2Y_substream *subs = runtime->private_data; - mutex_lock(&subs->usX2Y->prepare_mutex); - snd_printdd("snd_usX2Y_hw_free(%p)\n", substream); - - if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) { - struct snd_usX2Y_substream *cap_subs = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE]; - atomic_set(&subs->state, state_STOPPED); - usX2Y_urbs_release(subs); - if (!cap_subs->pcm_substream || - !cap_subs->pcm_substream->runtime || - !cap_subs->pcm_substream->runtime->status || - cap_subs->pcm_substream->runtime->status->state < SNDRV_PCM_STATE_PREPARED) { - atomic_set(&cap_subs->state, state_STOPPED); - usX2Y_urbs_release(cap_subs); - } - } else { - struct snd_usX2Y_substream *playback_subs = subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]; - if (atomic_read(&playback_subs->state) < state_PREPARED) { - atomic_set(&subs->state, state_STOPPED); - usX2Y_urbs_release(subs); - } - } - mutex_unlock(&subs->usX2Y->prepare_mutex); - return snd_pcm_lib_free_pages(substream); -} -/* - * prepare callback - * - * set format and initialize urbs - */ -static int snd_usX2Y_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_usX2Y_substream *subs = runtime->private_data; - struct usX2Ydev *usX2Y = subs->usX2Y; - struct snd_usX2Y_substream *capsubs = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE]; - int err = 0; - snd_printdd("snd_usX2Y_pcm_prepare(%p)\n", substream); - - mutex_lock(&usX2Y->prepare_mutex); - usX2Y_subs_prepare(subs); -// Start hardware streams -// SyncStream first.... - if (atomic_read(&capsubs->state) < state_PREPARED) { - if (usX2Y->format != runtime->format) - if ((err = usX2Y_format_set(usX2Y, runtime->format)) < 0) - goto up_prepare_mutex; - if (usX2Y->rate != runtime->rate) - if ((err = usX2Y_rate_set(usX2Y, runtime->rate)) < 0) - goto up_prepare_mutex; - snd_printdd("starting capture pipe for %s\n", subs == capsubs ? "self" : "playpipe"); - if (0 > (err = usX2Y_urbs_start(capsubs))) - goto up_prepare_mutex; - } - - if (subs != capsubs && atomic_read(&subs->state) < state_PREPARED) - err = usX2Y_urbs_start(subs); - - up_prepare_mutex: - mutex_unlock(&usX2Y->prepare_mutex); - return err; -} - -static struct snd_pcm_hardware snd_usX2Y_2c = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_BATCH), - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE, - .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, - .rate_min = 44100, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = (2*128*1024), - .period_bytes_min = 64, - .period_bytes_max = (128*1024), - .periods_min = 2, - .periods_max = 1024, - .fifo_size = 0 -}; - - - -static int snd_usX2Y_pcm_open(struct snd_pcm_substream *substream) -{ - struct snd_usX2Y_substream *subs = ((struct snd_usX2Y_substream **) - snd_pcm_substream_chip(substream))[substream->stream]; - struct snd_pcm_runtime *runtime = substream->runtime; - - if (subs->usX2Y->chip_status & USX2Y_STAT_CHIP_MMAP_PCM_URBS) - return -EBUSY; - - runtime->hw = snd_usX2Y_2c; - runtime->private_data = subs; - subs->pcm_substream = substream; - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 1000, 200000); - return 0; -} - - - -static int snd_usX2Y_pcm_close(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_usX2Y_substream *subs = runtime->private_data; - - subs->pcm_substream = NULL; - - return 0; -} - - -static struct snd_pcm_ops snd_usX2Y_pcm_ops = -{ - .open = snd_usX2Y_pcm_open, - .close = snd_usX2Y_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_usX2Y_pcm_hw_params, - .hw_free = snd_usX2Y_pcm_hw_free, - .prepare = snd_usX2Y_pcm_prepare, - .trigger = snd_usX2Y_pcm_trigger, - .pointer = snd_usX2Y_pcm_pointer, -}; - - -/* - * free a usb stream instance - */ -static void usX2Y_audio_stream_free(struct snd_usX2Y_substream **usX2Y_substream) -{ - kfree(usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK]); - usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK] = NULL; - - kfree(usX2Y_substream[SNDRV_PCM_STREAM_CAPTURE]); - usX2Y_substream[SNDRV_PCM_STREAM_CAPTURE] = NULL; -} - -static void snd_usX2Y_pcm_private_free(struct snd_pcm *pcm) -{ - struct snd_usX2Y_substream **usX2Y_stream = pcm->private_data; - if (usX2Y_stream) - usX2Y_audio_stream_free(usX2Y_stream); -} - -static int usX2Y_audio_stream_new(struct snd_card *card, int playback_endpoint, int capture_endpoint) -{ - struct snd_pcm *pcm; - int err, i; - struct snd_usX2Y_substream **usX2Y_substream = - usX2Y(card)->subs + 2 * usX2Y(card)->pcm_devs; - - for (i = playback_endpoint ? SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE; - i <= SNDRV_PCM_STREAM_CAPTURE; ++i) { - usX2Y_substream[i] = kzalloc(sizeof(struct snd_usX2Y_substream), GFP_KERNEL); - if (NULL == usX2Y_substream[i]) { - snd_printk(KERN_ERR "cannot malloc\n"); - return -ENOMEM; - } - usX2Y_substream[i]->usX2Y = usX2Y(card); - } - - if (playback_endpoint) - usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK]->endpoint = playback_endpoint; - usX2Y_substream[SNDRV_PCM_STREAM_CAPTURE]->endpoint = capture_endpoint; - - err = snd_pcm_new(card, NAME_ALLCAPS" Audio", usX2Y(card)->pcm_devs, - playback_endpoint ? 1 : 0, 1, - &pcm); - if (err < 0) { - usX2Y_audio_stream_free(usX2Y_substream); - return err; - } - - if (playback_endpoint) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_usX2Y_pcm_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_usX2Y_pcm_ops); - - pcm->private_data = usX2Y_substream; - pcm->private_free = snd_usX2Y_pcm_private_free; - pcm->info_flags = 0; - - sprintf(pcm->name, NAME_ALLCAPS" Audio #%d", usX2Y(card)->pcm_devs); - - if ((playback_endpoint && - 0 > (err = snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream, - SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data(GFP_KERNEL), - 64*1024, 128*1024))) || - 0 > (err = snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream, - SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data(GFP_KERNEL), - 64*1024, 128*1024))) { - snd_usX2Y_pcm_private_free(pcm); - return err; - } - usX2Y(card)->pcm_devs++; - - return 0; -} - -/* - * create a chip instance and set its names. - */ -int usX2Y_audio_create(struct snd_card *card) -{ - int err = 0; - - INIT_LIST_HEAD(&usX2Y(card)->pcm_list); - - if (0 > (err = usX2Y_audio_stream_new(card, 0xA, 0x8))) - return err; - if (le16_to_cpu(usX2Y(card)->dev->descriptor.idProduct) == USB_ID_US428) - if (0 > (err = usX2Y_audio_stream_new(card, 0, 0xA))) - return err; - if (le16_to_cpu(usX2Y(card)->dev->descriptor.idProduct) != USB_ID_US122) - err = usX2Y_rate_set(usX2Y(card), 44100); // Lets us428 recognize output-volume settings, disturbs us122. - return err; -} diff --git a/ANDROID_3.4.5/sound/usb/usx2y/usx2y.h b/ANDROID_3.4.5/sound/usb/usx2y/usx2y.h deleted file mode 100644 index 7e59263d..00000000 --- a/ANDROID_3.4.5/sound/usb/usx2y/usx2y.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Driver for Tascam US-X2Y USB soundcards - * - * Copyright (c) 2003 by Karsten Wiese - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __SOUND_USX2Y_COMMON_H -#define __SOUND_USX2Y_COMMON_H - - -#define USX2Y_DRIVER_VERSION 0x0100 /* 0.1.0 */ - - -/* hwdep id string */ -#define SND_USX2Y_LOADER_ID "USX2Y Loader" -#define SND_USX2Y_USBPCM_ID "USX2Y USBPCM" - -/* hardware type */ -enum { - USX2Y_TYPE_122, - USX2Y_TYPE_224, - USX2Y_TYPE_428, - USX2Y_TYPE_NUMS -}; - -#define USB_ID_US122 0x8007 -#define USB_ID_US224 0x8005 -#define USB_ID_US428 0x8001 - -/* chip status */ -enum { - USX2Y_STAT_CHIP_INIT = (1 << 0), /* all operational */ - USX2Y_STAT_CHIP_MMAP_PCM_URBS = (1 << 1), /* pcm transport over mmaped urbs */ - USX2Y_STAT_CHIP_HUP = (1 << 31), /* all operational */ -}; - -#endif /* __SOUND_USX2Y_COMMON_H */ diff --git a/ANDROID_3.4.5/sound/usb/usx2y/usx2yhwdeppcm.c b/ANDROID_3.4.5/sound/usb/usx2y/usx2yhwdeppcm.c deleted file mode 100644 index 8e40b6e6..00000000 --- a/ANDROID_3.4.5/sound/usb/usx2y/usx2yhwdeppcm.c +++ /dev/null @@ -1,794 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* USX2Y "rawusb" aka hwdep_pcm implementation - - Its usb's unableness to atomically handle power of 2 period sized data chuncs - at standard samplerates, - what led to this part of the usx2y module: - It provides the alsa kernel half of the usx2y-alsa-jack driver pair. - The pair uses a hardware dependent alsa-device for mmaped pcm transport. - Advantage achieved: - The usb_hc moves pcm data from/into memory via DMA. - That memory is mmaped by jack's usx2y driver. - Jack's usx2y driver is the first/last to read/write pcm data. - Read/write is a combination of power of 2 period shaping and - float/int conversation. - Compared to mainline alsa/jack we leave out power of 2 period shaping inside - snd-usb-usx2y which needs memcpy() and additional buffers. - As a side effect possible unwanted pcm-data coruption resulting of - standard alsa's snd-usb-usx2y period shaping scheme falls away. - Result is sane jack operation at buffering schemes down to 128frames, - 2 periods. - plain usx2y alsa mode is able to achieve 64frames, 4periods, but only at the - cost of easier triggered i.e. aeolus xruns (128 or 256frames, - 2periods works but is useless cause of crackling). - - This is a first "proof of concept" implementation. - Later, functionalities should migrate to more appropriate places: - Userland: - - The jackd could mmap its float-pcm buffers directly from alsa-lib. - - alsa-lib could provide power of 2 period sized shaping combined with int/float - conversation. - Currently the usx2y jack driver provides above 2 services. - Kernel: - - rawusb dma pcm buffer transport should go to snd-usb-lib, so also snd-usb-audio - devices can use it. - Currently rawusb dma pcm buffer transport (this file) is only available to snd-usb-usx2y. -*/ - -#include -#include -#include "usbusx2yaudio.c" - -#if defined(USX2Y_NRPACKS_VARIABLE) || USX2Y_NRPACKS == 1 - -#include - - -static int usX2Y_usbpcm_urb_capt_retire(struct snd_usX2Y_substream *subs) -{ - struct urb *urb = subs->completed_urb; - struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; - int i, lens = 0, hwptr_done = subs->hwptr_done; - struct usX2Ydev *usX2Y = subs->usX2Y; - if (0 > usX2Y->hwdep_pcm_shm->capture_iso_start) { //FIXME - int head = usX2Y->hwdep_pcm_shm->captured_iso_head + 1; - if (head >= ARRAY_SIZE(usX2Y->hwdep_pcm_shm->captured_iso)) - head = 0; - usX2Y->hwdep_pcm_shm->capture_iso_start = head; - snd_printdd("cap start %i\n", head); - } - for (i = 0; i < nr_of_packs(); i++) { - if (urb->iso_frame_desc[i].status) { /* active? hmm, skip this */ - snd_printk(KERN_ERR "active frame status %i. Most probably some hardware problem.\n", urb->iso_frame_desc[i].status); - return urb->iso_frame_desc[i].status; - } - lens += urb->iso_frame_desc[i].actual_length / usX2Y->stride; - } - if ((hwptr_done += lens) >= runtime->buffer_size) - hwptr_done -= runtime->buffer_size; - subs->hwptr_done = hwptr_done; - subs->transfer_done += lens; - /* update the pointer, call callback if necessary */ - if (subs->transfer_done >= runtime->period_size) { - subs->transfer_done -= runtime->period_size; - snd_pcm_period_elapsed(subs->pcm_substream); - } - return 0; -} - -static inline int usX2Y_iso_frames_per_buffer(struct snd_pcm_runtime *runtime, - struct usX2Ydev * usX2Y) -{ - return (runtime->buffer_size * 1000) / usX2Y->rate + 1; //FIXME: so far only correct period_size == 2^x ? -} - -/* - * prepare urb for playback data pipe - * - * we copy the data directly from the pcm buffer. - * the current position to be copied is held in hwptr field. - * since a urb can handle only a single linear buffer, if the total - * transferred area overflows the buffer boundary, we cannot send - * it directly from the buffer. thus the data is once copied to - * a temporary buffer and urb points to that. - */ -static int usX2Y_hwdep_urb_play_prepare(struct snd_usX2Y_substream *subs, - struct urb *urb) -{ - int count, counts, pack; - struct usX2Ydev *usX2Y = subs->usX2Y; - struct snd_usX2Y_hwdep_pcm_shm *shm = usX2Y->hwdep_pcm_shm; - struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; - - if (0 > shm->playback_iso_start) { - shm->playback_iso_start = shm->captured_iso_head - - usX2Y_iso_frames_per_buffer(runtime, usX2Y); - if (0 > shm->playback_iso_start) - shm->playback_iso_start += ARRAY_SIZE(shm->captured_iso); - shm->playback_iso_head = shm->playback_iso_start; - } - - count = 0; - for (pack = 0; pack < nr_of_packs(); pack++) { - /* calculate the size of a packet */ - counts = shm->captured_iso[shm->playback_iso_head].length / usX2Y->stride; - if (counts < 43 || counts > 50) { - snd_printk(KERN_ERR "should not be here with counts=%i\n", counts); - return -EPIPE; - } - /* set up descriptor */ - urb->iso_frame_desc[pack].offset = shm->captured_iso[shm->playback_iso_head].offset; - urb->iso_frame_desc[pack].length = shm->captured_iso[shm->playback_iso_head].length; - if (atomic_read(&subs->state) != state_RUNNING) - memset((char *)urb->transfer_buffer + urb->iso_frame_desc[pack].offset, 0, - urb->iso_frame_desc[pack].length); - if (++shm->playback_iso_head >= ARRAY_SIZE(shm->captured_iso)) - shm->playback_iso_head = 0; - count += counts; - } - urb->transfer_buffer_length = count * usX2Y->stride; - return 0; -} - - -static inline void usX2Y_usbpcm_urb_capt_iso_advance(struct snd_usX2Y_substream *subs, - struct urb *urb) -{ - int pack; - for (pack = 0; pack < nr_of_packs(); ++pack) { - struct usb_iso_packet_descriptor *desc = urb->iso_frame_desc + pack; - if (NULL != subs) { - struct snd_usX2Y_hwdep_pcm_shm *shm = subs->usX2Y->hwdep_pcm_shm; - int head = shm->captured_iso_head + 1; - if (head >= ARRAY_SIZE(shm->captured_iso)) - head = 0; - shm->captured_iso[head].frame = urb->start_frame + pack; - shm->captured_iso[head].offset = desc->offset; - shm->captured_iso[head].length = desc->actual_length; - shm->captured_iso_head = head; - shm->captured_iso_frames++; - } - if ((desc->offset += desc->length * NRURBS*nr_of_packs()) + - desc->length >= SSS) - desc->offset -= (SSS - desc->length); - } -} - -static inline int usX2Y_usbpcm_usbframe_complete(struct snd_usX2Y_substream *capsubs, - struct snd_usX2Y_substream *capsubs2, - struct snd_usX2Y_substream *playbacksubs, - int frame) -{ - int err, state; - struct urb *urb = playbacksubs->completed_urb; - - state = atomic_read(&playbacksubs->state); - if (NULL != urb) { - if (state == state_RUNNING) - usX2Y_urb_play_retire(playbacksubs, urb); - else if (state >= state_PRERUNNING) - atomic_inc(&playbacksubs->state); - } else { - switch (state) { - case state_STARTING1: - urb = playbacksubs->urb[0]; - atomic_inc(&playbacksubs->state); - break; - case state_STARTING2: - urb = playbacksubs->urb[1]; - atomic_inc(&playbacksubs->state); - break; - } - } - if (urb) { - if ((err = usX2Y_hwdep_urb_play_prepare(playbacksubs, urb)) || - (err = usX2Y_urb_submit(playbacksubs, urb, frame))) { - return err; - } - } - - playbacksubs->completed_urb = NULL; - - state = atomic_read(&capsubs->state); - if (state >= state_PREPARED) { - if (state == state_RUNNING) { - if ((err = usX2Y_usbpcm_urb_capt_retire(capsubs))) - return err; - } else if (state >= state_PRERUNNING) - atomic_inc(&capsubs->state); - usX2Y_usbpcm_urb_capt_iso_advance(capsubs, capsubs->completed_urb); - if (NULL != capsubs2) - usX2Y_usbpcm_urb_capt_iso_advance(NULL, capsubs2->completed_urb); - if ((err = usX2Y_urb_submit(capsubs, capsubs->completed_urb, frame))) - return err; - if (NULL != capsubs2) - if ((err = usX2Y_urb_submit(capsubs2, capsubs2->completed_urb, frame))) - return err; - } - capsubs->completed_urb = NULL; - if (NULL != capsubs2) - capsubs2->completed_urb = NULL; - return 0; -} - - -static void i_usX2Y_usbpcm_urb_complete(struct urb *urb) -{ - struct snd_usX2Y_substream *subs = urb->context; - struct usX2Ydev *usX2Y = subs->usX2Y; - struct snd_usX2Y_substream *capsubs, *capsubs2, *playbacksubs; - - if (unlikely(atomic_read(&subs->state) < state_PREPARED)) { - snd_printdd("hcd_frame=%i ep=%i%s status=%i start_frame=%i\n", - usb_get_current_frame_number(usX2Y->dev), - subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out", - urb->status, urb->start_frame); - return; - } - if (unlikely(urb->status)) { - usX2Y_error_urb_status(usX2Y, subs, urb); - return; - } - if (likely((urb->start_frame & 0xFFFF) == (usX2Y->wait_iso_frame & 0xFFFF))) - subs->completed_urb = urb; - else { - usX2Y_error_sequence(usX2Y, subs, urb); - return; - } - - capsubs = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE]; - capsubs2 = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE + 2]; - playbacksubs = usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]; - if (capsubs->completed_urb && atomic_read(&capsubs->state) >= state_PREPARED && - (NULL == capsubs2 || capsubs2->completed_urb) && - (playbacksubs->completed_urb || atomic_read(&playbacksubs->state) < state_PREPARED)) { - if (!usX2Y_usbpcm_usbframe_complete(capsubs, capsubs2, playbacksubs, urb->start_frame)) - usX2Y->wait_iso_frame += nr_of_packs(); - else { - snd_printdd("\n"); - usX2Y_clients_stop(usX2Y); - } - } -} - - -static void usX2Y_hwdep_urb_release(struct urb **urb) -{ - usb_kill_urb(*urb); - usb_free_urb(*urb); - *urb = NULL; -} - -/* - * release a substream - */ -static void usX2Y_usbpcm_urbs_release(struct snd_usX2Y_substream *subs) -{ - int i; - snd_printdd("snd_usX2Y_urbs_release() %i\n", subs->endpoint); - for (i = 0; i < NRURBS; i++) - usX2Y_hwdep_urb_release(subs->urb + i); -} - -static void usX2Y_usbpcm_subs_startup_finish(struct usX2Ydev * usX2Y) -{ - usX2Y_urbs_set_complete(usX2Y, i_usX2Y_usbpcm_urb_complete); - usX2Y->prepare_subs = NULL; -} - -static void i_usX2Y_usbpcm_subs_startup(struct urb *urb) -{ - struct snd_usX2Y_substream *subs = urb->context; - struct usX2Ydev *usX2Y = subs->usX2Y; - struct snd_usX2Y_substream *prepare_subs = usX2Y->prepare_subs; - if (NULL != prepare_subs && - urb->start_frame == prepare_subs->urb[0]->start_frame) { - atomic_inc(&prepare_subs->state); - if (prepare_subs == usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE]) { - struct snd_usX2Y_substream *cap_subs2 = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE + 2]; - if (cap_subs2 != NULL) - atomic_inc(&cap_subs2->state); - } - usX2Y_usbpcm_subs_startup_finish(usX2Y); - wake_up(&usX2Y->prepare_wait_queue); - } - - i_usX2Y_usbpcm_urb_complete(urb); -} - -/* - * initialize a substream's urbs - */ -static int usX2Y_usbpcm_urbs_allocate(struct snd_usX2Y_substream *subs) -{ - int i; - unsigned int pipe; - int is_playback = subs == subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]; - struct usb_device *dev = subs->usX2Y->dev; - - pipe = is_playback ? usb_sndisocpipe(dev, subs->endpoint) : - usb_rcvisocpipe(dev, subs->endpoint); - subs->maxpacksize = usb_maxpacket(dev, pipe, is_playback); - if (!subs->maxpacksize) - return -EINVAL; - - /* allocate and initialize data urbs */ - for (i = 0; i < NRURBS; i++) { - struct urb **purb = subs->urb + i; - if (*purb) { - usb_kill_urb(*purb); - continue; - } - *purb = usb_alloc_urb(nr_of_packs(), GFP_KERNEL); - if (NULL == *purb) { - usX2Y_usbpcm_urbs_release(subs); - return -ENOMEM; - } - (*purb)->transfer_buffer = is_playback ? - subs->usX2Y->hwdep_pcm_shm->playback : ( - subs->endpoint == 0x8 ? - subs->usX2Y->hwdep_pcm_shm->capture0x8 : - subs->usX2Y->hwdep_pcm_shm->capture0xA); - - (*purb)->dev = dev; - (*purb)->pipe = pipe; - (*purb)->number_of_packets = nr_of_packs(); - (*purb)->context = subs; - (*purb)->interval = 1; - (*purb)->complete = i_usX2Y_usbpcm_subs_startup; - } - return 0; -} - -/* - * free the buffer - */ -static int snd_usX2Y_usbpcm_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_usX2Y_substream *subs = runtime->private_data, - *cap_subs2 = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE + 2]; - mutex_lock(&subs->usX2Y->prepare_mutex); - snd_printdd("snd_usX2Y_usbpcm_hw_free(%p)\n", substream); - - if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) { - struct snd_usX2Y_substream *cap_subs = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE]; - atomic_set(&subs->state, state_STOPPED); - usX2Y_usbpcm_urbs_release(subs); - if (!cap_subs->pcm_substream || - !cap_subs->pcm_substream->runtime || - !cap_subs->pcm_substream->runtime->status || - cap_subs->pcm_substream->runtime->status->state < SNDRV_PCM_STATE_PREPARED) { - atomic_set(&cap_subs->state, state_STOPPED); - if (NULL != cap_subs2) - atomic_set(&cap_subs2->state, state_STOPPED); - usX2Y_usbpcm_urbs_release(cap_subs); - if (NULL != cap_subs2) - usX2Y_usbpcm_urbs_release(cap_subs2); - } - } else { - struct snd_usX2Y_substream *playback_subs = subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]; - if (atomic_read(&playback_subs->state) < state_PREPARED) { - atomic_set(&subs->state, state_STOPPED); - if (NULL != cap_subs2) - atomic_set(&cap_subs2->state, state_STOPPED); - usX2Y_usbpcm_urbs_release(subs); - if (NULL != cap_subs2) - usX2Y_usbpcm_urbs_release(cap_subs2); - } - } - mutex_unlock(&subs->usX2Y->prepare_mutex); - return snd_pcm_lib_free_pages(substream); -} - -static void usX2Y_usbpcm_subs_startup(struct snd_usX2Y_substream *subs) -{ - struct usX2Ydev * usX2Y = subs->usX2Y; - usX2Y->prepare_subs = subs; - subs->urb[0]->start_frame = -1; - smp_wmb(); // Make sure above modifications are seen by i_usX2Y_subs_startup() - usX2Y_urbs_set_complete(usX2Y, i_usX2Y_usbpcm_subs_startup); -} - -static int usX2Y_usbpcm_urbs_start(struct snd_usX2Y_substream *subs) -{ - int p, u, err, - stream = subs->pcm_substream->stream; - struct usX2Ydev *usX2Y = subs->usX2Y; - - if (SNDRV_PCM_STREAM_CAPTURE == stream) { - usX2Y->hwdep_pcm_shm->captured_iso_head = -1; - usX2Y->hwdep_pcm_shm->captured_iso_frames = 0; - } - - for (p = 0; 3 >= (stream + p); p += 2) { - struct snd_usX2Y_substream *subs = usX2Y->subs[stream + p]; - if (subs != NULL) { - if ((err = usX2Y_usbpcm_urbs_allocate(subs)) < 0) - return err; - subs->completed_urb = NULL; - } - } - - for (p = 0; p < 4; p++) { - struct snd_usX2Y_substream *subs = usX2Y->subs[p]; - if (subs != NULL && atomic_read(&subs->state) >= state_PREPARED) - goto start; - } - - start: - usX2Y_usbpcm_subs_startup(subs); - for (u = 0; u < NRURBS; u++) { - for (p = 0; 3 >= (stream + p); p += 2) { - struct snd_usX2Y_substream *subs = usX2Y->subs[stream + p]; - if (subs != NULL) { - struct urb *urb = subs->urb[u]; - if (usb_pipein(urb->pipe)) { - unsigned long pack; - if (0 == u) - atomic_set(&subs->state, state_STARTING3); - urb->dev = usX2Y->dev; - urb->transfer_flags = URB_ISO_ASAP; - for (pack = 0; pack < nr_of_packs(); pack++) { - urb->iso_frame_desc[pack].offset = subs->maxpacksize * (pack + u * nr_of_packs()); - urb->iso_frame_desc[pack].length = subs->maxpacksize; - } - urb->transfer_buffer_length = subs->maxpacksize * nr_of_packs(); - if ((err = usb_submit_urb(urb, GFP_KERNEL)) < 0) { - snd_printk (KERN_ERR "cannot usb_submit_urb() for urb %d, err = %d\n", u, err); - err = -EPIPE; - goto cleanup; - } else { - snd_printdd("%i\n", urb->start_frame); - if (u == 0) - usX2Y->wait_iso_frame = urb->start_frame; - } - urb->transfer_flags = 0; - } else { - atomic_set(&subs->state, state_STARTING1); - break; - } - } - } - } - err = 0; - wait_event(usX2Y->prepare_wait_queue, NULL == usX2Y->prepare_subs); - if (atomic_read(&subs->state) != state_PREPARED) - err = -EPIPE; - - cleanup: - if (err) { - usX2Y_subs_startup_finish(usX2Y); // Call it now - usX2Y_clients_stop(usX2Y); // something is completely wroong > stop evrything - } - return err; -} - -/* - * prepare callback - * - * set format and initialize urbs - */ -static int snd_usX2Y_usbpcm_prepare(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_usX2Y_substream *subs = runtime->private_data; - struct usX2Ydev *usX2Y = subs->usX2Y; - struct snd_usX2Y_substream *capsubs = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE]; - int err = 0; - snd_printdd("snd_usX2Y_pcm_prepare(%p)\n", substream); - - if (NULL == usX2Y->hwdep_pcm_shm) { - if (NULL == (usX2Y->hwdep_pcm_shm = snd_malloc_pages(sizeof(struct snd_usX2Y_hwdep_pcm_shm), GFP_KERNEL))) - return -ENOMEM; - memset(usX2Y->hwdep_pcm_shm, 0, sizeof(struct snd_usX2Y_hwdep_pcm_shm)); - } - - mutex_lock(&usX2Y->prepare_mutex); - usX2Y_subs_prepare(subs); -// Start hardware streams -// SyncStream first.... - if (atomic_read(&capsubs->state) < state_PREPARED) { - if (usX2Y->format != runtime->format) - if ((err = usX2Y_format_set(usX2Y, runtime->format)) < 0) - goto up_prepare_mutex; - if (usX2Y->rate != runtime->rate) - if ((err = usX2Y_rate_set(usX2Y, runtime->rate)) < 0) - goto up_prepare_mutex; - snd_printdd("starting capture pipe for %s\n", subs == capsubs ? - "self" : "playpipe"); - if (0 > (err = usX2Y_usbpcm_urbs_start(capsubs))) - goto up_prepare_mutex; - } - - if (subs != capsubs) { - usX2Y->hwdep_pcm_shm->playback_iso_start = -1; - if (atomic_read(&subs->state) < state_PREPARED) { - while (usX2Y_iso_frames_per_buffer(runtime, usX2Y) > - usX2Y->hwdep_pcm_shm->captured_iso_frames) { - snd_printdd("Wait: iso_frames_per_buffer=%i," - "captured_iso_frames=%i\n", - usX2Y_iso_frames_per_buffer(runtime, usX2Y), - usX2Y->hwdep_pcm_shm->captured_iso_frames); - if (msleep_interruptible(10)) { - err = -ERESTARTSYS; - goto up_prepare_mutex; - } - } - if (0 > (err = usX2Y_usbpcm_urbs_start(subs))) - goto up_prepare_mutex; - } - snd_printdd("Ready: iso_frames_per_buffer=%i,captured_iso_frames=%i\n", - usX2Y_iso_frames_per_buffer(runtime, usX2Y), - usX2Y->hwdep_pcm_shm->captured_iso_frames); - } else - usX2Y->hwdep_pcm_shm->capture_iso_start = -1; - - up_prepare_mutex: - mutex_unlock(&usX2Y->prepare_mutex); - return err; -} - -static struct snd_pcm_hardware snd_usX2Y_4c = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE, - .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, - .rate_min = 44100, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 4, - .buffer_bytes_max = (2*128*1024), - .period_bytes_min = 64, - .period_bytes_max = (128*1024), - .periods_min = 2, - .periods_max = 1024, - .fifo_size = 0 -}; - - - -static int snd_usX2Y_usbpcm_open(struct snd_pcm_substream *substream) -{ - struct snd_usX2Y_substream *subs = ((struct snd_usX2Y_substream **) - snd_pcm_substream_chip(substream))[substream->stream]; - struct snd_pcm_runtime *runtime = substream->runtime; - - if (!(subs->usX2Y->chip_status & USX2Y_STAT_CHIP_MMAP_PCM_URBS)) - return -EBUSY; - - runtime->hw = SNDRV_PCM_STREAM_PLAYBACK == substream->stream ? snd_usX2Y_2c : - (subs->usX2Y->subs[3] ? snd_usX2Y_4c : snd_usX2Y_2c); - runtime->private_data = subs; - subs->pcm_substream = substream; - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 1000, 200000); - return 0; -} - - -static int snd_usX2Y_usbpcm_close(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_usX2Y_substream *subs = runtime->private_data; - - subs->pcm_substream = NULL; - return 0; -} - - -static struct snd_pcm_ops snd_usX2Y_usbpcm_ops = -{ - .open = snd_usX2Y_usbpcm_open, - .close = snd_usX2Y_usbpcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_usX2Y_pcm_hw_params, - .hw_free = snd_usX2Y_usbpcm_hw_free, - .prepare = snd_usX2Y_usbpcm_prepare, - .trigger = snd_usX2Y_pcm_trigger, - .pointer = snd_usX2Y_pcm_pointer, -}; - - -static int usX2Y_pcms_lock_check(struct snd_card *card) -{ - struct list_head *list; - struct snd_device *dev; - struct snd_pcm *pcm; - int err = 0; - list_for_each(list, &card->devices) { - dev = snd_device(list); - if (dev->type != SNDRV_DEV_PCM) - continue; - pcm = dev->device_data; - mutex_lock(&pcm->open_mutex); - } - list_for_each(list, &card->devices) { - int s; - dev = snd_device(list); - if (dev->type != SNDRV_DEV_PCM) - continue; - pcm = dev->device_data; - for (s = 0; s < 2; ++s) { - struct snd_pcm_substream *substream; - substream = pcm->streams[s].substream; - if (substream && SUBSTREAM_BUSY(substream)) - err = -EBUSY; - } - } - return err; -} - - -static void usX2Y_pcms_unlock(struct snd_card *card) -{ - struct list_head *list; - struct snd_device *dev; - struct snd_pcm *pcm; - list_for_each(list, &card->devices) { - dev = snd_device(list); - if (dev->type != SNDRV_DEV_PCM) - continue; - pcm = dev->device_data; - mutex_unlock(&pcm->open_mutex); - } -} - - -static int snd_usX2Y_hwdep_pcm_open(struct snd_hwdep *hw, struct file *file) -{ - // we need to be the first - struct snd_card *card = hw->card; - int err = usX2Y_pcms_lock_check(card); - if (0 == err) - usX2Y(card)->chip_status |= USX2Y_STAT_CHIP_MMAP_PCM_URBS; - usX2Y_pcms_unlock(card); - return err; -} - - -static int snd_usX2Y_hwdep_pcm_release(struct snd_hwdep *hw, struct file *file) -{ - struct snd_card *card = hw->card; - int err = usX2Y_pcms_lock_check(card); - if (0 == err) - usX2Y(hw->card)->chip_status &= ~USX2Y_STAT_CHIP_MMAP_PCM_URBS; - usX2Y_pcms_unlock(card); - return err; -} - - -static void snd_usX2Y_hwdep_pcm_vm_open(struct vm_area_struct *area) -{ -} - - -static void snd_usX2Y_hwdep_pcm_vm_close(struct vm_area_struct *area) -{ -} - - -static int snd_usX2Y_hwdep_pcm_vm_fault(struct vm_area_struct *area, - struct vm_fault *vmf) -{ - unsigned long offset; - void *vaddr; - - offset = vmf->pgoff << PAGE_SHIFT; - vaddr = (char*)((struct usX2Ydev *)area->vm_private_data)->hwdep_pcm_shm + offset; - vmf->page = virt_to_page(vaddr); - get_page(vmf->page); - return 0; -} - - -static const struct vm_operations_struct snd_usX2Y_hwdep_pcm_vm_ops = { - .open = snd_usX2Y_hwdep_pcm_vm_open, - .close = snd_usX2Y_hwdep_pcm_vm_close, - .fault = snd_usX2Y_hwdep_pcm_vm_fault, -}; - - -static int snd_usX2Y_hwdep_pcm_mmap(struct snd_hwdep * hw, struct file *filp, struct vm_area_struct *area) -{ - unsigned long size = (unsigned long)(area->vm_end - area->vm_start); - struct usX2Ydev *usX2Y = hw->private_data; - - if (!(usX2Y->chip_status & USX2Y_STAT_CHIP_INIT)) - return -EBUSY; - - /* if userspace tries to mmap beyond end of our buffer, fail */ - if (size > PAGE_ALIGN(sizeof(struct snd_usX2Y_hwdep_pcm_shm))) { - snd_printd("%lu > %lu\n", size, (unsigned long)sizeof(struct snd_usX2Y_hwdep_pcm_shm)); - return -EINVAL; - } - - if (!usX2Y->hwdep_pcm_shm) { - return -ENODEV; - } - area->vm_ops = &snd_usX2Y_hwdep_pcm_vm_ops; - area->vm_flags |= VM_RESERVED | VM_DONTEXPAND; - area->vm_private_data = hw->private_data; - return 0; -} - - -static void snd_usX2Y_hwdep_pcm_private_free(struct snd_hwdep *hwdep) -{ - struct usX2Ydev *usX2Y = hwdep->private_data; - if (NULL != usX2Y->hwdep_pcm_shm) - snd_free_pages(usX2Y->hwdep_pcm_shm, sizeof(struct snd_usX2Y_hwdep_pcm_shm)); -} - - -int usX2Y_hwdep_pcm_new(struct snd_card *card) -{ - int err; - struct snd_hwdep *hw; - struct snd_pcm *pcm; - struct usb_device *dev = usX2Y(card)->dev; - if (1 != nr_of_packs()) - return 0; - - if ((err = snd_hwdep_new(card, SND_USX2Y_USBPCM_ID, 1, &hw)) < 0) - return err; - - hw->iface = SNDRV_HWDEP_IFACE_USX2Y_PCM; - hw->private_data = usX2Y(card); - hw->private_free = snd_usX2Y_hwdep_pcm_private_free; - hw->ops.open = snd_usX2Y_hwdep_pcm_open; - hw->ops.release = snd_usX2Y_hwdep_pcm_release; - hw->ops.mmap = snd_usX2Y_hwdep_pcm_mmap; - hw->exclusive = 1; - sprintf(hw->name, "/proc/bus/usb/%03d/%03d/hwdeppcm", dev->bus->busnum, dev->devnum); - - err = snd_pcm_new(card, NAME_ALLCAPS" hwdep Audio", 2, 1, 1, &pcm); - if (err < 0) { - return err; - } - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_usX2Y_usbpcm_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_usX2Y_usbpcm_ops); - - pcm->private_data = usX2Y(card)->subs; - pcm->info_flags = 0; - - sprintf(pcm->name, NAME_ALLCAPS" hwdep Audio"); - if (0 > (err = snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream, - SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data(GFP_KERNEL), - 64*1024, 128*1024)) || - 0 > (err = snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream, - SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data(GFP_KERNEL), - 64*1024, 128*1024))) { - return err; - } - - - return 0; -} - -#else - -int usX2Y_hwdep_pcm_new(struct snd_card *card) -{ - return 0; -} - -#endif diff --git a/ANDROID_3.4.5/sound/usb/usx2y/usx2yhwdeppcm.h b/ANDROID_3.4.5/sound/usb/usx2y/usx2yhwdeppcm.h deleted file mode 100644 index 9c4fb84b..00000000 --- a/ANDROID_3.4.5/sound/usb/usx2y/usx2yhwdeppcm.h +++ /dev/null @@ -1,22 +0,0 @@ -#define MAXPACK 50 -#define MAXBUFFERMS 100 -#define MAXSTRIDE 3 - -#define SSS (((MAXPACK*MAXBUFFERMS*MAXSTRIDE + 4096) / 4096) * 4096) -struct snd_usX2Y_hwdep_pcm_shm { - char playback[SSS]; - char capture0x8[SSS]; - char capture0xA[SSS]; - volatile int playback_iso_head; - int playback_iso_start; - struct { - int frame, - offset, - length; - } captured_iso[128]; - volatile int captured_iso_head; - volatile unsigned captured_iso_frames; - int capture_iso_start; -}; - -int usX2Y_hwdep_pcm_new(struct snd_card *card); -- cgit