I wrote: > Oliver Neukum wrote: >> Yes, I noticed. I thought midi is a separate driver. Is there documentation >> on the midi API? > > Documentation/DocBook/writing-an-alsa-driver, section > "RawMIDI Interface". > > Just use the *_open/*_close and *_disconnect callbacks.
Sorry, what I wrote isn't true for input because the driver uses an active URB regardless of whether some input MIDI device is open. If you do autosuspend changes, they would have to go on top of the patch below, which makes the driver submit the endpoint's URB only when some MIDI stream is open. -- Regards, Clemens --- a/sound/usb/usbmidi.c 2008-02-02 11:05:08.000000000 +0100 +++ b/sound/usb/usbmidi.c 2008-02-04 21:58:12.000000000 +0100 @@ -151,6 +151,7 @@ struct snd_usb_midi_in_endpoint { u8 seen_f5; u8 error_resubmit; int current_port; + int open_substreams; }; static void snd_usbmidi_do_output(struct snd_usb_midi_out_endpoint* ep); @@ -245,8 +246,12 @@ static void snd_usbmidi_in_urb_complete( } } - urb->dev = ep->umidi->chip->dev; - snd_usbmidi_submit_urb(urb, GFP_ATOMIC); + spin_lock(&ep->umidi->disc_lock); + if (ep->open_substreams) { + urb->dev = ep->umidi->chip->dev; + snd_usbmidi_submit_urb(urb, GFP_ATOMIC); + } + spin_unlock(&ep->umidi->disc_lock); } static void snd_usbmidi_out_urb_complete(struct urb* urb) @@ -850,11 +855,52 @@ static void snd_usbmidi_output_trigger(s static int snd_usbmidi_input_open(struct snd_rawmidi_substream *substream) { + struct snd_usb_midi* umidi = substream->rmidi->private_data; + struct snd_usb_midi_in_endpoint *endpoint; + unsigned int ep, p; + int needs_submit; + + endpoint = NULL; + for (ep = 0; ep < MIDI_MAX_ENDPOINTS; ++ep) { + struct snd_usb_midi_in_endpoint *in = umidi->endpoints[ep].in; + if (!in) + continue; + for (p = 0; p < 0x10; ++p) + if (in->ports[p].substream == substream) { + endpoint = in; + break; + } + } + if (!endpoint) { + snd_BUG(); + return -ENXIO; + } + substream->runtime->private_data = endpoint; + spin_lock_irq(&umidi->disc_lock); + needs_submit = endpoint->open_substreams == 0; + endpoint->open_substreams++; + spin_unlock_irq(&umidi->disc_lock); + if (needs_submit) { + endpoint->urb->dev = umidi->chip->dev; + snd_usbmidi_submit_urb(endpoint->urb, GFP_KERNEL); + } return 0; } static int snd_usbmidi_input_close(struct snd_rawmidi_substream *substream) { + struct snd_usb_midi_in_endpoint *endpoint; + int needs_kill; + + endpoint = substream->runtime->private_data; + spin_lock_irq(&endpoint->umidi->disc_lock); + endpoint->open_substreams--; + needs_kill = endpoint->open_substreams == 0; + if (needs_kill) + endpoint->error_resubmit = 0; + spin_unlock_irq(&endpoint->umidi->disc_lock); + if (needs_kill) + usb_kill_urb(endpoint->urb); return 0; } @@ -1661,7 +1707,7 @@ void snd_usbmidi_input_stop(struct list_ static void snd_usbmidi_input_start_ep(struct snd_usb_midi_in_endpoint* ep) { - if (ep) { + if (ep && ep->open_substreams) { struct urb* urb = ep->urb; urb->dev = ep->umidi->chip->dev; snd_usbmidi_submit_urb(urb, GFP_KERNEL); @@ -1780,9 +1826,6 @@ int snd_usb_create_midi_interface(struct } list_add(&umidi->list, &umidi->chip->midi_list); - - for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) - snd_usbmidi_input_start_ep(umidi->endpoints[i].in); return 0; } - To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html