aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/sco.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/bluetooth/sco.c')
-rw-r--r--net/bluetooth/sco.c75
1 files changed, 44 insertions, 31 deletions
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index f6ab12907963..cbdd313659a7 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -61,8 +61,6 @@ static struct bt_sock_list sco_sk_list = {
61static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent); 61static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent);
62static void sco_chan_del(struct sock *sk, int err); 62static void sco_chan_del(struct sock *sk, int err);
63 63
64static int sco_conn_del(struct hci_conn *conn, int err);
65
66static void sco_sock_close(struct sock *sk); 64static void sco_sock_close(struct sock *sk);
67static void sco_sock_kill(struct sock *sk); 65static void sco_sock_kill(struct sock *sk);
68 66
@@ -95,12 +93,12 @@ static void sco_sock_clear_timer(struct sock *sk)
95} 93}
96 94
97/* ---- SCO connections ---- */ 95/* ---- SCO connections ---- */
98static struct sco_conn *sco_conn_add(struct hci_conn *hcon, __u8 status) 96static struct sco_conn *sco_conn_add(struct hci_conn *hcon)
99{ 97{
100 struct hci_dev *hdev = hcon->hdev; 98 struct hci_dev *hdev = hcon->hdev;
101 struct sco_conn *conn = hcon->sco_data; 99 struct sco_conn *conn = hcon->sco_data;
102 100
103 if (conn || status) 101 if (conn)
104 return conn; 102 return conn;
105 103
106 conn = kzalloc(sizeof(struct sco_conn), GFP_ATOMIC); 104 conn = kzalloc(sizeof(struct sco_conn), GFP_ATOMIC);
@@ -195,13 +193,14 @@ static int sco_connect(struct sock *sk)
195 else 193 else
196 type = SCO_LINK; 194 type = SCO_LINK;
197 195
198 hcon = hci_connect(hdev, type, dst, BT_SECURITY_LOW, HCI_AT_NO_BONDING); 196 hcon = hci_connect(hdev, type, dst, BDADDR_BREDR, BT_SECURITY_LOW,
197 HCI_AT_NO_BONDING);
199 if (IS_ERR(hcon)) { 198 if (IS_ERR(hcon)) {
200 err = PTR_ERR(hcon); 199 err = PTR_ERR(hcon);
201 goto done; 200 goto done;
202 } 201 }
203 202
204 conn = sco_conn_add(hcon, 0); 203 conn = sco_conn_add(hcon);
205 if (!conn) { 204 if (!conn) {
206 hci_conn_put(hcon); 205 hci_conn_put(hcon);
207 err = -ENOMEM; 206 err = -ENOMEM;
@@ -233,7 +232,7 @@ static inline int sco_send_frame(struct sock *sk, struct msghdr *msg, int len)
233{ 232{
234 struct sco_conn *conn = sco_pi(sk)->conn; 233 struct sco_conn *conn = sco_pi(sk)->conn;
235 struct sk_buff *skb; 234 struct sk_buff *skb;
236 int err, count; 235 int err;
237 236
238 /* Check outgoing MTU */ 237 /* Check outgoing MTU */
239 if (len > conn->mtu) 238 if (len > conn->mtu)
@@ -241,20 +240,18 @@ static inline int sco_send_frame(struct sock *sk, struct msghdr *msg, int len)
241 240
242 BT_DBG("sk %p len %d", sk, len); 241 BT_DBG("sk %p len %d", sk, len);
243 242
244 count = min_t(unsigned int, conn->mtu, len); 243 skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err);
245 skb = bt_skb_send_alloc(sk, count,
246 msg->msg_flags & MSG_DONTWAIT, &err);
247 if (!skb) 244 if (!skb)
248 return err; 245 return err;
249 246
250 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) { 247 if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
251 kfree_skb(skb); 248 kfree_skb(skb);
252 return -EFAULT; 249 return -EFAULT;
253 } 250 }
254 251
255 hci_send_sco(conn->hcon, skb); 252 hci_send_sco(conn->hcon, skb);
256 253
257 return count; 254 return len;
258} 255}
259 256
260static inline void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb) 257static inline void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb)
@@ -277,17 +274,20 @@ drop:
277} 274}
278 275
279/* -------- Socket interface ---------- */ 276/* -------- Socket interface ---------- */
280static struct sock *__sco_get_sock_by_addr(bdaddr_t *ba) 277static struct sock *__sco_get_sock_listen_by_addr(bdaddr_t *ba)
281{ 278{
282 struct sock *sk;
283 struct hlist_node *node; 279 struct hlist_node *node;
280 struct sock *sk;
281
282 sk_for_each(sk, node, &sco_sk_list.head) {
283 if (sk->sk_state != BT_LISTEN)
284 continue;
284 285
285 sk_for_each(sk, node, &sco_sk_list.head)
286 if (!bacmp(&bt_sk(sk)->src, ba)) 286 if (!bacmp(&bt_sk(sk)->src, ba))
287 goto found; 287 return sk;
288 sk = NULL; 288 }
289found: 289
290 return sk; 290 return NULL;
291} 291}
292 292
293/* Find socket listening on source bdaddr. 293/* Find socket listening on source bdaddr.
@@ -466,7 +466,6 @@ static int sco_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_le
466{ 466{
467 struct sockaddr_sco *sa = (struct sockaddr_sco *) addr; 467 struct sockaddr_sco *sa = (struct sockaddr_sco *) addr;
468 struct sock *sk = sock->sk; 468 struct sock *sk = sock->sk;
469 bdaddr_t *src = &sa->sco_bdaddr;
470 int err = 0; 469 int err = 0;
471 470
472 BT_DBG("sk %p %s", sk, batostr(&sa->sco_bdaddr)); 471 BT_DBG("sk %p %s", sk, batostr(&sa->sco_bdaddr));
@@ -481,17 +480,14 @@ static int sco_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_le
481 goto done; 480 goto done;
482 } 481 }
483 482
484 write_lock(&sco_sk_list.lock); 483 if (sk->sk_type != SOCK_SEQPACKET) {
485 484 err = -EINVAL;
486 if (bacmp(src, BDADDR_ANY) && __sco_get_sock_by_addr(src)) { 485 goto done;
487 err = -EADDRINUSE;
488 } else {
489 /* Save source address */
490 bacpy(&bt_sk(sk)->src, &sa->sco_bdaddr);
491 sk->sk_state = BT_BOUND;
492 } 486 }
493 487
494 write_unlock(&sco_sk_list.lock); 488 bacpy(&bt_sk(sk)->src, &sa->sco_bdaddr);
489
490 sk->sk_state = BT_BOUND;
495 491
496done: 492done:
497 release_sock(sk); 493 release_sock(sk);
@@ -537,21 +533,38 @@ done:
537static int sco_sock_listen(struct socket *sock, int backlog) 533static int sco_sock_listen(struct socket *sock, int backlog)
538{ 534{
539 struct sock *sk = sock->sk; 535 struct sock *sk = sock->sk;
536 bdaddr_t *src = &bt_sk(sk)->src;
540 int err = 0; 537 int err = 0;
541 538
542 BT_DBG("sk %p backlog %d", sk, backlog); 539 BT_DBG("sk %p backlog %d", sk, backlog);
543 540
544 lock_sock(sk); 541 lock_sock(sk);
545 542
546 if (sk->sk_state != BT_BOUND || sock->type != SOCK_SEQPACKET) { 543 if (sk->sk_state != BT_BOUND) {
547 err = -EBADFD; 544 err = -EBADFD;
548 goto done; 545 goto done;
549 } 546 }
550 547
548 if (sk->sk_type != SOCK_SEQPACKET) {
549 err = -EINVAL;
550 goto done;
551 }
552
553 write_lock(&sco_sk_list.lock);
554
555 if (__sco_get_sock_listen_by_addr(src)) {
556 err = -EADDRINUSE;
557 goto unlock;
558 }
559
551 sk->sk_max_ack_backlog = backlog; 560 sk->sk_max_ack_backlog = backlog;
552 sk->sk_ack_backlog = 0; 561 sk->sk_ack_backlog = 0;
562
553 sk->sk_state = BT_LISTEN; 563 sk->sk_state = BT_LISTEN;
554 564
565unlock:
566 write_unlock(&sco_sk_list.lock);
567
555done: 568done:
556 release_sock(sk); 569 release_sock(sk);
557 return err; 570 return err;
@@ -923,7 +936,7 @@ int sco_connect_cfm(struct hci_conn *hcon, __u8 status)
923 if (!status) { 936 if (!status) {
924 struct sco_conn *conn; 937 struct sco_conn *conn;
925 938
926 conn = sco_conn_add(hcon, status); 939 conn = sco_conn_add(hcon);
927 if (conn) 940 if (conn)
928 sco_conn_ready(conn); 941 sco_conn_ready(conn);
929 } else 942 } else