OSDN Git Service

Merge android-4.4.191 (6da3fbc) into msm-4.4
[sagit-ice-cold/kernel_xiaomi_msm8998.git] / sound / usb / mixer.c
index de8fe20..ddf6620 100644 (file)
@@ -82,6 +82,7 @@ struct mixer_build {
        unsigned char *buffer;
        unsigned int buflen;
        DECLARE_BITMAP(unitbitmap, MAX_ID_ELEMS);
+       DECLARE_BITMAP(termbitmap, MAX_ID_ELEMS);
        struct usb_audio_term oterm;
        const struct usbmix_name_map *map;
        const struct usbmix_selector_map *selector_map;
@@ -721,15 +722,24 @@ static int get_term_name(struct mixer_build *state, struct usb_audio_term *iterm
  * parse the source unit recursively until it reaches to a terminal
  * 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)
 {
        int err;
        void *p1;
+       unsigned char *hdr;
 
        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;
                switch (hdr[2]) {
                case UAC_INPUT_TERMINAL:
@@ -744,7 +754,7 @@ static int check_input_term(struct mixer_build *state, int id,
 
                                /* call recursively to verify that the
                                 * referenced clock entity is valid */
-                               err = check_input_term(state, d->bCSourceID, term);
+                               err = __check_input_term(state, d->bCSourceID, term);
                                if (err < 0)
                                        return err;
 
@@ -759,8 +769,8 @@ static int check_input_term(struct mixer_build *state, int id,
                        } else { /* UAC_VERSION_3 */
                                struct uac3_input_terminal_descriptor *d = p1;
 
-                               err = check_input_term(state,
-                                                       d->bCSourceID, term);
+                               err = __check_input_term(state,
+                                                        d->bCSourceID, term);
                                if (err < 0)
                                        return err;
 
@@ -817,8 +827,8 @@ static int check_input_term(struct mixer_build *state, int id,
                        } else {
                                struct uac_selector_unit_descriptor *d = p1;
                                /* call recursively to retrieve channel info */
-                               err = check_input_term(state,
-                                                       d->baSourceID[0], term);
+                               err = __check_input_term(state,
+                                                        d->baSourceID[0], term);
                                if (err < 0)
                                        return err;
                                /* virtual type */
@@ -881,6 +891,15 @@ static int check_input_term(struct mixer_build *state, int id,
        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
  */
@@ -1886,7 +1905,8 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid,
                    NUM_CHANNELS_MONO : NUM_CHANNELS_STEREO;
        } else {
                if (desc->bLength < 11 || !(input_pins = desc->bNrInPins) ||
-               !(num_outs = uac_mixer_unit_bNrChannels(desc))) {
+                   desc->bLength < sizeof(*desc) + desc->bNrInPins ||
+                   !(num_outs = uac_mixer_unit_bNrChannels(desc))) {
                        usb_audio_err(state->chip,
                                      "invalid MIXER UNIT descriptor %d\n",
                                      unitid);