if (d->bLength < sizeof(*d) || !d->bNrInPins) returnfalse;
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 */ staticbool validate_processing_unit(constvoid *p, conststruct usb_desc_validator *v)
{ conststruct uac_processing_unit_descriptor *d = p; constunsignedchar *hdr = p;
size_t len, m;
if (d->bLength < sizeof(*d)) returnfalse;
len = sizeof(*d) + d->bNrInPins; if (d->bLength < len) returnfalse; switch (v->protocol) { case UAC_VERSION_1: default: /* bNrChannels, wChannelConfig, iChannelNames */
len += 1 + 2 + 1; if (d->bLength < len + 1) /* bControlSize */ returnfalse;
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;
} if (d->bLength < len) returnfalse;
switch (v->protocol) { case UAC_VERSION_1: default: if (v->type == UAC1_EXTENSION_UNIT) returntrue; /* OK */ switch (le16_to_cpu(d->wProcessType)) { case UAC_PROCESS_UP_DOWNMIX: case UAC_PROCESS_DOLBY_PROLOGIC: if (d->bLength < len + 1) /* bNrModes */ returnfalse;
m = hdr[len];
len += 1 + m * 2; /* bNrModes, waModes(n) */ break; default: break;
} break; case UAC_VERSION_2: if (v->type == UAC2_EXTENSION_UNIT_V2) returntrue; /* OK */ switch (le16_to_cpu(d->wProcessType)) { case UAC2_PROCESS_UP_DOWNMIX: case UAC2_PROCESS_DOLBY_PROLOCIC: /* SiC! */ if (d->bLength < len + 1) /* bNrModes */ returnfalse;
m = hdr[len];
len += 1 + m * 4; /* bNrModes, daModes(n) */ break; default: break;
} break; case UAC_VERSION_3: if (v->type == UAC3_EXTENSION_UNIT) {
len += 2; /* wClusterDescrID */ break;
} switch (le16_to_cpu(d->wProcessType)) { case UAC3_PROCESS_UP_DOWNMIX: if (d->bLength < len + 1) /* bNrModes */ returnfalse;
m = hdr[len];
len += 1 + m * 2; /* bNrModes, waClusterDescrID(n) */ break; case UAC3_PROCESS_MULTI_FUNCTION:
len += 2 + 4; /* wClusterDescrID, bmAlgorighms */ break; default: break;
} break;
} if (d->bLength < len) returnfalse;
returntrue;
}
/* both for selector and clock selector units; covering all UACs */ staticbool validate_selector_unit(constvoid *p, conststruct usb_desc_validator *v)
{ conststruct uac_selector_unit_descriptor *d = p;
size_t len;
if (d->bLength < sizeof(*d)) returnfalse;
len = sizeof(*d) + d->bNrInPins; switch (v->protocol) { case UAC_VERSION_1: default:
len += 1; /* iSelector */ break; case UAC_VERSION_2:
len += 1 + 1; /* bmControls, iSelector */ break; case UAC_VERSION_3:
len += 4 + 2; /* bmControls, wSelectorDescrStr */ break;
} return d->bLength >= len;
}
/* UAC2 */
FIXED(UAC_VERSION_2, UAC_HEADER, struct uac2_ac_header_descriptor),
FIXED(UAC_VERSION_2, UAC_INPUT_TERMINAL, struct uac2_input_terminal_descriptor),
FIXED(UAC_VERSION_2, UAC_OUTPUT_TERMINAL, struct uac2_output_terminal_descriptor),
FUNC(UAC_VERSION_2, UAC_MIXER_UNIT, validate_mixer_unit),
FUNC(UAC_VERSION_2, UAC_SELECTOR_UNIT, validate_selector_unit),
FUNC(UAC_VERSION_2, UAC_FEATURE_UNIT, validate_uac2_feature_unit), /* just a stop-gap, it should be a proper function for the array * once if the unit is really parsed/used
*/
FIXED(UAC_VERSION_2, UAC2_EFFECT_UNIT, struct uac2_effect_unit_descriptor),
FUNC(UAC_VERSION_2, UAC2_PROCESSING_UNIT_V2, validate_processing_unit),
FUNC(UAC_VERSION_2, UAC2_EXTENSION_UNIT_V2, validate_processing_unit),
FIXED(UAC_VERSION_2, UAC2_CLOCK_SOURCE, struct uac_clock_source_descriptor),
FUNC(UAC_VERSION_2, UAC2_CLOCK_SELECTOR, validate_selector_unit),
FIXED(UAC_VERSION_2, UAC2_CLOCK_MULTIPLIER, struct uac_clock_multiplier_descriptor), /* UAC_VERSION_2, UAC2_SAMPLE_RATE_CONVERTER: not implemented yet */
/* Validate the given unit descriptor, return true if it's OK */ staticbool validate_desc(unsignedchar *hdr, int protocol, conststruct usb_desc_validator *v)
{ if (hdr[1] != USB_DT_CS_INTERFACE) returntrue; /* don't care */
for (; v->type; v++) { if (v->type == hdr[2] &&
(v->protocol == UAC_VERSION_ALL ||
v->protocol == protocol)) { if (v->func) return v->func(hdr, v); /* check for the fixed size */ return hdr[0] >= v->size;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.