Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Bluetooth: hci_core: Introduce HCI_CONN_FLAG_PAST

This introduces a new device flag so userspace can indicate if it
wants to enable PAST Receiver for a specific device.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

+55 -1
+1
include/net/bluetooth/hci_core.h
··· 166 166 HCI_CONN_FLAG_REMOTE_WAKEUP = BIT(0), 167 167 HCI_CONN_FLAG_DEVICE_PRIVACY = BIT(1), 168 168 HCI_CONN_FLAG_ADDRESS_RESOLUTION = BIT(2), 169 + HCI_CONN_FLAG_PAST = BIT(3), 169 170 }; 170 171 typedef u8 hci_conn_flags_t; 171 172
+54 -1
net/bluetooth/hci_sync.c
··· 4324 4324 if (ll_privacy_capable(hdev)) 4325 4325 hdev->conn_flags |= HCI_CONN_FLAG_ADDRESS_RESOLUTION; 4326 4326 4327 + /* Mark PAST if supported */ 4328 + if (past_capable(hdev)) 4329 + hdev->conn_flags |= HCI_CONN_FLAG_PAST; 4330 + 4327 4331 /* If the controller supports Extended Scanner Filter 4328 4332 * Policies, enable the corresponding event. 4329 4333 */ ··· 7028 7024 hci_dev_unlock(hdev); 7029 7025 } 7030 7026 7027 + static int hci_le_past_params_sync(struct hci_dev *hdev, struct hci_conn *conn, 7028 + struct hci_conn *acl, struct bt_iso_qos *qos) 7029 + { 7030 + struct hci_cp_le_past_params cp; 7031 + int err; 7032 + 7033 + memset(&cp, 0, sizeof(cp)); 7034 + cp.handle = cpu_to_le16(acl->handle); 7035 + /* An HCI_LE_Periodic_Advertising_Sync_Transfer_Received event is sent 7036 + * to the Host. HCI_LE_Periodic_Advertising_Report events will be 7037 + * enabled with duplicate filtering enabled. 7038 + */ 7039 + cp.mode = 0x03; 7040 + cp.skip = cpu_to_le16(qos->bcast.skip); 7041 + cp.sync_timeout = cpu_to_le16(qos->bcast.sync_timeout); 7042 + cp.cte_type = qos->bcast.sync_cte_type; 7043 + 7044 + /* HCI_LE_PAST_PARAMS command returns a command complete event so it 7045 + * cannot wait for HCI_EV_LE_PAST_RECEIVED. 7046 + */ 7047 + err = __hci_cmd_sync_status(hdev, HCI_OP_LE_PAST_PARAMS, 7048 + sizeof(cp), &cp, HCI_CMD_TIMEOUT); 7049 + if (err) 7050 + return err; 7051 + 7052 + /* Wait for HCI_EV_LE_PAST_RECEIVED event */ 7053 + return __hci_cmd_sync_status_sk(hdev, HCI_OP_NOP, 0, NULL, 7054 + HCI_EV_LE_PAST_RECEIVED, 7055 + conn->conn_timeout, NULL); 7056 + } 7057 + 7031 7058 static int hci_le_pa_create_sync(struct hci_dev *hdev, void *data) 7032 7059 { 7033 7060 struct hci_cp_le_pa_create_sync cp; 7034 - struct hci_conn *conn = data; 7061 + struct hci_conn *conn = data, *le; 7035 7062 struct bt_iso_qos *qos = &conn->iso_qos; 7036 7063 int err; 7037 7064 ··· 7093 7058 set_bit(HCI_CONN_CREATE_PA_SYNC, &conn->flags); 7094 7059 7095 7060 hci_update_passive_scan_sync(hdev); 7061 + 7062 + /* Check if PAST is possible: 7063 + * 7064 + * 1. Check if an ACL connection with the destination address exists 7065 + * 2. Check if that HCI_CONN_FLAG_PAST has been set which indicates that 7066 + * user really intended to use PAST. 7067 + */ 7068 + le = hci_conn_hash_lookup_le(hdev, &conn->dst, conn->dst_type); 7069 + if (le) { 7070 + struct hci_conn_params *params; 7071 + 7072 + params = hci_conn_params_lookup(hdev, &le->dst, le->dst_type); 7073 + if (params && params->flags & HCI_CONN_FLAG_PAST) { 7074 + err = hci_le_past_params_sync(hdev, conn, le, qos); 7075 + if (!err) 7076 + goto done; 7077 + } 7078 + } 7096 7079 7097 7080 /* SID has not been set listen for HCI_EV_LE_EXT_ADV_REPORT to update 7098 7081 * it.