.. | .. |
---|
68 | 68 | bdaddr_t dst; |
---|
69 | 69 | __u32 flags; |
---|
70 | 70 | __u16 setting; |
---|
| 71 | + __u8 cmsg_mask; |
---|
71 | 72 | struct sco_conn *conn; |
---|
72 | 73 | }; |
---|
73 | 74 | |
---|
.. | .. |
---|
279 | 280 | return err; |
---|
280 | 281 | } |
---|
281 | 282 | |
---|
282 | | -static int sco_send_frame(struct sock *sk, void *buf, int len, |
---|
283 | | - unsigned int msg_flags) |
---|
| 283 | +static int sco_send_frame(struct sock *sk, struct sk_buff *skb) |
---|
284 | 284 | { |
---|
285 | 285 | struct sco_conn *conn = sco_pi(sk)->conn; |
---|
286 | | - struct sk_buff *skb; |
---|
287 | | - int err; |
---|
| 286 | + int len = skb->len; |
---|
288 | 287 | |
---|
289 | 288 | /* Check outgoing MTU */ |
---|
290 | 289 | if (len > conn->mtu) |
---|
.. | .. |
---|
292 | 291 | |
---|
293 | 292 | BT_DBG("sk %p len %d", sk, len); |
---|
294 | 293 | |
---|
295 | | - skb = bt_skb_send_alloc(sk, len, msg_flags & MSG_DONTWAIT, &err); |
---|
296 | | - if (!skb) |
---|
297 | | - return err; |
---|
298 | | - |
---|
299 | | - memcpy(skb_put(skb, len), buf, len); |
---|
300 | 294 | hci_send_sco(conn->hcon, skb); |
---|
301 | 295 | |
---|
302 | 296 | return len; |
---|
.. | .. |
---|
451 | 445 | release_sock(sk); |
---|
452 | 446 | } |
---|
453 | 447 | |
---|
| 448 | +static void sco_skb_put_cmsg(struct sk_buff *skb, struct msghdr *msg, |
---|
| 449 | + struct sock *sk) |
---|
| 450 | +{ |
---|
| 451 | + if (sco_pi(sk)->cmsg_mask & SCO_CMSG_PKT_STATUS) |
---|
| 452 | + put_cmsg(msg, SOL_BLUETOOTH, BT_SCM_PKT_STATUS, |
---|
| 453 | + sizeof(bt_cb(skb)->sco.pkt_status), |
---|
| 454 | + &bt_cb(skb)->sco.pkt_status); |
---|
| 455 | +} |
---|
| 456 | + |
---|
454 | 457 | static void sco_sock_init(struct sock *sk, struct sock *parent) |
---|
455 | 458 | { |
---|
456 | 459 | BT_DBG("sk %p", sk); |
---|
.. | .. |
---|
459 | 462 | sk->sk_type = parent->sk_type; |
---|
460 | 463 | bt_sk(sk)->flags = bt_sk(parent)->flags; |
---|
461 | 464 | security_sk_clone(parent, sk); |
---|
| 465 | + } else { |
---|
| 466 | + bt_sk(sk)->skb_put_cmsg = sco_skb_put_cmsg; |
---|
462 | 467 | } |
---|
463 | 468 | } |
---|
464 | 469 | |
---|
.. | .. |
---|
523 | 528 | struct sock *sk = sock->sk; |
---|
524 | 529 | int err = 0; |
---|
525 | 530 | |
---|
526 | | - BT_DBG("sk %p %pMR", sk, &sa->sco_bdaddr); |
---|
527 | | - |
---|
528 | 531 | if (!addr || addr_len < sizeof(struct sockaddr_sco) || |
---|
529 | 532 | addr->sa_family != AF_BLUETOOTH) |
---|
530 | 533 | return -EINVAL; |
---|
| 534 | + |
---|
| 535 | + BT_DBG("sk %p %pMR", sk, &sa->sco_bdaddr); |
---|
531 | 536 | |
---|
532 | 537 | lock_sock(sk); |
---|
533 | 538 | |
---|
.. | .. |
---|
563 | 568 | addr->sa_family != AF_BLUETOOTH) |
---|
564 | 569 | return -EINVAL; |
---|
565 | 570 | |
---|
566 | | - if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND) |
---|
567 | | - return -EBADFD; |
---|
| 571 | + lock_sock(sk); |
---|
| 572 | + if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND) { |
---|
| 573 | + err = -EBADFD; |
---|
| 574 | + goto done; |
---|
| 575 | + } |
---|
568 | 576 | |
---|
569 | | - if (sk->sk_type != SOCK_SEQPACKET) |
---|
570 | | - return -EINVAL; |
---|
| 577 | + if (sk->sk_type != SOCK_SEQPACKET) { |
---|
| 578 | + err = -EINVAL; |
---|
| 579 | + goto done; |
---|
| 580 | + } |
---|
571 | 581 | |
---|
572 | 582 | hdev = hci_get_route(&sa->sco_bdaddr, &sco_pi(sk)->src, BDADDR_BREDR); |
---|
573 | | - if (!hdev) |
---|
574 | | - return -EHOSTUNREACH; |
---|
| 583 | + if (!hdev) { |
---|
| 584 | + err = -EHOSTUNREACH; |
---|
| 585 | + goto done; |
---|
| 586 | + } |
---|
575 | 587 | hci_dev_lock(hdev); |
---|
576 | | - |
---|
577 | | - lock_sock(sk); |
---|
578 | 588 | |
---|
579 | 589 | /* Set destination address and psm */ |
---|
580 | 590 | bacpy(&sco_pi(sk)->dst, &sa->sco_bdaddr); |
---|
.. | .. |
---|
710 | 720 | size_t len) |
---|
711 | 721 | { |
---|
712 | 722 | struct sock *sk = sock->sk; |
---|
713 | | - void *buf; |
---|
| 723 | + struct sk_buff *skb; |
---|
714 | 724 | int err; |
---|
715 | 725 | |
---|
716 | 726 | BT_DBG("sock %p, sk %p", sock, sk); |
---|
.. | .. |
---|
722 | 732 | if (msg->msg_flags & MSG_OOB) |
---|
723 | 733 | return -EOPNOTSUPP; |
---|
724 | 734 | |
---|
725 | | - buf = kmalloc(len, GFP_KERNEL); |
---|
726 | | - if (!buf) |
---|
727 | | - return -ENOMEM; |
---|
728 | | - |
---|
729 | | - if (memcpy_from_msg(buf, msg, len)) { |
---|
730 | | - kfree(buf); |
---|
731 | | - return -EFAULT; |
---|
732 | | - } |
---|
| 735 | + skb = bt_skb_sendmsg(sk, msg, len, len, 0, 0); |
---|
| 736 | + if (IS_ERR(skb)) |
---|
| 737 | + return PTR_ERR(skb); |
---|
733 | 738 | |
---|
734 | 739 | lock_sock(sk); |
---|
735 | 740 | |
---|
736 | 741 | if (sk->sk_state == BT_CONNECTED) |
---|
737 | | - err = sco_send_frame(sk, buf, len, msg->msg_flags); |
---|
| 742 | + err = sco_send_frame(sk, skb); |
---|
738 | 743 | else |
---|
739 | 744 | err = -ENOTCONN; |
---|
740 | 745 | |
---|
741 | 746 | release_sock(sk); |
---|
742 | | - kfree(buf); |
---|
| 747 | + |
---|
| 748 | + if (err < 0) |
---|
| 749 | + kfree_skb(skb); |
---|
743 | 750 | return err; |
---|
744 | 751 | } |
---|
745 | 752 | |
---|
.. | .. |
---|
815 | 822 | } |
---|
816 | 823 | |
---|
817 | 824 | static int sco_sock_setsockopt(struct socket *sock, int level, int optname, |
---|
818 | | - char __user *optval, unsigned int optlen) |
---|
| 825 | + sockptr_t optval, unsigned int optlen) |
---|
819 | 826 | { |
---|
820 | 827 | struct sock *sk = sock->sk; |
---|
821 | 828 | int len, err = 0; |
---|
.. | .. |
---|
834 | 841 | break; |
---|
835 | 842 | } |
---|
836 | 843 | |
---|
837 | | - if (get_user(opt, (u32 __user *) optval)) { |
---|
| 844 | + if (copy_from_sockptr(&opt, optval, sizeof(u32))) { |
---|
838 | 845 | err = -EFAULT; |
---|
839 | 846 | break; |
---|
840 | 847 | } |
---|
.. | .. |
---|
855 | 862 | voice.setting = sco_pi(sk)->setting; |
---|
856 | 863 | |
---|
857 | 864 | len = min_t(unsigned int, sizeof(voice), optlen); |
---|
858 | | - if (copy_from_user((char *)&voice, optval, len)) { |
---|
| 865 | + if (copy_from_sockptr(&voice, optval, len)) { |
---|
859 | 866 | err = -EFAULT; |
---|
860 | 867 | break; |
---|
861 | 868 | } |
---|
.. | .. |
---|
868 | 875 | } |
---|
869 | 876 | |
---|
870 | 877 | sco_pi(sk)->setting = voice.setting; |
---|
| 878 | + break; |
---|
| 879 | + |
---|
| 880 | + case BT_PKT_STATUS: |
---|
| 881 | + if (copy_from_sockptr(&opt, optval, sizeof(u32))) { |
---|
| 882 | + err = -EFAULT; |
---|
| 883 | + break; |
---|
| 884 | + } |
---|
| 885 | + |
---|
| 886 | + if (opt) |
---|
| 887 | + sco_pi(sk)->cmsg_mask |= SCO_CMSG_PKT_STATUS; |
---|
| 888 | + else |
---|
| 889 | + sco_pi(sk)->cmsg_mask &= SCO_CMSG_PKT_STATUS; |
---|
871 | 890 | break; |
---|
872 | 891 | |
---|
873 | 892 | default: |
---|
.. | .. |
---|
946 | 965 | struct sock *sk = sock->sk; |
---|
947 | 966 | int len, err = 0; |
---|
948 | 967 | struct bt_voice voice; |
---|
| 968 | + u32 phys; |
---|
| 969 | + int pkt_status; |
---|
949 | 970 | |
---|
950 | 971 | BT_DBG("sk %p", sk); |
---|
951 | 972 | |
---|
.. | .. |
---|
978 | 999 | if (copy_to_user(optval, (char *)&voice, len)) |
---|
979 | 1000 | err = -EFAULT; |
---|
980 | 1001 | |
---|
| 1002 | + break; |
---|
| 1003 | + |
---|
| 1004 | + case BT_PHY: |
---|
| 1005 | + if (sk->sk_state != BT_CONNECTED) { |
---|
| 1006 | + err = -ENOTCONN; |
---|
| 1007 | + break; |
---|
| 1008 | + } |
---|
| 1009 | + |
---|
| 1010 | + phys = hci_conn_get_phy(sco_pi(sk)->conn->hcon); |
---|
| 1011 | + |
---|
| 1012 | + if (put_user(phys, (u32 __user *) optval)) |
---|
| 1013 | + err = -EFAULT; |
---|
| 1014 | + break; |
---|
| 1015 | + |
---|
| 1016 | + case BT_PKT_STATUS: |
---|
| 1017 | + pkt_status = (sco_pi(sk)->cmsg_mask & SCO_CMSG_PKT_STATUS); |
---|
| 1018 | + |
---|
| 1019 | + if (put_user(pkt_status, (int __user *)optval)) |
---|
| 1020 | + err = -EFAULT; |
---|
| 1021 | + break; |
---|
| 1022 | + |
---|
| 1023 | + case BT_SNDMTU: |
---|
| 1024 | + case BT_RCVMTU: |
---|
| 1025 | + if (sk->sk_state != BT_CONNECTED) { |
---|
| 1026 | + err = -ENOTCONN; |
---|
| 1027 | + break; |
---|
| 1028 | + } |
---|
| 1029 | + |
---|
| 1030 | + if (put_user(sco_pi(sk)->conn->mtu, (u32 __user *)optval)) |
---|
| 1031 | + err = -EFAULT; |
---|
981 | 1032 | break; |
---|
982 | 1033 | |
---|
983 | 1034 | default: |
---|
.. | .. |
---|
1197 | 1248 | return 0; |
---|
1198 | 1249 | } |
---|
1199 | 1250 | |
---|
1200 | | -static int sco_debugfs_open(struct inode *inode, struct file *file) |
---|
1201 | | -{ |
---|
1202 | | - return single_open(file, sco_debugfs_show, inode->i_private); |
---|
1203 | | -} |
---|
1204 | | - |
---|
1205 | | -static const struct file_operations sco_debugfs_fops = { |
---|
1206 | | - .open = sco_debugfs_open, |
---|
1207 | | - .read = seq_read, |
---|
1208 | | - .llseek = seq_lseek, |
---|
1209 | | - .release = single_release, |
---|
1210 | | -}; |
---|
| 1251 | +DEFINE_SHOW_ATTRIBUTE(sco_debugfs); |
---|
1211 | 1252 | |
---|
1212 | 1253 | static struct dentry *sco_debugfs; |
---|
1213 | 1254 | |
---|
.. | .. |
---|
1224 | 1265 | .recvmsg = sco_sock_recvmsg, |
---|
1225 | 1266 | .poll = bt_sock_poll, |
---|
1226 | 1267 | .ioctl = bt_sock_ioctl, |
---|
| 1268 | + .gettstamp = sock_gettstamp, |
---|
1227 | 1269 | .mmap = sock_no_mmap, |
---|
1228 | 1270 | .socketpair = sock_no_socketpair, |
---|
1229 | 1271 | .shutdown = sco_sock_shutdown, |
---|