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 support for LL Extended Feature Set

This adds support for emulating LL Extended Feature Set introduced in 6.0
that adds the following:

Commands:

- HCI_LE_Read_All_Local_Supported_­Features(0x2087)(Feature:47,1)
- HCI_LE_Read_All_Remote_Features(0x2088)(Feature:47,2)

Events:

- HCI_LE_Read_All_Remote_Features_Complete(0x2b)(Mask bit:42)

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

+227 -30
+23
include/net/bluetooth/hci.h
··· 653 653 #define HCI_LE_CIS_PERIPHERAL 0x20 654 654 #define HCI_LE_ISO_BROADCASTER 0x40 655 655 #define HCI_LE_ISO_SYNC_RECEIVER 0x80 656 + #define HCI_LE_LL_EXT_FEATURE 0x80 656 657 657 658 /* Connection modes */ 658 659 #define HCI_CM_ACTIVE 0x0000 ··· 2256 2255 __u8 bit_value; 2257 2256 } __packed; 2258 2257 2258 + #define HCI_OP_LE_READ_ALL_LOCAL_FEATURES 0x2087 2259 + struct hci_rp_le_read_all_local_features { 2260 + __u8 status; 2261 + __u8 page; 2262 + __u8 features[248]; 2263 + } __packed; 2264 + 2265 + #define HCI_OP_LE_READ_ALL_REMOTE_FEATURES 0x2088 2266 + struct hci_cp_le_read_all_remote_features { 2267 + __le16 handle; 2268 + __u8 pages; 2269 + } __packed; 2270 + 2259 2271 /* ---- HCI Events ---- */ 2260 2272 struct hci_ev_status { 2261 2273 __u8 status; ··· 2949 2935 __u8 phy; 2950 2936 __u8 framing; 2951 2937 __u8 encryption; 2938 + } __packed; 2939 + 2940 + #define HCI_EVT_LE_ALL_REMOTE_FEATURES_COMPLETE 0x2b 2941 + struct hci_evt_le_read_all_remote_features_complete { 2942 + __u8 status; 2943 + __le16 handle; 2944 + __u8 max_pages; 2945 + __u8 valid_pages; 2946 + __u8 features[248]; 2952 2947 } __packed; 2953 2948 2954 2949 #define HCI_EV_VENDOR 0xff
+4 -1
include/net/bluetooth/hci_core.h
··· 378 378 __u8 minor_class; 379 379 __u8 max_page; 380 380 __u8 features[HCI_MAX_PAGES][8]; 381 - __u8 le_features[8]; 381 + __u8 le_features[248]; 382 382 __u8 le_accept_list_size; 383 383 __u8 le_resolv_list_size; 384 384 __u8 le_num_of_adv_sets; ··· 702 702 __u8 attempt; 703 703 __u8 dev_class[3]; 704 704 __u8 features[HCI_MAX_PAGES][8]; 705 + __u8 le_features[248]; 705 706 __u16 pkt_type; 706 707 __u16 link_policy; 707 708 __u8 key_type; ··· 2068 2067 (le_enabled(dev) && past_receiver_capable(dev)) 2069 2068 #define past_enabled(dev) \ 2070 2069 (past_sender_enabled(dev) || past_receiver_enabled(dev)) 2070 + #define ll_ext_feature_capable(dev) \ 2071 + ((dev)->le_features[7] & HCI_LE_LL_EXT_FEATURE) 2071 2072 2072 2073 #define mws_transport_config_capable(dev) (((dev)->commands[30] & 0x08) && \ 2073 2074 (!hci_test_quirk((dev), HCI_QUIRK_BROKEN_MWS_TRANSPORT_CONFIG)))
+2
include/net/bluetooth/hci_sync.h
··· 189 189 int hci_connect_pa_sync(struct hci_dev *hdev, struct hci_conn *conn); 190 190 int hci_connect_big_sync(struct hci_dev *hdev, struct hci_conn *conn); 191 191 int hci_past_sync(struct hci_conn *conn, struct hci_conn *le); 192 + 193 + int hci_le_read_remote_features(struct hci_conn *conn);
+98 -27
net/bluetooth/hci_event.c
··· 2886 2886 hci_dev_lock(hdev); 2887 2887 2888 2888 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 2889 - if (conn) { 2890 - if (conn->state == BT_CONFIG) { 2891 - hci_connect_cfm(conn, status); 2892 - hci_conn_drop(conn); 2893 - } 2894 - } 2889 + if (conn && conn->state == BT_CONFIG) 2890 + hci_connect_cfm(conn, status); 2895 2891 2896 2892 hci_dev_unlock(hdev); 2897 2893 } ··· 3911 3915 return rp->status; 3912 3916 } 3913 3917 3918 + static u8 hci_cc_le_read_all_local_features(struct hci_dev *hdev, void *data, 3919 + struct sk_buff *skb) 3920 + { 3921 + struct hci_rp_le_read_all_local_features *rp = data; 3922 + 3923 + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); 3924 + 3925 + if (rp->status) 3926 + return rp->status; 3927 + 3928 + memcpy(hdev->le_features, rp->features, 248); 3929 + 3930 + return rp->status; 3931 + } 3932 + 3914 3933 static void hci_cs_le_create_big(struct hci_dev *hdev, u8 status) 3915 3934 { 3916 3935 bt_dev_dbg(hdev, "status 0x%2.2x", status); 3936 + } 3937 + 3938 + static void hci_cs_le_read_all_remote_features(struct hci_dev *hdev, u8 status) 3939 + { 3940 + struct hci_cp_le_read_remote_features *cp; 3941 + struct hci_conn *conn; 3942 + 3943 + bt_dev_dbg(hdev, "status 0x%2.2x", status); 3944 + 3945 + if (!status) 3946 + return; 3947 + 3948 + cp = hci_sent_cmd_data(hdev, HCI_OP_LE_READ_ALL_REMOTE_FEATURES); 3949 + if (!cp) 3950 + return; 3951 + 3952 + hci_dev_lock(hdev); 3953 + 3954 + conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 3955 + if (conn && conn->state == BT_CONFIG) 3956 + hci_connect_cfm(conn, status); 3957 + 3958 + hci_dev_unlock(hdev); 3917 3959 } 3918 3960 3919 3961 static u8 hci_cc_set_per_adv_param(struct hci_dev *hdev, void *data, ··· 4205 4171 sizeof(struct hci_rp_le_set_cig_params), HCI_MAX_EVENT_SIZE), 4206 4172 HCI_CC(HCI_OP_LE_SETUP_ISO_PATH, hci_cc_le_setup_iso_path, 4207 4173 sizeof(struct hci_rp_le_setup_iso_path)), 4174 + HCI_CC(HCI_OP_LE_READ_ALL_LOCAL_FEATURES, 4175 + hci_cc_le_read_all_local_features, 4176 + sizeof(struct hci_rp_le_read_all_local_features)), 4208 4177 }; 4209 4178 4210 4179 static u8 hci_cc_func(struct hci_dev *hdev, const struct hci_cc *cc, ··· 4362 4325 HCI_CS(HCI_OP_LE_EXT_CREATE_CONN, hci_cs_le_ext_create_conn), 4363 4326 HCI_CS(HCI_OP_LE_CREATE_CIS, hci_cs_le_create_cis), 4364 4327 HCI_CS(HCI_OP_LE_CREATE_BIG, hci_cs_le_create_big), 4328 + HCI_CS(HCI_OP_LE_READ_ALL_REMOTE_FEATURES, 4329 + hci_cs_le_read_all_remote_features), 4365 4330 }; 4366 4331 4367 4332 static void hci_cmd_status_evt(struct hci_dev *hdev, void *data, ··· 5684 5645 struct hci_conn *conn; 5685 5646 struct smp_irk *irk; 5686 5647 u8 addr_type; 5648 + int err; 5687 5649 5688 5650 hci_dev_lock(hdev); 5689 5651 ··· 5815 5775 hci_debugfs_create_conn(conn); 5816 5776 hci_conn_add_sysfs(conn); 5817 5777 5818 - /* The remote features procedure is defined for central 5819 - * role only. So only in case of an initiated connection 5820 - * request the remote features. 5821 - * 5822 - * If the local controller supports peripheral-initiated features 5823 - * exchange, then requesting the remote features in peripheral 5824 - * role is possible. Otherwise just transition into the 5825 - * connected state without requesting the remote features. 5826 - */ 5827 - if (conn->out || 5828 - (hdev->le_features[0] & HCI_LE_PERIPHERAL_FEATURES)) { 5829 - struct hci_cp_le_read_remote_features cp; 5830 - 5831 - cp.handle = __cpu_to_le16(conn->handle); 5832 - 5833 - hci_send_cmd(hdev, HCI_OP_LE_READ_REMOTE_FEATURES, 5834 - sizeof(cp), &cp); 5835 - 5836 - hci_conn_hold(conn); 5837 - } else { 5778 + err = hci_le_read_remote_features(conn); 5779 + if (err) { 5838 5780 conn->state = BT_CONNECTED; 5839 5781 hci_connect_cfm(conn, status); 5840 5782 } ··· 6630 6608 6631 6609 conn->state = BT_CONNECTED; 6632 6610 hci_connect_cfm(conn, status); 6633 - hci_conn_drop(conn); 6634 6611 } 6635 6612 } 6636 6613 ··· 7207 7186 hci_dev_unlock(hdev); 7208 7187 } 7209 7188 7189 + static void hci_le_read_all_remote_features_evt(struct hci_dev *hdev, 7190 + void *data, struct sk_buff *skb) 7191 + { 7192 + struct hci_evt_le_read_all_remote_features_complete *ev = data; 7193 + struct hci_conn *conn; 7194 + 7195 + bt_dev_dbg(hdev, "status 0x%2.2x", ev->status); 7196 + 7197 + hci_dev_lock(hdev); 7198 + 7199 + conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 7200 + if (!conn) 7201 + goto unlock; 7202 + 7203 + if (!ev->status) 7204 + memcpy(conn->le_features, ev->features, 248); 7205 + 7206 + if (conn->state == BT_CONFIG) { 7207 + __u8 status; 7208 + 7209 + /* If the local controller supports peripheral-initiated 7210 + * features exchange, but the remote controller does 7211 + * not, then it is possible that the error code 0x1a 7212 + * for unsupported remote feature gets returned. 7213 + * 7214 + * In this specific case, allow the connection to 7215 + * transition into connected state and mark it as 7216 + * successful. 7217 + */ 7218 + if (!conn->out && 7219 + ev->status == HCI_ERROR_UNSUPPORTED_REMOTE_FEATURE && 7220 + (hdev->le_features[0] & HCI_LE_PERIPHERAL_FEATURES)) 7221 + status = 0x00; 7222 + else 7223 + status = ev->status; 7224 + 7225 + conn->state = BT_CONNECTED; 7226 + hci_connect_cfm(conn, status); 7227 + } 7228 + 7229 + unlock: 7230 + hci_dev_unlock(hdev); 7231 + } 7232 + 7210 7233 #define HCI_LE_EV_VL(_op, _func, _min_len, _max_len) \ 7211 7234 [_op] = { \ 7212 7235 .func = _func, \ ··· 7355 7290 HCI_LE_EV_VL(HCI_EVT_LE_BIG_INFO_ADV_REPORT, 7356 7291 hci_le_big_info_adv_report_evt, 7357 7292 sizeof(struct hci_evt_le_big_info_adv_report), 7293 + HCI_MAX_EVENT_SIZE), 7294 + /* [0x2b = HCI_EVT_LE_ALL_REMOTE_FEATURES_COMPLETE] */ 7295 + HCI_LE_EV_VL(HCI_EVT_LE_ALL_REMOTE_FEATURES_COMPLETE, 7296 + hci_le_read_all_remote_features_evt, 7297 + sizeof(struct 7298 + hci_evt_le_read_all_remote_features_complete), 7358 7299 HCI_MAX_EVENT_SIZE), 7359 7300 }; 7360 7301
+100 -2
net/bluetooth/hci_sync.c
··· 4011 4011 /* Read LE Local Supported Features */ 4012 4012 static int hci_le_read_local_features_sync(struct hci_dev *hdev) 4013 4013 { 4014 - return __hci_cmd_sync_status(hdev, HCI_OP_LE_READ_LOCAL_FEATURES, 4015 - 0, NULL, HCI_CMD_TIMEOUT); 4014 + int err; 4015 + 4016 + err = __hci_cmd_sync_status(hdev, HCI_OP_LE_READ_LOCAL_FEATURES, 4017 + 0, NULL, HCI_CMD_TIMEOUT); 4018 + if (err) 4019 + return err; 4020 + 4021 + if (ll_ext_feature_capable(hdev) && hdev->commands[47] & BIT(2)) 4022 + return __hci_cmd_sync_status(hdev, 4023 + HCI_OP_LE_READ_ALL_LOCAL_FEATURES, 4024 + 0, NULL, HCI_CMD_TIMEOUT); 4025 + 4026 + return err; 4016 4027 } 4017 4028 4018 4029 /* Read LE Supported States */ ··· 7328 7317 7329 7318 if (err) 7330 7319 kfree(data); 7320 + 7321 + return err; 7322 + } 7323 + 7324 + static void le_read_features_complete(struct hci_dev *hdev, void *data, int err) 7325 + { 7326 + struct hci_conn *conn = data; 7327 + 7328 + bt_dev_dbg(hdev, "err %d", err); 7329 + 7330 + if (err == -ECANCELED) 7331 + return; 7332 + 7333 + hci_conn_drop(conn); 7334 + } 7335 + 7336 + static int hci_le_read_all_remote_features_sync(struct hci_dev *hdev, 7337 + void *data) 7338 + { 7339 + struct hci_conn *conn = data; 7340 + struct hci_cp_le_read_all_remote_features cp; 7341 + 7342 + memset(&cp, 0, sizeof(cp)); 7343 + cp.handle = cpu_to_le16(conn->handle); 7344 + cp.pages = 10; /* Attempt to read all pages */ 7345 + 7346 + /* Wait for HCI_EVT_LE_ALL_REMOTE_FEATURES_COMPLETE event otherwise 7347 + * hci_conn_drop may run prematurely causing a disconnection. 7348 + */ 7349 + return __hci_cmd_sync_status_sk(hdev, 7350 + HCI_OP_LE_READ_ALL_REMOTE_FEATURES, 7351 + sizeof(cp), &cp, 7352 + HCI_EVT_LE_ALL_REMOTE_FEATURES_COMPLETE, 7353 + HCI_CMD_TIMEOUT, NULL); 7354 + 7355 + return __hci_cmd_sync_status(hdev, HCI_OP_LE_READ_ALL_REMOTE_FEATURES, 7356 + sizeof(cp), &cp, HCI_CMD_TIMEOUT); 7357 + } 7358 + 7359 + static int hci_le_read_remote_features_sync(struct hci_dev *hdev, void *data) 7360 + { 7361 + struct hci_conn *conn = data; 7362 + struct hci_cp_le_read_remote_features cp; 7363 + 7364 + if (!hci_conn_valid(hdev, conn)) 7365 + return -ECANCELED; 7366 + 7367 + /* Check if LL Extended Feature Set is supported and 7368 + * HCI_OP_LE_READ_ALL_REMOTE_FEATURES is supported then use that to read 7369 + * all features. 7370 + */ 7371 + if (ll_ext_feature_capable(hdev) && hdev->commands[47] & BIT(3)) 7372 + return hci_le_read_all_remote_features_sync(hdev, data); 7373 + 7374 + memset(&cp, 0, sizeof(cp)); 7375 + cp.handle = cpu_to_le16(conn->handle); 7376 + 7377 + /* Wait for HCI_EV_LE_REMOTE_FEAT_COMPLETE event otherwise 7378 + * hci_conn_drop may run prematurely causing a disconnection. 7379 + */ 7380 + return __hci_cmd_sync_status_sk(hdev, HCI_OP_LE_READ_REMOTE_FEATURES, 7381 + sizeof(cp), &cp, 7382 + HCI_EV_LE_REMOTE_FEAT_COMPLETE, 7383 + HCI_CMD_TIMEOUT, NULL); 7384 + } 7385 + 7386 + int hci_le_read_remote_features(struct hci_conn *conn) 7387 + { 7388 + struct hci_dev *hdev = conn->hdev; 7389 + int err; 7390 + 7391 + /* The remote features procedure is defined for central 7392 + * role only. So only in case of an initiated connection 7393 + * request the remote features. 7394 + * 7395 + * If the local controller supports peripheral-initiated features 7396 + * exchange, then requesting the remote features in peripheral 7397 + * role is possible. Otherwise just transition into the 7398 + * connected state without requesting the remote features. 7399 + */ 7400 + if (conn->out || (hdev->le_features[0] & HCI_LE_PERIPHERAL_FEATURES)) 7401 + err = hci_cmd_sync_queue_once(hdev, 7402 + hci_le_read_remote_features_sync, 7403 + hci_conn_hold(conn), 7404 + le_read_features_complete); 7405 + else 7406 + err = -EOPNOTSUPP; 7331 7407 7332 7408 return err; 7333 7409 }