sound/usb/midi2.c

Source file repositories/reference/linux-study-clean/sound/usb/midi2.c

File Facts

System
Linux kernel
Corpus path
sound/usb/midi2.c
Extension
.c
Size
33450 bytes
Lines
1235
Domain
Driver Families
Bucket
sound/usb
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct snd_usb_midi2_urb {
	struct urb *urb;
	struct snd_usb_midi2_endpoint *ep;
	unsigned int index;		/* array index */
};

/* A USB MIDI input/output endpoint */
struct snd_usb_midi2_endpoint {
	struct usb_device *dev;
	const struct usb_ms20_endpoint_descriptor *ms_ep; /* reference to EP descriptor */
	struct snd_usb_midi2_endpoint *pair;	/* bidirectional pair EP */
	struct snd_usb_midi2_ump *rmidi;	/* assigned UMP EP pair */
	struct snd_ump_endpoint *ump;		/* assigned UMP EP */
	int direction;			/* direction (STR_IN/OUT) */
	unsigned int endpoint;		/* EP number */
	unsigned int pipe;		/* URB pipe */
	unsigned int packets;		/* packet buffer size in bytes */
	unsigned int interval;		/* interval for INT EP */
	wait_queue_head_t wait;		/* URB waiter */
	spinlock_t lock;		/* URB locking */
	struct snd_rawmidi_substream *substream; /* NULL when closed */
	unsigned int num_urbs;		/* number of allocated URBs */
	unsigned long urb_free;		/* bitmap for free URBs */
	unsigned long urb_free_mask;	/* bitmask for free URBs */
	atomic_t running;		/* running status */
	atomic_t suspended;		/* saved running status for suspend */
	bool disconnected;		/* shadow of umidi->disconnected */
	struct list_head list;		/* list to umidi->ep_list */
	struct snd_usb_midi2_urb urbs[NUM_URBS];
};

/* A UMP endpoint - one or two USB MIDI endpoints are assigned */
struct snd_usb_midi2_ump {
	struct usb_device *dev;
	struct snd_usb_midi2_interface *umidi;	/* reference to MIDI iface */
	struct snd_ump_endpoint *ump;		/* assigned UMP EP object */
	struct snd_usb_midi2_endpoint *eps[2];	/* USB MIDI endpoints */
	int index;				/* rawmidi device index */
	unsigned char usb_block_id;		/* USB GTB id used for finding a pair */
	bool ump_parsed;			/* Parsed UMP 1.1 EP/FB info*/
	struct list_head list;		/* list to umidi->rawmidi_list */
};

/* top-level instance per USB MIDI interface */
struct snd_usb_midi2_interface {
	struct snd_usb_audio *chip;	/* assigned USB-audio card */
	struct usb_interface *iface;	/* assigned USB interface */
	struct usb_host_interface *hostif;
	const char *blk_descs;		/* group terminal block descriptors */
	unsigned int blk_desc_size;	/* size of GTB descriptors */
	bool disconnected;
	struct list_head ep_list;	/* list of endpoints */
	struct list_head rawmidi_list;	/* list of UMP rawmidis */
	struct list_head list;		/* list to chip->midi_v2_list */
};

/* submit URBs as much as possible; used for both input and output */
static void do_submit_urbs_locked(struct snd_usb_midi2_endpoint *ep,
				  int (*prepare)(struct snd_usb_midi2_endpoint *,
						 struct urb *))
{
	struct snd_usb_midi2_urb *ctx;
	int index, err = 0;

	if (ep->disconnected)
		return;

	while (ep->urb_free) {
		index = find_first_bit(&ep->urb_free, ep->num_urbs);
		if (index >= ep->num_urbs)
			return;
		ctx = &ep->urbs[index];
		err = prepare(ep, ctx->urb);
		if (err < 0)
			return;
		if (!ctx->urb->transfer_buffer_length)
			return;
		ctx->urb->dev = ep->dev;
		err = usb_submit_urb(ctx->urb, GFP_ATOMIC);
		if (err < 0) {
			dev_dbg(&ep->dev->dev,
				"usb_submit_urb error %d\n", err);
			return;
		}
		clear_bit(index, &ep->urb_free);
	}
}

/* prepare for output submission: copy from rawmidi buffer to urb packet */
static int prepare_output_urb(struct snd_usb_midi2_endpoint *ep,

Annotation

Implementation Notes