aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/hci_event.c
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@nokia.com>2011-01-24 18:19:58 -0500
committerGustavo F. Padovan <padovan@profusion.mobi>2011-02-07 22:40:06 -0500
commitd5859e22cd40b73164b3e5d8d5d796f96edcc6af (patch)
tree6a5fa908020f59dd8b6dd94eb042f4a0634d1e20 /net/bluetooth/hci_event.c
parentd83506003608910d24d5ace9ec06ad1bfd9ad110 (diff)
Bluetooth: Implement a more complete adapter initialization sequence
Using the managment interface means that user space doesn't need to do any HCI command sending at all. This patch moves the remaining initialization commands from user space to the kernel side. The patch makes use of the new feature of __hci_request which allows the request to be dynamically modified while it is ongoing (something that is needed to react appropriately to the local features and the version of the adapter). Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net/bluetooth/hci_event.c')
-rw-r--r--net/bluetooth/hci_event.c194
1 files changed, 193 insertions, 1 deletions
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 49b387cdcc38..c69ee44d5bd7 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -424,6 +424,115 @@ static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
424 hdev->ssp_mode = *((__u8 *) sent); 424 hdev->ssp_mode = *((__u8 *) sent);
425} 425}
426 426
427static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
428{
429 if (hdev->features[6] & LMP_EXT_INQ)
430 return 2;
431
432 if (hdev->features[3] & LMP_RSSI_INQ)
433 return 1;
434
435 if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
436 hdev->lmp_subver == 0x0757)
437 return 1;
438
439 if (hdev->manufacturer == 15) {
440 if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
441 return 1;
442 if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
443 return 1;
444 if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
445 return 1;
446 }
447
448 if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
449 hdev->lmp_subver == 0x1805)
450 return 1;
451
452 return 0;
453}
454
455static void hci_setup_inquiry_mode(struct hci_dev *hdev)
456{
457 u8 mode;
458
459 mode = hci_get_inquiry_mode(hdev);
460
461 hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
462}
463
464static void hci_setup_event_mask(struct hci_dev *hdev)
465{
466 /* The second byte is 0xff instead of 0x9f (two reserved bits
467 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
468 * command otherwise */
469 u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
470
471 /* Events for 1.2 and newer controllers */
472 if (hdev->lmp_ver > 1) {
473 events[4] |= 0x01; /* Flow Specification Complete */
474 events[4] |= 0x02; /* Inquiry Result with RSSI */
475 events[4] |= 0x04; /* Read Remote Extended Features Complete */
476 events[5] |= 0x08; /* Synchronous Connection Complete */
477 events[5] |= 0x10; /* Synchronous Connection Changed */
478 }
479
480 if (hdev->features[3] & LMP_RSSI_INQ)
481 events[4] |= 0x04; /* Inquiry Result with RSSI */
482
483 if (hdev->features[5] & LMP_SNIFF_SUBR)
484 events[5] |= 0x20; /* Sniff Subrating */
485
486 if (hdev->features[5] & LMP_PAUSE_ENC)
487 events[5] |= 0x80; /* Encryption Key Refresh Complete */
488
489 if (hdev->features[6] & LMP_EXT_INQ)
490 events[5] |= 0x40; /* Extended Inquiry Result */
491
492 if (hdev->features[6] & LMP_NO_FLUSH)
493 events[7] |= 0x01; /* Enhanced Flush Complete */
494
495 if (hdev->features[7] & LMP_LSTO)
496 events[6] |= 0x80; /* Link Supervision Timeout Changed */
497
498 if (hdev->features[6] & LMP_SIMPLE_PAIR) {
499 events[6] |= 0x01; /* IO Capability Request */
500 events[6] |= 0x02; /* IO Capability Response */
501 events[6] |= 0x04; /* User Confirmation Request */
502 events[6] |= 0x08; /* User Passkey Request */
503 events[6] |= 0x10; /* Remote OOB Data Request */
504 events[6] |= 0x20; /* Simple Pairing Complete */
505 events[7] |= 0x04; /* User Passkey Notification */
506 events[7] |= 0x08; /* Keypress Notification */
507 events[7] |= 0x10; /* Remote Host Supported
508 * Features Notification */
509 }
510
511 if (hdev->features[4] & LMP_LE)
512 events[7] |= 0x20; /* LE Meta-Event */
513
514 hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
515}
516
517static void hci_setup(struct hci_dev *hdev)
518{
519 hci_setup_event_mask(hdev);
520
521 if (hdev->lmp_ver > 1)
522 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
523
524 if (hdev->features[6] & LMP_SIMPLE_PAIR) {
525 u8 mode = 0x01;
526 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
527 }
528
529 if (hdev->features[3] & LMP_RSSI_INQ)
530 hci_setup_inquiry_mode(hdev);
531
532 if (hdev->features[7] & LMP_INQ_TX_PWR)
533 hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
534}
535
427static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) 536static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
428{ 537{
429 struct hci_rp_read_local_version *rp = (void *) skb->data; 538 struct hci_rp_read_local_version *rp = (void *) skb->data;
@@ -435,11 +544,34 @@ static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
435 544
436 hdev->hci_ver = rp->hci_ver; 545 hdev->hci_ver = rp->hci_ver;
437 hdev->hci_rev = __le16_to_cpu(rp->hci_rev); 546 hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
547 hdev->lmp_ver = rp->lmp_ver;
438 hdev->manufacturer = __le16_to_cpu(rp->manufacturer); 548 hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
549 hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
439 550
440 BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name, 551 BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
441 hdev->manufacturer, 552 hdev->manufacturer,
442 hdev->hci_ver, hdev->hci_rev); 553 hdev->hci_ver, hdev->hci_rev);
554
555 if (test_bit(HCI_INIT, &hdev->flags))
556 hci_setup(hdev);
557}
558
559static void hci_setup_link_policy(struct hci_dev *hdev)
560{
561 u16 link_policy = 0;
562
563 if (hdev->features[0] & LMP_RSWITCH)
564 link_policy |= HCI_LP_RSWITCH;
565 if (hdev->features[0] & LMP_HOLD)
566 link_policy |= HCI_LP_HOLD;
567 if (hdev->features[0] & LMP_SNIFF)
568 link_policy |= HCI_LP_SNIFF;
569 if (hdev->features[1] & LMP_PARK)
570 link_policy |= HCI_LP_PARK;
571
572 link_policy = cpu_to_le16(link_policy);
573 hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY,
574 sizeof(link_policy), &link_policy);
443} 575}
444 576
445static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb) 577static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
@@ -449,9 +581,15 @@ static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb
449 BT_DBG("%s status 0x%x", hdev->name, rp->status); 581 BT_DBG("%s status 0x%x", hdev->name, rp->status);
450 582
451 if (rp->status) 583 if (rp->status)
452 return; 584 goto done;
453 585
454 memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); 586 memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
587
588 if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
589 hci_setup_link_policy(hdev);
590
591done:
592 hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
455} 593}
456 594
457static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb) 595static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
@@ -567,6 +705,44 @@ static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
567 hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status); 705 hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
568} 706}
569 707
708static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
709{
710 __u8 status = *((__u8 *) skb->data);
711
712 BT_DBG("%s status 0x%x", hdev->name, status);
713
714 hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
715}
716
717static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
718 struct sk_buff *skb)
719{
720 __u8 status = *((__u8 *) skb->data);
721
722 BT_DBG("%s status 0x%x", hdev->name, status);
723
724 hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
725}
726
727static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
728 struct sk_buff *skb)
729{
730 __u8 status = *((__u8 *) skb->data);
731
732 BT_DBG("%s status 0x%x", hdev->name, status);
733
734 hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status);
735}
736
737static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
738{
739 __u8 status = *((__u8 *) skb->data);
740
741 BT_DBG("%s status 0x%x", hdev->name, status);
742
743 hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
744}
745
570static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 746static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
571{ 747{
572 BT_DBG("%s status 0x%x", hdev->name, status); 748 BT_DBG("%s status 0x%x", hdev->name, status);
@@ -1416,6 +1592,22 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
1416 hci_cc_delete_stored_link_key(hdev, skb); 1592 hci_cc_delete_stored_link_key(hdev, skb);
1417 break; 1593 break;
1418 1594
1595 case HCI_OP_SET_EVENT_MASK:
1596 hci_cc_set_event_mask(hdev, skb);
1597 break;
1598
1599 case HCI_OP_WRITE_INQUIRY_MODE:
1600 hci_cc_write_inquiry_mode(hdev, skb);
1601 break;
1602
1603 case HCI_OP_READ_INQ_RSP_TX_POWER:
1604 hci_cc_read_inq_rsp_tx_power(hdev, skb);
1605 break;
1606
1607 case HCI_OP_SET_EVENT_FLT:
1608 hci_cc_set_event_flt(hdev, skb);
1609 break;
1610
1419 default: 1611 default:
1420 BT_DBG("%s opcode 0x%x", hdev->name, opcode); 1612 BT_DBG("%s opcode 0x%x", hdev->name, opcode);
1421 break; 1613 break;