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: Add initial support for PAST

This adds PAST related commands (HCI_OP_LE_PAST,
HCI_OP_LE_PAST_SET_INFO and HCI_OP_LE_PAST_PARAMS) and events
(HCI_EV_LE_PAST_RECEIVED) along with handling of PAST sender and
receiver features bits including new MGMG settings (
HCI_EV_LE_PAST_RECEIVED and MGMT_SETTING_PAST_RECEIVER) which
userspace can use to determine if PAST is supported by the
controller.

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

+177 -10
+54
include/net/bluetooth/hci.h
··· 647 647 #define HCI_LE_EXT_ADV 0x10 648 648 #define HCI_LE_PERIODIC_ADV 0x20 649 649 #define HCI_LE_CHAN_SEL_ALG2 0x40 650 + #define HCI_LE_PAST_SENDER 0x01 651 + #define HCI_LE_PAST_RECEIVER 0x02 650 652 #define HCI_LE_CIS_CENTRAL 0x10 651 653 #define HCI_LE_CIS_PERIPHERAL 0x20 652 654 #define HCI_LE_ISO_BROADCASTER 0x40 ··· 2070 2068 __u8 mode; 2071 2069 } __packed; 2072 2070 2071 + #define HCI_OP_LE_PAST 0x205a 2072 + struct hci_cp_le_past { 2073 + __le16 handle; 2074 + __le16 service_data; 2075 + __le16 sync_handle; 2076 + } __packed; 2077 + 2078 + struct hci_rp_le_past { 2079 + __u8 status; 2080 + __le16 handle; 2081 + } __packed; 2082 + 2083 + #define HCI_OP_LE_PAST_SET_INFO 0x205b 2084 + struct hci_cp_le_past_set_info { 2085 + __le16 handle; 2086 + __le16 service_data; 2087 + __u8 adv_handle; 2088 + } __packed; 2089 + 2090 + struct hci_rp_le_past_set_info { 2091 + __u8 status; 2092 + __le16 handle; 2093 + } __packed; 2094 + 2095 + #define HCI_OP_LE_PAST_PARAMS 0x205c 2096 + struct hci_cp_le_past_params { 2097 + __le16 handle; 2098 + __u8 mode; 2099 + __le16 skip; 2100 + __le16 sync_timeout; 2101 + __u8 cte_type; 2102 + } __packed; 2103 + 2104 + struct hci_rp_le_past_params { 2105 + __u8 status; 2106 + __le16 handle; 2107 + } __packed; 2108 + 2073 2109 #define HCI_OP_LE_READ_BUFFER_SIZE_V2 0x2060 2074 2110 struct hci_rp_le_read_buffer_size_v2 { 2075 2111 __u8 status; ··· 2838 2798 __u8 handle; 2839 2799 __le16 conn_handle; 2840 2800 __u8 num_evts; 2801 + } __packed; 2802 + 2803 + #define HCI_EV_LE_PAST_RECEIVED 0x18 2804 + struct hci_ev_le_past_received { 2805 + __u8 status; 2806 + __le16 handle; 2807 + __le16 service_data; 2808 + __le16 sync_handle; 2809 + __u8 sid; 2810 + __u8 bdaddr_type; 2811 + bdaddr_t bdaddr; 2812 + __u8 phy; 2813 + __le16 interval; 2814 + __u8 clock_accuracy; 2841 2815 } __packed; 2842 2816 2843 2817 #define HCI_EVT_LE_CIS_ESTABLISHED 0x19
+12
include/net/bluetooth/hci_core.h
··· 2053 2053 #define sync_recv_capable(dev) \ 2054 2054 ((dev)->le_features[3] & HCI_LE_ISO_SYNC_RECEIVER) 2055 2055 #define sync_recv_enabled(dev) (le_enabled(dev) && sync_recv_capable(dev)) 2056 + #define past_sender_capable(dev) \ 2057 + ((dev)->le_features[3] & HCI_LE_PAST_SENDER) 2058 + #define past_receiver_capable(dev) \ 2059 + ((dev)->le_features[3] & HCI_LE_PAST_RECEIVER) 2060 + #define past_capable(dev) \ 2061 + (past_sender_capable(dev) || past_receiver_capable(dev)) 2062 + #define past_sender_enabled(dev) \ 2063 + (le_enabled(dev) && past_sender_capable(dev)) 2064 + #define past_receiver_enabled(dev) \ 2065 + (le_enabled(dev) && past_receiver_capable(dev)) 2066 + #define past_enabled(dev) \ 2067 + (past_sender_enabled(dev) || past_receiver_enabled(dev)) 2056 2068 2057 2069 #define mws_transport_config_capable(dev) (((dev)->commands[30] & 0x08) && \ 2058 2070 (!hci_test_quirk((dev), HCI_QUIRK_BROKEN_MWS_TRANSPORT_CONFIG)))
+2
include/net/bluetooth/mgmt.h
··· 119 119 #define MGMT_SETTING_ISO_BROADCASTER BIT(20) 120 120 #define MGMT_SETTING_ISO_SYNC_RECEIVER BIT(21) 121 121 #define MGMT_SETTING_LL_PRIVACY BIT(22) 122 + #define MGMT_SETTING_PAST_SENDER BIT(23) 123 + #define MGMT_SETTING_PAST_RECEIVER BIT(24) 122 124 123 125 #define MGMT_OP_READ_INFO 0x0004 124 126 #define MGMT_READ_INFO_SIZE 0
+69 -10
net/bluetooth/hci_event.c
··· 5936 5936 hci_dev_unlock(hdev); 5937 5937 } 5938 5938 5939 + static int hci_le_pa_term_sync(struct hci_dev *hdev, __le16 handle) 5940 + { 5941 + struct hci_cp_le_pa_term_sync cp; 5942 + 5943 + memset(&cp, 0, sizeof(cp)); 5944 + cp.handle = handle; 5945 + 5946 + return hci_send_cmd(hdev, HCI_OP_LE_PA_TERM_SYNC, sizeof(cp), &cp); 5947 + } 5948 + 5949 + static void hci_le_past_received_evt(struct hci_dev *hdev, void *data, 5950 + struct sk_buff *skb) 5951 + { 5952 + struct hci_ev_le_past_received *ev = data; 5953 + int mask = hdev->link_mode; 5954 + __u8 flags = 0; 5955 + struct hci_conn *pa_sync, *conn; 5956 + 5957 + bt_dev_dbg(hdev, "status 0x%2.2x", ev->status); 5958 + 5959 + hci_dev_lock(hdev); 5960 + 5961 + hci_dev_clear_flag(hdev, HCI_PA_SYNC); 5962 + 5963 + conn = hci_conn_hash_lookup_create_pa_sync(hdev); 5964 + if (!conn) { 5965 + bt_dev_err(hdev, 5966 + "Unable to find connection for dst %pMR sid 0x%2.2x", 5967 + &ev->bdaddr, ev->sid); 5968 + goto unlock; 5969 + } 5970 + 5971 + conn->sync_handle = le16_to_cpu(ev->sync_handle); 5972 + conn->sid = HCI_SID_INVALID; 5973 + 5974 + mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, PA_LINK, 5975 + &flags); 5976 + if (!(mask & HCI_LM_ACCEPT)) { 5977 + hci_le_pa_term_sync(hdev, ev->sync_handle); 5978 + goto unlock; 5979 + } 5980 + 5981 + if (!(flags & HCI_PROTO_DEFER)) 5982 + goto unlock; 5983 + 5984 + /* Add connection to indicate PA sync event */ 5985 + pa_sync = hci_conn_add_unset(hdev, PA_LINK, BDADDR_ANY, 5986 + HCI_ROLE_SLAVE); 5987 + 5988 + if (IS_ERR(pa_sync)) 5989 + goto unlock; 5990 + 5991 + pa_sync->sync_handle = le16_to_cpu(ev->sync_handle); 5992 + 5993 + if (ev->status) { 5994 + set_bit(HCI_CONN_PA_SYNC_FAILED, &pa_sync->flags); 5995 + 5996 + /* Notify iso layer */ 5997 + hci_connect_cfm(pa_sync, ev->status); 5998 + } 5999 + 6000 + unlock: 6001 + hci_dev_unlock(hdev); 6002 + } 6003 + 5939 6004 static void hci_le_conn_update_complete_evt(struct hci_dev *hdev, void *data, 5940 6005 struct sk_buff *skb) 5941 6006 { ··· 6475 6410 } 6476 6411 6477 6412 hci_dev_unlock(hdev); 6478 - } 6479 - 6480 - static int hci_le_pa_term_sync(struct hci_dev *hdev, __le16 handle) 6481 - { 6482 - struct hci_cp_le_pa_term_sync cp; 6483 - 6484 - memset(&cp, 0, sizeof(cp)); 6485 - cp.handle = handle; 6486 - 6487 - return hci_send_cmd(hdev, HCI_OP_LE_PA_TERM_SYNC, sizeof(cp), &cp); 6488 6413 } 6489 6414 6490 6415 static void hci_le_pa_sync_established_evt(struct hci_dev *hdev, void *data, ··· 7261 7206 /* [0x12 = HCI_EV_LE_EXT_ADV_SET_TERM] */ 7262 7207 HCI_LE_EV(HCI_EV_LE_EXT_ADV_SET_TERM, hci_le_ext_adv_term_evt, 7263 7208 sizeof(struct hci_evt_le_ext_adv_set_term)), 7209 + /* [0x18 = HCI_EVT_LE_PAST_RECEIVED] */ 7210 + HCI_LE_EV(HCI_EV_LE_PAST_RECEIVED, 7211 + hci_le_past_received_evt, 7212 + sizeof(struct hci_ev_le_past_received)), 7264 7213 /* [0x19 = HCI_EVT_LE_CIS_ESTABLISHED] */ 7265 7214 HCI_LE_EV(HCI_EVT_LE_CIS_ESTABLISHED, hci_le_cis_established_evt, 7266 7215 sizeof(struct hci_evt_le_cis_established)),
+3
net/bluetooth/hci_sync.c
··· 4393 4393 if (ext_adv_capable(hdev)) 4394 4394 events[2] |= 0x02; /* LE Advertising Set Terminated */ 4395 4395 4396 + if (past_receiver_capable(hdev)) 4397 + events[2] |= 0x80; /* LE PAST Received */ 4398 + 4396 4399 if (cis_capable(hdev)) { 4397 4400 events[3] |= 0x01; /* LE CIS Established */ 4398 4401 if (cis_peripheral_capable(hdev))
+25
net/bluetooth/iso.c
··· 80 80 static bool check_ucast_qos(struct bt_iso_qos *qos); 81 81 static bool check_bcast_qos(struct bt_iso_qos *qos); 82 82 static bool iso_match_sid(struct sock *sk, void *data); 83 + static bool iso_match_sid_past(struct sock *sk, void *data); 83 84 static bool iso_match_sync_handle(struct sock *sk, void *data); 84 85 static bool iso_match_sync_handle_pa_report(struct sock *sk, void *data); 85 86 static void iso_sock_disconn(struct sock *sk); ··· 2091 2090 return ev->sid == iso_pi(sk)->bc_sid; 2092 2091 } 2093 2092 2093 + static bool iso_match_sid_past(struct sock *sk, void *data) 2094 + { 2095 + struct hci_ev_le_past_received *ev = data; 2096 + 2097 + if (iso_pi(sk)->bc_sid == HCI_SID_INVALID) 2098 + return true; 2099 + 2100 + return ev->sid == iso_pi(sk)->bc_sid; 2101 + } 2102 + 2094 2103 static bool iso_match_sync_handle(struct sock *sk, void *data) 2095 2104 { 2096 2105 struct hci_evt_le_big_info_adv_report *ev = data; ··· 2120 2109 int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags) 2121 2110 { 2122 2111 struct hci_ev_le_pa_sync_established *ev1; 2112 + struct hci_ev_le_past_received *ev1a; 2123 2113 struct hci_evt_le_big_info_adv_report *ev2; 2124 2114 struct hci_ev_le_per_adv_report *ev3; 2125 2115 struct sock *sk; ··· 2134 2122 * SID to listen to and once sync is established its handle needs to 2135 2123 * be stored in iso_pi(sk)->sync_handle so it can be matched once 2136 2124 * receiving the BIG Info. 2125 + * 1a. HCI_EV_LE_PAST_RECEIVED: alternative to 1. 2137 2126 * 2. HCI_EVT_LE_BIG_INFO_ADV_REPORT: When connect_ind is triggered by a 2138 2127 * a BIG Info it attempts to check if there any listening socket with 2139 2128 * the same sync_handle and if it does then attempt to create a sync. ··· 2149 2136 if (sk && !ev1->status) { 2150 2137 iso_pi(sk)->sync_handle = le16_to_cpu(ev1->handle); 2151 2138 iso_pi(sk)->bc_sid = ev1->sid; 2139 + } 2140 + 2141 + goto done; 2142 + } 2143 + 2144 + ev1a = hci_recv_event_data(hdev, HCI_EV_LE_PAST_RECEIVED); 2145 + if (ev1a) { 2146 + sk = iso_get_sock(&hdev->bdaddr, bdaddr, BT_LISTEN, 2147 + iso_match_sid_past, ev1a); 2148 + if (sk && !ev1a->status) { 2149 + iso_pi(sk)->sync_handle = le16_to_cpu(ev1a->sync_handle); 2150 + iso_pi(sk)->bc_sid = ev1a->sid; 2152 2151 } 2153 2152 2154 2153 goto done;
+12
net/bluetooth/mgmt.c
··· 852 852 if (ll_privacy_capable(hdev)) 853 853 settings |= MGMT_SETTING_LL_PRIVACY; 854 854 855 + if (past_sender_capable(hdev)) 856 + settings |= MGMT_SETTING_PAST_SENDER; 857 + 858 + if (past_receiver_capable(hdev)) 859 + settings |= MGMT_SETTING_PAST_RECEIVER; 860 + 855 861 settings |= MGMT_SETTING_PHY_CONFIGURATION; 856 862 857 863 return settings; ··· 942 936 943 937 if (ll_privacy_enabled(hdev)) 944 938 settings |= MGMT_SETTING_LL_PRIVACY; 939 + 940 + if (past_sender_enabled(hdev)) 941 + settings |= MGMT_SETTING_PAST_SENDER; 942 + 943 + if (past_receiver_enabled(hdev)) 944 + settings |= MGMT_SETTING_PAST_RECEIVER; 945 945 946 946 return settings; 947 947 }