]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
Bluetooth: Implement PHY changed event
authorJaganath Kanakkassery <jaganath.k.os@gmail.com>
Thu, 19 Jul 2018 11:39:36 +0000 (17:09 +0530)
committerMarcel Holtmann <marcel@holtmann.org>
Mon, 30 Jul 2018 11:44:52 +0000 (13:44 +0200)
This defines and implement phy changed event and send it to user
whenever selected PHYs changes using SET_PHY_CONFIGURATION.

This will be also trigerred when BREDR pkt_type is changed using
the legacy ioctl HCISETPTYPE.

@ MGMT Command: Set PHY Configuration (0x0045) plen 4
Selected 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
< HCI Command: LE Set Default PHY (0x08|0x0031) plen 3
All PHYs preference: 0x00
TX PHYs preference: 0x07
  LE 1M
  LE 2M
  LE Coded
RX PHYs preference: 0x07
  LE 1M
  LE 2M
  LE Coded
> HCI Event: Command Complete (0x0e) plen 4
  LE Set Default PHY (0x08|0x0031) ncmd 1
Status: Success (0x00)
@ MGMT Event: Command Complete (0x0001) plen 3
  Set PHY Configuration (0x0045) plen 0
Status: Success (0x00)
@ MGMT Event: PHY Configuration Changed (0x0026) plen 4
Selected 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

Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
include/net/bluetooth/hci_core.h
include/net/bluetooth/mgmt.h
net/bluetooth/hci_core.c
net/bluetooth/mgmt.c

index a64d13f91d09c0c00355d877d7dea56f1cf608d1..ab5d494a545a9648f8a387ebe28dc44139000275 100644 (file)
@@ -1544,6 +1544,7 @@ void mgmt_advertising_added(struct sock *sk, struct hci_dev *hdev,
                            u8 instance);
 void mgmt_advertising_removed(struct sock *sk, struct hci_dev *hdev,
                              u8 instance);
+int mgmt_phy_configuration_changed(struct hci_dev *hdev, struct sock *skip);
 
 u8 hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, u16 latency,
                      u16 to_multiplier);
index 0916e203e5d9f0a182d1fc9811d4a1559f114809..7f372e9067c915ed67de52a283af7effe5ed45f9 100644 (file)
@@ -868,3 +868,8 @@ struct mgmt_ev_ext_info_changed {
        __le16  eir_len;
        __u8    eir[0];
 } __packed;
+
+#define MGMT_EV_PHY_CONFIGURATION_CHANGED      0x0026
+struct mgmt_ev_phy_configuration_changed {
+       __le32  selected_phys;
+} __packed;
index 432f89f390c05e4f2aa1fd38f7afa8ea8c31066a..523e91ad64d08cfe6f348fcd7fda19eb2ed7e815 100644 (file)
@@ -1924,7 +1924,11 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg)
                break;
 
        case HCISETPTYPE:
+               if (hdev->pkt_type == (__u16) dr.dev_opt)
+                       break;
+
                hdev->pkt_type = (__u16) dr.dev_opt;
+               mgmt_phy_configuration_changed(hdev, NULL);
                break;
 
        case HCISETACLMTU:
index 7cd6a37a63eecf20020bc104f7d2a7923c21484e..1867aadc506147dec9f7e3246233cda4218421b7 100644 (file)
@@ -3328,6 +3328,18 @@ static int get_phy_configuration(struct sock *sk, struct hci_dev *hdev,
                                 &rp, sizeof(rp));
 }
 
+int mgmt_phy_configuration_changed(struct hci_dev *hdev, struct sock *skip)
+{
+       struct mgmt_ev_phy_configuration_changed ev;
+
+       memset(&ev, 0, sizeof(ev));
+
+       ev.selected_phys = cpu_to_le32(get_selected_phys(hdev));
+
+       return mgmt_event(MGMT_EV_PHY_CONFIGURATION_CHANGED, hdev, &ev,
+                         sizeof(ev), skip);
+}
+
 static void set_default_phy_complete(struct hci_dev *hdev, u8 status,
                                     u16 opcode, struct sk_buff *skb)
 {
@@ -3352,6 +3364,8 @@ static void set_default_phy_complete(struct hci_dev *hdev, u8 status,
                mgmt_cmd_complete(cmd->sk, hdev->id,
                                  MGMT_OP_SET_PHY_CONFIGURATION, 0,
                                  NULL, 0);
+
+               mgmt_phy_configuration_changed(hdev, cmd->sk);
        }
 
        mgmt_pending_remove(cmd);
@@ -3369,6 +3383,7 @@ static int set_phy_configuration(struct sock *sk, struct hci_dev *hdev,
        struct hci_request req;
        u32 selected_phys, configurable_phys, supported_phys, unconfigure_phys;
        u16 pkt_type = (HCI_DH1 | HCI_DM1);
+       bool changed = false;
        int err;
 
        BT_DBG("sock %p %s", sk, hdev->name);
@@ -3450,11 +3465,16 @@ static int set_phy_configuration(struct sock *sk, struct hci_dev *hdev,
        else
                pkt_type |= HCI_3DH5;
 
-       if (pkt_type != hdev->pkt_type)
+       if (pkt_type != hdev->pkt_type) {
                hdev->pkt_type = pkt_type;
+               changed = true;
+       }
 
        if ((selected_phys & MGMT_PHY_LE_MASK) ==
            (get_selected_phys(hdev) & MGMT_PHY_LE_MASK)) {
+               if (changed)
+                       mgmt_phy_configuration_changed(hdev, sk);
+
                err = mgmt_cmd_complete(sk, hdev->id,
                                        MGMT_OP_SET_PHY_CONFIGURATION,
                                        0, NULL, 0);