Commit 030a07e4 authored by Karsten Wiese's avatar Karsten Wiese Committed by Jaroslav Kysela

ALSA: Add USB US122L driver

Added a new US122L usb-audio driver.  This driver works together with a
dedicated alsa-lib plugin.
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
Signed-off-by: default avatarJaroslav Kysela <perex@perex.cz>
parent 896e6cc2
...@@ -93,9 +93,10 @@ enum { ...@@ -93,9 +93,10 @@ enum {
SNDRV_HWDEP_IFACE_PCXHR, /* Digigram PCXHR */ SNDRV_HWDEP_IFACE_PCXHR, /* Digigram PCXHR */
SNDRV_HWDEP_IFACE_SB_RC, /* SB Extigy/Audigy2NX remote control */ SNDRV_HWDEP_IFACE_SB_RC, /* SB Extigy/Audigy2NX remote control */
SNDRV_HWDEP_IFACE_HDA, /* HD-audio */ SNDRV_HWDEP_IFACE_HDA, /* HD-audio */
SNDRV_HWDEP_IFACE_USB_STREAM, /* direct access to usb stream */
/* Don't forget to change the following: */ /* Don't forget to change the following: */
SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_HDA SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_USB_STREAM
}; };
struct snd_hwdep_info { struct snd_hwdep_info {
......
...@@ -67,5 +67,16 @@ config SND_USB_CAIAQ_INPUT ...@@ -67,5 +67,16 @@ config SND_USB_CAIAQ_INPUT
* Native Instruments Kore Controller 2 * Native Instruments Kore Controller 2
* Native Instruments Audio Kontrol 1 * Native Instruments Audio Kontrol 1
config SND_USB_US122L
tristate "Tascam US-122L USB driver"
depends on X86 && EXPERIMENTAL
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.
endif # SND_USB endif # SND_USB
...@@ -8,5 +8,6 @@ snd-usb-lib-objs := usbmidi.o ...@@ -8,5 +8,6 @@ snd-usb-lib-objs := usbmidi.o
# Toplevel Module Dependency # Toplevel Module Dependency
obj-$(CONFIG_SND_USB_AUDIO) += snd-usb-audio.o snd-usb-lib.o obj-$(CONFIG_SND_USB_AUDIO) += snd-usb-audio.o snd-usb-lib.o
obj-$(CONFIG_SND_USB_USX2Y) += snd-usb-lib.o obj-$(CONFIG_SND_USB_USX2Y) += snd-usb-lib.o
obj-$(CONFIG_SND_USB_US122L) += snd-usb-lib.o
obj-$(CONFIG_SND) += usx2y/ caiaq/ obj-$(CONFIG_SND) += usx2y/ caiaq/
...@@ -156,6 +156,7 @@ enum quirk_type { ...@@ -156,6 +156,7 @@ enum quirk_type {
QUIRK_MIDI_RAW, QUIRK_MIDI_RAW,
QUIRK_MIDI_EMAGIC, QUIRK_MIDI_EMAGIC,
QUIRK_MIDI_CME, QUIRK_MIDI_CME,
QUIRK_MIDI_US122L,
QUIRK_AUDIO_STANDARD_INTERFACE, QUIRK_AUDIO_STANDARD_INTERFACE,
QUIRK_AUDIO_FIXED_ENDPOINT, QUIRK_AUDIO_FIXED_ENDPOINT,
QUIRK_AUDIO_EDIROL_UA700_UA25, QUIRK_AUDIO_EDIROL_UA700_UA25,
......
...@@ -669,6 +669,42 @@ static struct usb_protocol_ops snd_usbmidi_raw_ops = { ...@@ -669,6 +669,42 @@ static struct usb_protocol_ops snd_usbmidi_raw_ops = {
.output = snd_usbmidi_raw_output, .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)
{
int count;
if (!ep->ports[0].active)
return;
count = ep->urb->dev->speed == USB_SPEED_HIGH ? 1 : 2;
count = snd_rawmidi_transmit(ep->ports[0].substream,
ep->urb->transfer_buffer,
count);
if (count < 1) {
ep->ports[0].active = 0;
return;
}
memset(ep->urb->transfer_buffer + count, 0xFD, 9 - count);
ep->urb->transfer_buffer_length = count;
}
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. * Emagic USB MIDI protocol: raw MIDI with "F5 xx" port switching.
*/ */
...@@ -1714,6 +1750,9 @@ int snd_usb_create_midi_interface(struct snd_usb_audio* chip, ...@@ -1714,6 +1750,9 @@ int snd_usb_create_midi_interface(struct snd_usb_audio* chip,
umidi->usb_protocol_ops = umidi->usb_protocol_ops =
&snd_usbmidi_maudio_broken_running_status_ops; &snd_usbmidi_maudio_broken_running_status_ops;
break; break;
case QUIRK_MIDI_US122L:
umidi->usb_protocol_ops = &snd_usbmidi_122l_ops;
/* fall through */
case QUIRK_MIDI_FIXED_ENDPOINT: case QUIRK_MIDI_FIXED_ENDPOINT:
memcpy(&endpoints[0], quirk->data, memcpy(&endpoints[0], quirk->data,
sizeof(struct snd_usb_midi_endpoint_info)); sizeof(struct snd_usb_midi_endpoint_info));
......
snd-usb-usx2y-objs := usbusx2y.o usX2Yhwdep.o usx2yhwdeppcm.o 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_USX2Y) += snd-usb-usx2y.o
obj-$(CONFIG_SND_USB_US122L) += snd-usb-us122l.o
This diff is collapsed.
#ifndef US122L_H
#define US122L_H
struct us122l {
struct snd_usb_audio chip;
int stride;
struct usb_stream_kernel sk;
struct mutex mutex;
struct file *first;
unsigned second_periods_polled;
struct file *master;
struct file *slave;
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
#endif
This diff is collapsed.
/*
* Copyright (C) 2007, 2008 Karsten Wiese <fzu@wemgehoertderstaat.de>
*
* 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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment