sound/usb/validate.c

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

File Facts

System
Linux kernel
Corpus path
sound/usb/validate.c
Extension
.c
Size
10797 bytes
Lines
367
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 usb_desc_validator {
	unsigned char protocol;
	unsigned char type;
	bool (*func)(const void *p, const struct usb_desc_validator *v);
	size_t size;
};

#define UAC_VERSION_ALL		(unsigned char)(-1)

/* UAC1 only */
static bool validate_uac1_header(const void *p,
				 const struct usb_desc_validator *v)
{
	const struct uac1_ac_header_descriptor *d = p;

	return d->bLength >= sizeof(*d) &&
		d->bLength >= sizeof(*d) + d->bInCollection;
}

/* for mixer unit; covering all UACs */
static bool validate_mixer_unit(const void *p,
				const struct usb_desc_validator *v)
{
	const struct uac_mixer_unit_descriptor *d = p;
	size_t len;

	if (d->bLength < sizeof(*d) || !d->bNrInPins)
		return false;
	len = sizeof(*d) + d->bNrInPins;
	/* We can't determine the bitmap size only from this unit descriptor,
	 * so just check with the remaining length.
	 * The actual bitmap is checked at mixer unit parser.
	 */
	switch (v->protocol) {
	case UAC_VERSION_1:
	default:
		len += 2 + 1; /* wChannelConfig, iChannelNames */
		/* bmControls[n*m] */
		len += 1; /* iMixer */
		break;
	case UAC_VERSION_2:
		len += 4 + 1; /* bmChannelConfig, iChannelNames */
		/* bmMixerControls[n*m] */
		len += 1 + 1; /* bmControls, iMixer */
		break;
	case UAC_VERSION_3:
		len += 2; /* wClusterDescrID */
		/* bmMixerControls[n*m] */
		break;
	}
	return d->bLength >= len;
}

/* both for processing and extension units; covering all UACs */
static bool validate_processing_unit(const void *p,
				     const struct usb_desc_validator *v)
{
	const struct uac_processing_unit_descriptor *d = p;
	const unsigned char *hdr = p;
	size_t len, m;

	if (d->bLength < sizeof(*d))
		return false;
	len = sizeof(*d) + d->bNrInPins;
	if (d->bLength < len)
		return false;
	switch (v->protocol) {
	case UAC_VERSION_1:
	default:
		/* bNrChannels, wChannelConfig, iChannelNames */
		len += 1 + 2 + 1;
		if (d->bLength < len + 1) /* bControlSize */
			return false;
		m = hdr[len];
		len += 1 + m + 1; /* bControlSize, bmControls, iProcessing */
		break;
	case UAC_VERSION_2:
		/* bNrChannels, bmChannelConfig, iChannelNames */
		len += 1 + 4 + 1;
		if (v->type == UAC2_PROCESSING_UNIT_V2)
			len += 2; /* bmControls -- 2 bytes for PU */
		else
			len += 1; /* bmControls -- 1 byte for EU */
		len += 1; /* iProcessing */
		break;
	case UAC_VERSION_3:
		/* wProcessingDescrStr, bmControls */
		len += 2 + 4;
		break;
	}

Annotation

Implementation Notes