/* * Processes the data read from the device. */ static void snd_usbmidi_in_urb_complete(struct urb* urb, struct pt_regs *regs) { snd_usb_midi_in_endpoint_t* ep = urb->context; if (urb->status == 0) { dump_urb("received", urb->transfer_buffer, urb->actual_length); ep->umidi->usb_protocol_ops->input(ep, urb->transfer_buffer, urb->actual_length); } else { int err = snd_usbmidi_urb_error(urb->status); if (err < 0) { if (err != -ENODEV) { ep->error_resubmit = 1; mod_timer(&ep->umidi->error_timer, jiffies + ERROR_DELAY_JIFFIES); } return; } } if (usb_pipe_needs_resubmit(urb->pipe)) { urb->dev = ep->umidi->chip->dev; snd_usbmidi_submit_urb(urb, GFP_ATOMIC); } }
/* called after transfers had been interrupted due to some USB error */ static void snd_usbmidi_error_timer(unsigned long data) { snd_usb_midi_t *umidi = (snd_usb_midi_t *)data; int i; for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) { snd_usb_midi_in_endpoint_t *in = umidi->endpoints[i].in; if (in && in->error_resubmit) { in->error_resubmit = 0; in->urb->dev = umidi->chip->dev; snd_usbmidi_submit_urb(in->urb, GFP_ATOMIC); } if (umidi->endpoints[i].out) snd_usbmidi_do_output(umidi->endpoints[i].out); } }
/* * Processes the data read from the device. */ static void snd_usbmidi_in_urb_complete(struct urb* urb, struct pt_regs *regs) { snd_usb_midi_in_endpoint_t* ep = urb->context; if (urb->status == 0) { uint8_t* buffer = (uint8_t*)ep->urb->transfer_buffer; int i; for (i = 0; i + 4 <= urb->actual_length; i += 4) if (buffer[i] != 0) snd_usbmidi_input_packet(ep, &buffer[i]); } else { if (snd_usbmidi_urb_error(urb->status) < 0) return; } if (usb_pipe_needs_resubmit(urb->pipe)) { urb->dev = ep->umidi->chip->dev; snd_usbmidi_submit_urb(urb, GFP_ATOMIC); } }
/* * This is called when some data should be transferred to the device * (from one or more substreams). */ static void snd_usbmidi_do_output(snd_usb_midi_out_endpoint_t* ep) { struct urb* urb = ep->urb; unsigned long flags; spin_lock_irqsave(&ep->buffer_lock, flags); if (ep->urb_active || ep->umidi->chip->shutdown) { spin_unlock_irqrestore(&ep->buffer_lock, flags); return; } urb->transfer_buffer_length = 0; ep->umidi->usb_protocol_ops->output(ep); if (urb->transfer_buffer_length > 0) { dump_urb("sending", urb->transfer_buffer, urb->transfer_buffer_length); urb->dev = ep->umidi->chip->dev; ep->urb_active = snd_usbmidi_submit_urb(urb, GFP_ATOMIC) >= 0; } spin_unlock_irqrestore(&ep->buffer_lock, flags); }