diff options
Diffstat (limited to 'net/bluetooth/sco.c')
-rw-r--r-- | net/bluetooth/sco.c | 75 |
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 = { | |||
61 | static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent); | 61 | static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent); |
62 | static void sco_chan_del(struct sock *sk, int err); | 62 | static void sco_chan_del(struct sock *sk, int err); |
63 | 63 | ||
64 | static int sco_conn_del(struct hci_conn *conn, int err); | ||
65 | |||
66 | static void sco_sock_close(struct sock *sk); | 64 | static void sco_sock_close(struct sock *sk); |
67 | static void sco_sock_kill(struct sock *sk); | 65 | static 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 ---- */ |
98 | static struct sco_conn *sco_conn_add(struct hci_conn *hcon, __u8 status) | 96 | static 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 | ||
260 | static inline void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb) | 257 | static 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 ---------- */ |
280 | static struct sock *__sco_get_sock_by_addr(bdaddr_t *ba) | 277 | static 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 | } |
289 | found: | 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 | ||
496 | done: | 492 | done: |
497 | release_sock(sk); | 493 | release_sock(sk); |
@@ -537,21 +533,38 @@ done: | |||
537 | static int sco_sock_listen(struct socket *sock, int backlog) | 533 | static 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 | ||
565 | unlock: | ||
566 | write_unlock(&sco_sk_list.lock); | ||
567 | |||
555 | done: | 568 | done: |
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 |