aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb/usbmidi.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/usb/usbmidi.c')
-rw-r--r--sound/usb/usbmidi.c87
1 files changed, 54 insertions, 33 deletions
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c
index 2fb35cc22a30..cc17401de95e 100644
--- a/sound/usb/usbmidi.c
+++ b/sound/usb/usbmidi.c
@@ -62,6 +62,8 @@
62 */ 62 */
63#define ERROR_DELAY_JIFFIES (HZ / 10) 63#define ERROR_DELAY_JIFFIES (HZ / 10)
64 64
65#define INPUT_URBS 7
66
65 67
66MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); 68MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
67MODULE_DESCRIPTION("USB Audio/MIDI helper module"); 69MODULE_DESCRIPTION("USB Audio/MIDI helper module");
@@ -143,7 +145,7 @@ struct snd_usb_midi_out_endpoint {
143 145
144struct snd_usb_midi_in_endpoint { 146struct snd_usb_midi_in_endpoint {
145 struct snd_usb_midi* umidi; 147 struct snd_usb_midi* umidi;
146 struct urb* urb; 148 struct urb* urbs[INPUT_URBS];
147 struct usbmidi_in_port { 149 struct usbmidi_in_port {
148 struct snd_rawmidi_substream *substream; 150 struct snd_rawmidi_substream *substream;
149 u8 running_status_length; 151 u8 running_status_length;
@@ -306,7 +308,7 @@ static void snd_usbmidi_out_tasklet(unsigned long data)
306static void snd_usbmidi_error_timer(unsigned long data) 308static void snd_usbmidi_error_timer(unsigned long data)
307{ 309{
308 struct snd_usb_midi *umidi = (struct snd_usb_midi *)data; 310 struct snd_usb_midi *umidi = (struct snd_usb_midi *)data;
309 int i; 311 unsigned int i, j;
310 312
311 spin_lock(&umidi->disc_lock); 313 spin_lock(&umidi->disc_lock);
312 if (umidi->disconnected) { 314 if (umidi->disconnected) {
@@ -317,8 +319,10 @@ static void snd_usbmidi_error_timer(unsigned long data)
317 struct snd_usb_midi_in_endpoint *in = umidi->endpoints[i].in; 319 struct snd_usb_midi_in_endpoint *in = umidi->endpoints[i].in;
318 if (in && in->error_resubmit) { 320 if (in && in->error_resubmit) {
319 in->error_resubmit = 0; 321 in->error_resubmit = 0;
320 in->urb->dev = umidi->chip->dev; 322 for (j = 0; j < INPUT_URBS; ++j) {
321 snd_usbmidi_submit_urb(in->urb, GFP_ATOMIC); 323 in->urbs[j]->dev = umidi->chip->dev;
324 snd_usbmidi_submit_urb(in->urbs[j], GFP_ATOMIC);
325 }
322 } 326 }
323 if (umidi->endpoints[i].out) 327 if (umidi->endpoints[i].out)
324 snd_usbmidi_do_output(umidi->endpoints[i].out); 328 snd_usbmidi_do_output(umidi->endpoints[i].out);
@@ -922,12 +926,16 @@ static struct snd_rawmidi_ops snd_usbmidi_input_ops = {
922 */ 926 */
923static void snd_usbmidi_in_endpoint_delete(struct snd_usb_midi_in_endpoint* ep) 927static void snd_usbmidi_in_endpoint_delete(struct snd_usb_midi_in_endpoint* ep)
924{ 928{
925 if (ep->urb) { 929 unsigned int i;
926 usb_buffer_free(ep->umidi->chip->dev, 930
927 ep->urb->transfer_buffer_length, 931 for (i = 0; i < INPUT_URBS; ++i) {
928 ep->urb->transfer_buffer, 932 if (ep->urbs[i]) {
929 ep->urb->transfer_dma); 933 usb_buffer_free(ep->umidi->chip->dev,
930 usb_free_urb(ep->urb); 934 ep->urbs[i]->transfer_buffer_length,
935 ep->urbs[i]->transfer_buffer,
936 ep->urbs[i]->transfer_dma);
937 usb_free_urb(ep->urbs[i]);
938 }
931 } 939 }
932 kfree(ep); 940 kfree(ep);
933} 941}
@@ -943,6 +951,7 @@ static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi* umidi,
943 void* buffer; 951 void* buffer;
944 unsigned int pipe; 952 unsigned int pipe;
945 int length; 953 int length;
954 unsigned int i;
946 955
947 rep->in = NULL; 956 rep->in = NULL;
948 ep = kzalloc(sizeof(*ep), GFP_KERNEL); 957 ep = kzalloc(sizeof(*ep), GFP_KERNEL);
@@ -950,30 +959,36 @@ static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi* umidi,
950 return -ENOMEM; 959 return -ENOMEM;
951 ep->umidi = umidi; 960 ep->umidi = umidi;
952 961
953 ep->urb = usb_alloc_urb(0, GFP_KERNEL); 962 for (i = 0; i < INPUT_URBS; ++i) {
954 if (!ep->urb) { 963 ep->urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
955 snd_usbmidi_in_endpoint_delete(ep); 964 if (!ep->urbs[i]) {
956 return -ENOMEM; 965 snd_usbmidi_in_endpoint_delete(ep);
966 return -ENOMEM;
967 }
957 } 968 }
958 if (ep_info->in_interval) 969 if (ep_info->in_interval)
959 pipe = usb_rcvintpipe(umidi->chip->dev, ep_info->in_ep); 970 pipe = usb_rcvintpipe(umidi->chip->dev, ep_info->in_ep);
960 else 971 else
961 pipe = usb_rcvbulkpipe(umidi->chip->dev, ep_info->in_ep); 972 pipe = usb_rcvbulkpipe(umidi->chip->dev, ep_info->in_ep);
962 length = usb_maxpacket(umidi->chip->dev, pipe, 0); 973 length = usb_maxpacket(umidi->chip->dev, pipe, 0);
963 buffer = usb_buffer_alloc(umidi->chip->dev, length, GFP_KERNEL, 974 for (i = 0; i < INPUT_URBS; ++i) {
964 &ep->urb->transfer_dma); 975 buffer = usb_buffer_alloc(umidi->chip->dev, length, GFP_KERNEL,
965 if (!buffer) { 976 &ep->urbs[i]->transfer_dma);
966 snd_usbmidi_in_endpoint_delete(ep); 977 if (!buffer) {
967 return -ENOMEM; 978 snd_usbmidi_in_endpoint_delete(ep);
979 return -ENOMEM;
980 }
981 if (ep_info->in_interval)
982 usb_fill_int_urb(ep->urbs[i], umidi->chip->dev,
983 pipe, buffer, length,
984 snd_usbmidi_in_urb_complete,
985 ep, ep_info->in_interval);
986 else
987 usb_fill_bulk_urb(ep->urbs[i], umidi->chip->dev,
988 pipe, buffer, length,
989 snd_usbmidi_in_urb_complete, ep);
990 ep->urbs[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
968 } 991 }
969 if (ep_info->in_interval)
970 usb_fill_int_urb(ep->urb, umidi->chip->dev, pipe, buffer,
971 length, snd_usbmidi_in_urb_complete, ep,
972 ep_info->in_interval);
973 else
974 usb_fill_bulk_urb(ep->urb, umidi->chip->dev, pipe, buffer,
975 length, snd_usbmidi_in_urb_complete, ep);
976 ep->urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
977 992
978 rep->in = ep; 993 rep->in = ep;
979 return 0; 994 return 0;
@@ -1090,7 +1105,7 @@ static void snd_usbmidi_free(struct snd_usb_midi* umidi)
1090void snd_usbmidi_disconnect(struct list_head* p) 1105void snd_usbmidi_disconnect(struct list_head* p)
1091{ 1106{
1092 struct snd_usb_midi* umidi; 1107 struct snd_usb_midi* umidi;
1093 int i; 1108 unsigned int i, j;
1094 1109
1095 umidi = list_entry(p, struct snd_usb_midi, list); 1110 umidi = list_entry(p, struct snd_usb_midi, list);
1096 /* 1111 /*
@@ -1111,7 +1126,8 @@ void snd_usbmidi_disconnect(struct list_head* p)
1111 umidi->usb_protocol_ops->finish_out_endpoint(ep->out); 1126 umidi->usb_protocol_ops->finish_out_endpoint(ep->out);
1112 } 1127 }
1113 if (ep->in) 1128 if (ep->in)
1114 usb_kill_urb(ep->in->urb); 1129 for (j = 0; j < INPUT_URBS; ++j)
1130 usb_kill_urb(ep->in->urbs[j]);
1115 /* free endpoints here; later call can result in Oops */ 1131 /* free endpoints here; later call can result in Oops */
1116 if (ep->out) { 1132 if (ep->out) {
1117 snd_usbmidi_out_endpoint_delete(ep->out); 1133 snd_usbmidi_out_endpoint_delete(ep->out);
@@ -1692,20 +1708,25 @@ static int snd_usbmidi_create_rawmidi(struct snd_usb_midi* umidi,
1692void snd_usbmidi_input_stop(struct list_head* p) 1708void snd_usbmidi_input_stop(struct list_head* p)
1693{ 1709{
1694 struct snd_usb_midi* umidi; 1710 struct snd_usb_midi* umidi;
1695 int i; 1711 unsigned int i, j;
1696 1712
1697 umidi = list_entry(p, struct snd_usb_midi, list); 1713 umidi = list_entry(p, struct snd_usb_midi, list);
1698 for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) { 1714 for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
1699 struct snd_usb_midi_endpoint* ep = &umidi->endpoints[i]; 1715 struct snd_usb_midi_endpoint* ep = &umidi->endpoints[i];
1700 if (ep->in) 1716 if (ep->in)
1701 usb_kill_urb(ep->in->urb); 1717 for (j = 0; j < INPUT_URBS; ++j)
1718 usb_kill_urb(ep->in->urbs[j]);
1702 } 1719 }
1703} 1720}
1704 1721
1705static void snd_usbmidi_input_start_ep(struct snd_usb_midi_in_endpoint* ep) 1722static void snd_usbmidi_input_start_ep(struct snd_usb_midi_in_endpoint* ep)
1706{ 1723{
1707 if (ep) { 1724 unsigned int i;
1708 struct urb* urb = ep->urb; 1725
1726 if (!ep)
1727 return;
1728 for (i = 0; i < INPUT_URBS; ++i) {
1729 struct urb* urb = ep->urbs[i];
1709 urb->dev = ep->umidi->chip->dev; 1730 urb->dev = ep->umidi->chip->dev;
1710 snd_usbmidi_submit_urb(urb, GFP_KERNEL); 1731 snd_usbmidi_submit_urb(urb, GFP_KERNEL);
1711 } 1732 }