diff options
Diffstat (limited to 'net/bluetooth/hci_conn.c')
-rw-r--r-- | net/bluetooth/hci_conn.c | 64 |
1 files changed, 41 insertions, 23 deletions
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index a4a789f24c8d..1181db08d9de 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -123,6 +123,8 @@ void hci_add_sco(struct hci_conn *conn, __u16 handle) | |||
123 | conn->state = BT_CONNECT; | 123 | conn->state = BT_CONNECT; |
124 | conn->out = 1; | 124 | conn->out = 1; |
125 | 125 | ||
126 | conn->attempt++; | ||
127 | |||
126 | cp.handle = cpu_to_le16(handle); | 128 | cp.handle = cpu_to_le16(handle); |
127 | cp.pkt_type = cpu_to_le16(conn->pkt_type); | 129 | cp.pkt_type = cpu_to_le16(conn->pkt_type); |
128 | 130 | ||
@@ -139,6 +141,8 @@ void hci_setup_sync(struct hci_conn *conn, __u16 handle) | |||
139 | conn->state = BT_CONNECT; | 141 | conn->state = BT_CONNECT; |
140 | conn->out = 1; | 142 | conn->out = 1; |
141 | 143 | ||
144 | conn->attempt++; | ||
145 | |||
142 | cp.handle = cpu_to_le16(handle); | 146 | cp.handle = cpu_to_le16(handle); |
143 | cp.pkt_type = cpu_to_le16(conn->pkt_type); | 147 | cp.pkt_type = cpu_to_le16(conn->pkt_type); |
144 | 148 | ||
@@ -155,6 +159,7 @@ static void hci_conn_timeout(unsigned long arg) | |||
155 | { | 159 | { |
156 | struct hci_conn *conn = (void *) arg; | 160 | struct hci_conn *conn = (void *) arg; |
157 | struct hci_dev *hdev = conn->hdev; | 161 | struct hci_dev *hdev = conn->hdev; |
162 | __u8 reason; | ||
158 | 163 | ||
159 | BT_DBG("conn %p state %d", conn, conn->state); | 164 | BT_DBG("conn %p state %d", conn, conn->state); |
160 | 165 | ||
@@ -173,7 +178,8 @@ static void hci_conn_timeout(unsigned long arg) | |||
173 | break; | 178 | break; |
174 | case BT_CONFIG: | 179 | case BT_CONFIG: |
175 | case BT_CONNECTED: | 180 | case BT_CONNECTED: |
176 | hci_acl_disconn(conn, 0x13); | 181 | reason = hci_proto_disconn_ind(conn); |
182 | hci_acl_disconn(conn, reason); | ||
177 | break; | 183 | break; |
178 | default: | 184 | default: |
179 | conn->state = BT_CLOSED; | 185 | conn->state = BT_CLOSED; |
@@ -216,12 +222,13 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) | |||
216 | break; | 222 | break; |
217 | case SCO_LINK: | 223 | case SCO_LINK: |
218 | if (lmp_esco_capable(hdev)) | 224 | if (lmp_esco_capable(hdev)) |
219 | conn->pkt_type = hdev->esco_type & SCO_ESCO_MASK; | 225 | conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | |
226 | (hdev->esco_type & EDR_ESCO_MASK); | ||
220 | else | 227 | else |
221 | conn->pkt_type = hdev->pkt_type & SCO_PTYPE_MASK; | 228 | conn->pkt_type = hdev->pkt_type & SCO_PTYPE_MASK; |
222 | break; | 229 | break; |
223 | case ESCO_LINK: | 230 | case ESCO_LINK: |
224 | conn->pkt_type = hdev->esco_type; | 231 | conn->pkt_type = hdev->esco_type & ~EDR_ESCO_MASK; |
225 | break; | 232 | break; |
226 | } | 233 | } |
227 | 234 | ||
@@ -280,6 +287,8 @@ int hci_conn_del(struct hci_conn *conn) | |||
280 | 287 | ||
281 | skb_queue_purge(&conn->data_q); | 288 | skb_queue_purge(&conn->data_q); |
282 | 289 | ||
290 | hci_conn_del_sysfs(conn); | ||
291 | |||
283 | return 0; | 292 | return 0; |
284 | } | 293 | } |
285 | 294 | ||
@@ -325,7 +334,7 @@ EXPORT_SYMBOL(hci_get_route); | |||
325 | 334 | ||
326 | /* Create SCO or ACL connection. | 335 | /* Create SCO or ACL connection. |
327 | * Device _must_ be locked */ | 336 | * Device _must_ be locked */ |
328 | struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 auth_type) | 337 | struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 sec_level, __u8 auth_type) |
329 | { | 338 | { |
330 | struct hci_conn *acl; | 339 | struct hci_conn *acl; |
331 | struct hci_conn *sco; | 340 | struct hci_conn *sco; |
@@ -340,6 +349,7 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 | |||
340 | hci_conn_hold(acl); | 349 | hci_conn_hold(acl); |
341 | 350 | ||
342 | if (acl->state == BT_OPEN || acl->state == BT_CLOSED) { | 351 | if (acl->state == BT_OPEN || acl->state == BT_CLOSED) { |
352 | acl->sec_level = sec_level; | ||
343 | acl->auth_type = auth_type; | 353 | acl->auth_type = auth_type; |
344 | hci_acl_connect(acl); | 354 | hci_acl_connect(acl); |
345 | } | 355 | } |
@@ -385,51 +395,59 @@ int hci_conn_check_link_mode(struct hci_conn *conn) | |||
385 | EXPORT_SYMBOL(hci_conn_check_link_mode); | 395 | EXPORT_SYMBOL(hci_conn_check_link_mode); |
386 | 396 | ||
387 | /* Authenticate remote device */ | 397 | /* Authenticate remote device */ |
388 | int hci_conn_auth(struct hci_conn *conn) | 398 | static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) |
389 | { | 399 | { |
390 | BT_DBG("conn %p", conn); | 400 | BT_DBG("conn %p", conn); |
391 | 401 | ||
392 | if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0) { | 402 | if (sec_level > conn->sec_level) |
393 | if (!(conn->auth_type & 0x01)) { | 403 | conn->sec_level = sec_level; |
394 | conn->auth_type |= 0x01; | 404 | else if (conn->link_mode & HCI_LM_AUTH) |
395 | conn->link_mode &= ~HCI_LM_AUTH; | ||
396 | } | ||
397 | } | ||
398 | |||
399 | if (conn->link_mode & HCI_LM_AUTH) | ||
400 | return 1; | 405 | return 1; |
401 | 406 | ||
407 | conn->auth_type = auth_type; | ||
408 | |||
402 | if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { | 409 | if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { |
403 | struct hci_cp_auth_requested cp; | 410 | struct hci_cp_auth_requested cp; |
404 | cp.handle = cpu_to_le16(conn->handle); | 411 | cp.handle = cpu_to_le16(conn->handle); |
405 | hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED, | 412 | hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED, |
406 | sizeof(cp), &cp); | 413 | sizeof(cp), &cp); |
407 | } | 414 | } |
415 | |||
408 | return 0; | 416 | return 0; |
409 | } | 417 | } |
410 | EXPORT_SYMBOL(hci_conn_auth); | ||
411 | 418 | ||
412 | /* Enable encryption */ | 419 | /* Enable security */ |
413 | int hci_conn_encrypt(struct hci_conn *conn) | 420 | int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) |
414 | { | 421 | { |
415 | BT_DBG("conn %p", conn); | 422 | BT_DBG("conn %p", conn); |
416 | 423 | ||
424 | if (sec_level == BT_SECURITY_SDP) | ||
425 | return 1; | ||
426 | |||
427 | if (sec_level == BT_SECURITY_LOW) { | ||
428 | if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0) | ||
429 | return hci_conn_auth(conn, sec_level, auth_type); | ||
430 | else | ||
431 | return 1; | ||
432 | } | ||
433 | |||
417 | if (conn->link_mode & HCI_LM_ENCRYPT) | 434 | if (conn->link_mode & HCI_LM_ENCRYPT) |
418 | return hci_conn_auth(conn); | 435 | return hci_conn_auth(conn, sec_level, auth_type); |
419 | 436 | ||
420 | if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) | 437 | if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) |
421 | return 0; | 438 | return 0; |
422 | 439 | ||
423 | if (hci_conn_auth(conn)) { | 440 | if (hci_conn_auth(conn, sec_level, auth_type)) { |
424 | struct hci_cp_set_conn_encrypt cp; | 441 | struct hci_cp_set_conn_encrypt cp; |
425 | cp.handle = cpu_to_le16(conn->handle); | 442 | cp.handle = cpu_to_le16(conn->handle); |
426 | cp.encrypt = 1; | 443 | cp.encrypt = 1; |
427 | hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT, | 444 | hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT, |
428 | sizeof(cp), &cp); | 445 | sizeof(cp), &cp); |
429 | } | 446 | } |
447 | |||
430 | return 0; | 448 | return 0; |
431 | } | 449 | } |
432 | EXPORT_SYMBOL(hci_conn_encrypt); | 450 | EXPORT_SYMBOL(hci_conn_security); |
433 | 451 | ||
434 | /* Change link key */ | 452 | /* Change link key */ |
435 | int hci_conn_change_link_key(struct hci_conn *conn) | 453 | int hci_conn_change_link_key(struct hci_conn *conn) |
@@ -442,12 +460,13 @@ int hci_conn_change_link_key(struct hci_conn *conn) | |||
442 | hci_send_cmd(conn->hdev, HCI_OP_CHANGE_CONN_LINK_KEY, | 460 | hci_send_cmd(conn->hdev, HCI_OP_CHANGE_CONN_LINK_KEY, |
443 | sizeof(cp), &cp); | 461 | sizeof(cp), &cp); |
444 | } | 462 | } |
463 | |||
445 | return 0; | 464 | return 0; |
446 | } | 465 | } |
447 | EXPORT_SYMBOL(hci_conn_change_link_key); | 466 | EXPORT_SYMBOL(hci_conn_change_link_key); |
448 | 467 | ||
449 | /* Switch role */ | 468 | /* Switch role */ |
450 | int hci_conn_switch_role(struct hci_conn *conn, uint8_t role) | 469 | int hci_conn_switch_role(struct hci_conn *conn, __u8 role) |
451 | { | 470 | { |
452 | BT_DBG("conn %p", conn); | 471 | BT_DBG("conn %p", conn); |
453 | 472 | ||
@@ -460,6 +479,7 @@ int hci_conn_switch_role(struct hci_conn *conn, uint8_t role) | |||
460 | cp.role = role; | 479 | cp.role = role; |
461 | hci_send_cmd(conn->hdev, HCI_OP_SWITCH_ROLE, sizeof(cp), &cp); | 480 | hci_send_cmd(conn->hdev, HCI_OP_SWITCH_ROLE, sizeof(cp), &cp); |
462 | } | 481 | } |
482 | |||
463 | return 0; | 483 | return 0; |
464 | } | 484 | } |
465 | EXPORT_SYMBOL(hci_conn_switch_role); | 485 | EXPORT_SYMBOL(hci_conn_switch_role); |
@@ -542,9 +562,7 @@ void hci_conn_hash_flush(struct hci_dev *hdev) | |||
542 | 562 | ||
543 | c->state = BT_CLOSED; | 563 | c->state = BT_CLOSED; |
544 | 564 | ||
545 | hci_conn_del_sysfs(c); | 565 | hci_proto_disconn_cfm(c, 0x16); |
546 | |||
547 | hci_proto_disconn_ind(c, 0x16); | ||
548 | hci_conn_del(c); | 566 | hci_conn_del(c); |
549 | } | 567 | } |
550 | } | 568 | } |