Re: [PATCH v3] sco:Add support for BT_PKT_STATUS CMSG data

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Alain, Marcel,

On Wed, Jun 3, 2020 at 7:56 AM Alain Michaud <alainm@xxxxxxxxxxxx> wrote:
>
> This change adds support for reporting the BT_PKT_STATUS to the socket
> CMSG data to allow the implementation of a packet loss correction on
> erronous data received on the SCO socket.
>
> The patch was partially developed by Marcel Holtmann and validated by
> Hsin-yu Chao
>
> Signed-off-by: Alain Michaud <alainm@xxxxxxxxxxxx>
>
> ---
>
>  include/net/bluetooth/bluetooth.h |  8 +++++++
>  include/net/bluetooth/sco.h       |  3 +++
>  net/bluetooth/af_bluetooth.c      |  3 +++
>  net/bluetooth/hci_core.c          |  1 +
>  net/bluetooth/sco.c               | 35 +++++++++++++++++++++++++++++++
>  5 files changed, 50 insertions(+)
>
> diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
> index 3fa7b1e3c5d9..85e6c5754448 100644
> --- a/include/net/bluetooth/bluetooth.h
> +++ b/include/net/bluetooth/bluetooth.h
> @@ -147,6 +147,8 @@ struct bt_voice {
>  #define BT_MODE_LE_FLOWCTL     0x03
>  #define BT_MODE_EXT_FLOWCTL    0x04
>
> +#define BT_PKT_STATUS          16
> +
>  __printf(1, 2)
>  void bt_info(const char *fmt, ...);
>  __printf(1, 2)
> @@ -275,6 +277,7 @@ struct bt_sock {
>         struct sock *parent;
>         unsigned long flags;
>         void (*skb_msg_name)(struct sk_buff *, void *, int *);
> +       void (*skb_put_cmsg)(struct sk_buff *, struct msghdr *, struct sock *);
>  };
>
>  enum {
> @@ -324,6 +327,10 @@ struct l2cap_ctrl {
>         struct l2cap_chan *chan;
>  };
>
> +struct sco_ctrl {
> +       u8      pkt_status;
> +};
> +
>  struct hci_dev;
>
>  typedef void (*hci_req_complete_t)(struct hci_dev *hdev, u8 status, u16 opcode);
> @@ -350,6 +357,7 @@ struct bt_skb_cb {
>         u8 incoming:1;
>         union {
>                 struct l2cap_ctrl l2cap;
> +               struct sco_ctrl sco;
>                 struct hci_ctrl hci;
>         };
>  };
> diff --git a/include/net/bluetooth/sco.h b/include/net/bluetooth/sco.h
> index f40ddb4264fc..7f0d7bdc53f6 100644
> --- a/include/net/bluetooth/sco.h
> +++ b/include/net/bluetooth/sco.h
> @@ -46,4 +46,7 @@ struct sco_conninfo {
>         __u8  dev_class[3];
>  };
>
> +/* CMSG flags */
> +#define SCO_CMSG_PKT_STATUS    0x0001
> +

I wonder if we can make this generic since ISO also has similar status
of received packets so I was hoping I could reuse the same flag to
indicate we want packet status to be transmitted with cmsg. Maybe have
it as BT_CMSG_PKT_STATUS?

>  #endif /* __SCO_H */
> diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
> index 3fd124927d4d..d0abea8d08cc 100644
> --- a/net/bluetooth/af_bluetooth.c
> +++ b/net/bluetooth/af_bluetooth.c
> @@ -286,6 +286,9 @@ int bt_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
>                 if (msg->msg_name && bt_sk(sk)->skb_msg_name)
>                         bt_sk(sk)->skb_msg_name(skb, msg->msg_name,
>                                                 &msg->msg_namelen);
> +
> +               if (bt_sk(sk)->skb_put_cmsg)
> +                       bt_sk(sk)->skb_put_cmsg(skb, msg, sk);
>         }
>
>         skb_free_datagram(sk, skb);
> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> index 51d399273276..7b5e46198d99 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -4549,6 +4549,7 @@ static void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb)
>
>         if (conn) {
>                 /* Send to upper protocol */
> +               bt_cb(skb)->sco.pkt_status = flags & 0x03;
>                 sco_recv_scodata(conn, skb);
>                 return;
>         } else {
> diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
> index c8c3d38cdc7b..f6b54853e547 100644
> --- a/net/bluetooth/sco.c
> +++ b/net/bluetooth/sco.c
> @@ -66,6 +66,7 @@ struct sco_pinfo {
>         bdaddr_t        dst;
>         __u32           flags;
>         __u16           setting;
> +       __u32           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_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;
> +       u32 pkt_status;
>
>         BT_DBG("sk %p", sk);
>
> @@ -969,6 +994,16 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname,
>                         err = -EFAULT;
>                 break;
>
> +       case BT_PKT_STATUS:
> +               if (sco_pi(sk)->cmsg_mask & SCO_CMSG_PKT_STATUS)
> +                       pkt_status = 1;
> +               else
> +                       pkt_status = 0;
> +
> +               if (put_user(pkt_status, (u32 __user *)optval))
> +                       err = -EFAULT;
> +               break;
> +
>         default:
>                 err = -ENOPROTOOPT;
>                 break;
> --
> 2.27.0.rc2.251.g90737beb825-goog
>


-- 
Luiz Augusto von Dentz



[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux