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 | |
| 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>
| -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 f9fbdbae269d..ab56e738c5fc 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 30b57f97c6e4..f19fd360c936 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 | ||
