diff options
author | Takashi Iwai <tiwai@suse.de> | 2009-01-08 09:32:56 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-01-08 09:32:56 -0500 |
commit | f3f80a9205da74fa56d613f4c14b88b6e4e6caa8 (patch) | |
tree | 45bc5d27b7be884431c19f5cf7042d11af682ef3 /sound | |
parent | 9e42d0cf5020aaf217433cad1a224745241d212a (diff) |
ALSA: caiaq - Fix Oops with MIDI
The snd-usb-caiaq driver causes Oops occasionally when accessing MIDI
devices. This patch fixes the Oops and invalid URB submission errors
as well.
Cc: stable@kernel.org
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/usb/caiaq/caiaq-device.h | 1 | ||||
-rw-r--r-- | sound/usb/caiaq/caiaq-midi.c | 32 |
2 files changed, 19 insertions, 14 deletions
diff --git a/sound/usb/caiaq/caiaq-device.h b/sound/usb/caiaq/caiaq-device.h index f9fbdbae269..ab56e738c5f 100644 --- a/sound/usb/caiaq/caiaq-device.h +++ b/sound/usb/caiaq/caiaq-device.h | |||
@@ -75,6 +75,7 @@ struct snd_usb_caiaqdev { | |||
75 | wait_queue_head_t ep1_wait_queue; | 75 | wait_queue_head_t ep1_wait_queue; |
76 | wait_queue_head_t prepare_wait_queue; | 76 | wait_queue_head_t prepare_wait_queue; |
77 | int spec_received, audio_parm_answer; | 77 | int spec_received, audio_parm_answer; |
78 | int midi_out_active; | ||
78 | 79 | ||
79 | char vendor_name[CAIAQ_USB_STR_LEN]; | 80 | char vendor_name[CAIAQ_USB_STR_LEN]; |
80 | char product_name[CAIAQ_USB_STR_LEN]; | 81 | char product_name[CAIAQ_USB_STR_LEN]; |
diff --git a/sound/usb/caiaq/caiaq-midi.c b/sound/usb/caiaq/caiaq-midi.c index 30b57f97c6e..f19fd360c93 100644 --- a/sound/usb/caiaq/caiaq-midi.c +++ b/sound/usb/caiaq/caiaq-midi.c | |||
@@ -59,6 +59,11 @@ static int snd_usb_caiaq_midi_output_open(struct snd_rawmidi_substream *substrea | |||
59 | 59 | ||
60 | static int snd_usb_caiaq_midi_output_close(struct snd_rawmidi_substream *substream) | 60 | static int snd_usb_caiaq_midi_output_close(struct snd_rawmidi_substream *substream) |
61 | { | 61 | { |
62 | struct snd_usb_caiaqdev *dev = substream->rmidi->private_data; | ||
63 | if (dev->midi_out_active) { | ||
64 | usb_kill_urb(&dev->midi_out_urb); | ||
65 | dev->midi_out_active = 0; | ||
66 | } | ||
62 | return 0; | 67 | return 0; |
63 | } | 68 | } |
64 | 69 | ||
@@ -69,7 +74,8 @@ static void snd_usb_caiaq_midi_send(struct snd_usb_caiaqdev *dev, | |||
69 | 74 | ||
70 | dev->midi_out_buf[0] = EP1_CMD_MIDI_WRITE; | 75 | dev->midi_out_buf[0] = EP1_CMD_MIDI_WRITE; |
71 | dev->midi_out_buf[1] = 0; /* port */ | 76 | dev->midi_out_buf[1] = 0; /* port */ |
72 | len = snd_rawmidi_transmit_peek(substream, dev->midi_out_buf+3, EP1_BUFSIZE-3); | 77 | len = snd_rawmidi_transmit(substream, dev->midi_out_buf + 3, |
78 | EP1_BUFSIZE - 3); | ||
73 | 79 | ||
74 | if (len <= 0) | 80 | if (len <= 0) |
75 | return; | 81 | return; |
@@ -79,24 +85,24 @@ static void snd_usb_caiaq_midi_send(struct snd_usb_caiaqdev *dev, | |||
79 | 85 | ||
80 | ret = usb_submit_urb(&dev->midi_out_urb, GFP_ATOMIC); | 86 | ret = usb_submit_urb(&dev->midi_out_urb, GFP_ATOMIC); |
81 | if (ret < 0) | 87 | if (ret < 0) |
82 | log("snd_usb_caiaq_midi_send(%p): usb_submit_urb() failed, %d\n", | 88 | log("snd_usb_caiaq_midi_send(%p): usb_submit_urb() failed," |
83 | substream, ret); | 89 | "ret=%d, len=%d\n", |
90 | substream, ret, len); | ||
91 | else | ||
92 | dev->midi_out_active = 1; | ||
84 | } | 93 | } |
85 | 94 | ||
86 | static void snd_usb_caiaq_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) | 95 | static void snd_usb_caiaq_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) |
87 | { | 96 | { |
88 | struct snd_usb_caiaqdev *dev = substream->rmidi->private_data; | 97 | struct snd_usb_caiaqdev *dev = substream->rmidi->private_data; |
89 | 98 | ||
90 | if (dev->midi_out_substream != NULL) | 99 | if (up) { |
91 | return; | 100 | dev->midi_out_substream = substream; |
92 | 101 | if (!dev->midi_out_active) | |
93 | if (!up) { | 102 | snd_usb_caiaq_midi_send(dev, substream); |
103 | } else { | ||
94 | dev->midi_out_substream = NULL; | 104 | dev->midi_out_substream = NULL; |
95 | return; | ||
96 | } | 105 | } |
97 | |||
98 | dev->midi_out_substream = substream; | ||
99 | snd_usb_caiaq_midi_send(dev, substream); | ||
100 | } | 106 | } |
101 | 107 | ||
102 | 108 | ||
@@ -161,16 +167,14 @@ int snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *device) | |||
161 | void snd_usb_caiaq_midi_output_done(struct urb* urb) | 167 | void snd_usb_caiaq_midi_output_done(struct urb* urb) |
162 | { | 168 | { |
163 | struct snd_usb_caiaqdev *dev = urb->context; | 169 | struct snd_usb_caiaqdev *dev = urb->context; |
164 | char *buf = urb->transfer_buffer; | ||
165 | 170 | ||
171 | dev->midi_out_active = 0; | ||
166 | if (urb->status != 0) | 172 | if (urb->status != 0) |
167 | return; | 173 | return; |
168 | 174 | ||
169 | if (!dev->midi_out_substream) | 175 | if (!dev->midi_out_substream) |
170 | return; | 176 | return; |
171 | 177 | ||
172 | snd_rawmidi_transmit_ack(dev->midi_out_substream, buf[2]); | ||
173 | dev->midi_out_substream = NULL; | ||
174 | snd_usb_caiaq_midi_send(dev, dev->midi_out_substream); | 178 | snd_usb_caiaq_midi_send(dev, dev->midi_out_substream); |
175 | } | 179 | } |
176 | 180 | ||