Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetoot...
[platform/kernel/linux-starfive.git] / net / bluetooth / sco.c
index 37260ba..6e6b038 100644 (file)
@@ -66,6 +66,7 @@ struct sco_pinfo {
        bdaddr_t        dst;
        __u32           flags;
        __u16           setting;
+       __u8            cmsg_mask;
        struct sco_conn *conn;
 };
 
@@ -449,6 +450,15 @@ static void sco_sock_close(struct sock *sk)
        sco_sock_kill(sk);
 }
 
+static void sco_skb_put_cmsg(struct sk_buff *skb, struct msghdr *msg,
+                            struct sock *sk)
+{
+       if (sco_pi(sk)->cmsg_mask & SCO_CMSG_PKT_STATUS)
+               put_cmsg(msg, SOL_BLUETOOTH, BT_SCM_PKT_STATUS,
+                        sizeof(bt_cb(skb)->sco.pkt_status),
+                        &bt_cb(skb)->sco.pkt_status);
+}
+
 static void sco_sock_init(struct sock *sk, struct sock *parent)
 {
        BT_DBG("sk %p", sk);
@@ -457,6 +467,8 @@ static void sco_sock_init(struct sock *sk, struct sock *parent)
                sk->sk_type = parent->sk_type;
                bt_sk(sk)->flags = bt_sk(parent)->flags;
                security_sk_clone(parent, sk);
+       } else {
+               bt_sk(sk)->skb_put_cmsg = sco_skb_put_cmsg;
        }
 }
 
@@ -846,6 +858,18 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
                sco_pi(sk)->setting = voice.setting;
                break;
 
+       case BT_PKT_STATUS:
+               if (get_user(opt, (u32 __user *)optval)) {
+                       err = -EFAULT;
+                       break;
+               }
+
+               if (opt)
+                       sco_pi(sk)->cmsg_mask |= SCO_CMSG_PKT_STATUS;
+               else
+                       sco_pi(sk)->cmsg_mask &= SCO_CMSG_PKT_STATUS;
+               break;
+
        default:
                err = -ENOPROTOOPT;
                break;
@@ -923,6 +947,7 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname,
        int len, err = 0;
        struct bt_voice voice;
        u32 phys;
+       int pkt_status;
 
        BT_DBG("sk %p", sk);
 
@@ -969,6 +994,13 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname,
                        err = -EFAULT;
                break;
 
+       case BT_PKT_STATUS:
+               pkt_status = (sco_pi(sk)->cmsg_mask & SCO_CMSG_PKT_STATUS);
+
+               if (put_user(pkt_status, (int __user *)optval))
+                       err = -EFAULT;
+               break;
+
        default:
                err = -ENOPROTOOPT;
                break;