sound/usb/usx2y/us122l.c

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

File Facts

System
Linux kernel
Corpus path
sound/usb/usx2y/us122l.c
Extension
.c
Size
16218 bytes
Lines
683
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

if (s && s->state == usb_stream_ready) {
			if (us122l->first == file)
				polled = &s->periods_polled;
			else
				polled = &us122l->second_periods_polled;
			if (*polled != s->periods_done) {
				*polled = s->periods_done;
				mask = EPOLLIN | EPOLLOUT | EPOLLWRNORM;
			} else {
				mask = 0;
			}
		}
		mutex_unlock(&us122l->mutex);
	}
	return mask;
}

static void us122l_stop(struct us122l *us122l)
{
	struct list_head *p;

	list_for_each(p, &us122l->midi_list)
		snd_usbmidi_input_stop(p);

	usb_stream_stop(&us122l->sk);
	usb_stream_free(&us122l->sk);
}

static int us122l_set_sample_rate(struct usb_device *dev, int rate)
{
	unsigned int ep = 0x81;
	unsigned char data[3];
	int err;

	data[0] = rate;
	data[1] = rate >> 8;
	data[2] = rate >> 16;
	err = usb_control_msg_send(dev, 0, UAC_SET_CUR,
				   USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT,
				   UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep, data, 3,
				   1000, GFP_NOIO);
	if (err)
		dev_err(&dev->dev, "%d: cannot set freq %d to ep 0x%x\n",
			dev->devnum, rate, ep);
	return err;
}

static bool us122l_start(struct us122l *us122l,
			 unsigned int rate, unsigned int period_frames)
{
	struct list_head *p;
	int err;
	unsigned int use_packsize = 0;
	bool success = false;

	if (us122l->dev->speed == USB_SPEED_HIGH) {
		/* The us-122l's descriptor defaults to iso max_packsize 78,
		   which isn't needed for samplerates <= 48000.
		   Lets save some memory:
		*/
		switch (rate) {
		case 44100:
			use_packsize = 36;
			break;
		case 48000:
			use_packsize = 42;
			break;
		case 88200:
			use_packsize = 72;
			break;
		}
	}
	if (!usb_stream_new(&us122l->sk, us122l->dev, 1, 2,
			    rate, use_packsize, period_frames, 6))
		goto out;

	err = us122l_set_sample_rate(us122l->dev, rate);
	if (err < 0) {
		us122l_stop(us122l);
		dev_err(&us122l->dev->dev, "us122l_set_sample_rate error\n");
		goto out;
	}
	err = usb_stream_start(&us122l->sk);
	if (err < 0) {
		us122l_stop(us122l);
		dev_err(&us122l->dev->dev, "%s error %i\n", __func__, err);
		goto out;
	}
	list_for_each(p, &us122l->midi_list)
		snd_usbmidi_input_start(p);

Annotation

Implementation Notes