ALSA: line6: Distinguish device init (ctrl EP) and MIDI data transfer (int EP)
authorAndrej Krutak <dev@andree.sk>
Sun, 18 Sep 2016 18:59:26 +0000 (20:59 +0200)
committerTakashi Iwai <tiwai@suse.de>
Mon, 19 Sep 2016 21:00:47 +0000 (23:00 +0200)
POD X3 can initialize similarly to older PODs, but it doesn't have the MIDI
interface. Instead, configuration is done via proprietary bulk EP messages.

Signed-off-by: Andrej Krutak <dev@andree.sk>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/usb/line6/driver.c
sound/usb/line6/driver.h
sound/usb/line6/pod.c
sound/usb/line6/variax.c

index 14032d96da6749080d5bef05c27a3d9c3c26c417..9b16777d7a7595888e8823c162ecbe78ff7f3a41 100644 (file)
@@ -66,10 +66,17 @@ static int line6_start_listen(struct usb_line6 *line6)
 {
        int err;
 
-       usb_fill_int_urb(line6->urb_listen, line6->usbdev,
-               usb_rcvintpipe(line6->usbdev, line6->properties->ep_ctrl_r),
-               line6->buffer_listen, LINE6_BUFSIZE_LISTEN,
-               line6_data_received, line6, line6->interval);
+       if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI) {
+               usb_fill_int_urb(line6->urb_listen, line6->usbdev,
+                       usb_rcvintpipe(line6->usbdev, line6->properties->ep_ctrl_r),
+                       line6->buffer_listen, LINE6_BUFSIZE_LISTEN,
+                       line6_data_received, line6, line6->interval);
+       } else {
+               usb_fill_bulk_urb(line6->urb_listen, line6->usbdev,
+                       usb_rcvbulkpipe(line6->usbdev, line6->properties->ep_ctrl_r),
+                       line6->buffer_listen, LINE6_BUFSIZE_LISTEN,
+                       line6_data_received, line6);
+       }
        line6->urb_listen->actual_length = 0;
        err = usb_submit_urb(line6->urb_listen, GFP_ATOMIC);
        return err;
@@ -90,6 +97,7 @@ static int line6_send_raw_message(struct usb_line6 *line6, const char *buffer,
                                  int size)
 {
        int i, done = 0;
+       const struct line6_properties *properties = line6->properties;
 
        for (i = 0; i < size; i += line6->max_packet_size) {
                int partial;
@@ -97,15 +105,21 @@ static int line6_send_raw_message(struct usb_line6 *line6, const char *buffer,
                int frag_size = min(line6->max_packet_size, size - i);
                int retval;
 
-               retval = usb_interrupt_msg(line6->usbdev,
-                                       usb_sndintpipe(line6->usbdev,
-                                               line6->properties->ep_ctrl_w),
-                                       (char *)frag_buf, frag_size,
-                                       &partial, LINE6_TIMEOUT * HZ);
+               if (properties->capabilities & LINE6_CAP_CONTROL_MIDI) {
+                       retval = usb_interrupt_msg(line6->usbdev,
+                                               usb_sndintpipe(line6->usbdev, properties->ep_ctrl_w),
+                                               (char *)frag_buf, frag_size,
+                                               &partial, LINE6_TIMEOUT * HZ);
+               } else {
+                       retval = usb_bulk_msg(line6->usbdev,
+                                               usb_sndbulkpipe(line6->usbdev, properties->ep_ctrl_w),
+                                               (char *)frag_buf, frag_size,
+                                               &partial, LINE6_TIMEOUT * HZ);
+               }
 
                if (retval) {
                        dev_err(line6->ifcdev,
-                               "usb_interrupt_msg failed (%d)\n", retval);
+                               "usb_bulk_msg failed (%d)\n", retval);
                        break;
                }
 
@@ -140,10 +154,17 @@ static int line6_send_raw_message_async_part(struct message *msg,
        int done = msg->done;
        int bytes = min(msg->size - done, line6->max_packet_size);
 
-       usb_fill_int_urb(urb, line6->usbdev,
-               usb_sndintpipe(line6->usbdev, line6->properties->ep_ctrl_w),
-               (char *)msg->buffer + done, bytes,
-               line6_async_request_sent, msg, line6->interval);
+       if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI) {
+               usb_fill_int_urb(urb, line6->usbdev,
+                       usb_sndintpipe(line6->usbdev, line6->properties->ep_ctrl_w),
+                       (char *)msg->buffer + done, bytes,
+                       line6_async_request_sent, msg, line6->interval);
+       } else {
+               usb_fill_bulk_urb(urb, line6->usbdev,
+                       usb_sndbulkpipe(line6->usbdev, line6->properties->ep_ctrl_w),
+                       (char *)msg->buffer + done, bytes,
+                       line6_async_request_sent, msg);
+       }
 
        msg->done += bytes;
        retval = usb_submit_urb(urb, GFP_ATOMIC);
@@ -462,7 +483,18 @@ static void line6_destruct(struct snd_card *card)
 static void line6_get_interval(struct usb_line6 *line6)
 {
        struct usb_device *usbdev = line6->usbdev;
-       struct usb_host_endpoint *ep = usbdev->ep_in[line6->properties->ep_ctrl_r];
+       const struct line6_properties *properties = line6->properties;
+       int pipe;
+       struct usb_host_endpoint *ep;
+
+       if (properties->capabilities & LINE6_CAP_CONTROL_MIDI) {
+               pipe =
+                       usb_rcvintpipe(line6->usbdev, line6->properties->ep_ctrl_r);
+       } else {
+               pipe =
+                       usb_rcvbulkpipe(line6->usbdev, line6->properties->ep_ctrl_r);
+       }
+       ep = usbdev->ep_in[usb_pipeendpoint(pipe)];
 
        if (ep) {
                line6->interval = ep->desc.bInterval;
@@ -483,7 +515,7 @@ static void line6_get_interval(struct usb_line6 *line6)
        }
 }
 
-static int line6_init_cap_control(struct usb_line6 *line6)
+static int line6_init_cap_control_midi(struct usb_line6 *line6)
 {
        int ret;
 
@@ -573,8 +605,8 @@ int line6_probe(struct usb_interface *interface,
 
        line6_get_interval(line6);
 
-       if (properties->capabilities & LINE6_CAP_CONTROL) {
-               ret = line6_init_cap_control(line6);
+       if (properties->capabilities & LINE6_CAP_CONTROL_MIDI) {
+               ret = line6_init_cap_control_midi(line6);
                if (ret < 0)
                        goto error;
        }
@@ -644,7 +676,7 @@ int line6_suspend(struct usb_interface *interface, pm_message_t message)
 
        snd_power_change_state(line6->card, SNDRV_CTL_POWER_D3hot);
 
-       if (line6->properties->capabilities & LINE6_CAP_CONTROL)
+       if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI)
                line6_stop_listen(line6);
 
        if (line6pcm != NULL) {
@@ -663,7 +695,7 @@ int line6_resume(struct usb_interface *interface)
 {
        struct usb_line6 *line6 = usb_get_intfdata(interface);
 
-       if (line6->properties->capabilities & LINE6_CAP_CONTROL)
+       if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI)
                line6_start_listen(line6);
 
        snd_power_change_state(line6->card, SNDRV_CTL_POWER_D0);
index 0bcab38ac10db70053d6f76d694737e933f944f5..d48c7d2f1575f8b71fddbf7378c1c6d8e204349a 100644 (file)
@@ -104,6 +104,8 @@ enum {
        LINE6_CAP_HWMON =       1 << 2,
        /* device requires output data when input is read */
        LINE6_CAP_IN_NEEDS_OUT = 1 << 3,
+       /* device uses raw MIDI via USB (data endpoints) */
+       LINE6_CAP_CONTROL_MIDI = 1 << 4,
 };
 
 /*
@@ -142,10 +144,10 @@ struct usb_line6 {
        /* Line 6 MIDI device data structure */
        struct snd_line6_midi *line6midi;
 
-       /* URB for listening to PODxt Pro control endpoint */
+       /* URB for listening to POD data endpoint */
        struct urb *urb_listen;
 
-       /* Buffer for listening to PODxt Pro control endpoint */
+       /* Buffer for listening to POD data endpoint */
        unsigned char *buffer_listen;
 
        /* Buffer for message to be processed */
index 36e727418d309c587fb4964aa7588c7abf532cad..17aa616e61f53bd7b196422900308fefc16a7136 100644 (file)
@@ -475,6 +475,7 @@ static const struct line6_properties pod_properties_table[] = {
                .id = "BassPODxt",
                .name = "BassPODxt",
                .capabilities   = LINE6_CAP_CONTROL
+                               | LINE6_CAP_CONTROL_MIDI
                                | LINE6_CAP_PCM
                                | LINE6_CAP_HWMON,
                .altsetting = 5,
@@ -487,6 +488,7 @@ static const struct line6_properties pod_properties_table[] = {
                .id = "BassPODxtLive",
                .name = "BassPODxt Live",
                .capabilities   = LINE6_CAP_CONTROL
+                               | LINE6_CAP_CONTROL_MIDI
                                | LINE6_CAP_PCM
                                | LINE6_CAP_HWMON,
                .altsetting = 1,
@@ -499,6 +501,7 @@ static const struct line6_properties pod_properties_table[] = {
                .id = "BassPODxtPro",
                .name = "BassPODxt Pro",
                .capabilities   = LINE6_CAP_CONTROL
+                               | LINE6_CAP_CONTROL_MIDI
                                | LINE6_CAP_PCM
                                | LINE6_CAP_HWMON,
                .altsetting = 5,
@@ -510,7 +513,8 @@ static const struct line6_properties pod_properties_table[] = {
        [LINE6_POCKETPOD] = {
                .id = "PocketPOD",
                .name = "Pocket POD",
-               .capabilities   = LINE6_CAP_CONTROL,
+               .capabilities   = LINE6_CAP_CONTROL
+                               | LINE6_CAP_CONTROL_MIDI,
                .altsetting = 0,
                .ep_ctrl_r = 0x82,
                .ep_ctrl_w = 0x02,
@@ -520,6 +524,7 @@ static const struct line6_properties pod_properties_table[] = {
                .id = "PODxt",
                .name = "PODxt",
                .capabilities   = LINE6_CAP_CONTROL
+                               | LINE6_CAP_CONTROL_MIDI
                                | LINE6_CAP_PCM
                                | LINE6_CAP_HWMON,
                .altsetting = 5,
@@ -532,6 +537,7 @@ static const struct line6_properties pod_properties_table[] = {
                .id = "PODxtLive",
                .name = "PODxt Live",
                .capabilities   = LINE6_CAP_CONTROL
+                               | LINE6_CAP_CONTROL_MIDI
                                | LINE6_CAP_PCM
                                | LINE6_CAP_HWMON,
                .altsetting = 1,
@@ -544,6 +550,7 @@ static const struct line6_properties pod_properties_table[] = {
                .id = "PODxtPro",
                .name = "PODxt Pro",
                .capabilities   = LINE6_CAP_CONTROL
+                               | LINE6_CAP_CONTROL_MIDI
                                | LINE6_CAP_PCM
                                | LINE6_CAP_HWMON,
                .altsetting = 5,
index ddc23ddf0750ae39c64f5563389297db119ebcc9..0c4512d0382eab1cfb9e4b5aaf329c462f68c922 100644 (file)
@@ -259,7 +259,8 @@ static const struct line6_properties variax_properties_table[] = {
        [LINE6_PODXTLIVE_VARIAX] = {
                .id = "PODxtLive",
                .name = "PODxt Live",
-               .capabilities   = LINE6_CAP_CONTROL,
+               .capabilities   = LINE6_CAP_CONTROL
+                               | LINE6_CAP_CONTROL_MIDI,
                .altsetting = 1,
                .ep_ctrl_r = 0x86,
                .ep_ctrl_w = 0x05,
@@ -269,7 +270,8 @@ static const struct line6_properties variax_properties_table[] = {
        [LINE6_VARIAX] = {
                .id = "Variax",
                .name = "Variax Workbench",
-               .capabilities   = LINE6_CAP_CONTROL,
+               .capabilities   = LINE6_CAP_CONTROL
+                               | LINE6_CAP_CONTROL_MIDI,
                .altsetting = 1,
                .ep_ctrl_r = 0x82,
                .ep_ctrl_w = 0x01,