diff options
-rw-r--r-- | include/net/bluetooth/hci_core.h | 1 | ||||
-rw-r--r-- | net/bluetooth/hci_conn.c | 39 | ||||
-rw-r--r-- | net/bluetooth/hci_core.c | 22 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 99 | ||||
-rw-r--r-- | net/bluetooth/sco.c | 12 |
5 files changed, 151 insertions, 22 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 0db89ed6b00c..ea13baa3851b 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
@@ -313,6 +313,7 @@ static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev, | |||
313 | void hci_acl_connect(struct hci_conn *conn); | 313 | void hci_acl_connect(struct hci_conn *conn); |
314 | void hci_acl_disconn(struct hci_conn *conn, __u8 reason); | 314 | void hci_acl_disconn(struct hci_conn *conn, __u8 reason); |
315 | void hci_add_sco(struct hci_conn *conn, __u16 handle); | 315 | void hci_add_sco(struct hci_conn *conn, __u16 handle); |
316 | void hci_setup_sync(struct hci_conn *conn, __u16 handle); | ||
316 | 317 | ||
317 | struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst); | 318 | struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst); |
318 | int hci_conn_del(struct hci_conn *conn); | 319 | int hci_conn_del(struct hci_conn *conn); |
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 797a30bec6fd..9483320f6dad 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -78,9 +78,9 @@ void hci_acl_connect(struct hci_conn *conn) | |||
78 | 78 | ||
79 | cp.pkt_type = cpu_to_le16(hdev->pkt_type & ACL_PTYPE_MASK); | 79 | cp.pkt_type = cpu_to_le16(hdev->pkt_type & ACL_PTYPE_MASK); |
80 | if (lmp_rswitch_capable(hdev) && !(hdev->link_mode & HCI_LM_MASTER)) | 80 | if (lmp_rswitch_capable(hdev) && !(hdev->link_mode & HCI_LM_MASTER)) |
81 | cp.role_switch = 0x01; | 81 | cp.role_switch = 0x01; |
82 | else | 82 | else |
83 | cp.role_switch = 0x00; | 83 | cp.role_switch = 0x00; |
84 | 84 | ||
85 | hci_send_cmd(hdev, HCI_OP_CREATE_CONN, sizeof(cp), &cp); | 85 | hci_send_cmd(hdev, HCI_OP_CREATE_CONN, sizeof(cp), &cp); |
86 | } | 86 | } |
@@ -127,6 +127,28 @@ void hci_add_sco(struct hci_conn *conn, __u16 handle) | |||
127 | hci_send_cmd(hdev, HCI_OP_ADD_SCO, sizeof(cp), &cp); | 127 | hci_send_cmd(hdev, HCI_OP_ADD_SCO, sizeof(cp), &cp); |
128 | } | 128 | } |
129 | 129 | ||
130 | void hci_setup_sync(struct hci_conn *conn, __u16 handle) | ||
131 | { | ||
132 | struct hci_dev *hdev = conn->hdev; | ||
133 | struct hci_cp_setup_sync_conn cp; | ||
134 | |||
135 | BT_DBG("%p", conn); | ||
136 | |||
137 | conn->state = BT_CONNECT; | ||
138 | conn->out = 1; | ||
139 | |||
140 | cp.handle = cpu_to_le16(handle); | ||
141 | cp.pkt_type = cpu_to_le16(hdev->esco_type); | ||
142 | |||
143 | cp.tx_bandwidth = cpu_to_le32(0x00001f40); | ||
144 | cp.rx_bandwidth = cpu_to_le32(0x00001f40); | ||
145 | cp.max_latency = cpu_to_le16(0xffff); | ||
146 | cp.voice_setting = cpu_to_le16(hdev->voice_setting); | ||
147 | cp.retrans_effort = 0xff; | ||
148 | |||
149 | hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp); | ||
150 | } | ||
151 | |||
130 | static void hci_conn_timeout(unsigned long arg) | 152 | static void hci_conn_timeout(unsigned long arg) |
131 | { | 153 | { |
132 | struct hci_conn *conn = (void *) arg; | 154 | struct hci_conn *conn = (void *) arg; |
@@ -141,7 +163,10 @@ static void hci_conn_timeout(unsigned long arg) | |||
141 | 163 | ||
142 | switch (conn->state) { | 164 | switch (conn->state) { |
143 | case BT_CONNECT: | 165 | case BT_CONNECT: |
144 | hci_acl_connect_cancel(conn); | 166 | if (conn->type == ACL_LINK) |
167 | hci_acl_connect_cancel(conn); | ||
168 | else | ||
169 | hci_acl_disconn(conn, 0x13); | ||
145 | break; | 170 | break; |
146 | case BT_CONNECTED: | 171 | case BT_CONNECTED: |
147 | hci_acl_disconn(conn, 0x13); | 172 | hci_acl_disconn(conn, 0x13); |
@@ -328,8 +353,12 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst) | |||
328 | hci_conn_hold(sco); | 353 | hci_conn_hold(sco); |
329 | 354 | ||
330 | if (acl->state == BT_CONNECTED && | 355 | if (acl->state == BT_CONNECTED && |
331 | (sco->state == BT_OPEN || sco->state == BT_CLOSED)) | 356 | (sco->state == BT_OPEN || sco->state == BT_CLOSED)) { |
332 | hci_add_sco(sco, acl->handle); | 357 | if (lmp_esco_capable(hdev)) |
358 | hci_setup_sync(sco, acl->handle); | ||
359 | else | ||
360 | hci_add_sco(sco, acl->handle); | ||
361 | } | ||
333 | 362 | ||
334 | return sco; | 363 | return sco; |
335 | } | 364 | } |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 2894382dd26d..372b0d3b75a8 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -1361,6 +1361,26 @@ static inline void hci_sched_sco(struct hci_dev *hdev) | |||
1361 | } | 1361 | } |
1362 | } | 1362 | } |
1363 | 1363 | ||
1364 | static inline void hci_sched_esco(struct hci_dev *hdev) | ||
1365 | { | ||
1366 | struct hci_conn *conn; | ||
1367 | struct sk_buff *skb; | ||
1368 | int quote; | ||
1369 | |||
1370 | BT_DBG("%s", hdev->name); | ||
1371 | |||
1372 | while (hdev->sco_cnt && (conn = hci_low_sent(hdev, ESCO_LINK, "e))) { | ||
1373 | while (quote-- && (skb = skb_dequeue(&conn->data_q))) { | ||
1374 | BT_DBG("skb %p len %d", skb, skb->len); | ||
1375 | hci_send_frame(skb); | ||
1376 | |||
1377 | conn->sent++; | ||
1378 | if (conn->sent == ~0) | ||
1379 | conn->sent = 0; | ||
1380 | } | ||
1381 | } | ||
1382 | } | ||
1383 | |||
1364 | static void hci_tx_task(unsigned long arg) | 1384 | static void hci_tx_task(unsigned long arg) |
1365 | { | 1385 | { |
1366 | struct hci_dev *hdev = (struct hci_dev *) arg; | 1386 | struct hci_dev *hdev = (struct hci_dev *) arg; |
@@ -1376,6 +1396,8 @@ static void hci_tx_task(unsigned long arg) | |||
1376 | 1396 | ||
1377 | hci_sched_sco(hdev); | 1397 | hci_sched_sco(hdev); |
1378 | 1398 | ||
1399 | hci_sched_esco(hdev); | ||
1400 | |||
1379 | /* Send next queued raw (unknown type) packet */ | 1401 | /* Send next queued raw (unknown type) packet */ |
1380 | while ((skb = skb_dequeue(&hdev->raw_q))) | 1402 | while ((skb = skb_dequeue(&hdev->raw_q))) |
1381 | hci_send_frame(skb); | 1403 | hci_send_frame(skb); |
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) |
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 65b6fb1c4154..82d0dfdfa7e2 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
@@ -189,7 +189,7 @@ static int sco_connect(struct sock *sk) | |||
189 | struct sco_conn *conn; | 189 | struct sco_conn *conn; |
190 | struct hci_conn *hcon; | 190 | struct hci_conn *hcon; |
191 | struct hci_dev *hdev; | 191 | struct hci_dev *hdev; |
192 | int err = 0; | 192 | int err, type; |
193 | 193 | ||
194 | BT_DBG("%s -> %s", batostr(src), batostr(dst)); | 194 | BT_DBG("%s -> %s", batostr(src), batostr(dst)); |
195 | 195 | ||
@@ -200,7 +200,9 @@ static int sco_connect(struct sock *sk) | |||
200 | 200 | ||
201 | err = -ENOMEM; | 201 | err = -ENOMEM; |
202 | 202 | ||
203 | hcon = hci_connect(hdev, SCO_LINK, dst); | 203 | type = lmp_esco_capable(hdev) ? ESCO_LINK : SCO_LINK; |
204 | |||
205 | hcon = hci_connect(hdev, type, dst); | ||
204 | if (!hcon) | 206 | if (!hcon) |
205 | goto done; | 207 | goto done; |
206 | 208 | ||
@@ -224,6 +226,7 @@ static int sco_connect(struct sock *sk) | |||
224 | sk->sk_state = BT_CONNECT; | 226 | sk->sk_state = BT_CONNECT; |
225 | sco_sock_set_timer(sk, sk->sk_sndtimeo); | 227 | sco_sock_set_timer(sk, sk->sk_sndtimeo); |
226 | } | 228 | } |
229 | |||
227 | done: | 230 | done: |
228 | hci_dev_unlock_bh(hdev); | 231 | hci_dev_unlock_bh(hdev); |
229 | hci_dev_put(hdev); | 232 | hci_dev_put(hdev); |
@@ -846,7 +849,7 @@ static int sco_connect_cfm(struct hci_conn *hcon, __u8 status) | |||
846 | { | 849 | { |
847 | BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status); | 850 | BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status); |
848 | 851 | ||
849 | if (hcon->type != SCO_LINK) | 852 | if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK) |
850 | return 0; | 853 | return 0; |
851 | 854 | ||
852 | if (!status) { | 855 | if (!status) { |
@@ -865,10 +868,11 @@ static int sco_disconn_ind(struct hci_conn *hcon, __u8 reason) | |||
865 | { | 868 | { |
866 | BT_DBG("hcon %p reason %d", hcon, reason); | 869 | BT_DBG("hcon %p reason %d", hcon, reason); |
867 | 870 | ||
868 | if (hcon->type != SCO_LINK) | 871 | if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK) |
869 | return 0; | 872 | return 0; |
870 | 873 | ||
871 | sco_conn_del(hcon, bt_err(reason)); | 874 | sco_conn_del(hcon, bt_err(reason)); |
875 | |||
872 | return 0; | 876 | return 0; |
873 | } | 877 | } |
874 | 878 | ||