aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/hci_event.c
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@nokia.com>2010-11-18 15:22:29 -0500
committerGustavo F. Padovan <padovan@profusion.mobi>2010-12-01 18:04:35 -0500
commit127178d24c7eb2df53b1ba2b6f6f743e88178a1b (patch)
treec7ad18dcce00c21d41971fdb1cace5699549e3a0 /net/bluetooth/hci_event.c
parent392599b95d76f4f3102d8614bdc1957795cd1a3a (diff)
Bluetooth: Automate remote name requests
In Bluetooth there are no automatic updates of remote device names when they get changed on the remote side. Instead, it is a good idea to do a manual name request when a new connection gets created (for whatever reason) since at this point it is very cheap (no costly baseband connection creation needed just for the sake of the name request). So far userspace has been responsible for this extra name request but tighter control is needed in order not to flood Bluetooth controllers with two many commands during connection creation. It has been shown that some controllers simply fail to function correctly if they get too many (almost) simultaneous commands during connection creation. The simplest way to acheive better control of these commands is to move their sending completely to the kernel side. This patch inserts name requests into the sequence of events that the kernel performs during connection creation. It does this after the remote features have been successfully requested and before any pending authentication requests are performed. The code will work sub-optimally with userspace versions that still do the name requesting themselves (it shouldn't break anything though) so it is recommended to combine this with a userspace software version that doesn't have automated name requests. Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net/bluetooth/hci_event.c')
-rw-r--r--net/bluetooth/hci_event.c72
1 files changed, 54 insertions, 18 deletions
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 9c6d9bc1d8af..4165895049b3 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -677,11 +677,9 @@ static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
677 hci_dev_unlock(hdev); 677 hci_dev_unlock(hdev);
678} 678}
679 679
680static int hci_request_outgoing_auth(struct hci_dev *hdev, 680static int hci_outgoing_auth_needed(struct hci_dev *hdev,
681 struct hci_conn *conn) 681 struct hci_conn *conn)
682{ 682{
683 struct hci_cp_auth_requested cp;
684
685 if (conn->state != BT_CONFIG || !conn->out) 683 if (conn->state != BT_CONFIG || !conn->out)
686 return 0; 684 return 0;
687 685
@@ -694,15 +692,35 @@ static int hci_request_outgoing_auth(struct hci_dev *hdev,
694 conn->sec_level != BT_SECURITY_HIGH) 692 conn->sec_level != BT_SECURITY_HIGH)
695 return 0; 693 return 0;
696 694
697 cp.handle = __cpu_to_le16(conn->handle);
698 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
699
700 return 1; 695 return 1;
701} 696}
702 697
703static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) 698static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
704{ 699{
700 struct hci_cp_remote_name_req *cp;
701 struct hci_conn *conn;
702
705 BT_DBG("%s status 0x%x", hdev->name, status); 703 BT_DBG("%s status 0x%x", hdev->name, status);
704
705 /* If successful wait for the name req complete event before
706 * checking for the need to do authentication */
707 if (!status)
708 return;
709
710 cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
711 if (!cp)
712 return;
713
714 hci_dev_lock(hdev);
715
716 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
717 if (conn && hci_outgoing_auth_needed(hdev, conn)) {
718 struct hci_cp_auth_requested cp;
719 cp.handle = __cpu_to_le16(conn->handle);
720 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
721 }
722
723 hci_dev_unlock(hdev);
706} 724}
707 725
708static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) 726static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
@@ -1113,9 +1131,23 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s
1113 1131
1114static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) 1132static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1115{ 1133{
1134 struct hci_ev_remote_name *ev = (void *) skb->data;
1135 struct hci_conn *conn;
1136
1116 BT_DBG("%s", hdev->name); 1137 BT_DBG("%s", hdev->name);
1117 1138
1118 hci_conn_check_pending(hdev); 1139 hci_conn_check_pending(hdev);
1140
1141 hci_dev_lock(hdev);
1142
1143 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1144 if (conn && hci_outgoing_auth_needed(hdev, conn)) {
1145 struct hci_cp_auth_requested cp;
1146 cp.handle = __cpu_to_le16(conn->handle);
1147 hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1148 }
1149
1150 hci_dev_unlock(hdev);
1119} 1151}
1120 1152
1121static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 1153static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
@@ -1179,7 +1211,6 @@ static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff
1179{ 1211{
1180 struct hci_ev_remote_features *ev = (void *) skb->data; 1212 struct hci_ev_remote_features *ev = (void *) skb->data;
1181 struct hci_conn *conn; 1213 struct hci_conn *conn;
1182 int auth_requested;
1183 1214
1184 BT_DBG("%s status %d", hdev->name, ev->status); 1215 BT_DBG("%s status %d", hdev->name, ev->status);
1185 1216
@@ -1204,12 +1235,15 @@ static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff
1204 goto unlock; 1235 goto unlock;
1205 } 1236 }
1206 1237
1207 if (!ev->status) 1238 if (!ev->status) {
1208 auth_requested = hci_request_outgoing_auth(hdev, conn); 1239 struct hci_cp_remote_name_req cp;
1209 else 1240 memset(&cp, 0, sizeof(cp));
1210 auth_requested = 0; 1241 bacpy(&cp.bdaddr, &conn->dst);
1242 cp.pscan_rep_mode = 0x02;
1243 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1244 }
1211 1245
1212 if (!auth_requested) { 1246 if (!hci_outgoing_auth_needed(hdev, conn)) {
1213 conn->state = BT_CONNECTED; 1247 conn->state = BT_CONNECTED;
1214 hci_proto_connect_cfm(conn, ev->status); 1248 hci_proto_connect_cfm(conn, ev->status);
1215 hci_conn_put(conn); 1249 hci_conn_put(conn);
@@ -1667,7 +1701,6 @@ static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_b
1667{ 1701{
1668 struct hci_ev_remote_ext_features *ev = (void *) skb->data; 1702 struct hci_ev_remote_ext_features *ev = (void *) skb->data;
1669 struct hci_conn *conn; 1703 struct hci_conn *conn;
1670 int auth_requested;
1671 1704
1672 BT_DBG("%s", hdev->name); 1705 BT_DBG("%s", hdev->name);
1673 1706
@@ -1689,12 +1722,15 @@ static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_b
1689 if (conn->state != BT_CONFIG) 1722 if (conn->state != BT_CONFIG)
1690 goto unlock; 1723 goto unlock;
1691 1724
1692 if (!ev->status) 1725 if (!ev->status) {
1693 auth_requested = hci_request_outgoing_auth(hdev, conn); 1726 struct hci_cp_remote_name_req cp;
1694 else 1727 memset(&cp, 0, sizeof(cp));
1695 auth_requested = 0; 1728 bacpy(&cp.bdaddr, &conn->dst);
1729 cp.pscan_rep_mode = 0x02;
1730 hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1731 }
1696 1732
1697 if (!auth_requested) { 1733 if (!hci_outgoing_auth_needed(hdev, conn)) {
1698 conn->state = BT_CONNECTED; 1734 conn->state = BT_CONNECTED;
1699 hci_proto_connect_cfm(conn, ev->status); 1735 hci_proto_connect_cfm(conn, ev->status);
1700 hci_conn_put(conn); 1736 hci_conn_put(conn);