Commit 174e1fc0 authored by Andrej Krutak's avatar Andrej Krutak Committed by Takashi Iwai

ALSA: line6: Distinguish device init (ctrl EP) and MIDI data transfer (int EP)

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: default avatarAndrej Krutak <dev@andree.sk>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent f56742cc
...@@ -66,10 +66,17 @@ static int line6_start_listen(struct usb_line6 *line6) ...@@ -66,10 +66,17 @@ static int line6_start_listen(struct usb_line6 *line6)
{ {
int err; int err;
if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI) {
usb_fill_int_urb(line6->urb_listen, line6->usbdev, usb_fill_int_urb(line6->urb_listen, line6->usbdev,
usb_rcvintpipe(line6->usbdev, line6->properties->ep_ctrl_r), usb_rcvintpipe(line6->usbdev, line6->properties->ep_ctrl_r),
line6->buffer_listen, LINE6_BUFSIZE_LISTEN, line6->buffer_listen, LINE6_BUFSIZE_LISTEN,
line6_data_received, line6, line6->interval); 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; line6->urb_listen->actual_length = 0;
err = usb_submit_urb(line6->urb_listen, GFP_ATOMIC); err = usb_submit_urb(line6->urb_listen, GFP_ATOMIC);
return err; return err;
...@@ -90,6 +97,7 @@ static int line6_send_raw_message(struct usb_line6 *line6, const char *buffer, ...@@ -90,6 +97,7 @@ static int line6_send_raw_message(struct usb_line6 *line6, const char *buffer,
int size) int size)
{ {
int i, done = 0; int i, done = 0;
const struct line6_properties *properties = line6->properties;
for (i = 0; i < size; i += line6->max_packet_size) { for (i = 0; i < size; i += line6->max_packet_size) {
int partial; int partial;
...@@ -97,15 +105,21 @@ static int line6_send_raw_message(struct usb_line6 *line6, const char *buffer, ...@@ -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 frag_size = min(line6->max_packet_size, size - i);
int retval; int retval;
if (properties->capabilities & LINE6_CAP_CONTROL_MIDI) {
retval = usb_interrupt_msg(line6->usbdev, retval = usb_interrupt_msg(line6->usbdev,
usb_sndintpipe(line6->usbdev, usb_sndintpipe(line6->usbdev, properties->ep_ctrl_w),
line6->properties->ep_ctrl_w),
(char *)frag_buf, frag_size, (char *)frag_buf, frag_size,
&partial, LINE6_TIMEOUT * HZ); &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) { if (retval) {
dev_err(line6->ifcdev, dev_err(line6->ifcdev,
"usb_interrupt_msg failed (%d)\n", retval); "usb_bulk_msg failed (%d)\n", retval);
break; break;
} }
...@@ -140,10 +154,17 @@ static int line6_send_raw_message_async_part(struct message *msg, ...@@ -140,10 +154,17 @@ static int line6_send_raw_message_async_part(struct message *msg,
int done = msg->done; int done = msg->done;
int bytes = min(msg->size - done, line6->max_packet_size); int bytes = min(msg->size - done, line6->max_packet_size);
if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI) {
usb_fill_int_urb(urb, line6->usbdev, usb_fill_int_urb(urb, line6->usbdev,
usb_sndintpipe(line6->usbdev, line6->properties->ep_ctrl_w), usb_sndintpipe(line6->usbdev, line6->properties->ep_ctrl_w),
(char *)msg->buffer + done, bytes, (char *)msg->buffer + done, bytes,
line6_async_request_sent, msg, line6->interval); 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; msg->done += bytes;
retval = usb_submit_urb(urb, GFP_ATOMIC); retval = usb_submit_urb(urb, GFP_ATOMIC);
...@@ -462,7 +483,18 @@ static void line6_destruct(struct snd_card *card) ...@@ -462,7 +483,18 @@ static void line6_destruct(struct snd_card *card)
static void line6_get_interval(struct usb_line6 *line6) static void line6_get_interval(struct usb_line6 *line6)
{ {
struct usb_device *usbdev = line6->usbdev; 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) { if (ep) {
line6->interval = ep->desc.bInterval; line6->interval = ep->desc.bInterval;
...@@ -483,7 +515,7 @@ static void line6_get_interval(struct usb_line6 *line6) ...@@ -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; int ret;
...@@ -573,8 +605,8 @@ int line6_probe(struct usb_interface *interface, ...@@ -573,8 +605,8 @@ int line6_probe(struct usb_interface *interface,
line6_get_interval(line6); line6_get_interval(line6);
if (properties->capabilities & LINE6_CAP_CONTROL) { if (properties->capabilities & LINE6_CAP_CONTROL_MIDI) {
ret = line6_init_cap_control(line6); ret = line6_init_cap_control_midi(line6);
if (ret < 0) if (ret < 0)
goto error; goto error;
} }
...@@ -644,7 +676,7 @@ int line6_suspend(struct usb_interface *interface, pm_message_t message) ...@@ -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); 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); line6_stop_listen(line6);
if (line6pcm != NULL) { if (line6pcm != NULL) {
...@@ -663,7 +695,7 @@ int line6_resume(struct usb_interface *interface) ...@@ -663,7 +695,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) if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI)
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);
......
...@@ -104,6 +104,8 @@ enum { ...@@ -104,6 +104,8 @@ enum {
LINE6_CAP_HWMON = 1 << 2, LINE6_CAP_HWMON = 1 << 2,
/* device requires output data when input is read */ /* device requires output data when input is read */
LINE6_CAP_IN_NEEDS_OUT = 1 << 3, 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 { ...@@ -142,10 +144,10 @@ struct usb_line6 {
/* Line 6 MIDI device data structure */ /* Line 6 MIDI device data structure */
struct snd_line6_midi *line6midi; struct snd_line6_midi *line6midi;
/* URB for listening to PODxt Pro control endpoint */ /* URB for listening to POD data endpoint */
struct urb *urb_listen; struct urb *urb_listen;
/* Buffer for listening to PODxt Pro control endpoint */ /* Buffer for listening to POD data endpoint */
unsigned char *buffer_listen; unsigned char *buffer_listen;
/* Buffer for message to be processed */ /* Buffer for message to be processed */
......
...@@ -475,6 +475,7 @@ static const struct line6_properties pod_properties_table[] = { ...@@ -475,6 +475,7 @@ static const struct line6_properties pod_properties_table[] = {
.id = "BassPODxt", .id = "BassPODxt",
.name = "BassPODxt", .name = "BassPODxt",
.capabilities = LINE6_CAP_CONTROL .capabilities = LINE6_CAP_CONTROL
| LINE6_CAP_CONTROL_MIDI
| LINE6_CAP_PCM | LINE6_CAP_PCM
| LINE6_CAP_HWMON, | LINE6_CAP_HWMON,
.altsetting = 5, .altsetting = 5,
...@@ -487,6 +488,7 @@ static const struct line6_properties pod_properties_table[] = { ...@@ -487,6 +488,7 @@ static const struct line6_properties pod_properties_table[] = {
.id = "BassPODxtLive", .id = "BassPODxtLive",
.name = "BassPODxt Live", .name = "BassPODxt Live",
.capabilities = LINE6_CAP_CONTROL .capabilities = LINE6_CAP_CONTROL
| LINE6_CAP_CONTROL_MIDI
| LINE6_CAP_PCM | LINE6_CAP_PCM
| LINE6_CAP_HWMON, | LINE6_CAP_HWMON,
.altsetting = 1, .altsetting = 1,
...@@ -499,6 +501,7 @@ static const struct line6_properties pod_properties_table[] = { ...@@ -499,6 +501,7 @@ static const struct line6_properties pod_properties_table[] = {
.id = "BassPODxtPro", .id = "BassPODxtPro",
.name = "BassPODxt Pro", .name = "BassPODxt Pro",
.capabilities = LINE6_CAP_CONTROL .capabilities = LINE6_CAP_CONTROL
| LINE6_CAP_CONTROL_MIDI
| LINE6_CAP_PCM | LINE6_CAP_PCM
| LINE6_CAP_HWMON, | LINE6_CAP_HWMON,
.altsetting = 5, .altsetting = 5,
...@@ -510,7 +513,8 @@ static const struct line6_properties pod_properties_table[] = { ...@@ -510,7 +513,8 @@ static const struct line6_properties pod_properties_table[] = {
[LINE6_POCKETPOD] = { [LINE6_POCKETPOD] = {
.id = "PocketPOD", .id = "PocketPOD",
.name = "Pocket POD", .name = "Pocket POD",
.capabilities = LINE6_CAP_CONTROL, .capabilities = LINE6_CAP_CONTROL
| LINE6_CAP_CONTROL_MIDI,
.altsetting = 0, .altsetting = 0,
.ep_ctrl_r = 0x82, .ep_ctrl_r = 0x82,
.ep_ctrl_w = 0x02, .ep_ctrl_w = 0x02,
...@@ -520,6 +524,7 @@ static const struct line6_properties pod_properties_table[] = { ...@@ -520,6 +524,7 @@ static const struct line6_properties pod_properties_table[] = {
.id = "PODxt", .id = "PODxt",
.name = "PODxt", .name = "PODxt",
.capabilities = LINE6_CAP_CONTROL .capabilities = LINE6_CAP_CONTROL
| LINE6_CAP_CONTROL_MIDI
| LINE6_CAP_PCM | LINE6_CAP_PCM
| LINE6_CAP_HWMON, | LINE6_CAP_HWMON,
.altsetting = 5, .altsetting = 5,
...@@ -532,6 +537,7 @@ static const struct line6_properties pod_properties_table[] = { ...@@ -532,6 +537,7 @@ static const struct line6_properties pod_properties_table[] = {
.id = "PODxtLive", .id = "PODxtLive",
.name = "PODxt Live", .name = "PODxt Live",
.capabilities = LINE6_CAP_CONTROL .capabilities = LINE6_CAP_CONTROL
| LINE6_CAP_CONTROL_MIDI
| LINE6_CAP_PCM | LINE6_CAP_PCM
| LINE6_CAP_HWMON, | LINE6_CAP_HWMON,
.altsetting = 1, .altsetting = 1,
...@@ -544,6 +550,7 @@ static const struct line6_properties pod_properties_table[] = { ...@@ -544,6 +550,7 @@ static const struct line6_properties pod_properties_table[] = {
.id = "PODxtPro", .id = "PODxtPro",
.name = "PODxt Pro", .name = "PODxt Pro",
.capabilities = LINE6_CAP_CONTROL .capabilities = LINE6_CAP_CONTROL
| LINE6_CAP_CONTROL_MIDI
| LINE6_CAP_PCM | LINE6_CAP_PCM
| LINE6_CAP_HWMON, | LINE6_CAP_HWMON,
.altsetting = 5, .altsetting = 5,
......
...@@ -259,7 +259,8 @@ static const struct line6_properties variax_properties_table[] = { ...@@ -259,7 +259,8 @@ static const struct line6_properties variax_properties_table[] = {
[LINE6_PODXTLIVE_VARIAX] = { [LINE6_PODXTLIVE_VARIAX] = {
.id = "PODxtLive", .id = "PODxtLive",
.name = "PODxt Live", .name = "PODxt Live",
.capabilities = LINE6_CAP_CONTROL, .capabilities = LINE6_CAP_CONTROL
| LINE6_CAP_CONTROL_MIDI,
.altsetting = 1, .altsetting = 1,
.ep_ctrl_r = 0x86, .ep_ctrl_r = 0x86,
.ep_ctrl_w = 0x05, .ep_ctrl_w = 0x05,
...@@ -269,7 +270,8 @@ static const struct line6_properties variax_properties_table[] = { ...@@ -269,7 +270,8 @@ static const struct line6_properties variax_properties_table[] = {
[LINE6_VARIAX] = { [LINE6_VARIAX] = {
.id = "Variax", .id = "Variax",
.name = "Variax Workbench", .name = "Variax Workbench",
.capabilities = LINE6_CAP_CONTROL, .capabilities = LINE6_CAP_CONTROL
| LINE6_CAP_CONTROL_MIDI,
.altsetting = 1, .altsetting = 1,
.ep_ctrl_r = 0x82, .ep_ctrl_r = 0x82,
.ep_ctrl_w = 0x01, .ep_ctrl_w = 0x01,
......
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