aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/mgmt.c
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2014-07-02 16:10:52 -0400
committerMarcel Holtmann <marcel@holtmann.org>2014-07-03 11:42:58 -0400
commit73d1df2a7a1036a1f000e5f0ece6ade3e082b854 (patch)
tree6f810f637d3ea3d97b2ee20fcedf66e2d6570fbb /net/bluetooth/mgmt.c
parentedd3896bc41059fc064c4ec76da004a57203d88e (diff)
Bluetooth: Add support for Read Unconfigured Index List command
This command allows to get the list of currently known controller that are in unconfigured state. Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Diffstat (limited to 'net/bluetooth/mgmt.c')
-rw-r--r--net/bluetooth/mgmt.c91
1 files changed, 81 insertions, 10 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 1a78d26b0049..325bb8136d2c 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -89,6 +89,7 @@ static const u16 mgmt_commands[] = {
89 MGMT_OP_ADD_DEVICE, 89 MGMT_OP_ADD_DEVICE,
90 MGMT_OP_REMOVE_DEVICE, 90 MGMT_OP_REMOVE_DEVICE,
91 MGMT_OP_LOAD_CONN_PARAM, 91 MGMT_OP_LOAD_CONN_PARAM,
92 MGMT_OP_READ_UNCONF_INDEX_LIST,
92}; 93};
93 94
94static const u16 mgmt_events[] = { 95static const u16 mgmt_events[] = {
@@ -336,7 +337,8 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
336 337
337 count = 0; 338 count = 0;
338 list_for_each_entry(d, &hci_dev_list, list) { 339 list_for_each_entry(d, &hci_dev_list, list) {
339 if (d->dev_type == HCI_BREDR) 340 if (d->dev_type == HCI_BREDR &&
341 !test_bit(HCI_UNCONFIGURED, &d->dev_flags))
340 count++; 342 count++;
341 } 343 }
342 344
@@ -349,16 +351,18 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
349 351
350 count = 0; 352 count = 0;
351 list_for_each_entry(d, &hci_dev_list, list) { 353 list_for_each_entry(d, &hci_dev_list, list) {
352 if (test_bit(HCI_SETUP, &d->dev_flags)) 354 if (test_bit(HCI_SETUP, &d->dev_flags) ||
355 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
353 continue; 356 continue;
354 357
355 if (test_bit(HCI_USER_CHANNEL, &d->dev_flags)) 358 /* Devices marked as raw-only are neither configured
356 continue; 359 * nor unconfigured controllers.
357 360 */
358 if (test_bit(HCI_UNCONFIGURED, &d->dev_flags)) 361 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
359 continue; 362 continue;
360 363
361 if (d->dev_type == HCI_BREDR) { 364 if (d->dev_type == HCI_BREDR &&
365 !test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
362 rp->index[count++] = cpu_to_le16(d->id); 366 rp->index[count++] = cpu_to_le16(d->id);
363 BT_DBG("Added hci%u", d->id); 367 BT_DBG("Added hci%u", d->id);
364 } 368 }
@@ -377,6 +381,65 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
377 return err; 381 return err;
378} 382}
379 383
384static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
385 void *data, u16 data_len)
386{
387 struct mgmt_rp_read_unconf_index_list *rp;
388 struct hci_dev *d;
389 size_t rp_len;
390 u16 count;
391 int err;
392
393 BT_DBG("sock %p", sk);
394
395 read_lock(&hci_dev_list_lock);
396
397 count = 0;
398 list_for_each_entry(d, &hci_dev_list, list) {
399 if (d->dev_type == HCI_BREDR &&
400 test_bit(HCI_UNCONFIGURED, &d->dev_flags))
401 count++;
402 }
403
404 rp_len = sizeof(*rp) + (2 * count);
405 rp = kmalloc(rp_len, GFP_ATOMIC);
406 if (!rp) {
407 read_unlock(&hci_dev_list_lock);
408 return -ENOMEM;
409 }
410
411 count = 0;
412 list_for_each_entry(d, &hci_dev_list, list) {
413 if (test_bit(HCI_SETUP, &d->dev_flags) ||
414 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
415 continue;
416
417 /* Devices marked as raw-only are neither configured
418 * nor unconfigured controllers.
419 */
420 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
421 continue;
422
423 if (d->dev_type == HCI_BREDR &&
424 test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
425 rp->index[count++] = cpu_to_le16(d->id);
426 BT_DBG("Added hci%u", d->id);
427 }
428 }
429
430 rp->num_controllers = cpu_to_le16(count);
431 rp_len = sizeof(*rp) + (2 * count);
432
433 read_unlock(&hci_dev_list_lock);
434
435 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_UNCONF_INDEX_LIST,
436 0, rp, rp_len);
437
438 kfree(rp);
439
440 return err;
441}
442
380static u32 get_supported_settings(struct hci_dev *hdev) 443static u32 get_supported_settings(struct hci_dev *hdev)
381{ 444{
382 u32 settings = 0; 445 u32 settings = 0;
@@ -5273,7 +5336,8 @@ static const struct mgmt_handler {
5273 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE }, 5336 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
5274 { add_device, false, MGMT_ADD_DEVICE_SIZE }, 5337 { add_device, false, MGMT_ADD_DEVICE_SIZE },
5275 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE }, 5338 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
5276 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE }, 5339 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
5340 { read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE },
5277}; 5341};
5278 5342
5279int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) 5343int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
@@ -5335,8 +5399,15 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
5335 goto done; 5399 goto done;
5336 } 5400 }
5337 5401
5338 if ((hdev && opcode < MGMT_OP_READ_INFO) || 5402 if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST ||
5339 (!hdev && opcode >= MGMT_OP_READ_INFO)) { 5403 opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) {
5404 err = cmd_status(sk, index, opcode,
5405 MGMT_STATUS_INVALID_INDEX);
5406 goto done;
5407 }
5408
5409 if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST &&
5410 opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) {
5340 err = cmd_status(sk, index, opcode, 5411 err = cmd_status(sk, index, opcode,
5341 MGMT_STATUS_INVALID_INDEX); 5412 MGMT_STATUS_INVALID_INDEX);
5342 goto done; 5413 goto done;