diff options
-rw-r--r-- | include/net/bluetooth/bluetooth.h | 11 | ||||
-rw-r--r-- | net/bluetooth/af_bluetooth.c | 7 | ||||
-rw-r--r-- | net/bluetooth/iso.c | 21 |
3 files changed, 35 insertions, 4 deletions
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 114299bd8b98..ada5b56a4413 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -244,6 +244,12 @@ struct bt_codecs { #define BT_ISO_BASE 20 +/* Socket option value 21 reserved */ + +#define BT_PKT_SEQNUM 22 + +#define BT_SCM_PKT_SEQNUM 0x05 + __printf(1, 2) void bt_info(const char *fmt, ...); __printf(1, 2) @@ -391,7 +397,8 @@ struct bt_sock { enum { BT_SK_DEFER_SETUP, BT_SK_SUSPEND, - BT_SK_PKT_STATUS + BT_SK_PKT_STATUS, + BT_SK_PKT_SEQNUM, }; struct bt_sock_list { @@ -475,6 +482,7 @@ struct bt_skb_cb { u8 pkt_type; u8 force_active; u16 expect; + u16 pkt_seqnum; u8 incoming:1; u8 pkt_status:2; union { @@ -488,6 +496,7 @@ struct bt_skb_cb { #define hci_skb_pkt_type(skb) bt_cb((skb))->pkt_type #define hci_skb_pkt_status(skb) bt_cb((skb))->pkt_status +#define hci_skb_pkt_seqnum(skb) bt_cb((skb))->pkt_seqnum #define hci_skb_expect(skb) bt_cb((skb))->expect #define hci_skb_opcode(skb) bt_cb((skb))->hci.opcode #define hci_skb_event(skb) bt_cb((skb))->hci.req_event diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index ee9bf84c88a7..2b94e2077203 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -364,6 +364,13 @@ int bt_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, put_cmsg(msg, SOL_BLUETOOTH, BT_SCM_PKT_STATUS, sizeof(pkt_status), &pkt_status); } + + if (test_bit(BT_SK_PKT_SEQNUM, &bt_sk(sk)->flags)) { + u16 pkt_seqnum = hci_skb_pkt_seqnum(skb); + + put_cmsg(msg, SOL_BLUETOOTH, BT_SCM_PKT_SEQNUM, + sizeof(pkt_seqnum), &pkt_seqnum); + } } skb_free_datagram(sk, skb); diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c index 5e752950e266..2f229f2077e8 100644 --- a/net/bluetooth/iso.c +++ b/net/bluetooth/iso.c @@ -1687,6 +1687,17 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname, clear_bit(BT_SK_PKT_STATUS, &bt_sk(sk)->flags); break; + case BT_PKT_SEQNUM: + err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen); + if (err) + break; + + if (opt) + set_bit(BT_SK_PKT_SEQNUM, &bt_sk(sk)->flags); + else + clear_bit(BT_SK_PKT_SEQNUM, &bt_sk(sk)->flags); + break; + case BT_ISO_QOS: if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECT2 && @@ -2278,7 +2289,7 @@ static void iso_disconn_cfm(struct hci_conn *hcon, __u8 reason) void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) { struct iso_conn *conn = hcon->iso_data; - __u16 pb, ts, len; + __u16 pb, ts, len, sn; if (!conn) goto drop; @@ -2308,6 +2319,7 @@ void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) goto drop; } + sn = __le16_to_cpu(hdr->sn); len = __le16_to_cpu(hdr->slen); } else { struct hci_iso_data_hdr *hdr; @@ -2318,18 +2330,20 @@ void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) goto drop; } + sn = __le16_to_cpu(hdr->sn); len = __le16_to_cpu(hdr->slen); } flags = hci_iso_data_flags(len); len = hci_iso_data_len(len); - BT_DBG("Start: total len %d, frag len %d flags 0x%4.4x", len, - skb->len, flags); + BT_DBG("Start: total len %d, frag len %d flags 0x%4.4x sn %d", + len, skb->len, flags, sn); if (len == skb->len) { /* Complete frame received */ hci_skb_pkt_status(skb) = flags & 0x03; + hci_skb_pkt_seqnum(skb) = sn; iso_recv_frame(conn, skb); return; } @@ -2352,6 +2366,7 @@ void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) goto drop; hci_skb_pkt_status(conn->rx_skb) = flags & 0x03; + hci_skb_pkt_seqnum(conn->rx_skb) = sn; skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), skb->len); conn->rx_len = len - skb->len; |