aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2015-03-14 22:27:57 -0400
committerJohan Hedberg <johan.hedberg@intel.com>2015-03-15 03:55:51 -0400
commit96f1474af040a4ec267efe141cbf264891e67e5a (patch)
treed6338341eb2eb29eca832068d21820efdd1b343f /net/bluetooth
parentced85549c3a769dfb9d084bb8d6d9ca8075f8728 (diff)
Bluetooth: Add support for extended index management command
The Read Extended Contoller Index List command can be used for retrieving the complete list of local available controllers. This included configured, unconfigured and also AMP controllers. Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/mgmt.c80
1 files changed, 80 insertions, 0 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 56f49e9c4189..ff636bd9523b 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -96,6 +96,7 @@ static const u16 mgmt_commands[] = {
96 MGMT_OP_SET_EXTERNAL_CONFIG, 96 MGMT_OP_SET_EXTERNAL_CONFIG,
97 MGMT_OP_SET_PUBLIC_ADDRESS, 97 MGMT_OP_SET_PUBLIC_ADDRESS,
98 MGMT_OP_START_SERVICE_DISCOVERY, 98 MGMT_OP_START_SERVICE_DISCOVERY,
99 MGMT_OP_READ_EXT_INDEX_LIST,
99}; 100};
100 101
101static const u16 mgmt_events[] = { 102static const u16 mgmt_events[] = {
@@ -518,6 +519,82 @@ static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
518 return err; 519 return err;
519} 520}
520 521
522static int read_ext_index_list(struct sock *sk, struct hci_dev *hdev,
523 void *data, u16 data_len)
524{
525 struct mgmt_rp_read_ext_index_list *rp;
526 struct hci_dev *d;
527 size_t rp_len;
528 u16 count;
529 int err;
530
531 BT_DBG("sock %p", sk);
532
533 read_lock(&hci_dev_list_lock);
534
535 count = 0;
536 list_for_each_entry(d, &hci_dev_list, list) {
537 if (d->dev_type == HCI_BREDR || d->dev_type == HCI_AMP)
538 count++;
539 }
540
541 rp_len = sizeof(*rp) + (sizeof(rp->entry[0]) * count);
542 rp = kmalloc(rp_len, GFP_ATOMIC);
543 if (!rp) {
544 read_unlock(&hci_dev_list_lock);
545 return -ENOMEM;
546 }
547
548 count = 0;
549 list_for_each_entry(d, &hci_dev_list, list) {
550 if (hci_dev_test_flag(d, HCI_SETUP) ||
551 hci_dev_test_flag(d, HCI_CONFIG) ||
552 hci_dev_test_flag(d, HCI_USER_CHANNEL))
553 continue;
554
555 /* Devices marked as raw-only are neither configured
556 * nor unconfigured controllers.
557 */
558 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
559 continue;
560
561 if (d->dev_type == HCI_BREDR) {
562 if (hci_dev_test_flag(d, HCI_UNCONFIGURED))
563 rp->entry[count].type = 0x01;
564 else
565 rp->entry[count].type = 0x00;
566 } else if (d->dev_type == HCI_AMP) {
567 rp->entry[count].type = 0x02;
568 } else {
569 continue;
570 }
571
572 rp->entry[count].bus = d->bus;
573 rp->entry[count++].index = cpu_to_le16(d->id);
574 BT_DBG("Added hci%u", d->id);
575 }
576
577 rp->num_controllers = cpu_to_le16(count);
578 rp_len = sizeof(*rp) + (sizeof(rp->entry[0]) * count);
579
580 read_unlock(&hci_dev_list_lock);
581
582 /* If this command is called at least once, then all the
583 * default index and unconfigured index events are disabled
584 * and from now on only extended index events are used.
585 */
586 hci_sock_set_flag(sk, HCI_MGMT_EXT_INDEX_EVENTS);
587 hci_sock_clear_flag(sk, HCI_MGMT_INDEX_EVENTS);
588 hci_sock_clear_flag(sk, HCI_MGMT_UNCONF_INDEX_EVENTS);
589
590 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE,
591 MGMT_OP_READ_EXT_INDEX_LIST, 0, rp, rp_len);
592
593 kfree(rp);
594
595 return err;
596}
597
521static bool is_configured(struct hci_dev *hdev) 598static bool is_configured(struct hci_dev *hdev)
522{ 599{
523 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) && 600 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
@@ -6264,6 +6341,9 @@ static const struct hci_mgmt_handler mgmt_handlers[] = {
6264 HCI_MGMT_UNCONFIGURED }, 6341 HCI_MGMT_UNCONFIGURED },
6265 { start_service_discovery, MGMT_START_SERVICE_DISCOVERY_SIZE, 6342 { start_service_discovery, MGMT_START_SERVICE_DISCOVERY_SIZE,
6266 HCI_MGMT_VAR_LEN }, 6343 HCI_MGMT_VAR_LEN },
6344 { NULL },
6345 { read_ext_index_list, MGMT_READ_EXT_INDEX_LIST_SIZE,
6346 HCI_MGMT_NO_HDEV },
6267}; 6347};
6268 6348
6269int mgmt_control(struct hci_mgmt_chan *chan, struct sock *sk, 6349int mgmt_control(struct hci_mgmt_chan *chan, struct sock *sk,