sound/usb/usx2y/usb_stream.c

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

File Facts

System
Linux kernel
Corpus path
sound/usb/usx2y/usb_stream.c
Extension
.c
Size
18925 bytes
Lines
776
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 (il <= ol) {
			memcpy(o, i, il);
			o += il;
			ol -= il;
		} else {
			memcpy(o, i, ol);
			singen_6pack(o, ol);
			o = s->playback_to;
			memcpy(o, i + ol, il - ol);
			o += il - ol;
			ol = s->period_size - s->playback1st_size;
		}
		l += il;
	}
	if (iu == sk->completed_inurb) {
		if (l != s->period_size)
			dev_dbg(&sk->dev->dev, "%s:%i %i\n", __func__, __LINE__,
				l/(int)s->cfg.frame_size);

		return;
	}
second:
	iu = sk->completed_inurb;
	id = iu->iso_frame_desc;
	p = 0;
	goto loop;

}
#else
static void loop_back(struct usb_stream *s)
{
}
#endif

static void stream_idle(struct usb_stream_kernel *sk,
			struct urb *inurb, struct urb *outurb)
{
	struct usb_stream *s = sk->s;
	int l, p;
	int insize = s->idle_insize;
	int urb_size = 0;

	s->inpacket_split = s->next_inpacket_split;
	s->inpacket_split_at = s->next_inpacket_split_at;
	s->next_inpacket_split = -1;
	s->next_inpacket_split_at = 0;

	for (p = 0; p < inurb->number_of_packets; ++p) {
		struct usb_iso_packet_descriptor *id = inurb->iso_frame_desc;

		l = id[p].actual_length;
		if (unlikely(l == 0 || id[p].status)) {
			dev_warn(&sk->dev->dev, "%s: underrun, status=%u\n",
				 __func__, id[p].status);
			goto err_out;
		}
		s->inpacket_head++;
		s->inpacket_head %= s->inpackets;
		if (s->inpacket_split == -1)
			s->inpacket_split = s->inpacket_head;

		s->inpacket[s->inpacket_head].offset =
			id[p].offset + (inurb->transfer_buffer - (void *)s);
		s->inpacket[s->inpacket_head].length = l;
		if (insize + l > s->period_size &&
		    s->next_inpacket_split == -1) {
			s->next_inpacket_split = s->inpacket_head;
			s->next_inpacket_split_at = s->period_size - insize;
		}
		insize += l;
		urb_size += l;
	}
	s->idle_insize += urb_size - s->period_size;
	if (s->idle_insize < 0) {
		dev_warn(&sk->dev->dev, "%s error: %i\n", __func__,
			 (s->idle_insize)/(int)s->cfg.frame_size);
		goto err_out;
	}
	s->insize_done += urb_size;

	l = s->idle_outsize;
	s->outpacket[0].offset = (sk->idle_outurb->transfer_buffer -
				  sk->write_page) - l;

	if (usb_stream_prepare_playback(sk, inurb) < 0)
		goto err_out;

	s->outpacket[0].length = sk->idle_outurb->transfer_buffer_length + l;
	s->outpacket[1].offset = sk->completed_outurb->transfer_buffer -
		sk->write_page;

Annotation

Implementation Notes