sound/usb/usx2y/usbusx2y.c

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

File Facts

System
Linux kernel
Corpus path
sound/usb/usx2y/usbusx2y.c
Extension
.c
Size
13192 bytes
Lines
484
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 (us428ctls->ctl_snapshot_last == -2) {
			diff = 0;
			memcpy(usx2y->in04_last, usx2y->in04_buf, sizeof(usx2y->in04_last));
			us428ctls->ctl_snapshot_last = -1;
		} else {
			for (i = 0; i < 21; i++) {
				if (usx2y->in04_last[i] != ((char *)usx2y->in04_buf)[i]) {
					if (diff < 0)
						diff = i;
					usx2y->in04_last[i] = ((char *)usx2y->in04_buf)[i];
				}
			}
		}
		if (diff >= 0) {
			n = us428ctls->ctl_snapshot_last + 1;
			if (n >= N_US428_CTL_BUFS || n < 0)
				n = 0;
			memcpy(us428ctls->ctl_snapshot + n, usx2y->in04_buf, sizeof(us428ctls->ctl_snapshot[0]));
			us428ctls->ctl_snapshot_differs_at[n] = diff;
			us428ctls->ctl_snapshot_last = n;
			wake_up(&usx2y->us428ctls_wait_queue_head);
		}
	}

	if (usx2y->us04) {
		if (!usx2y->us04->submitted) {
			do {
				err = usb_submit_urb(usx2y->us04->urb[usx2y->us04->submitted++], GFP_ATOMIC);
			} while (!err && usx2y->us04->submitted < usx2y->us04->len);
		}
	} else {
		while (us428ctls &&
		       us428ctls->p4out_last >= 0 &&
		       us428ctls->p4out_last < N_US428_P4OUT_BUFS &&
		       us428ctls->p4out_last != us428ctls->p4out_sent) {
			for (j = 0; j < URBS_ASYNC_SEQ && !err; ++j) {
				if (!usx2y->as04.urb[j]->status) {
					send = us428ctls->p4out_sent + 1;
					if (send >= N_US428_P4OUT_BUFS)
						send = 0;

					p4out = us428ctls->p4out + send;
					len = p4out->type == ELT_LIGHT ?
						sizeof(struct us428_lights) : 5;
					memcpy(usx2y->as04.urb[j]->transfer_buffer,
					       &p4out->val.vol, len);
					usx2y->as04.urb[j]->transfer_buffer_length = len;
					err = usb_submit_urb(usx2y->as04.urb[j], GFP_ATOMIC);
					if (!err)
						us428ctls->p4out_sent = send;

					break;
				}
			}
			if (j >= URBS_ASYNC_SEQ || err)
				break;
		}
	}

	if (err)
		dev_err(&urb->dev->dev, "in04_int() usb_submit_urb err=%i\n", err);

	urb->dev = usx2y->dev;
	usb_submit_urb(urb, GFP_ATOMIC);
}

/*
 * Prepare some urbs
 */
int usx2y_async_seq04_init(struct usx2ydev *usx2y)
{
	int	err = 0, i;

	if (WARN_ON(usx2y->as04.buffer))
		return -EBUSY;

	usx2y->as04.buffer = kmalloc_array(URBS_ASYNC_SEQ,
					   URB_DATA_LEN_ASYNC_SEQ, GFP_KERNEL);
	if (!usx2y->as04.buffer) {
		err = -ENOMEM;
	} else {
		for (i = 0; i < URBS_ASYNC_SEQ; ++i) {
			usx2y->as04.urb[i] = usb_alloc_urb(0, GFP_KERNEL);
			if (!usx2y->as04.urb[i]) {
				err = -ENOMEM;
				break;
			}
			usb_fill_bulk_urb(usx2y->as04.urb[i], usx2y->dev,
					  usb_sndbulkpipe(usx2y->dev, 0x04),
					  usx2y->as04.buffer + URB_DATA_LEN_ASYNC_SEQ * i, 0,

Annotation

Implementation Notes