diff options
Diffstat (limited to 'net/bluetooth/hci_event.c')
-rw-r--r-- | net/bluetooth/hci_event.c | 99 |
1 files changed, 86 insertions, 13 deletions
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index e2cfeea5ee72..46df2e403df8 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -511,11 +511,11 @@ static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) | |||
511 | struct hci_conn *acl, *sco; | 511 | struct hci_conn *acl, *sco; |
512 | __u16 handle; | 512 | __u16 handle; |
513 | 513 | ||
514 | BT_DBG("%s status 0x%x", hdev->name, status); | ||
515 | |||
514 | if (!status) | 516 | if (!status) |
515 | return; | 517 | return; |
516 | 518 | ||
517 | BT_DBG("%s status 0x%x", hdev->name, status); | ||
518 | |||
519 | cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); | 519 | cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); |
520 | if (!cp) | 520 | if (!cp) |
521 | return; | 521 | return; |
@@ -544,7 +544,34 @@ static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) | |||
544 | 544 | ||
545 | static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) | 545 | static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) |
546 | { | 546 | { |
547 | struct hci_cp_setup_sync_conn *cp; | ||
548 | struct hci_conn *acl, *sco; | ||
549 | __u16 handle; | ||
550 | |||
547 | BT_DBG("%s status 0x%x", hdev->name, status); | 551 | BT_DBG("%s status 0x%x", hdev->name, status); |
552 | |||
553 | if (!status) | ||
554 | return; | ||
555 | |||
556 | cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN); | ||
557 | if (!cp) | ||
558 | return; | ||
559 | |||
560 | handle = __le16_to_cpu(cp->handle); | ||
561 | |||
562 | BT_DBG("%s handle %d", hdev->name, handle); | ||
563 | |||
564 | hci_dev_lock(hdev); | ||
565 | |||
566 | acl = hci_conn_hash_lookup_handle(hdev, handle); | ||
567 | if (acl && (sco = acl->link)) { | ||
568 | sco->state = BT_CLOSED; | ||
569 | |||
570 | hci_proto_connect_cfm(sco, status); | ||
571 | hci_conn_del(sco); | ||
572 | } | ||
573 | |||
574 | hci_dev_unlock(hdev); | ||
548 | } | 575 | } |
549 | 576 | ||
550 | static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) | 577 | static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) |
@@ -692,9 +719,12 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s | |||
692 | if (conn->type == ACL_LINK) { | 719 | if (conn->type == ACL_LINK) { |
693 | struct hci_conn *sco = conn->link; | 720 | struct hci_conn *sco = conn->link; |
694 | if (sco) { | 721 | if (sco) { |
695 | if (!ev->status) | 722 | if (!ev->status) { |
696 | hci_add_sco(sco, conn->handle); | 723 | if (lmp_esco_capable(hdev)) |
697 | else { | 724 | hci_setup_sync(sco, conn->handle); |
725 | else | ||
726 | hci_add_sco(sco, conn->handle); | ||
727 | } else { | ||
698 | hci_proto_connect_cfm(sco, ev->status); | 728 | hci_proto_connect_cfm(sco, ev->status); |
699 | hci_conn_del(sco); | 729 | hci_conn_del(sco); |
700 | } | 730 | } |
@@ -724,9 +754,9 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk | |||
724 | if (mask & HCI_LM_ACCEPT) { | 754 | if (mask & HCI_LM_ACCEPT) { |
725 | /* Connection accepted */ | 755 | /* Connection accepted */ |
726 | struct hci_conn *conn; | 756 | struct hci_conn *conn; |
727 | struct hci_cp_accept_conn_req cp; | ||
728 | 757 | ||
729 | hci_dev_lock(hdev); | 758 | hci_dev_lock(hdev); |
759 | |||
730 | conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); | 760 | conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); |
731 | if (!conn) { | 761 | if (!conn) { |
732 | if (!(conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr))) { | 762 | if (!(conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr))) { |
@@ -735,18 +765,39 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk | |||
735 | return; | 765 | return; |
736 | } | 766 | } |
737 | } | 767 | } |
768 | |||
738 | memcpy(conn->dev_class, ev->dev_class, 3); | 769 | memcpy(conn->dev_class, ev->dev_class, 3); |
739 | conn->state = BT_CONNECT; | 770 | conn->state = BT_CONNECT; |
771 | |||
740 | hci_dev_unlock(hdev); | 772 | hci_dev_unlock(hdev); |
741 | 773 | ||
742 | bacpy(&cp.bdaddr, &ev->bdaddr); | 774 | if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) { |
775 | struct hci_cp_accept_conn_req cp; | ||
743 | 776 | ||
744 | if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) | 777 | bacpy(&cp.bdaddr, &ev->bdaddr); |
745 | cp.role = 0x00; /* Become master */ | 778 | |
746 | else | 779 | if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) |
747 | cp.role = 0x01; /* Remain slave */ | 780 | cp.role = 0x00; /* Become master */ |
781 | else | ||
782 | cp.role = 0x01; /* Remain slave */ | ||
783 | |||
784 | hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, | ||
785 | sizeof(cp), &cp); | ||
786 | } else { | ||
787 | struct hci_cp_accept_sync_conn_req cp; | ||
788 | |||
789 | bacpy(&cp.bdaddr, &ev->bdaddr); | ||
790 | cp.pkt_type = cpu_to_le16(hdev->esco_type); | ||
791 | |||
792 | cp.tx_bandwidth = cpu_to_le32(0x00001f40); | ||
793 | cp.rx_bandwidth = cpu_to_le32(0x00001f40); | ||
794 | cp.max_latency = cpu_to_le16(0xffff); | ||
795 | cp.content_format = cpu_to_le16(hdev->voice_setting); | ||
796 | cp.retrans_effort = 0xff; | ||
748 | 797 | ||
749 | hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp); | 798 | hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, |
799 | sizeof(cp), &cp); | ||
800 | } | ||
750 | } else { | 801 | } else { |
751 | /* Connection rejected */ | 802 | /* Connection rejected */ |
752 | struct hci_cp_reject_conn_req cp; | 803 | struct hci_cp_reject_conn_req cp; |
@@ -1254,7 +1305,29 @@ static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_b | |||
1254 | 1305 | ||
1255 | static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | 1306 | static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) |
1256 | { | 1307 | { |
1257 | BT_DBG("%s", hdev->name); | 1308 | struct hci_ev_sync_conn_complete *ev = (void *) skb->data; |
1309 | struct hci_conn *conn; | ||
1310 | |||
1311 | BT_DBG("%s status %d", hdev->name, ev->status); | ||
1312 | |||
1313 | hci_dev_lock(hdev); | ||
1314 | |||
1315 | conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); | ||
1316 | if (!conn) | ||
1317 | goto unlock; | ||
1318 | |||
1319 | if (!ev->status) { | ||
1320 | conn->handle = __le16_to_cpu(ev->handle); | ||
1321 | conn->state = BT_CONNECTED; | ||
1322 | } else | ||
1323 | conn->state = BT_CLOSED; | ||
1324 | |||
1325 | hci_proto_connect_cfm(conn, ev->status); | ||
1326 | if (ev->status) | ||
1327 | hci_conn_del(conn); | ||
1328 | |||
1329 | unlock: | ||
1330 | hci_dev_unlock(hdev); | ||
1258 | } | 1331 | } |
1259 | 1332 | ||
1260 | static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb) | 1333 | static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb) |