Update of /cvsroot/alsa/alsa-kernel/usb
In directory usw-pr-cvs1:/tmp/cvs-serv15463
Modified Files:
Config.help Makefile usbaudio.c usbaudio.h usbmidi.c
Log Message:
rewrite of usb-midi using rawmidi by Clemens.
Index: Config.help
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/usb/Config.help,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- Config.help 26 Aug 2002 16:05:42 -0000 1.2
+++ Config.help 22 Oct 2002 10:14:19 -0000 1.3
@@ -1,4 +1,2 @@
CONFIG_SND_USB_AUDIO
- Say 'Y' or 'M' to include support for USB audio devices.
- To support USB MIDI devices, you need to enable ALSA sequencer support
- (CONFIG_SND_SEQUENCER).
+ Say 'Y' or 'M' to include support for USB audio and USB MIDI devices.
Index: Makefile
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/usb/Makefile,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- Makefile 26 Aug 2002 16:05:42 -0000 1.2
+++ Makefile 22 Oct 2002 10:14:19 -0000 1.3
@@ -2,15 +2,9 @@
# Makefile for ALSA
#
-snd-usb-audio-objs := usbaudio.o usbmixer.o
-ifeq ($(subst m,y,$(CONFIG_SND_SEQUENCER)),y)
-snd-usb-midi-objs := usbmidi.o
-endif
+snd-usb-audio-objs := usbaudio.o usbmixer.o usbmidi.o
# Toplevel Module Dependency
obj-$(CONFIG_SND_USB_AUDIO) += snd-usb-audio.o
-ifeq ($(subst m,y,$(CONFIG_SND_SEQUENCER)),y)
-obj-$(CONFIG_SND_USB_AUDIO) += snd-usb-midi.o
-endif
include $(TOPDIR)/Rules.make
Index: usbaudio.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/usb/usbaudio.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -r1.20 -r1.21
--- usbaudio.c 21 Oct 2002 18:28:26 -0000 1.20
+++ usbaudio.c 22 Oct 2002 10:14:19 -0000 1.21
@@ -1833,11 +1833,6 @@
/*
* parse audio control descriptor and create pcm/midi streams
*/
-
-static int snd_usb_create_midi_interface(snd_usb_audio_t *chip,
- struct usb_interface *iface,
- const snd_usb_audio_quirk_t *quirk);
-
static int snd_usb_create_streams(snd_usb_audio_t *chip, int ctrlif,
unsigned char *buffer, int buflen)
{
@@ -1893,32 +1888,6 @@
usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1);
}
- return 0;
-}
-
-static int snd_usb_create_midi_interface(snd_usb_audio_t *chip,
- struct usb_interface *iface,
- const snd_usb_audio_quirk_t *quirk)
-{
-#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
- snd_seq_device_t *seq_device;
- snd_usb_midi_t *umidi;
- int err;
-
- err = snd_seq_device_new(chip->card, chip->next_seq_device,
- SNDRV_SEQ_DEV_ID_USBMIDI,
- sizeof(snd_usb_midi_t), &seq_device);
- if (err < 0)
- return err;
- chip->next_seq_device++;
- strcpy(seq_device->name, chip->card->shortname);
- umidi = (snd_usb_midi_t *)SNDRV_SEQ_DEVICE_ARGPTR(seq_device);
- umidi->chip = chip;
- umidi->iface = iface;
- umidi->ifnum = iface->altsetting->bInterfaceNumber;
- umidi->quirk = quirk;
- umidi->seq_client = -1;
-#endif
return 0;
}
Index: usbaudio.h
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/usb/usbaudio.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- usbaudio.h 4 Oct 2002 16:05:28 -0000 1.4
+++ usbaudio.h 22 Oct 2002 10:14:19 -0000 1.5
@@ -123,8 +123,6 @@
/* maximum number of endpoints per interface */
#define MIDI_MAX_ENDPOINTS 2
-#define SNDRV_SEQ_DEV_ID_USBMIDI "usb-midi"
-
/*
*/
@@ -140,9 +138,7 @@
struct list_head pcm_list; /* list of pcm streams */
int pcm_devs;
-#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
- int next_seq_device;
-#endif
+ int next_midi_device;
};
/*
@@ -177,31 +173,6 @@
/* for QUIRK_MIDI_MIDIMAN, data is the number of ports */
/*
- * USB MIDI sequencer device data
- */
-typedef struct snd_usb_midi snd_usb_midi_t;
-typedef struct snd_usb_midi_endpoint snd_usb_midi_endpoint_t;
-typedef struct snd_usb_midi_out_endpoint snd_usb_midi_out_endpoint_t;
-typedef struct snd_usb_midi_in_endpoint snd_usb_midi_in_endpoint_t;
-
-struct snd_usb_midi {
- /* filled by usbaudio.c */
- snd_usb_audio_t *chip;
- struct usb_interface *iface;
- int ifnum;
- const snd_usb_audio_quirk_t *quirk;
-
- /* used internally in usbmidi.c */
- int seq_client;
- struct snd_usb_midi_endpoint {
- snd_usb_midi_out_endpoint_t *out;
- snd_usb_midi_in_endpoint_t *in;
- snd_rawmidi_t *rmidi[0x10];
- } endpoints[MIDI_MAX_ENDPOINTS];
-};
-
-
-/*
*/
#define combine_word(s) ((*s) | ((unsigned int)(s)[1] << 8))
@@ -214,5 +185,7 @@
void *snd_usb_find_csint_desc(void *descstart, int desclen, void *after, u8 dsubtype,
int iface, int altsetting);
int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif, unsigned char *buffer,
int buflen);
+
+int snd_usb_create_midi_interface(snd_usb_audio_t *chip, struct usb_interface *iface,
+const snd_usb_audio_quirk_t *quirk);
#endif /* __USBAUDIO_H */
Index: usbmidi.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/usb/usbmidi.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- usbmidi.c 4 Oct 2002 16:05:30 -0000 1.7
+++ usbmidi.c 22 Oct 2002 10:14:19 -0000 1.8
@@ -46,34 +46,9 @@
#include <linux/usb.h>
#include <sound/core.h>
#include <sound/minors.h>
-#include <sound/asequencer.h>
-#include <sound/seq_device.h>
-#include <sound/seq_kernel.h>
-#include <sound/seq_virmidi.h>
-#include <sound/seq_midi_event.h>
-#include <sound/initval.h>
+#include <sound/rawmidi.h>
#include "usbaudio.h"
-MODULE_AUTHOR("Clemens Ladisch <[EMAIL PROTECTED]>");
-MODULE_DESCRIPTION("USB MIDI");
-MODULE_LICENSE("Dual BSD/GPL");
-MODULE_CLASSES("{sound}");
-
-/* size of the per-endpoint output buffer, must be a multiple of 4 */
-#define OUTPUT_BUFFER_SIZE 0x400
-
-/* max. size of incoming sysex messages */
-#define INPUT_BUFFER_SIZE 0x200
-
-typedef struct usb_driver usb_driver_t;
-typedef struct usb_device usb_device_t;
-typedef struct usb_device_id usb_device_id_t;
-typedef struct usb_interface usb_interface_t;
-typedef struct usb_interface_descriptor usb_interface_descriptor_t;
-typedef struct usb_ms_header_descriptor usb_ms_header_descriptor_t;
-typedef struct usb_endpoint_descriptor usb_endpoint_descriptor_t;
-typedef struct usb_ms_endpoint_descriptor usb_ms_endpoint_descriptor_t;
-
struct usb_ms_header_descriptor {
__u8 bLength;
__u8 bDescriptorType;
@@ -90,35 +65,56 @@
__u8 baAssocJackID[0];
} __attribute__ ((packed));
+typedef struct snd_usb_midi snd_usb_midi_t;
+typedef struct snd_usb_midi_endpoint snd_usb_midi_endpoint_t;
+typedef struct snd_usb_midi_out_endpoint snd_usb_midi_out_endpoint_t;
+typedef struct snd_usb_midi_in_endpoint snd_usb_midi_in_endpoint_t;
typedef struct usbmidi_out_port usbmidi_out_port_t;
typedef struct usbmidi_in_port usbmidi_in_port_t;
+struct snd_usb_midi {
+ snd_usb_audio_t *chip;
+ struct usb_interface *iface;
+ const snd_usb_audio_quirk_t *quirk;
+ snd_rawmidi_t* rmidi;
+
+ struct snd_usb_midi_endpoint {
+ snd_usb_midi_out_endpoint_t *out;
+ snd_usb_midi_in_endpoint_t *in;
+ } endpoints[MIDI_MAX_ENDPOINTS];
+};
+
struct snd_usb_midi_out_endpoint {
snd_usb_midi_t* umidi;
struct urb* urb;
int max_transfer; /* size of urb buffer */
struct tasklet_struct tasklet;
- uint8_t buffer[OUTPUT_BUFFER_SIZE]; /* ring buffer */
- int data_begin;
- int data_size;
spinlock_t buffer_lock;
struct usbmidi_out_port {
snd_usb_midi_out_endpoint_t* ep;
+ snd_rawmidi_substream_t* substream;
+ int active;
uint8_t cable; /* cable number << 4 */
- uint8_t sysex_len;
- uint8_t sysex[2];
+ 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];
};
struct snd_usb_midi_in_endpoint {
snd_usb_midi_t* umidi;
- snd_usb_midi_endpoint_t* ep;
struct urb* urb;
struct usbmidi_in_port {
- int seq_port;
- snd_midi_event_t* midi_event;
+ snd_rawmidi_substream_t* substream;
+ int active;
} ports[0x10];
};
@@ -155,28 +151,18 @@
}
/*
- * Converts a USB MIDI packet into an ALSA sequencer event.
+ * Receives a USB MIDI packet.
*/
static void snd_usbmidi_input_packet(snd_usb_midi_in_endpoint_t* ep,
uint8_t packet[4])
{
int cable = packet[0] >> 4;
usbmidi_in_port_t* port = &ep->ports[cable];
- snd_seq_event_t ev;
- if (!port->midi_event)
+ if (!port->active)
return;
- memset(&ev, 0, sizeof(ev));
- if (snd_midi_event_encode(port->midi_event, &packet[1],
- snd_usbmidi_cin_length[packet[0] & 0x0f], &ev) > 0
- && ev.type != SNDRV_SEQ_EVENT_NONE) {
- ev.source.port = port->seq_port;
- ev.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS;
- snd_seq_kernel_client_dispatch(ep->umidi->seq_client,
- &ev, 1, 0);
- if (ep->ep->rmidi[cable])
- snd_virmidi_receive(ep->ep->rmidi[cable], &ev);
- }
+ snd_rawmidi_receive(port->substream, &packet[1],
+ snd_usbmidi_cin_length[packet[0] & 0x0f]);
}
/*
@@ -239,15 +225,12 @@
static void snd_usbmidi_out_urb_complete(struct urb* urb)
{
snd_usb_midi_out_endpoint_t* ep = snd_magic_cast(snd_usb_midi_out_endpoint_t,
urb->context, return);
- unsigned long flags;
if (urb->status < 0) {
if (snd_usbmidi_urb_error(urb->status) < 0)
return;
}
- spin_lock_irqsave(&ep->buffer_lock, flags);
snd_usbmidi_do_output(ep);
- spin_unlock_irqrestore(&ep->buffer_lock, flags);
}
/*
@@ -268,261 +251,255 @@
}
/*
+ * Adds one USB MIDI packet to the output buffer.
+ */
+static inline void output_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;
+}
+
+/*
+ * Converts MIDI commands to USB MIDI packets.
+ */
+static void snd_usbmidi_transmit_byte(usbmidi_out_port_t* port,
+ uint8_t b, struct urb* urb)
+{
+ uint8_t p0 = port->cable;
+
+ 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;
+ }
+ }
+}
+
+/*
+ * Moves data from one substream buffer to the URB transfer buffer.
+ */
+static void snd_usbmidi_transmit(snd_usb_midi_out_endpoint_t* ep, int port_idx)
+{
+ struct urb* urb = ep->urb;
+ usbmidi_out_port_t* port = &ep->ports[port_idx];
+
+ while (urb->transfer_buffer_length < ep->max_transfer) {
+ uint8_t b;
+ if (snd_rawmidi_transmit_peek(port->substream, &b, 1) != 1) {
+ port->active = 0;
+ break;
+ }
+ snd_usbmidi_transmit_byte(port, b, urb);
+ snd_rawmidi_transmit_ack(port->substream, 1);
+ }
+}
+
+/*
* This is called when some data should be transferred to the device
- * (after the reception of one or more sequencer events, or after completion
- * of the previous transfer). ep->buffer_lock must be held.
+ * (from one or more substreams).
*/
static void snd_usbmidi_do_output(snd_usb_midi_out_endpoint_t* ep)
{
- int len;
- uint8_t* buffer;
-
- if (ep->urb->status == -EINPROGRESS ||
- ep->data_size == 0)
+ int p;
+ struct urb* urb = ep->urb;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ep->buffer_lock, flags);
+ if (urb->status == -EINPROGRESS) {
+ spin_unlock_irqrestore(&ep->buffer_lock, flags);
return;
- buffer = (uint8_t*)ep->urb->transfer_buffer;
-
- /* first chunk, up to the end of the buffer */
- len = OUTPUT_BUFFER_SIZE - ep->data_begin;
- if (len > ep->data_size)
- len = ep->data_size;
- if (len > ep->max_transfer)
- len = ep->max_transfer;
- if (len > 0) {
- memcpy(buffer, ep->buffer + ep->data_begin, len);
- ep->data_begin = (ep->data_begin + len) % OUTPUT_BUFFER_SIZE;
- ep->data_size -= len;
- buffer += len;
- ep->urb->transfer_buffer_length = len;
- }
-
- /* second chunk (after wraparound) */
- if (ep->data_begin == 0 && ep->data_size > 0 &&
- len < ep->max_transfer) {
- len = ep->max_transfer - len;
- if (len > ep->data_size)
- len = ep->data_size;
- memcpy(buffer, ep->buffer, len);
- ep->data_begin = len;
- ep->data_size -= len;
- ep->urb->transfer_buffer_length += len;
}
- if (len > 0) {
+ urb->transfer_buffer_length = 0;
+ for (p= 0; p < 0x10; ++p)
+ if (ep->ports[p].active)
+ snd_usbmidi_transmit(ep, p);
+
+ if (urb->transfer_buffer_length > 0) {
if (ep->umidi->quirk && ep->umidi->quirk->type == QUIRK_MIDI_MIDIMAN)
- snd_usbmidi_convert_to_midiman(ep->urb);
+ snd_usbmidi_convert_to_midiman(urb);
- ep->urb->dev = ep->umidi->chip->dev;
- snd_usbmidi_submit_urb(ep->urb, GFP_ATOMIC);
+ urb->dev = ep->umidi->chip->dev;
+ snd_usbmidi_submit_urb(urb, GFP_ATOMIC);
}
+ spin_unlock_irqrestore(&ep->buffer_lock, flags);
}
static void snd_usbmidi_out_tasklet(unsigned long data)
{
snd_usb_midi_out_endpoint_t* ep = snd_magic_cast(snd_usb_midi_out_endpoint_t,
(void*)data, return);
- unsigned long flags;
- spin_lock_irqsave(&ep->buffer_lock, flags);
snd_usbmidi_do_output(ep);
- spin_unlock_irqrestore(&ep->buffer_lock, flags);
}
-/*
- * Adds one USB MIDI packet to the output buffer.
- */
-static void output_packet(usbmidi_out_port_t* port,
- uint8_t p0, uint8_t p1, uint8_t p2, uint8_t p3)
+static int snd_usbmidi_output_open(snd_rawmidi_substream_t* substream)
{
- snd_usb_midi_out_endpoint_t* ep = port->ep;
- unsigned long flags;
+ snd_usb_midi_t* umidi = snd_magic_cast(snd_usb_midi_t,
+substream->rmidi->private_data, return -ENXIO);
+ usbmidi_out_port_t* port = NULL;
+ int i, j;
- spin_lock_irqsave(&ep->buffer_lock, flags);
- if (ep->data_size < OUTPUT_BUFFER_SIZE) {
- uint8_t* buf = ep->buffer + (ep->data_begin + ep->data_size) %
OUTPUT_BUFFER_SIZE;
- buf[0] = p0;
- buf[1] = p1;
- buf[2] = p2;
- buf[3] = p3;
- ep->data_size += 4;
- if (ep->data_size == ep->max_transfer)
- snd_usbmidi_do_output(ep);
- }
- spin_unlock_irqrestore(&ep->buffer_lock, flags);
+ 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)
+ return -ENXIO;
+ substream->runtime->private_data = port;
+ port->state = STATE_UNKNOWN;
+ return 0;
}
-/*
- * Callback for snd_seq_dump_var_event.
- */
-static int snd_usbmidi_sysex_dump(void* ptr, void* buf, int count)
+static int snd_usbmidi_output_close(snd_rawmidi_substream_t* substream)
{
- usbmidi_out_port_t* port = (usbmidi_out_port_t*)ptr;
- const uint8_t* dump = (const uint8_t*)buf;
+ return 0;
+}
- for (; count; --count) {
- uint8_t byte = *dump++;
-
- if (byte == 0xf0 && port->sysex_len > 0) {
- /*
- * The previous SysEx wasn't terminated correctly.
- * Send the last bytes anyway, and hope that the
- * receiving device won't be too upset about the
- * missing F7.
- */
- output_packet(port,
- port->cable | (0x04 + port->sysex_len),
- port->sysex[0],
- port->sysex_len >= 2 ? port->sysex[1] : 0,
- 0);
- port->sysex_len = 0;
- }
- if (byte != 0xf7) {
- if (port->sysex_len >= 2) {
- output_packet(port,
- port->cable | 0x04,
- port->sysex[0],
- port->sysex[1],
- byte);
- port->sysex_len = 0;
- } else {
- port->sysex[port->sysex_len++] = byte;
- }
- } else {
- uint8_t cin, data[3];
- int i;
+static void snd_usbmidi_output_trigger(snd_rawmidi_substream_t* substream, int up)
+{
+ usbmidi_out_port_t* port =
+(usbmidi_out_port_t*)substream->runtime->private_data;
- for (i = 0; i < port->sysex_len; ++i)
- data[i] = port->sysex[i];
- data[i++] = 0xf7;
- cin = port->cable | (0x04 + i);
- for (; i < 3; ++i)
- data[i] = 0;
- /*
- * cin,data[] is x5,{F7 00 00}
- * or x6,{xx F7 00}
- * or x7,{xx xx F7}
- */
- output_packet(port, cin, data[0], data[1], data[2]);
- port->sysex_len = 0;
- }
- }
- return 0;
+ port->active = up;
+ if (up)
+ tasklet_hi_schedule(&port->ep->tasklet);
}
-/*
- * Converts an ALSA sequencer event into USB MIDI packets.
- */
-static int snd_usbmidi_event_input(snd_seq_event_t* ev, int direct,
- void* private_data, int atomic, int hop)
+static int snd_usbmidi_input_open(snd_rawmidi_substream_t* substream)
{
- usbmidi_out_port_t* port = (usbmidi_out_port_t*)private_data;
- int err;
- uint8_t p0, p1;
+ snd_usb_midi_t* umidi = snd_magic_cast(snd_usb_midi_t,
+substream->rmidi->private_data, return -ENXIO);
+ usbmidi_in_port_t* port = NULL;
+ int i, j;
- p0 = port->cable;
- p1 = ev->data.note.channel & 0xf;
+ for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i)
+ if (umidi->endpoints[i].in)
+ for (j = 0; j < 0x10; ++j)
+ if (umidi->endpoints[i].in->ports[j].substream ==
+substream) {
+ port = &umidi->endpoints[i].in->ports[j];
+ break;
+ }
+ if (!port)
+ return -ENXIO;
+ substream->runtime->private_data = port;
+ return 0;
+}
- switch (ev->type) {
- case SNDRV_SEQ_EVENT_NOTEON:
- output_packet(port, p0 | 0x09, p1 | 0x90,
- ev->data.note.note & 0x7f,
- ev->data.note.velocity & 0x7f);
- break;
- case SNDRV_SEQ_EVENT_NOTEOFF:
- output_packet(port, p0 | 0x08, p1 | 0x80,
- ev->data.note.note & 0x7f,
- ev->data.note.velocity & 0x7f);
- break;
- case SNDRV_SEQ_EVENT_KEYPRESS:
- output_packet(port, p0 | 0x0a, p1 | 0xa0,
- ev->data.note.note & 0x7f,
- ev->data.note.velocity & 0x7f);
- break;
- case SNDRV_SEQ_EVENT_CONTROLLER:
- output_packet(port, p0 | 0x0b, p1 | 0xb0,
- ev->data.control.param & 0x7f,
- ev->data.control.value & 0x7f);
- break;
- case SNDRV_SEQ_EVENT_PGMCHANGE:
- output_packet(port, p0 | 0x0c, p1 | 0xc0,
- ev->data.control.value & 0x7f, 0);
- break;
- case SNDRV_SEQ_EVENT_CHANPRESS:
- output_packet(port, p0 | 0x0d, p1 | 0xd0,
- ev->data.control.value & 0x7f, 0);
- break;
- case SNDRV_SEQ_EVENT_PITCHBEND:
- output_packet(port, p0 | 0x0e, p1 | 0xe0,
- (ev->data.control.value + 0x2000) & 0x7f,
- ((ev->data.control.value + 0x2000) >> 7) & 0x7f);
- break;
- case SNDRV_SEQ_EVENT_CONTROL14:
- if (ev->data.control.param < 0x20) {
- output_packet(port, p0 | 0x0b, p1 | 0xb0,
- ev->data.control.param,
- (ev->data.control.value >> 7) & 0x7f);
- output_packet(port, p0 | 0x0b, p1 | 0xb0,
- ev->data.control.param + 0x20,
- ev->data.control.value & 0x7f);
- } else {
- output_packet(port, p0 | 0x0b, p1 | 0xb0,
- ev->data.control.param & 0x7f,
- ev->data.control.value & 0x7f);
- }
- break;
- case SNDRV_SEQ_EVENT_SONGPOS:
- output_packet(port, p0 | 0x03, 0xf2,
- ev->data.control.value & 0x7f,
- (ev->data.control.value >> 7) & 0x7f);
- break;
- case SNDRV_SEQ_EVENT_SONGSEL:
- output_packet(port, p0 | 0x02, 0xf3,
- ev->data.control.value & 0x7f, 0);
- break;
- case SNDRV_SEQ_EVENT_QFRAME:
- output_packet(port, p0 | 0x02, 0xf1,
- ev->data.control.value & 0x7f, 0);
- break;
- case SNDRV_SEQ_EVENT_START:
- output_packet(port, p0 | 0x0f, 0xfa, 0, 0);
- break;
- case SNDRV_SEQ_EVENT_CONTINUE:
- output_packet(port, p0 | 0x0f, 0xfb, 0, 0);
- break;
- case SNDRV_SEQ_EVENT_STOP:
- output_packet(port, p0 | 0x0f, 0xfc, 0, 0);
- break;
- case SNDRV_SEQ_EVENT_CLOCK:
- output_packet(port, p0 | 0x0f, 0xf8, 0, 0);
- break;
- case SNDRV_SEQ_EVENT_TUNE_REQUEST:
- output_packet(port, p0 | 0x05, 0xf6, 0, 0);
- break;
- case SNDRV_SEQ_EVENT_RESET:
- output_packet(port, p0 | 0x0f, 0xff, 0, 0);
- break;
- case SNDRV_SEQ_EVENT_SENSING:
- output_packet(port, p0 | 0x0f, 0xfe, 0, 0);
- break;
- case SNDRV_SEQ_EVENT_SYSEX:
- err = snd_seq_dump_var_event(ev, snd_usbmidi_sysex_dump, port);
- if (err < 0)
- return err;
- break;
- default:
- return 0;
- }
- tasklet_hi_schedule(&port->ep->tasklet);
+static int snd_usbmidi_input_close(snd_rawmidi_substream_t* substream)
+{
return 0;
}
+static void snd_usbmidi_input_trigger(snd_rawmidi_substream_t* substream, int up)
+{
+ usbmidi_in_port_t* port = (usbmidi_in_port_t*)substream->runtime->private_data;
+
+ port->active = up;
+}
+
+static snd_rawmidi_ops_t snd_usbmidi_output_ops = {
+ .open = snd_usbmidi_output_open,
+ .close = snd_usbmidi_output_close,
+ .trigger = snd_usbmidi_output_trigger,
+};
+
+static snd_rawmidi_ops_t snd_usbmidi_input_ops = {
+ .open = snd_usbmidi_input_open,
+ .close = snd_usbmidi_input_close,
+ .trigger = snd_usbmidi_input_trigger
+};
+
/*
* Frees an input endpoint.
* May be called when ep hasn't been initialized completely.
*/
static void snd_usbmidi_in_endpoint_delete(snd_usb_midi_in_endpoint_t* ep)
{
- int i;
-
if (ep->urb) {
if (ep->urb->transfer_buffer) {
usb_unlink_urb(ep->urb);
@@ -530,9 +507,6 @@
}
usb_free_urb(ep->urb);
}
- for (i = 0; i < 0x10; ++i)
- if (ep->ports[i].midi_event)
- snd_midi_event_free(ep->ports[i].midi_event);
snd_magic_kfree(ep);
}
@@ -540,11 +514,10 @@
* For Roland devices, use the alternate setting which uses interrupt
* transfers for input.
*/
-static usb_endpoint_descriptor_t* snd_usbmidi_get_int_epd(snd_usb_midi_t* umidi,
- uint8_t epnum)
+static struct usb_endpoint_descriptor* snd_usbmidi_get_int_epd(snd_usb_midi_t* umidi)
{
- usb_interface_t* intf;
- usb_interface_descriptor_t* intfd;
+ struct usb_interface* intf;
+ struct usb_interface_descriptor* intfd;
if (umidi->chip->dev->descriptor.idVendor != 0x0582)
return NULL;
@@ -569,41 +542,37 @@
return &intfd->endpoint[1];
}
-static usb_endpoint_descriptor_t* snd_usbmidi_get_midiman_int_epd(snd_usb_midi_t*
umidi)
+static struct usb_endpoint_descriptor*
+snd_usbmidi_get_midiman_int_epd(snd_usb_midi_t* umidi)
{
- usb_interface_t* intf = umidi->iface;
- if (!intf)
+ struct usb_interface* intf = umidi->iface;
+ if (!intf || intf->altsetting[0].bNumEndpoints < 1)
return NULL;
return &intf->altsetting[0].endpoint[0];
}
/*
- * Creates an input endpoint, and initalizes input ports.
- * ALSA ports are created later.
+ * Creates an input endpoint.
*/
static int snd_usbmidi_in_endpoint_create(snd_usb_midi_t* umidi,
snd_usb_midi_endpoint_info_t* ep_info,
snd_usb_midi_endpoint_t* rep)
{
snd_usb_midi_in_endpoint_t* ep;
- usb_endpoint_descriptor_t* int_epd;
+ struct usb_endpoint_descriptor* int_epd;
void* buffer;
unsigned int pipe;
- int length, i, err;
+ int length;
rep->in = NULL;
ep = snd_magic_kcalloc(snd_usb_midi_in_endpoint_t, 0, GFP_KERNEL);
if (!ep)
return -ENOMEM;
ep->umidi = umidi;
- ep->ep = rep;
- for (i = 0; i < 0x10; ++i)
- ep->ports[i].seq_port = -1;
if (umidi->quirk && umidi->quirk->type == QUIRK_MIDI_MIDIMAN)
int_epd = snd_usbmidi_get_midiman_int_epd(umidi);
else
- int_epd = snd_usbmidi_get_int_epd(umidi, ep_info->epnum);
+ int_epd = snd_usbmidi_get_int_epd(umidi);
ep->urb = usb_alloc_urb(0, GFP_KERNEL);
if (!ep->urb) {
@@ -627,16 +596,6 @@
FILL_BULK_URB(ep->urb, umidi->chip->dev, pipe, buffer, length,
snd_usbmidi_in_urb_complete, ep);
- for (i = 0; i < 0x10; ++i)
- if (ep_info->in_cables & (1 << i)) {
- err = snd_midi_event_new(INPUT_BUFFER_SIZE,
- &ep->ports[i].midi_event);
- if (err < 0) {
- snd_usbmidi_in_endpoint_delete(ep);
- return -ENOMEM;
- }
- }
-
rep->in = ep;
return 0;
}
@@ -670,7 +629,6 @@
/*
* Creates an output endpoint, and initializes output ports.
- * ALSA ports are created later.
*/
static int snd_usbmidi_out_endpoint_create(snd_usb_midi_t* umidi,
snd_usb_midi_endpoint_info_t* ep_info,
@@ -716,143 +674,54 @@
}
/*
- * Frees the sequencer client, endpoints and ports.
+ * Frees everything.
*/
-static int snd_usbmidi_seq_device_delete(snd_seq_device_t* seq_device)
+static void snd_usbmidi_free(snd_usb_midi_t* umidi)
{
- snd_usb_midi_t* umidi;
- int i, j;
-
- umidi = (snd_usb_midi_t*)SNDRV_SEQ_DEVICE_ARGPTR(seq_device);
+ int i;
- if (umidi->seq_client >= 0) {
- snd_seq_delete_kernel_client(umidi->seq_client);
- umidi->seq_client = -1;
- }
for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
snd_usb_midi_endpoint_t* ep = &umidi->endpoints[i];
- if (ep->out) {
+ if (ep->out)
snd_usbmidi_out_endpoint_delete(ep->out);
- ep->out = NULL;
- }
- if (ep->in) {
+ if (ep->in)
snd_usbmidi_in_endpoint_delete(ep->in);
- ep->in = NULL;
- }
- for (j = 0; j < 0x10; ++j)
- if (ep->rmidi[j]) {
- snd_device_free(umidi->chip->card, ep->rmidi[j]);
- ep->rmidi[j] = NULL;
- }
}
- return 0;
+ snd_magic_kfree(umidi);
}
-/*
- * Creates a sequencer port for an input/output cable pair.
- */
-static int snd_usbmidi_create_port(snd_usb_midi_t* umidi,
- snd_usb_midi_out_endpoint_t* out_ep,
- snd_usb_midi_in_endpoint_t* in_ep,
- int cable, int port_idx)
-{
- int cap, type, port;
- snd_seq_port_callback_t port_callback;
- char port_name[48];
-
- cap = 0;
- memset(&port_callback, 0, sizeof(port_callback));
- port_callback.owner = THIS_MODULE;
- if (out_ep) {
- port_callback.event_input = snd_usbmidi_event_input;
- port_callback.private_data = &out_ep->ports[cable];
- cap |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE;
- }
- if (in_ep) {
- cap |= SNDRV_SEQ_PORT_CAP_READ | SNDRV_SEQ_PORT_CAP_SUBS_READ;
- }
- if (out_ep && in_ep) {
- cap |= SNDRV_SEQ_PORT_CAP_DUPLEX;
- }
- /* TODO: read type bits from element descriptor */
- type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC;
- /* TODO: read port name from jack descriptor */
- snprintf(port_name, sizeof(port_name), "%s Port %d",
- umidi->chip->card->shortname, port_idx);
- port = snd_seq_event_port_attach(umidi->seq_client, &port_callback,
- cap, type, port_name);
- if (port < 0) {
- snd_printk(KERN_ERR "cannot create port (error code %d)\n", port);
- return port;
- }
- if (in_ep)
- in_ep->ports[cable].seq_port = port;
- return port;
+static void snd_usbmidi_rawmidi_free(snd_rawmidi_t* rmidi)
+{
+ snd_usb_midi_t* umidi = snd_magic_cast(snd_usb_midi_t, rmidi->private_data,
+return);
+ snd_usbmidi_free(umidi);
}
-/*
- * Creates a virmidi port emulating rawmidi for the sequencer port.
- */
-static int snd_usbmidi_create_virmidi(snd_usb_midi_t* umidi, int port,
- int port_idx, snd_rawmidi_t** rrmidi)
+static snd_rawmidi_substream_t* snd_usbmidi_find_substream(snd_usb_midi_t* umidi,
+ int stream, int number)
{
- snd_rawmidi_t *rmidi;
- snd_virmidi_dev_t *rdev;
- int err;
+ struct list_head* list;
- *rrmidi = NULL;
- err = snd_virmidi_new(umidi->chip->card, port_idx, &rmidi);
- if (err < 0)
- return err;
- sprintf(rmidi->name, "%s MIDI %d", umidi->chip->card->shortname, port_idx);
- rdev = snd_magic_cast(snd_virmidi_dev_t, rmidi->private_data, return -ENXIO);
- rdev->seq_mode = SNDRV_VIRMIDI_SEQ_ATTACH;
- rdev->client = umidi->seq_client;
- rdev->port = port;
- err = snd_device_register(umidi->chip->card, rmidi);
- if (err < 0) {
- snd_device_free(umidi->chip->card, rmidi);
- return err;
+ list_for_each(list, &umidi->rmidi->streams[stream].substreams) {
+ snd_rawmidi_substream_t* substream = list_entry(list,
+snd_rawmidi_substream_t, list);
+ if (substream->number == number)
+ return substream;
}
- *rrmidi = rmidi;
- return 0;
+ return NULL;
}
-/*
- * After input and output endpoints have been initialized, create
- * the ALSA port for each input/output port pair in the endpoint.
- * *port_idx is the port number, which must be unique over all endpoints.
- */
-static int snd_usbmidi_create_endpoint_ports(snd_usb_midi_t* umidi,
- snd_usb_midi_endpoint_t* endpoint,
- int* port_idx,
- snd_usb_midi_endpoint_info_t* ep_info)
-{
- int cable;
-
- for (cable = 0; cable < 0x10; ++cable) {
- int port, err;
- int out = ep_info->out_cables & (1 << cable);
- int in = ep_info->in_cables & (1 << cable);
- if (!(in || out))
- continue;
-
- port = snd_usbmidi_create_port(umidi,
- out ? endpoint->out : NULL,
- in ? endpoint->in : NULL,
- cable, *port_idx);
- if (port < 0)
- return port;
-
- if (*port_idx < SNDRV_MINOR_RAWMIDIS) {
- err = snd_usbmidi_create_virmidi(umidi, port, *port_idx,
- &endpoint->rmidi[cable]);
- if (err < 0)
- return err;
- }
- ++*port_idx;
+static void snd_usbmidi_init_substream(snd_usb_midi_t* umidi,
+ int stream, int number,
+ snd_rawmidi_substream_t** rsubstream)
+{
+ snd_rawmidi_substream_t* substream = snd_usbmidi_find_substream(umidi, stream,
+number);
+ if (!substream) {
+ snd_printd(KERN_ERR "substream %d:%d not found\n", stream, number);
+ return;
}
- return 0;
+ /* TODO: read port name from jack descriptor */
+ snprintf(substream->name, sizeof(substream->name),
+ "%s Port %d", umidi->chip->card->shortname, number);
+ *rsubstream = substream;
}
/*
@@ -861,7 +730,8 @@
static int snd_usbmidi_create_endpoints(snd_usb_midi_t* umidi,
snd_usb_midi_endpoint_info_t* endpoints)
{
- int i, err, port_idx = 0;
+ int i, j, err;
+ int out_ports = 0, in_ports = 0;
for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
if (!endpoints[i].epnum)
@@ -878,15 +748,22 @@
if (err < 0)
return err;
}
- err = snd_usbmidi_create_endpoint_ports(umidi, &umidi->endpoints[i],
- &port_idx, &endpoints[i]);
- if (err < 0)
- return err;
- printk(KERN_INFO "snd-usb-midi: endpoint %d: created %d output and %d
input ports\n",
- endpoints[i].epnum,
- snd_usbmidi_count_bits(endpoints[i].out_cables),
- snd_usbmidi_count_bits(endpoints[i].in_cables));
+
+ 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;
+ }
+ }
}
+ printk(KERN_INFO "snd-usb-midi: created %d output and %d input ports\n",
+ out_ports, in_ports);
return 0;
}
@@ -896,18 +773,18 @@
static int snd_usbmidi_get_ms_info(snd_usb_midi_t* umidi,
snd_usb_midi_endpoint_info_t* endpoints)
{
- usb_interface_t* intf;
- usb_interface_descriptor_t* intfd;
- usb_ms_header_descriptor_t* ms_header;
- usb_endpoint_descriptor_t* ep;
- usb_ms_endpoint_descriptor_t* ms_ep;
+ struct usb_interface* intf;
+ struct usb_interface_descriptor* intfd;
+ struct usb_ms_header_descriptor* ms_header;
+ struct usb_endpoint_descriptor* ep;
+ struct usb_ms_endpoint_descriptor* ms_ep;
int i, epidx;
intf = umidi->iface;
if (!intf)
return -ENXIO;
intfd = &intf->altsetting[0];
- ms_header = (usb_ms_header_descriptor_t*)intfd->extra;
+ ms_header = (struct usb_ms_header_descriptor*)intfd->extra;
if (intfd->extralen >= 7 &&
ms_header->bLength >= 7 &&
ms_header->bDescriptorType == USB_DT_CS_INTERFACE &&
@@ -922,7 +799,7 @@
ep = &intfd->endpoint[i];
if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
USB_ENDPOINT_XFER_BULK)
continue;
- ms_ep = (usb_ms_endpoint_descriptor_t*)ep->extra;
+ ms_ep = (struct usb_ms_endpoint_descriptor*)ep->extra;
if (ep->extralen < 4 ||
ms_ep->bLength < 4 ||
ms_ep->bDescriptorType != USB_DT_CS_ENDPOINT ||
@@ -957,9 +834,9 @@
static int snd_usbmidi_detect_endpoint(snd_usb_midi_t* umidi,
snd_usb_midi_endpoint_info_t* endpoint)
{
- usb_interface_t* intf;
- usb_interface_descriptor_t* intfd;
- usb_endpoint_descriptor_t* epd;
+ struct usb_interface* intf;
+ struct usb_interface_descriptor* intfd;
+ struct usb_endpoint_descriptor* epd;
if (endpoint->epnum == -1) {
intf = umidi->iface;
@@ -980,8 +857,8 @@
static int snd_usbmidi_detect_yamaha(snd_usb_midi_t* umidi,
snd_usb_midi_endpoint_info_t* endpoint)
{
- usb_interface_t* intf;
- usb_interface_descriptor_t* intfd;
+ struct usb_interface* intf;
+ struct usb_interface_descriptor* intfd;
uint8_t* cs_desc;
intf = umidi->iface;
@@ -1014,9 +891,9 @@
static int snd_usbmidi_create_endpoints_midiman(snd_usb_midi_t* umidi, int ports)
{
snd_usb_midi_endpoint_info_t ep_info;
- usb_interface_t* intf;
- usb_interface_descriptor_t* intfd;
- usb_endpoint_descriptor_t* epd;
+ struct usb_interface* intf;
+ struct usb_interface_descriptor* intfd;
+ struct usb_endpoint_descriptor* epd;
int cable, err;
intf = umidi->iface;
@@ -1071,77 +948,65 @@
}
for (cable = 0; cable < ports; ++cable) {
- int port = snd_usbmidi_create_port(umidi,
- umidi->endpoints[cable & 1].out,
- umidi->endpoints[0].in,
- cable, cable);
- if (port < 0)
- return port;
-
- if (cable < SNDRV_MINOR_RAWMIDIS) {
- int err = snd_usbmidi_create_virmidi(umidi, port, cable,
-
&umidi->endpoints[0].rmidi[cable]);
- if (err < 0)
- return err;
- }
+ snd_usbmidi_init_substream(umidi, SNDRV_RAWMIDI_STREAM_OUTPUT, cable,
+ &umidi->endpoints[cable &
+1].out->ports[cable].substream);
+ snd_usbmidi_init_substream(umidi, SNDRV_RAWMIDI_STREAM_INPUT, cable,
+
+&umidi->endpoints[0].in->ports[cable].substream);
}
return 0;
}
+static int snd_usbmidi_create_rawmidi(snd_usb_midi_t* umidi,
+ int out_ports, int in_ports)
+{
+ snd_rawmidi_t* rmidi;
+ int err;
+
+ err = snd_rawmidi_new(umidi->chip->card, "USB MIDI",
+ umidi->chip->next_midi_device++,
+ out_ports, in_ports, &rmidi);
+ if (err < 0)
+ return err;
+ strcpy(rmidi->name, umidi->chip->card->longname);
+ rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
+ SNDRV_RAWMIDI_INFO_INPUT |
+ SNDRV_RAWMIDI_INFO_DUPLEX;
+ 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;
+}
+
/*
- * Initialize the sequencer device.
+ * Creates and registers everything needed for a MIDI streaming interface.
*/
-static int snd_usbmidi_seq_device_new(snd_seq_device_t* seq_device)
+int snd_usb_create_midi_interface(snd_usb_audio_t* chip,
+ struct usb_interface* iface,
+ const snd_usb_audio_quirk_t* quirk)
{
snd_usb_midi_t* umidi;
- usb_device_t* dev;
- snd_seq_client_callback_t client_callback;
- snd_seq_client_info_t client_info;
snd_usb_midi_endpoint_info_t endpoints[MIDI_MAX_ENDPOINTS];
+ int out_ports, in_ports;
int i, err;
- umidi = (snd_usb_midi_t*)SNDRV_SEQ_DEVICE_ARGPTR(seq_device);
-
- memset(&client_callback, 0, sizeof(client_callback));
- client_callback.allow_output = 1;
- client_callback.allow_input = 1;
- umidi->seq_client = snd_seq_create_kernel_client(umidi->chip->card, 0,
- &client_callback);
- if (umidi->seq_client < 0)
- return umidi->seq_client;
-
- /* set the client name */
- memset(&client_info, 0, sizeof(client_info));
- client_info.client = umidi->seq_client;
- client_info.type = KERNEL_CLIENT;
- dev = umidi->chip->dev;
- if (dev->descriptor.iProduct)
- err = usb_string(dev, dev->descriptor.iProduct,
- client_info.name, sizeof(client_info.name));
- else
- err = 0;
- if (err <= 0) {
- if (umidi->quirk && umidi->quirk->product_name) {
- strncpy(client_info.name, umidi->quirk->product_name,
- sizeof(client_info.name) - 1);
- client_info.name[sizeof(client_info.name) - 1] = '\0';
- } else {
- sprintf(client_info.name, "USB Device %#04x:%#04x",
- dev->descriptor.idVendor, dev->descriptor.idProduct);
- }
- }
- snd_seq_kernel_client_ctl(umidi->seq_client,
- SNDRV_SEQ_IOCTL_SET_CLIENT_INFO,
- &client_info);
+ umidi = snd_magic_kcalloc(snd_usb_midi_t, 0, GFP_KERNEL);
+ if (!umidi)
+ return -ENOMEM;
+ umidi->chip = chip;
+ umidi->iface = iface;
+ umidi->quirk = quirk;
/* detect the endpoint(s) to use */
memset(endpoints, 0, sizeof(endpoints));
- if (!umidi->quirk) {
+ if (!quirk) {
err = snd_usbmidi_get_ms_info(umidi, endpoints);
} else {
- switch (umidi->quirk->type) {
+ switch (quirk->type) {
case QUIRK_MIDI_FIXED_ENDPOINT:
- memcpy(&endpoints[0], umidi->quirk->data,
+ memcpy(&endpoints[0], quirk->data,
sizeof(snd_usb_midi_endpoint_info_t));
err = snd_usbmidi_detect_endpoint(umidi, &endpoints[0]);
break;
@@ -1152,21 +1017,40 @@
err = 0;
break;
default:
- snd_printd(KERN_ERR "invalid quirk type %d\n",
umidi->quirk->type);
+ snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type);
err = -ENXIO;
break;
}
}
+ if (err < 0) {
+ snd_magic_kfree(umidi);
+ return err;
+ }
- /* create ports */
- if (err >= 0) {
- if (umidi->quirk && umidi->quirk->type == QUIRK_MIDI_MIDIMAN)
- err = snd_usbmidi_create_endpoints_midiman(umidi,
(int)umidi->quirk->data);
- else
- err = snd_usbmidi_create_endpoints(umidi, endpoints);
+ /* create rawmidi device */
+ if (quirk && quirk->type == QUIRK_MIDI_MIDIMAN) {
+ in_ports = out_ports = (int)quirk->data;
+ } else {
+ out_ports = 0;
+ in_ports = 0;
+ for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
+ out_ports += snd_usbmidi_count_bits(endpoints[i].out_cables);
+ in_ports += snd_usbmidi_count_bits(endpoints[i].in_cables);
+ }
+ }
+ err = snd_usbmidi_create_rawmidi(umidi, out_ports, in_ports);
+ if (err < 0) {
+ snd_magic_kfree(umidi);
+ return err;
}
+
+ /* create endpoint/port structures */
+ if (quirk && quirk->type == QUIRK_MIDI_MIDIMAN)
+ err = snd_usbmidi_create_endpoints_midiman(umidi, (int)quirk->data);
+ else
+ err = snd_usbmidi_create_endpoints(umidi, endpoints);
if (err < 0) {
- snd_usbmidi_seq_device_delete(seq_device);
+ snd_usbmidi_free(umidi);
return err;
}
@@ -1176,22 +1060,3 @@
GFP_KERNEL);
return 0;
}
-
-static int __init snd_usbmidi_module_init(void)
-{
- static snd_seq_dev_ops_t ops = {
- snd_usbmidi_seq_device_new,
- snd_usbmidi_seq_device_delete
- };
-
- return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_USBMIDI, &ops,
- sizeof(snd_usb_midi_t));
-}
-
-static void __exit snd_usbmidi_module_exit(void)
-{
- snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_USBMIDI);
-}
-
-module_init(snd_usbmidi_module_init)
-module_exit(snd_usbmidi_module_exit)
-------------------------------------------------------
This sf.net emial is sponsored by: Influence the future of
Java(TM) technology. Join the Java Community Process(SM) (JCP(SM))
program now. http://ad.doubleclick.net/clk;4699841;7576301;v?
http://www.sun.com/javavote
_______________________________________________
Alsa-cvslog mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/alsa-cvslog