Commit 769be974d0c7b4fe1a52f9cdaad22259b60953f7

Authored by Marcel Holtmann
1 parent a8bd28baf2

[Bluetooth] Use ACL config stage to retrieve remote features

The Bluetooth technology introduces new features on a regular basis
and for some of them it is important that the hardware on both sides
support them. For features like Simple Pairing it is important that
the host stacks on both sides have switched this feature on. To make
valid decisions, a config stage during ACL link establishment has been
introduced that retrieves remote features and if needed also the remote
extended features (known as remote host features) before signalling
this link as connected.

This change introduces full reference counting of incoming and outgoing
ACL links and the Bluetooth core will disconnect both if no owner of it
is present. To better handle interoperability during the pairing phase
the disconnect timeout for incoming connections has been increased to
10 seconds. This is five times more than for outgoing connections.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>

Showing 5 changed files with 118 additions and 23 deletions Side-by-side Diff

include/net/bluetooth/hci.h
... ... @@ -180,6 +180,8 @@
180 180  
181 181 #define LMP_SNIFF_SUBR 0x02
182 182  
  183 +#define LMP_SIMPLE_PAIR 0x08
  184 +
183 185 /* Connection modes */
184 186 #define HCI_CM_ACTIVE 0x0000
185 187 #define HCI_CM_HOLD 0x0001
include/net/bluetooth/hci_core.h
... ... @@ -348,7 +348,7 @@
348 348 if (conn->state == BT_CONNECTED) {
349 349 timeo = msecs_to_jiffies(HCI_DISCONN_TIMEOUT);
350 350 if (!conn->out)
351   - timeo *= 2;
  351 + timeo *= 5;
352 352 } else
353 353 timeo = msecs_to_jiffies(10);
354 354 } else
... ... @@ -463,6 +463,7 @@
463 463 #define lmp_sniff_capable(dev) ((dev)->features[0] & LMP_SNIFF)
464 464 #define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR)
465 465 #define lmp_esco_capable(dev) ((dev)->features[3] & LMP_ESCO)
  466 +#define lmp_ssp_capable(dev) ((dev)->features[6] & LMP_SIMPLE_PAIR)
466 467  
467 468 /* ----- HCI protocols ----- */
468 469 struct hci_proto {
net/bluetooth/hci_conn.c
... ... @@ -170,11 +170,13 @@
170 170  
171 171 switch (conn->state) {
172 172 case BT_CONNECT:
  173 + case BT_CONNECT2:
173 174 if (conn->type == ACL_LINK)
174 175 hci_acl_connect_cancel(conn);
175 176 else
176 177 hci_acl_disconn(conn, 0x13);
177 178 break;
  179 + case BT_CONFIG:
178 180 case BT_CONNECTED:
179 181 hci_acl_disconn(conn, 0x13);
180 182 break;
net/bluetooth/hci_core.c
... ... @@ -1283,9 +1283,12 @@
1283 1283 struct hci_conn *c;
1284 1284 c = list_entry(p, struct hci_conn, list);
1285 1285  
1286   - if (c->type != type || c->state != BT_CONNECTED
1287   - || skb_queue_empty(&c->data_q))
  1286 + if (c->type != type || skb_queue_empty(&c->data_q))
1288 1287 continue;
  1288 +
  1289 + if (c->state != BT_CONNECTED && c->state != BT_CONFIG)
  1290 + continue;
  1291 +
1289 1292 num++;
1290 1293  
1291 1294 if (c->sent < min) {
net/bluetooth/hci_event.c
... ... @@ -624,6 +624,62 @@
624 624 BT_DBG("%s status 0x%x", hdev->name, status);
625 625 }
626 626  
  627 +static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
  628 +{
  629 + struct hci_cp_read_remote_features *cp;
  630 + struct hci_conn *conn;
  631 +
  632 + BT_DBG("%s status 0x%x", hdev->name, status);
  633 +
  634 + if (!status)
  635 + return;
  636 +
  637 + cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
  638 + if (!cp)
  639 + return;
  640 +
  641 + hci_dev_lock(hdev);
  642 +
  643 + conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
  644 + if (conn) {
  645 + if (conn->state == BT_CONFIG) {
  646 + conn->state = BT_CONNECTED;
  647 + hci_proto_connect_cfm(conn, status);
  648 + hci_conn_put(conn);
  649 + }
  650 + }
  651 +
  652 + hci_dev_unlock(hdev);
  653 +}
  654 +
  655 +static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
  656 +{
  657 + struct hci_cp_read_remote_ext_features *cp;
  658 + struct hci_conn *conn;
  659 +
  660 + BT_DBG("%s status 0x%x", hdev->name, status);
  661 +
  662 + if (!status)
  663 + return;
  664 +
  665 + cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
  666 + if (!cp)
  667 + return;
  668 +
  669 + hci_dev_lock(hdev);
  670 +
  671 + conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
  672 + if (conn) {
  673 + if (conn->state == BT_CONFIG) {
  674 + conn->state = BT_CONNECTED;
  675 + hci_proto_connect_cfm(conn, status);
  676 + hci_conn_put(conn);
  677 + }
  678 + }
  679 +
  680 + hci_dev_unlock(hdev);
  681 +}
  682 +
627 683 static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
628 684 {
629 685 struct hci_cp_setup_sync_conn *cp;
630 686  
... ... @@ -759,8 +815,13 @@
759 815  
760 816 if (!ev->status) {
761 817 conn->handle = __le16_to_cpu(ev->handle);
762   - conn->state = BT_CONNECTED;
763 818  
  819 + if (conn->type == ACL_LINK) {
  820 + conn->state = BT_CONFIG;
  821 + hci_conn_hold(conn);
  822 + } else
  823 + conn->state = BT_CONNECTED;
  824 +
764 825 if (test_bit(HCI_AUTH, &hdev->flags))
765 826 conn->link_mode |= HCI_LM_AUTH;
766 827  
... ... @@ -771,7 +832,8 @@
771 832 if (conn->type == ACL_LINK) {
772 833 struct hci_cp_read_remote_features cp;
773 834 cp.handle = ev->handle;
774   - hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, sizeof(cp), &cp);
  835 + hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
  836 + sizeof(cp), &cp);
775 837 }
776 838  
777 839 /* Set packet type for incoming connection */
... ... @@ -781,10 +843,6 @@
781 843 cp.pkt_type = cpu_to_le16(conn->pkt_type);
782 844 hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
783 845 sizeof(cp), &cp);
784   - } else {
785   - /* Update disconnect timer */
786   - hci_conn_hold(conn);
787   - hci_conn_put(conn);
788 846 }
789 847 } else
790 848 conn->state = BT_CLOSED;
791 849  
... ... @@ -804,9 +862,10 @@
804 862 }
805 863 }
806 864  
807   - hci_proto_connect_cfm(conn, ev->status);
808   - if (ev->status)
  865 + if (ev->status) {
  866 + hci_proto_connect_cfm(conn, ev->status);
809 867 hci_conn_del(conn);
  868 + }
810 869  
811 870 unlock:
812 871 hci_dev_unlock(hdev);
813 872  
814 873  
... ... @@ -1006,15 +1065,30 @@
1006 1065  
1007 1066 BT_DBG("%s status %d", hdev->name, ev->status);
1008 1067  
1009   - if (ev->status)
1010   - return;
1011   -
1012 1068 hci_dev_lock(hdev);
1013 1069  
1014 1070 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1015   - if (conn)
1016   - memcpy(conn->features, ev->features, 8);
  1071 + if (conn) {
  1072 + if (!ev->status)
  1073 + memcpy(conn->features, ev->features, 8);
1017 1074  
  1075 + if (conn->state == BT_CONFIG) {
  1076 + if (!ev->status && lmp_ssp_capable(hdev) &&
  1077 + lmp_ssp_capable(conn)) {
  1078 + struct hci_cp_read_remote_ext_features cp;
  1079 + cp.handle = ev->handle;
  1080 + cp.page = 0x01;
  1081 + hci_send_cmd(hdev,
  1082 + HCI_OP_READ_REMOTE_EXT_FEATURES,
  1083 + sizeof(cp), &cp);
  1084 + } else {
  1085 + conn->state = BT_CONNECTED;
  1086 + hci_proto_connect_cfm(conn, ev->status);
  1087 + hci_conn_put(conn);
  1088 + }
  1089 + }
  1090 + }
  1091 +
1018 1092 hci_dev_unlock(hdev);
1019 1093 }
1020 1094  
... ... @@ -1180,6 +1254,14 @@
1180 1254 hci_cs_remote_name_req(hdev, ev->status);
1181 1255 break;
1182 1256  
  1257 + case HCI_OP_READ_REMOTE_FEATURES:
  1258 + hci_cs_read_remote_features(hdev, ev->status);
  1259 + break;
  1260 +
  1261 + case HCI_OP_READ_REMOTE_EXT_FEATURES:
  1262 + hci_cs_read_remote_ext_features(hdev, ev->status);
  1263 + break;
  1264 +
1183 1265 case HCI_OP_SETUP_SYNC_CONN:
1184 1266 hci_cs_setup_sync_conn(hdev, ev->status);
1185 1267 break;
1186 1268  
1187 1269  
1188 1270  
... ... @@ -1422,19 +1504,24 @@
1422 1504  
1423 1505 BT_DBG("%s", hdev->name);
1424 1506  
1425   - if (ev->status || ev->page != 0x01)
1426   - return;
1427   -
1428 1507 hci_dev_lock(hdev);
1429 1508  
1430 1509 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1431 1510 if (conn) {
1432   - struct inquiry_entry *ie;
  1511 + if (!ev->status && ev->page == 0x01) {
  1512 + struct inquiry_entry *ie;
1433 1513  
1434   - if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst)))
1435   - ie->data.ssp_mode = (ev->features[0] & 0x01);
  1514 + if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst)))
  1515 + ie->data.ssp_mode = (ev->features[0] & 0x01);
1436 1516  
1437   - conn->ssp_mode = (ev->features[0] & 0x01);
  1517 + conn->ssp_mode = (ev->features[0] & 0x01);
  1518 + }
  1519 +
  1520 + if (conn->state == BT_CONFIG) {
  1521 + conn->state = BT_CONNECTED;
  1522 + hci_proto_connect_cfm(conn, ev->status);
  1523 + hci_conn_put(conn);
  1524 + }
1438 1525 }
1439 1526  
1440 1527 hci_dev_unlock(hdev);