ALSA: line6: Allow processing of raw incoming messages

Not all PODs use MIDI via USB data interface, thus allow avoiding
that code and instead using direct processing.

Signed-off-by: Andrej Krutak <dev@andree.sk>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Andrej Krutak 2016-09-18 20:59:27 +02:00 committed by Takashi Iwai
parent 174e1fc0bf
commit 7811a3ad18
3 changed files with 42 additions and 30 deletions

View file

@ -290,26 +290,31 @@ static void line6_data_received(struct urb *urb)
if (urb->status == -ESHUTDOWN) if (urb->status == -ESHUTDOWN)
return; return;
done = if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI) {
line6_midibuf_write(mb, urb->transfer_buffer, urb->actual_length);
if (done < urb->actual_length) {
line6_midibuf_ignore(mb, done);
dev_dbg(line6->ifcdev, "%d %d buffer overflow - message skipped\n",
done, urb->actual_length);
}
for (;;) {
done = done =
line6_midibuf_read(mb, line6->buffer_message, line6_midibuf_write(mb, urb->transfer_buffer, urb->actual_length);
LINE6_MESSAGE_MAXLEN);
if (done == 0) if (done < urb->actual_length) {
break; line6_midibuf_ignore(mb, done);
dev_dbg(line6->ifcdev, "%d %d buffer overflow - message skipped\n",
done, urb->actual_length);
}
line6->message_length = done; for (;;) {
line6_midi_receive(line6, line6->buffer_message, done); done =
line6_midibuf_read(mb, line6->buffer_message,
LINE6_MESSAGE_MAXLEN);
if (done == 0)
break;
line6->message_length = done;
line6_midi_receive(line6, line6->buffer_message, done);
if (line6->process_message)
line6->process_message(line6);
}
} else {
if (line6->process_message) if (line6->process_message)
line6->process_message(line6); line6->process_message(line6);
} }
@ -469,7 +474,9 @@ static void line6_destruct(struct snd_card *card)
struct usb_device *usbdev = line6->usbdev; struct usb_device *usbdev = line6->usbdev;
/* free buffer memory first: */ /* free buffer memory first: */
kfree(line6->buffer_message); if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI)
kfree(line6->buffer_message);
kfree(line6->buffer_listen); kfree(line6->buffer_listen);
/* then free URBs: */ /* then free URBs: */
@ -515,7 +522,7 @@ static void line6_get_interval(struct usb_line6 *line6)
} }
} }
static int line6_init_cap_control_midi(struct usb_line6 *line6) static int line6_init_cap_control(struct usb_line6 *line6)
{ {
int ret; int ret;
@ -524,14 +531,16 @@ static int line6_init_cap_control_midi(struct usb_line6 *line6)
if (!line6->buffer_listen) if (!line6->buffer_listen)
return -ENOMEM; return -ENOMEM;
line6->buffer_message = kmalloc(LINE6_MESSAGE_MAXLEN, GFP_KERNEL);
if (!line6->buffer_message)
return -ENOMEM;
line6->urb_listen = usb_alloc_urb(0, GFP_KERNEL); line6->urb_listen = usb_alloc_urb(0, GFP_KERNEL);
if (!line6->urb_listen) if (!line6->urb_listen)
return -ENOMEM; return -ENOMEM;
if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI) {
line6->buffer_message = kmalloc(LINE6_MESSAGE_MAXLEN, GFP_KERNEL);
if (!line6->buffer_message)
return -ENOMEM;
}
ret = line6_start_listen(line6); ret = line6_start_listen(line6);
if (ret < 0) { if (ret < 0) {
dev_err(line6->ifcdev, "cannot start listening: %d\n", ret); dev_err(line6->ifcdev, "cannot start listening: %d\n", ret);
@ -605,8 +614,8 @@ int line6_probe(struct usb_interface *interface,
line6_get_interval(line6); line6_get_interval(line6);
if (properties->capabilities & LINE6_CAP_CONTROL_MIDI) { if (properties->capabilities & LINE6_CAP_CONTROL) {
ret = line6_init_cap_control_midi(line6); ret = line6_init_cap_control(line6);
if (ret < 0) if (ret < 0)
goto error; goto error;
} }
@ -676,7 +685,7 @@ int line6_suspend(struct usb_interface *interface, pm_message_t message)
snd_power_change_state(line6->card, SNDRV_CTL_POWER_D3hot); snd_power_change_state(line6->card, SNDRV_CTL_POWER_D3hot);
if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI) if (line6->properties->capabilities & LINE6_CAP_CONTROL)
line6_stop_listen(line6); line6_stop_listen(line6);
if (line6pcm != NULL) { if (line6pcm != NULL) {
@ -695,7 +704,7 @@ int line6_resume(struct usb_interface *interface)
{ {
struct usb_line6 *line6 = usb_get_intfdata(interface); struct usb_line6 *line6 = usb_get_intfdata(interface);
if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI) if (line6->properties->capabilities & LINE6_CAP_CONTROL)
line6_start_listen(line6); line6_start_listen(line6);
snd_power_change_state(line6->card, SNDRV_CTL_POWER_D0); snd_power_change_state(line6->card, SNDRV_CTL_POWER_D0);

View file

@ -147,15 +147,18 @@ struct usb_line6 {
/* URB for listening to POD data endpoint */ /* URB for listening to POD data endpoint */
struct urb *urb_listen; struct urb *urb_listen;
/* Buffer for listening to POD data endpoint */ /* Buffer for incoming data from POD data endpoint */
unsigned char *buffer_listen; unsigned char *buffer_listen;
/* Buffer for message to be processed */ /* Buffer for message to be processed, generated from MIDI layer */
unsigned char *buffer_message; unsigned char *buffer_message;
/* Length of message to be processed */ /* Length of message to be processed, generated from MIDI layer */
int message_length; int message_length;
/* If MIDI is supported, buffer_message contains the pre-processed data;
* otherwise the data is only in urb_listen (buffer_incoming).
*/
void (*process_message)(struct usb_line6 *); void (*process_message)(struct usb_line6 *);
void (*disconnect)(struct usb_line6 *line6); void (*disconnect)(struct usb_line6 *line6);
}; };

View file

@ -258,7 +258,7 @@ int line6_init_midi(struct usb_line6 *line6)
struct snd_rawmidi *rmidi; struct snd_rawmidi *rmidi;
struct snd_line6_midi *line6midi; struct snd_line6_midi *line6midi;
if (!(line6->properties->capabilities & LINE6_CAP_CONTROL)) { if (!(line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI)) {
/* skip MIDI initialization and report success */ /* skip MIDI initialization and report success */
return 0; return 0;
} }