aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorJaganath Kanakkassery <jaganath.k.os@gmail.com>2018-07-19 07:39:34 -0400
committerMarcel Holtmann <marcel@holtmann.org>2018-07-30 07:44:52 -0400
commit6244691fec4dd0adebca255e60e0ed7ac8155b2e (patch)
tree3eabeaf43ba365465eefec963ddefd069fed271d /net/bluetooth
parent5075b972f20ddad5bb19542ea4f5794d06673375 (diff)
Bluetooth: Implement Get PHY Configuration mgmt command
This commands basically retrieve the supported packet types of BREDR and supported PHYs of the controller. BR_1M_1SLOT, LE_1M_TX and LE_1M_RX would be supported by default. Other PHYs are supported based on the local features. Also this sets PHY_CONFIGURATION bit in supported settings. @ MGMT Command: Get PHY Configuration (0x0044) plen 0 @ MGMT Event: Command Complete (0x0001) plen 15 Get PHY Configuration (0x0044) plen 12 Status: Success (0x00) Supported PHYs: 0x7fff BR 1M 1SLOT BR 1M 3SLOT BR 1M 5SLOT EDR 2M 1SLOT EDR 2M 3SLOT EDR 2M 5SLOT EDR 3M 1SLOT EDR 3M 3SLOT EDR 3M 5SLOT LE 1M TX LE 1M RX LE 2M TX LE 2M RX LE CODED TX LE CODED RX Configurable PHYs: 0x79fe BR 1M 3SLOT BR 1M 5SLOT EDR 2M 1SLOT EDR 2M 3SLOT EDR 2M 5SLOT EDR 3M 1SLOT EDR 3M 3SLOT EDR 3M 5SLOT LE 2M TX LE 2M RX LE CODED TX LE CODED RX Selected PHYs: 0x07ff BR 1M 1SLOT BR 1M 3SLOT BR 1M 5SLOT EDR 2M 1SLOT EDR 2M 3SLOT EDR 2M 5SLOT EDR 3M 1SLOT EDR 3M 3SLOT EDR 3M 5SLOT LE 1M TX LE 1M RX Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/mgmt.c145
1 files changed, 145 insertions, 0 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 8a80d48d89c4..c8c3b39fa9f2 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -617,6 +617,127 @@ static int read_config_info(struct sock *sk, struct hci_dev *hdev,
617 &rp, sizeof(rp)); 617 &rp, sizeof(rp));
618} 618}
619 619
620static u32 get_supported_phys(struct hci_dev *hdev)
621{
622 u32 supported_phys = 0;
623
624 if (lmp_bredr_capable(hdev)) {
625 supported_phys |= MGMT_PHY_BR_1M_1SLOT;
626
627 if (hdev->features[0][0] & LMP_3SLOT)
628 supported_phys |= MGMT_PHY_BR_1M_3SLOT;
629
630 if (hdev->features[0][0] & LMP_5SLOT)
631 supported_phys |= MGMT_PHY_BR_1M_5SLOT;
632
633 if (lmp_edr_2m_capable(hdev)) {
634 supported_phys |= MGMT_PHY_EDR_2M_1SLOT;
635
636 if (lmp_edr_3slot_capable(hdev))
637 supported_phys |= MGMT_PHY_EDR_2M_3SLOT;
638
639 if (lmp_edr_5slot_capable(hdev))
640 supported_phys |= MGMT_PHY_EDR_2M_5SLOT;
641
642 if (lmp_edr_3m_capable(hdev)) {
643 supported_phys |= MGMT_PHY_EDR_3M_1SLOT;
644
645 if (lmp_edr_3slot_capable(hdev))
646 supported_phys |= MGMT_PHY_EDR_3M_3SLOT;
647
648 if (lmp_edr_5slot_capable(hdev))
649 supported_phys |= MGMT_PHY_EDR_3M_5SLOT;
650 }
651 }
652 }
653
654 if (lmp_le_capable(hdev)) {
655 supported_phys |= MGMT_PHY_LE_1M_TX;
656 supported_phys |= MGMT_PHY_LE_1M_RX;
657
658 if (hdev->le_features[1] & HCI_LE_PHY_2M) {
659 supported_phys |= MGMT_PHY_LE_2M_TX;
660 supported_phys |= MGMT_PHY_LE_2M_RX;
661 }
662
663 if (hdev->le_features[1] & HCI_LE_PHY_CODED) {
664 supported_phys |= MGMT_PHY_LE_CODED_TX;
665 supported_phys |= MGMT_PHY_LE_CODED_RX;
666 }
667 }
668
669 return supported_phys;
670}
671
672static u32 get_selected_phys(struct hci_dev *hdev)
673{
674 u32 selected_phys = 0;
675
676 if (lmp_bredr_capable(hdev)) {
677 selected_phys |= MGMT_PHY_BR_1M_1SLOT;
678
679 if (hdev->pkt_type & (HCI_DM3 | HCI_DH3))
680 selected_phys |= MGMT_PHY_BR_1M_3SLOT;
681
682 if (hdev->pkt_type & (HCI_DM5 | HCI_DH5))
683 selected_phys |= MGMT_PHY_BR_1M_5SLOT;
684
685 if (lmp_edr_2m_capable(hdev)) {
686 if (!(hdev->pkt_type & HCI_2DH1))
687 selected_phys |= MGMT_PHY_EDR_2M_1SLOT;
688
689 if (lmp_edr_3slot_capable(hdev) &&
690 !(hdev->pkt_type & HCI_2DH3))
691 selected_phys |= MGMT_PHY_EDR_2M_3SLOT;
692
693 if (lmp_edr_5slot_capable(hdev) &&
694 !(hdev->pkt_type & HCI_2DH5))
695 selected_phys |= MGMT_PHY_EDR_2M_5SLOT;
696
697 if (lmp_edr_3m_capable(hdev)) {
698 if (!(hdev->pkt_type & HCI_3DH1))
699 selected_phys |= MGMT_PHY_EDR_3M_1SLOT;
700
701 if (lmp_edr_3slot_capable(hdev) &&
702 !(hdev->pkt_type & HCI_3DH3))
703 selected_phys |= MGMT_PHY_EDR_3M_3SLOT;
704
705 if (lmp_edr_5slot_capable(hdev) &&
706 !(hdev->pkt_type & HCI_3DH5))
707 selected_phys |= MGMT_PHY_EDR_3M_5SLOT;
708 }
709 }
710 }
711
712 if (lmp_le_capable(hdev)) {
713 if (hdev->le_tx_def_phys & HCI_LE_SET_PHY_1M)
714 selected_phys |= MGMT_PHY_LE_1M_TX;
715
716 if (hdev->le_rx_def_phys & HCI_LE_SET_PHY_1M)
717 selected_phys |= MGMT_PHY_LE_1M_RX;
718
719 if (hdev->le_tx_def_phys & HCI_LE_SET_PHY_2M)
720 selected_phys |= MGMT_PHY_LE_2M_TX;
721
722 if (hdev->le_rx_def_phys & HCI_LE_SET_PHY_2M)
723 selected_phys |= MGMT_PHY_LE_2M_RX;
724
725 if (hdev->le_tx_def_phys & HCI_LE_SET_PHY_CODED)
726 selected_phys |= MGMT_PHY_LE_CODED_TX;
727
728 if (hdev->le_rx_def_phys & HCI_LE_SET_PHY_CODED)
729 selected_phys |= MGMT_PHY_LE_CODED_RX;
730 }
731
732 return selected_phys;
733}
734
735static u32 get_configurable_phys(struct hci_dev *hdev)
736{
737 return (get_supported_phys(hdev) & ~MGMT_PHY_BR_1M_1SLOT &
738 ~MGMT_PHY_LE_1M_TX & ~MGMT_PHY_LE_1M_RX);
739}
740
620static u32 get_supported_settings(struct hci_dev *hdev) 741static u32 get_supported_settings(struct hci_dev *hdev)
621{ 742{
622 u32 settings = 0; 743 u32 settings = 0;
@@ -654,6 +775,8 @@ static u32 get_supported_settings(struct hci_dev *hdev)
654 hdev->set_bdaddr) 775 hdev->set_bdaddr)
655 settings |= MGMT_SETTING_CONFIGURATION; 776 settings |= MGMT_SETTING_CONFIGURATION;
656 777
778 settings |= MGMT_SETTING_PHY_CONFIGURATION;
779
657 return settings; 780 return settings;
658} 781}
659 782
@@ -3184,6 +3307,27 @@ static int set_appearance(struct sock *sk, struct hci_dev *hdev, void *data,
3184 return err; 3307 return err;
3185} 3308}
3186 3309
3310static int get_phy_configuration(struct sock *sk, struct hci_dev *hdev,
3311 void *data, u16 len)
3312{
3313 struct mgmt_rp_get_phy_confguration rp;
3314
3315 BT_DBG("sock %p %s", sk, hdev->name);
3316
3317 hci_dev_lock(hdev);
3318
3319 memset(&rp, 0, sizeof(rp));
3320
3321 rp.supported_phys = cpu_to_le32(get_supported_phys(hdev));
3322 rp.selected_phys = cpu_to_le32(get_selected_phys(hdev));
3323 rp.configurable_phys = cpu_to_le32(get_configurable_phys(hdev));
3324
3325 hci_dev_unlock(hdev);
3326
3327 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_PHY_CONFIGURATION, 0,
3328 &rp, sizeof(rp));
3329}
3330
3187static void read_local_oob_data_complete(struct hci_dev *hdev, u8 status, 3331static void read_local_oob_data_complete(struct hci_dev *hdev, u8 status,
3188 u16 opcode, struct sk_buff *skb) 3332 u16 opcode, struct sk_buff *skb)
3189{ 3333{
@@ -6544,6 +6688,7 @@ static const struct hci_mgmt_handler mgmt_handlers[] = {
6544 { read_ext_controller_info,MGMT_READ_EXT_INFO_SIZE, 6688 { read_ext_controller_info,MGMT_READ_EXT_INFO_SIZE,
6545 HCI_MGMT_UNTRUSTED }, 6689 HCI_MGMT_UNTRUSTED },
6546 { set_appearance, MGMT_SET_APPEARANCE_SIZE }, 6690 { set_appearance, MGMT_SET_APPEARANCE_SIZE },
6691 { get_phy_configuration, MGMT_GET_PHY_CONFIGURATION_SIZE },
6547}; 6692};
6548 6693
6549void mgmt_index_added(struct hci_dev *hdev) 6694void mgmt_index_added(struct hci_dev *hdev)