diff options
Diffstat (limited to 'include/net/bluetooth/hci_core.h')
| -rw-r--r-- | include/net/bluetooth/hci_core.h | 84 |
1 files changed, 57 insertions, 27 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 46a43b721dd6..01f9316b4c23 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
| @@ -169,6 +169,7 @@ struct hci_conn { | |||
| 169 | __u16 link_policy; | 169 | __u16 link_policy; |
| 170 | __u32 link_mode; | 170 | __u32 link_mode; |
| 171 | __u8 auth_type; | 171 | __u8 auth_type; |
| 172 | __u8 sec_level; | ||
| 172 | __u8 power_save; | 173 | __u8 power_save; |
| 173 | unsigned long pend; | 174 | unsigned long pend; |
| 174 | 175 | ||
| @@ -325,12 +326,11 @@ int hci_conn_del(struct hci_conn *conn); | |||
| 325 | void hci_conn_hash_flush(struct hci_dev *hdev); | 326 | void hci_conn_hash_flush(struct hci_dev *hdev); |
| 326 | void hci_conn_check_pending(struct hci_dev *hdev); | 327 | void hci_conn_check_pending(struct hci_dev *hdev); |
| 327 | 328 | ||
| 328 | struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 auth_type); | 329 | struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 sec_level, __u8 auth_type); |
| 329 | int hci_conn_check_link_mode(struct hci_conn *conn); | 330 | int hci_conn_check_link_mode(struct hci_conn *conn); |
| 330 | int hci_conn_auth(struct hci_conn *conn); | 331 | int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type); |
| 331 | int hci_conn_encrypt(struct hci_conn *conn); | ||
| 332 | int hci_conn_change_link_key(struct hci_conn *conn); | 332 | int hci_conn_change_link_key(struct hci_conn *conn); |
| 333 | int hci_conn_switch_role(struct hci_conn *conn, uint8_t role); | 333 | int hci_conn_switch_role(struct hci_conn *conn, __u8 role); |
| 334 | 334 | ||
| 335 | void hci_conn_enter_active_mode(struct hci_conn *conn); | 335 | void hci_conn_enter_active_mode(struct hci_conn *conn); |
| 336 | void hci_conn_enter_sniff_mode(struct hci_conn *conn); | 336 | void hci_conn_enter_sniff_mode(struct hci_conn *conn); |
| @@ -470,26 +470,26 @@ void hci_conn_del_sysfs(struct hci_conn *conn); | |||
| 470 | 470 | ||
| 471 | /* ----- HCI protocols ----- */ | 471 | /* ----- HCI protocols ----- */ |
| 472 | struct hci_proto { | 472 | struct hci_proto { |
| 473 | char *name; | 473 | char *name; |
| 474 | unsigned int id; | 474 | unsigned int id; |
| 475 | unsigned long flags; | 475 | unsigned long flags; |
| 476 | 476 | ||
| 477 | void *priv; | 477 | void *priv; |
| 478 | 478 | ||
| 479 | int (*connect_ind) (struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type); | 479 | int (*connect_ind) (struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type); |
| 480 | int (*connect_cfm) (struct hci_conn *conn, __u8 status); | 480 | int (*connect_cfm) (struct hci_conn *conn, __u8 status); |
| 481 | int (*disconn_ind) (struct hci_conn *conn, __u8 reason); | 481 | int (*disconn_ind) (struct hci_conn *conn); |
| 482 | int (*disconn_cfm) (struct hci_conn *conn, __u8 reason); | ||
| 482 | int (*recv_acldata) (struct hci_conn *conn, struct sk_buff *skb, __u16 flags); | 483 | int (*recv_acldata) (struct hci_conn *conn, struct sk_buff *skb, __u16 flags); |
| 483 | int (*recv_scodata) (struct hci_conn *conn, struct sk_buff *skb); | 484 | int (*recv_scodata) (struct hci_conn *conn, struct sk_buff *skb); |
| 484 | int (*auth_cfm) (struct hci_conn *conn, __u8 status); | 485 | int (*security_cfm) (struct hci_conn *conn, __u8 status, __u8 encrypt); |
| 485 | int (*encrypt_cfm) (struct hci_conn *conn, __u8 status, __u8 encrypt); | ||
| 486 | }; | 486 | }; |
| 487 | 487 | ||
| 488 | static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type) | 488 | static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type) |
| 489 | { | 489 | { |
| 490 | register struct hci_proto *hp; | 490 | register struct hci_proto *hp; |
| 491 | int mask = 0; | 491 | int mask = 0; |
| 492 | 492 | ||
| 493 | hp = hci_proto[HCI_PROTO_L2CAP]; | 493 | hp = hci_proto[HCI_PROTO_L2CAP]; |
| 494 | if (hp && hp->connect_ind) | 494 | if (hp && hp->connect_ind) |
| 495 | mask |= hp->connect_ind(hdev, bdaddr, type); | 495 | mask |= hp->connect_ind(hdev, bdaddr, type); |
| @@ -514,30 +514,52 @@ static inline void hci_proto_connect_cfm(struct hci_conn *conn, __u8 status) | |||
| 514 | hp->connect_cfm(conn, status); | 514 | hp->connect_cfm(conn, status); |
| 515 | } | 515 | } |
| 516 | 516 | ||
| 517 | static inline void hci_proto_disconn_ind(struct hci_conn *conn, __u8 reason) | 517 | static inline int hci_proto_disconn_ind(struct hci_conn *conn) |
| 518 | { | 518 | { |
| 519 | register struct hci_proto *hp; | 519 | register struct hci_proto *hp; |
| 520 | int reason = 0x13; | ||
| 520 | 521 | ||
| 521 | hp = hci_proto[HCI_PROTO_L2CAP]; | 522 | hp = hci_proto[HCI_PROTO_L2CAP]; |
| 522 | if (hp && hp->disconn_ind) | 523 | if (hp && hp->disconn_ind) |
| 523 | hp->disconn_ind(conn, reason); | 524 | reason = hp->disconn_ind(conn); |
| 524 | 525 | ||
| 525 | hp = hci_proto[HCI_PROTO_SCO]; | 526 | hp = hci_proto[HCI_PROTO_SCO]; |
| 526 | if (hp && hp->disconn_ind) | 527 | if (hp && hp->disconn_ind) |
| 527 | hp->disconn_ind(conn, reason); | 528 | reason = hp->disconn_ind(conn); |
| 529 | |||
| 530 | return reason; | ||
| 531 | } | ||
| 532 | |||
| 533 | static inline void hci_proto_disconn_cfm(struct hci_conn *conn, __u8 reason) | ||
| 534 | { | ||
| 535 | register struct hci_proto *hp; | ||
| 536 | |||
| 537 | hp = hci_proto[HCI_PROTO_L2CAP]; | ||
| 538 | if (hp && hp->disconn_cfm) | ||
| 539 | hp->disconn_cfm(conn, reason); | ||
| 540 | |||
| 541 | hp = hci_proto[HCI_PROTO_SCO]; | ||
| 542 | if (hp && hp->disconn_cfm) | ||
| 543 | hp->disconn_cfm(conn, reason); | ||
| 528 | } | 544 | } |
| 529 | 545 | ||
| 530 | static inline void hci_proto_auth_cfm(struct hci_conn *conn, __u8 status) | 546 | static inline void hci_proto_auth_cfm(struct hci_conn *conn, __u8 status) |
| 531 | { | 547 | { |
| 532 | register struct hci_proto *hp; | 548 | register struct hci_proto *hp; |
| 549 | __u8 encrypt; | ||
| 550 | |||
| 551 | if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) | ||
| 552 | return; | ||
| 553 | |||
| 554 | encrypt = (conn->link_mode & HCI_LM_ENCRYPT) ? 0x01 : 0x00; | ||
| 533 | 555 | ||
| 534 | hp = hci_proto[HCI_PROTO_L2CAP]; | 556 | hp = hci_proto[HCI_PROTO_L2CAP]; |
| 535 | if (hp && hp->auth_cfm) | 557 | if (hp && hp->security_cfm) |
| 536 | hp->auth_cfm(conn, status); | 558 | hp->security_cfm(conn, status, encrypt); |
| 537 | 559 | ||
| 538 | hp = hci_proto[HCI_PROTO_SCO]; | 560 | hp = hci_proto[HCI_PROTO_SCO]; |
| 539 | if (hp && hp->auth_cfm) | 561 | if (hp && hp->security_cfm) |
| 540 | hp->auth_cfm(conn, status); | 562 | hp->security_cfm(conn, status, encrypt); |
| 541 | } | 563 | } |
| 542 | 564 | ||
| 543 | static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encrypt) | 565 | static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encrypt) |
| @@ -545,12 +567,12 @@ static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status, __u | |||
| 545 | register struct hci_proto *hp; | 567 | register struct hci_proto *hp; |
| 546 | 568 | ||
| 547 | hp = hci_proto[HCI_PROTO_L2CAP]; | 569 | hp = hci_proto[HCI_PROTO_L2CAP]; |
| 548 | if (hp && hp->encrypt_cfm) | 570 | if (hp && hp->security_cfm) |
| 549 | hp->encrypt_cfm(conn, status, encrypt); | 571 | hp->security_cfm(conn, status, encrypt); |
| 550 | 572 | ||
| 551 | hp = hci_proto[HCI_PROTO_SCO]; | 573 | hp = hci_proto[HCI_PROTO_SCO]; |
| 552 | if (hp && hp->encrypt_cfm) | 574 | if (hp && hp->security_cfm) |
| 553 | hp->encrypt_cfm(conn, status, encrypt); | 575 | hp->security_cfm(conn, status, encrypt); |
| 554 | } | 576 | } |
| 555 | 577 | ||
| 556 | int hci_register_proto(struct hci_proto *hproto); | 578 | int hci_register_proto(struct hci_proto *hproto); |
| @@ -562,8 +584,7 @@ struct hci_cb { | |||
| 562 | 584 | ||
| 563 | char *name; | 585 | char *name; |
| 564 | 586 | ||
| 565 | void (*auth_cfm) (struct hci_conn *conn, __u8 status); | 587 | void (*security_cfm) (struct hci_conn *conn, __u8 status, __u8 encrypt); |
| 566 | void (*encrypt_cfm) (struct hci_conn *conn, __u8 status, __u8 encrypt); | ||
| 567 | void (*key_change_cfm) (struct hci_conn *conn, __u8 status); | 588 | void (*key_change_cfm) (struct hci_conn *conn, __u8 status); |
| 568 | void (*role_switch_cfm) (struct hci_conn *conn, __u8 status, __u8 role); | 589 | void (*role_switch_cfm) (struct hci_conn *conn, __u8 status, __u8 role); |
| 569 | }; | 590 | }; |
| @@ -571,14 +592,20 @@ struct hci_cb { | |||
| 571 | static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status) | 592 | static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status) |
| 572 | { | 593 | { |
| 573 | struct list_head *p; | 594 | struct list_head *p; |
| 595 | __u8 encrypt; | ||
| 574 | 596 | ||
| 575 | hci_proto_auth_cfm(conn, status); | 597 | hci_proto_auth_cfm(conn, status); |
| 576 | 598 | ||
| 599 | if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) | ||
| 600 | return; | ||
| 601 | |||
| 602 | encrypt = (conn->link_mode & HCI_LM_ENCRYPT) ? 0x01 : 0x00; | ||
| 603 | |||
| 577 | read_lock_bh(&hci_cb_list_lock); | 604 | read_lock_bh(&hci_cb_list_lock); |
| 578 | list_for_each(p, &hci_cb_list) { | 605 | list_for_each(p, &hci_cb_list) { |
| 579 | struct hci_cb *cb = list_entry(p, struct hci_cb, list); | 606 | struct hci_cb *cb = list_entry(p, struct hci_cb, list); |
| 580 | if (cb->auth_cfm) | 607 | if (cb->security_cfm) |
| 581 | cb->auth_cfm(conn, status); | 608 | cb->security_cfm(conn, status, encrypt); |
| 582 | } | 609 | } |
| 583 | read_unlock_bh(&hci_cb_list_lock); | 610 | read_unlock_bh(&hci_cb_list_lock); |
| 584 | } | 611 | } |
| @@ -587,13 +614,16 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encr | |||
| 587 | { | 614 | { |
| 588 | struct list_head *p; | 615 | struct list_head *p; |
| 589 | 616 | ||
| 617 | if (conn->sec_level == BT_SECURITY_SDP) | ||
| 618 | conn->sec_level = BT_SECURITY_LOW; | ||
| 619 | |||
| 590 | hci_proto_encrypt_cfm(conn, status, encrypt); | 620 | hci_proto_encrypt_cfm(conn, status, encrypt); |
| 591 | 621 | ||
| 592 | read_lock_bh(&hci_cb_list_lock); | 622 | read_lock_bh(&hci_cb_list_lock); |
| 593 | list_for_each(p, &hci_cb_list) { | 623 | list_for_each(p, &hci_cb_list) { |
| 594 | struct hci_cb *cb = list_entry(p, struct hci_cb, list); | 624 | struct hci_cb *cb = list_entry(p, struct hci_cb, list); |
| 595 | if (cb->encrypt_cfm) | 625 | if (cb->security_cfm) |
| 596 | cb->encrypt_cfm(conn, status, encrypt); | 626 | cb->security_cfm(conn, status, encrypt); |
| 597 | } | 627 | } |
| 598 | read_unlock_bh(&hci_cb_list_lock); | 628 | read_unlock_bh(&hci_cb_list_lock); |
| 599 | } | 629 | } |
