return 0;
 }
 
+/* get the connectors status and report it as boolean type */
+static int mixer_ctl_connector_get(struct snd_kcontrol *kcontrol,
+                                  struct snd_ctl_elem_value *ucontrol)
+{
+       struct usb_mixer_elem_info *cval = kcontrol->private_data;
+       struct snd_usb_audio *chip = cval->head.mixer->chip;
+       int idx = 0, validx, ret, val;
+
+       validx = cval->control << 8 | 0;
+
+       ret = snd_usb_lock_shutdown(chip) ? -EIO : 0;
+       if (ret)
+               goto error;
+
+       idx = snd_usb_ctrl_intf(chip) | (cval->head.id << 8);
+       if (cval->head.mixer->protocol == UAC_VERSION_2) {
+               struct uac2_connectors_ctl_blk uac2_conn;
+
+               ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), UAC2_CS_CUR,
+                                     USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
+                                     validx, idx, &uac2_conn, sizeof(uac2_conn));
+               val = !!uac2_conn.bNrChannels;
+       } else { /* UAC_VERSION_3 */
+               struct uac3_insertion_ctl_blk uac3_conn;
+
+               ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), UAC2_CS_CUR,
+                                     USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
+                                     validx, idx, &uac3_conn, sizeof(uac3_conn));
+               val = !!uac3_conn.bmConInserted;
+       }
+
+       snd_usb_unlock_shutdown(chip);
+
+       if (ret < 0) {
+error:
+               usb_audio_err(chip,
+                       "cannot get connectors status: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
+                       UAC_GET_CUR, validx, idx, cval->val_type);
+               return ret;
+       }
+
+       ucontrol->value.integer.value[0] = val;
+       return 0;
+}
+
 static struct snd_kcontrol_new usb_feature_unit_ctl = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "", /* will be filled later manually */
        .put = NULL,
 };
 
+static const struct snd_kcontrol_new usb_connector_ctl_ro = {
+       .iface = SNDRV_CTL_ELEM_IFACE_CARD,
+       .name = "", /* will be filled later manually */
+       .access = SNDRV_CTL_ELEM_ACCESS_READ,
+       .info = snd_ctl_boolean_mono_info,
+       .get = mixer_ctl_connector_get,
+       .put = NULL,
+};
+
 /*
  * This symbol is exported in order to allow the mixer quirks to
  * hook up to the standard feature unit control mechanism
                return;
        snd_usb_mixer_elem_init_std(&cval->head, state->mixer, term->id);
        /*
-        * The first byte from reading the UAC2_TE_CONNECTOR control returns the
-        * number of channels connected.  This boolean ctl will simply report
-        * if any channels are connected or not.
-        * (Audio20_final.pdf Table 5-10: Connector Control CUR Parameter Block)
+        * UAC2: The first byte from reading the UAC2_TE_CONNECTOR control returns the
+        * number of channels connected.
+        *
+        * UAC3: The first byte specifies size of bitmap for the inserted controls. The
+        * following byte(s) specifies which connectors are inserted.
+        *
+        * This boolean ctl will simply report if any channels are connected
+        * or not.
         */
-       cval->control = UAC2_TE_CONNECTOR;
+       if (state->mixer->protocol == UAC_VERSION_2)
+               cval->control = UAC2_TE_CONNECTOR;
+       else /* UAC_VERSION_3 */
+               cval->control = UAC3_TE_INSERTION;
+
        cval->val_type = USB_MIXER_BOOLEAN;
        cval->channels = 1; /* report true if any channel is connected */
        cval->min = 0;
        cval->max = 1;
-       kctl = snd_ctl_new1(&usb_bool_master_control_ctl_ro, cval);
+       kctl = snd_ctl_new1(&usb_connector_ctl_ro, cval);
        if (!kctl) {
                usb_audio_err(state->chip, "cannot malloc kcontrol\n");
                kfree(cval);
                                      void *raw_desc)
 {
        struct usb_audio_term iterm;
-       struct uac2_input_terminal_descriptor *d = raw_desc;
+       unsigned int control, bmctls, term_id;
 
-       check_input_term(state, d->bTerminalID, &iterm);
        if (state->mixer->protocol == UAC_VERSION_2) {
-               /* Check for jack detection. */
-               if (uac_v2v3_control_is_readable(le16_to_cpu(d->bmControls),
-                                                UAC2_TE_CONNECTOR)) {
-                       build_connector_control(state, &iterm, true);
-               }
+               struct uac2_input_terminal_descriptor *d_v2 = raw_desc;
+               control = UAC2_TE_CONNECTOR;
+               term_id = d_v2->bTerminalID;
+               bmctls = le16_to_cpu(d_v2->bmControls);
+       } else if (state->mixer->protocol == UAC_VERSION_3) {
+               struct uac3_input_terminal_descriptor *d_v3 = raw_desc;
+               control = UAC3_TE_INSERTION;
+               term_id = d_v3->bTerminalID;
+               bmctls = le32_to_cpu(d_v3->bmControls);
+       } else {
+               return 0; /* UAC1. No Insertion control */
        }
+
+       check_input_term(state, term_id, &iterm);
+
+       /* Check for jack detection. */
+       if (uac_v2v3_control_is_readable(bmctls, control))
+               build_connector_control(state, &iterm, true);
+
        return 0;
 }
 
        } else { /* UAC_VERSION_3 */
                switch (p1[2]) {
                case UAC_INPUT_TERMINAL:
-                       return 0; /* NOP */
+                       return parse_audio_input_terminal(state, unitid, p1);
                case UAC3_MIXER_UNIT:
                        return parse_audio_mixer_unit(state, unitid, p1);
                case UAC3_CLOCK_SOURCE:
                        err = parse_audio_unit(&state, desc->bCSourceID);
                        if (err < 0 && err != -EINVAL)
                                return err;
+
+                       if (uac_v2v3_control_is_readable(le32_to_cpu(desc->bmControls),
+                                                        UAC3_TE_INSERTION)) {
+                               build_connector_control(&state, &state.oterm,
+                                                       false);
+                       }
                }
        }