aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2014-07-23 15:55:23 -0400
committerJohan Hedberg <johan.hedberg@intel.com>2014-07-23 17:37:23 -0400
commit4b9e7e7516135b1d5f047ad59188b5355bacc106 (patch)
tree6af247445db6e8f0cfa023ffef8bd3d7fb6a2961 /net
parentcd4d5671385ba0c6355e013512ea6d06b1ebce02 (diff)
Bluetooth: Fix issue with ADV_IND reports and auto-connection handling
When adding remote devices to the kernel using the Add Device management command, these devices are explicitly allowed to connect. This kind of incoming connections are possible even when the controller itself is not connectable. For BR/EDR this distinction is pretty simple since there is only one type of incoming connections. With LE this is not that simple anymore since there are ADV_IND and ADV_DIRECT_IND advertising events. The ADV_DIRECT_IND advertising events are send for incoming (slave initiated) connections only. And this is the only thing the kernel should allow when adding devices using action 0x01. This meaning of incoming connections is coming from BR/EDR and needs to be mapped to LE the same way. Supporting the auto-connection of devices using ADV_IND advertising events is an important feature as well. However it does not map to incoming connections. So introduce a new action 0x02 that allows the kernel to connect to devices using ADV_DIRECT_IND and in addition ADV_IND advertising reports. This difference is represented by the new HCI_AUTO_CONN_DIRECT value for only connecting to ADV_DIRECT_IND. For connection to ADV_IND and ADV_DIRECT_IND the old value HCI_AUTO_CONN_ALWAYS is used. Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/hci_core.c1
-rw-r--r--net/bluetooth/hci_event.c27
-rw-r--r--net/bluetooth/mgmt.c9
3 files changed, 33 insertions, 4 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 078f1ecbc058..d8f91d5b0e56 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -3647,6 +3647,7 @@ int hci_conn_params_set(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type,
3647 list_add(&params->action, &hdev->pend_le_reports); 3647 list_add(&params->action, &hdev->pend_le_reports);
3648 hci_update_background_scan(hdev); 3648 hci_update_background_scan(hdev);
3649 break; 3649 break;
3650 case HCI_AUTO_CONN_DIRECT:
3650 case HCI_AUTO_CONN_ALWAYS: 3651 case HCI_AUTO_CONN_ALWAYS:
3651 if (!is_connected(hdev, addr, addr_type)) { 3652 if (!is_connected(hdev, addr, addr_type)) {
3652 list_add(&params->action, &hdev->pend_le_conns); 3653 list_add(&params->action, &hdev->pend_le_conns);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 293dd98ae98f..ba26fbfe481a 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2259,6 +2259,7 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2259 break; 2259 break;
2260 /* Fall through */ 2260 /* Fall through */
2261 2261
2262 case HCI_AUTO_CONN_DIRECT:
2262 case HCI_AUTO_CONN_ALWAYS: 2263 case HCI_AUTO_CONN_ALWAYS:
2263 list_del_init(&params->action); 2264 list_del_init(&params->action);
2264 list_add(&params->action, &hdev->pend_le_conns); 2265 list_add(&params->action, &hdev->pend_le_conns);
@@ -4251,6 +4252,7 @@ static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr,
4251 u8 addr_type, u8 adv_type) 4252 u8 addr_type, u8 adv_type)
4252{ 4253{
4253 struct hci_conn *conn; 4254 struct hci_conn *conn;
4255 struct hci_conn_params *params;
4254 4256
4255 /* If the event is not connectable don't proceed further */ 4257 /* If the event is not connectable don't proceed further */
4256 if (adv_type != LE_ADV_IND && adv_type != LE_ADV_DIRECT_IND) 4258 if (adv_type != LE_ADV_IND && adv_type != LE_ADV_DIRECT_IND)
@@ -4269,8 +4271,31 @@ static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr,
4269 /* If we're not connectable only connect devices that we have in 4271 /* If we're not connectable only connect devices that we have in
4270 * our pend_le_conns list. 4272 * our pend_le_conns list.
4271 */ 4273 */
4272 if (!hci_pend_le_action_lookup(&hdev->pend_le_conns, addr, addr_type)) 4274 params = hci_pend_le_action_lookup(&hdev->pend_le_conns,
4275 addr, addr_type);
4276 if (!params)
4277 return;
4278
4279 switch (params->auto_connect) {
4280 case HCI_AUTO_CONN_DIRECT:
4281 /* Only devices advertising with ADV_DIRECT_IND are
4282 * triggering a connection attempt. This is allowing
4283 * incoming connections from slave devices.
4284 */
4285 if (adv_type != LE_ADV_DIRECT_IND)
4286 return;
4287 break;
4288 case HCI_AUTO_CONN_ALWAYS:
4289 /* Devices advertising with ADV_IND or ADV_DIRECT_IND
4290 * are triggering a connection attempt. This means
4291 * that incoming connectioms from slave device are
4292 * accepted and also outgoing connections to slave
4293 * devices are established when found.
4294 */
4295 break;
4296 default:
4273 return; 4297 return;
4298 }
4274 4299
4275 conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW, 4300 conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW,
4276 HCI_LE_AUTOCONN_TIMEOUT, HCI_ROLE_MASTER); 4301 HCI_LE_AUTOCONN_TIMEOUT, HCI_ROLE_MASTER);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 190668367e42..ccc4653ce658 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -5271,7 +5271,7 @@ static int add_device(struct sock *sk, struct hci_dev *hdev,
5271 MGMT_STATUS_INVALID_PARAMS, 5271 MGMT_STATUS_INVALID_PARAMS,
5272 &cp->addr, sizeof(cp->addr)); 5272 &cp->addr, sizeof(cp->addr));
5273 5273
5274 if (cp->action != 0x00 && cp->action != 0x01) 5274 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
5275 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE, 5275 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5276 MGMT_STATUS_INVALID_PARAMS, 5276 MGMT_STATUS_INVALID_PARAMS,
5277 &cp->addr, sizeof(cp->addr)); 5277 &cp->addr, sizeof(cp->addr));
@@ -5281,7 +5281,7 @@ static int add_device(struct sock *sk, struct hci_dev *hdev,
5281 if (cp->addr.type == BDADDR_BREDR) { 5281 if (cp->addr.type == BDADDR_BREDR) {
5282 bool update_scan; 5282 bool update_scan;
5283 5283
5284 /* Only "connect" action supported for now */ 5284 /* Only incoming connections action is supported for now */
5285 if (cp->action != 0x01) { 5285 if (cp->action != 0x01) {
5286 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE, 5286 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5287 MGMT_STATUS_INVALID_PARAMS, 5287 MGMT_STATUS_INVALID_PARAMS,
@@ -5307,8 +5307,10 @@ static int add_device(struct sock *sk, struct hci_dev *hdev,
5307 else 5307 else
5308 addr_type = ADDR_LE_DEV_RANDOM; 5308 addr_type = ADDR_LE_DEV_RANDOM;
5309 5309
5310 if (cp->action) 5310 if (cp->action == 0x02)
5311 auto_conn = HCI_AUTO_CONN_ALWAYS; 5311 auto_conn = HCI_AUTO_CONN_ALWAYS;
5312 else if (cp->action == 0x01)
5313 auto_conn = HCI_AUTO_CONN_DIRECT;
5312 else 5314 else
5313 auto_conn = HCI_AUTO_CONN_REPORT; 5315 auto_conn = HCI_AUTO_CONN_REPORT;
5314 5316
@@ -5870,6 +5872,7 @@ static void restart_le_actions(struct hci_dev *hdev)
5870 list_del_init(&p->action); 5872 list_del_init(&p->action);
5871 5873
5872 switch (p->auto_connect) { 5874 switch (p->auto_connect) {
5875 case HCI_AUTO_CONN_DIRECT:
5873 case HCI_AUTO_CONN_ALWAYS: 5876 case HCI_AUTO_CONN_ALWAYS:
5874 list_add(&p->action, &hdev->pend_le_conns); 5877 list_add(&p->action, &hdev->pend_le_conns);
5875 break; 5878 break;