aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2007-10-20 08:55:10 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-22 05:59:47 -0400
commitb6a0dc822497e1c0b9e8c4add270cc27fce48454 (patch)
treeecfd0a08f62e4c6c7d1e63e62c04b6c17ca09cb6 /net
parentdae6a0f6636d05bcb28ece1f3630b23ed2d66e18 (diff)
[Bluetooth] Add support for handling simple eSCO links
With the Bluetooth 1.2 specification the Extended SCO feature for better audio connections was introduced. So far the Bluetooth core wasn't able to handle any eSCO connections correctly. This patch adds simple eSCO support while keeping backward compatibility with older devices. Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/hci_conn.c39
-rw-r--r--net/bluetooth/hci_core.c22
-rw-r--r--net/bluetooth/hci_event.c99
-rw-r--r--net/bluetooth/sco.c12
4 files changed, 150 insertions, 22 deletions
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
130void 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
130static void hci_conn_timeout(unsigned long arg) 152static 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
1364static 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, &quote))) {
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
1364static void hci_tx_task(unsigned long arg) 1384static 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
545static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) 545static 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
550static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) 577static 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
1255static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1306static 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
1329unlock:
1330 hci_dev_unlock(hdev);
1258} 1331}
1259 1332
1260static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb) 1333static 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
227done: 230done:
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