sound/usb/mixer_us16x08.c

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

File Facts

System
Linux kernel
Corpus path
sound/usb/mixer_us16x08.c
Extension
.c
Size
38888 bytes
Lines
1447
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 (store->comp_active_index & 0x20) {
			/* reset comp_index to left channel*/
			if (store->comp_index -
				store->comp_active_index > 1)
				store->comp_index =
				store->comp_active_index;

			ret = store->comp_index++ & 0x1F;
		} else {
			/* no stereo link */
			ret = store->comp_active_index;
		}
	} else {
		/* skip channels with no compressor active */
		while (store->comp_index <= SND_US16X08_MAX_CHANNELS
			&& !store->comp_store->val[
			COMP_STORE_IDX(SND_US16X08_ID_COMP_SWITCH)]
			[store->comp_index - 1]) {
			store->comp_index++;
		}
		ret = store->comp_index++;
		if (store->comp_index > SND_US16X08_MAX_CHANNELS)
			store->comp_index = 1;
	}
	return ret;
}

/* retrieve the meter level values from URB message */
static void get_meter_levels_from_urb(int s,
	struct snd_us16x08_meter_store *store,
	u8 *meter_urb)
{
	int val = MUC2(meter_urb, s) + (MUC3(meter_urb, s) << 8);
	int ch = MUB2(meter_urb, s) - 1;

	if (ch < 0)
		return;

	if (MUA0(meter_urb, s) == 0x61 && MUA1(meter_urb, s) == 0x02 &&
		MUA2(meter_urb, s) == 0x04 && MUB0(meter_urb, s) == 0x62) {
		if (ch < SND_US16X08_MAX_CHANNELS) {
			if (MUC0(meter_urb, s) == 0x72)
				store->meter_level[ch] = val;
			if (MUC0(meter_urb, s) == 0xb2)
				store->comp_level[ch] = val;
		}
	}
	if (MUA0(meter_urb, s) == 0x61 && MUA1(meter_urb, s) == 0x02 &&
		MUA2(meter_urb, s) == 0x02 && MUB0(meter_urb, s) == 0x62) {
		if (ch < ARRAY_SIZE(store->master_level))
			store->master_level[ch] = val;
	}
}

/* Function to retrieve current meter values from the device.
 *
 * The device needs to be polled for meter values with an initial
 * requests. It will return with a sequence of different meter value
 * packages. The first request (case 0:) initiate this meter response sequence.
 * After the third response, an additional request can be placed,
 * to retrieve compressor reduction level value for given channel. This round
 * trip channel selector will skip all inactive compressors.
 * A mixer can interrupt this round-trip by selecting one ore two (stereo-link)
 * specific channels.
 */
static int snd_us16x08_meter_get(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_value *ucontrol)
{
	int i, set;
	struct usb_mixer_elem_info *elem = snd_kcontrol_chip(kcontrol);
	struct snd_usb_audio *chip = elem->head.mixer->chip;
	struct snd_us16x08_meter_store *store = elem->private_data;
	u8 meter_urb[64] = {0};

	switch (kcontrol->private_value) {
	case 0: {
		char tmp[sizeof(mix_init_msg1)];

		memcpy(tmp, mix_init_msg1, sizeof(mix_init_msg1));
		snd_us16x08_send_urb(chip, tmp, 4);
		snd_us16x08_recv_urb(chip, meter_urb,
			sizeof(meter_urb));
		kcontrol->private_value++;
		break;
	}
	case 1:
		snd_us16x08_recv_urb(chip, meter_urb,
			sizeof(meter_urb));
		kcontrol->private_value++;
		break;

Annotation

Implementation Notes