|
@@ -83,6 +83,7 @@ struct mixer_build {
|
|
|
unsigned char *buffer;
|
|
unsigned char *buffer;
|
|
|
unsigned int buflen;
|
|
unsigned int buflen;
|
|
|
DECLARE_BITMAP(unitbitmap, MAX_ID_ELEMS);
|
|
DECLARE_BITMAP(unitbitmap, MAX_ID_ELEMS);
|
|
|
|
|
+ DECLARE_BITMAP(termbitmap, MAX_ID_ELEMS);
|
|
|
struct usb_audio_term oterm;
|
|
struct usb_audio_term oterm;
|
|
|
const struct usbmix_name_map *map;
|
|
const struct usbmix_name_map *map;
|
|
|
const struct usbmix_selector_map *selector_map;
|
|
const struct usbmix_selector_map *selector_map;
|
|
@@ -788,16 +789,25 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state,
|
|
|
* parse the source unit recursively until it reaches to a terminal
|
|
* parse the source unit recursively until it reaches to a terminal
|
|
|
* or a branched unit.
|
|
* or a branched unit.
|
|
|
*/
|
|
*/
|
|
|
-static int check_input_term(struct mixer_build *state, int id,
|
|
|
|
|
|
|
+static int __check_input_term(struct mixer_build *state, int id,
|
|
|
struct usb_audio_term *term)
|
|
struct usb_audio_term *term)
|
|
|
{
|
|
{
|
|
|
int protocol = state->mixer->protocol;
|
|
int protocol = state->mixer->protocol;
|
|
|
int err;
|
|
int err;
|
|
|
void *p1;
|
|
void *p1;
|
|
|
|
|
+ unsigned char *hdr;
|
|
|
|
|
|
|
|
memset(term, 0, sizeof(*term));
|
|
memset(term, 0, sizeof(*term));
|
|
|
- while ((p1 = find_audio_control_unit(state, id)) != NULL) {
|
|
|
|
|
- unsigned char *hdr = p1;
|
|
|
|
|
|
|
+ for (;;) {
|
|
|
|
|
+ /* a loop in the terminal chain? */
|
|
|
|
|
+ if (test_and_set_bit(id, state->termbitmap))
|
|
|
|
|
+ return -EINVAL;
|
|
|
|
|
+
|
|
|
|
|
+ p1 = find_audio_control_unit(state, id);
|
|
|
|
|
+ if (!p1)
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ hdr = p1;
|
|
|
term->id = id;
|
|
term->id = id;
|
|
|
|
|
|
|
|
if (protocol == UAC_VERSION_1 || protocol == UAC_VERSION_2) {
|
|
if (protocol == UAC_VERSION_1 || protocol == UAC_VERSION_2) {
|
|
@@ -815,7 +825,7 @@ static int check_input_term(struct mixer_build *state, int id,
|
|
|
|
|
|
|
|
/* call recursively to verify that the
|
|
/* call recursively to verify that the
|
|
|
* referenced clock entity is valid */
|
|
* referenced clock entity is valid */
|
|
|
- err = check_input_term(state, d->bCSourceID, term);
|
|
|
|
|
|
|
+ err = __check_input_term(state, d->bCSourceID, term);
|
|
|
if (err < 0)
|
|
if (err < 0)
|
|
|
return err;
|
|
return err;
|
|
|
|
|
|
|
@@ -849,7 +859,7 @@ static int check_input_term(struct mixer_build *state, int id,
|
|
|
case UAC2_CLOCK_SELECTOR: {
|
|
case UAC2_CLOCK_SELECTOR: {
|
|
|
struct uac_selector_unit_descriptor *d = p1;
|
|
struct uac_selector_unit_descriptor *d = p1;
|
|
|
/* call recursively to retrieve the channel info */
|
|
/* call recursively to retrieve the channel info */
|
|
|
- err = check_input_term(state, d->baSourceID[0], term);
|
|
|
|
|
|
|
+ err = __check_input_term(state, d->baSourceID[0], term);
|
|
|
if (err < 0)
|
|
if (err < 0)
|
|
|
return err;
|
|
return err;
|
|
|
term->type = UAC3_SELECTOR_UNIT << 16; /* virtual type */
|
|
term->type = UAC3_SELECTOR_UNIT << 16; /* virtual type */
|
|
@@ -912,7 +922,7 @@ static int check_input_term(struct mixer_build *state, int id,
|
|
|
|
|
|
|
|
/* call recursively to verify that the
|
|
/* call recursively to verify that the
|
|
|
* referenced clock entity is valid */
|
|
* referenced clock entity is valid */
|
|
|
- err = check_input_term(state, d->bCSourceID, term);
|
|
|
|
|
|
|
+ err = __check_input_term(state, d->bCSourceID, term);
|
|
|
if (err < 0)
|
|
if (err < 0)
|
|
|
return err;
|
|
return err;
|
|
|
|
|
|
|
@@ -963,7 +973,7 @@ static int check_input_term(struct mixer_build *state, int id,
|
|
|
case UAC3_CLOCK_SELECTOR: {
|
|
case UAC3_CLOCK_SELECTOR: {
|
|
|
struct uac_selector_unit_descriptor *d = p1;
|
|
struct uac_selector_unit_descriptor *d = p1;
|
|
|
/* call recursively to retrieve the channel info */
|
|
/* call recursively to retrieve the channel info */
|
|
|
- err = check_input_term(state, d->baSourceID[0], term);
|
|
|
|
|
|
|
+ err = __check_input_term(state, d->baSourceID[0], term);
|
|
|
if (err < 0)
|
|
if (err < 0)
|
|
|
return err;
|
|
return err;
|
|
|
term->type = UAC3_SELECTOR_UNIT << 16; /* virtual type */
|
|
term->type = UAC3_SELECTOR_UNIT << 16; /* virtual type */
|
|
@@ -979,7 +989,7 @@ static int check_input_term(struct mixer_build *state, int id,
|
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
/* call recursively to retrieve the channel info */
|
|
/* call recursively to retrieve the channel info */
|
|
|
- err = check_input_term(state, d->baSourceID[0], term);
|
|
|
|
|
|
|
+ err = __check_input_term(state, d->baSourceID[0], term);
|
|
|
if (err < 0)
|
|
if (err < 0)
|
|
|
return err;
|
|
return err;
|
|
|
|
|
|
|
@@ -997,6 +1007,15 @@ static int check_input_term(struct mixer_build *state, int id,
|
|
|
return -ENODEV;
|
|
return -ENODEV;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+
|
|
|
|
|
+static int check_input_term(struct mixer_build *state, int id,
|
|
|
|
|
+ struct usb_audio_term *term)
|
|
|
|
|
+{
|
|
|
|
|
+ memset(term, 0, sizeof(*term));
|
|
|
|
|
+ memset(state->termbitmap, 0, sizeof(state->termbitmap));
|
|
|
|
|
+ return __check_input_term(state, id, term);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
/*
|
|
/*
|
|
|
* Feature Unit
|
|
* Feature Unit
|
|
|
*/
|
|
*/
|