MGMT_OP_ADD_DEVICE,
        MGMT_OP_REMOVE_DEVICE,
        MGMT_OP_LOAD_CONN_PARAM,
+       MGMT_OP_READ_UNCONF_INDEX_LIST,
 };
 
 static const u16 mgmt_events[] = {
 
        count = 0;
        list_for_each_entry(d, &hci_dev_list, list) {
-               if (d->dev_type == HCI_BREDR)
+               if (d->dev_type == HCI_BREDR &&
+                   !test_bit(HCI_UNCONFIGURED, &d->dev_flags))
                        count++;
        }
 
 
        count = 0;
        list_for_each_entry(d, &hci_dev_list, list) {
-               if (test_bit(HCI_SETUP, &d->dev_flags))
+               if (test_bit(HCI_SETUP, &d->dev_flags) ||
+                   test_bit(HCI_USER_CHANNEL, &d->dev_flags))
                        continue;
 
-               if (test_bit(HCI_USER_CHANNEL, &d->dev_flags))
-                       continue;
-
-               if (test_bit(HCI_UNCONFIGURED, &d->dev_flags))
+               /* Devices marked as raw-only are neither configured
+                * nor unconfigured controllers.
+                */
+               if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
                        continue;
 
-               if (d->dev_type == HCI_BREDR) {
+               if (d->dev_type == HCI_BREDR &&
+                   !test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
                        rp->index[count++] = cpu_to_le16(d->id);
                        BT_DBG("Added hci%u", d->id);
                }
        return err;
 }
 
+static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
+                                 void *data, u16 data_len)
+{
+       struct mgmt_rp_read_unconf_index_list *rp;
+       struct hci_dev *d;
+       size_t rp_len;
+       u16 count;
+       int err;
+
+       BT_DBG("sock %p", sk);
+
+       read_lock(&hci_dev_list_lock);
+
+       count = 0;
+       list_for_each_entry(d, &hci_dev_list, list) {
+               if (d->dev_type == HCI_BREDR &&
+                   test_bit(HCI_UNCONFIGURED, &d->dev_flags))
+                       count++;
+       }
+
+       rp_len = sizeof(*rp) + (2 * count);
+       rp = kmalloc(rp_len, GFP_ATOMIC);
+       if (!rp) {
+               read_unlock(&hci_dev_list_lock);
+               return -ENOMEM;
+       }
+
+       count = 0;
+       list_for_each_entry(d, &hci_dev_list, list) {
+               if (test_bit(HCI_SETUP, &d->dev_flags) ||
+                   test_bit(HCI_USER_CHANNEL, &d->dev_flags))
+                       continue;
+
+               /* Devices marked as raw-only are neither configured
+                * nor unconfigured controllers.
+                */
+               if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
+                       continue;
+
+               if (d->dev_type == HCI_BREDR &&
+                   test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
+                       rp->index[count++] = cpu_to_le16(d->id);
+                       BT_DBG("Added hci%u", d->id);
+               }
+       }
+
+       rp->num_controllers = cpu_to_le16(count);
+       rp_len = sizeof(*rp) + (2 * count);
+
+       read_unlock(&hci_dev_list_lock);
+
+       err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_UNCONF_INDEX_LIST,
+                          0, rp, rp_len);
+
+       kfree(rp);
+
+       return err;
+}
+
 static u32 get_supported_settings(struct hci_dev *hdev)
 {
        u32 settings = 0;
        { get_clock_info,         false, MGMT_GET_CLOCK_INFO_SIZE },
        { add_device,             false, MGMT_ADD_DEVICE_SIZE },
        { remove_device,          false, MGMT_REMOVE_DEVICE_SIZE },
-       { load_conn_param,        true, MGMT_LOAD_CONN_PARAM_SIZE },
+       { load_conn_param,        true,  MGMT_LOAD_CONN_PARAM_SIZE },
+       { read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE },
 };
 
 int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
                goto done;
        }
 
-       if ((hdev && opcode < MGMT_OP_READ_INFO) ||
-           (!hdev && opcode >= MGMT_OP_READ_INFO)) {
+       if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST ||
+                    opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) {
+               err = cmd_status(sk, index, opcode,
+                                MGMT_STATUS_INVALID_INDEX);
+               goto done;
+       }
+
+       if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST &&
+                     opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) {
                err = cmd_status(sk, index, opcode,
                                 MGMT_STATUS_INVALID_INDEX);
                goto done;