* [PATCHv4] Bluetooth: Use non-flushable by default L2CAP data packets @ 2011-01-03 9:14 Emeltchenko Andrei 2011-01-03 9:14 ` Emeltchenko Andrei 0 siblings, 1 reply; 7+ messages in thread From: Emeltchenko Andrei @ 2011-01-03 9:14 UTC (permalink / raw) To: linux-bluetooth From: Andrei Emeltchenko <andrei.emeltchenko@nokia.com> Modification of Nick Pelly <npelly@google.com> patch. Changes to previous releases: - rebasing, simplifying logic, using SOL_BLUETOOTH instead of SOL_L2CAP. - LMP_NO_FLUSH feature mask corrected, added check to l2cap_send_sframe - added check to setsockopt function Andrei Emeltchenko (1): Bluetooth: Use non-flushable by default L2CAP data packets include/net/bluetooth/bluetooth.h | 5 +++ include/net/bluetooth/hci.h | 2 + include/net/bluetooth/hci_core.h | 1 + include/net/bluetooth/l2cap.h | 1 + net/bluetooth/hci_core.c | 7 +++- net/bluetooth/l2cap.c | 59 ++++++++++++++++++++++++++++++++++-- 6 files changed, 69 insertions(+), 6 deletions(-) ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCHv4] Bluetooth: Use non-flushable by default L2CAP data packets 2011-01-03 9:14 [PATCHv4] Bluetooth: Use non-flushable by default L2CAP data packets Emeltchenko Andrei @ 2011-01-03 9:14 ` Emeltchenko Andrei 2011-01-07 11:08 ` Andrei Emeltchenko ` (2 more replies) 0 siblings, 3 replies; 7+ messages in thread From: Emeltchenko Andrei @ 2011-01-03 9:14 UTC (permalink / raw) To: linux-bluetooth From: Andrei Emeltchenko <andrei.emeltchenko@nokia.com> Modification of Nick Pelly <npelly@google.com> patch. With Bluetooth 2.1 ACL packets can be flushable or non-flushable. This commit makes ACL data packets non-flushable by default on compatible chipsets, and adds the BT_FLUSHABLE socket option to explicitly request flushable ACL data packets for a given L2CAP socket. This is useful for A2DP data which can be safely discarded if it can not be delivered within a short time (while other ACL data should not be discarded). Note that making ACL data flushable has no effect unless the automatic flush timeout for that ACL link is changed from its default of 0 (infinite). Default packet types (for compatible chipsets): Frame 34: 13 bytes on wire (104 bits), 13 bytes captured (104 bits) Bluetooth HCI H4 Bluetooth HCI ACL Packet .... 0000 0000 0010 = Connection Handle: 0x0002 ..00 .... .... .... = PB Flag: First Non-automatically Flushable Packet (0) 00.. .... .... .... = BC Flag: Point-To-Point (0) Data Total Length: 8 Bluetooth L2CAP Packet After setting BT_FLUSHABLE (sock.setsockopt(274 /*SOL_BLUETOOTH*/, 8 /* BT_FLUSHABLE */, 1 /* flush */)) Frame 34: 13 bytes on wire (104 bits), 13 bytes captured (104 bits) Bluetooth HCI H4 Bluetooth HCI ACL Packet .... 0000 0000 0010 = Connection Handle: 0x0002 ..10 .... .... .... = PB Flag: First Automatically Flushable Packet (2) 00.. .... .... .... = BC Flag: Point-To-Point (0) Data Total Length: 8 Bluetooth L2CAP Packet Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@nokia.com> --- include/net/bluetooth/bluetooth.h | 5 +++ include/net/bluetooth/hci.h | 2 + include/net/bluetooth/hci_core.h | 1 + include/net/bluetooth/l2cap.h | 1 + net/bluetooth/hci_core.c | 7 +++- net/bluetooth/l2cap.c | 59 ++++++++++++++++++++++++++++++++++-- 6 files changed, 69 insertions(+), 6 deletions(-) diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 0c5e725..ed7d775 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -64,6 +64,11 @@ struct bt_security { #define BT_DEFER_SETUP 7 +#define BT_FLUSHABLE 8 + +#define BT_FLUSHABLE_OFF 0 +#define BT_FLUSHABLE_ON 1 + #define BT_INFO(fmt, arg...) printk(KERN_INFO "Bluetooth: " fmt "\n" , ## arg) #define BT_ERR(fmt, arg...) printk(KERN_ERR "%s: " fmt "\n" , __func__ , ## arg) #define BT_DBG(fmt, arg...) pr_debug("%s: " fmt "\n" , __func__ , ## arg) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 29a7a8c..5d033dc 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -150,6 +150,7 @@ enum { #define EDR_ESCO_MASK (ESCO_2EV3 | ESCO_3EV3 | ESCO_2EV5 | ESCO_3EV5) /* ACL flags */ +#define ACL_START_NO_FLUSH 0x00 #define ACL_CONT 0x01 #define ACL_START 0x02 #define ACL_ACTIVE_BCAST 0x04 @@ -194,6 +195,7 @@ enum { #define LMP_EDR_3S_ESCO 0x80 #define LMP_SIMPLE_PAIR 0x08 +#define LMP_NO_FLUSH 0x40 /* Connection modes */ #define HCI_CM_ACTIVE 0x0000 diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index a29feb0..59135a6 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -457,6 +457,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn); #define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR) #define lmp_esco_capable(dev) ((dev)->features[3] & LMP_ESCO) #define lmp_ssp_capable(dev) ((dev)->features[6] & LMP_SIMPLE_PAIR) +#define lmp_no_flush_capable(dev) ((dev)->features[6] & LMP_NO_FLUSH) /* ----- HCI protocols ----- */ struct hci_proto { diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 7ad25ca..7f88a87 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -327,6 +327,7 @@ struct l2cap_pinfo { __u8 sec_level; __u8 role_switch; __u8 force_reliable; + __u8 flushable; __u8 conf_req[64]; __u8 conf_len; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 8b602d8..3c0990d 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1391,7 +1391,7 @@ void hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags) skb->dev = (void *) hdev; bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT; - hci_add_acl_hdr(skb, conn->handle, flags | ACL_START); + hci_add_acl_hdr(skb, conn->handle, flags); list = skb_shinfo(skb)->frag_list; if (!list) { @@ -1409,12 +1409,15 @@ void hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags) spin_lock_bh(&conn->data_q.lock); __skb_queue_tail(&conn->data_q, skb); + + flags &= ~ACL_START; + flags |= ACL_CONT; do { skb = list; list = list->next; skb->dev = (void *) hdev; bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT; - hci_add_acl_hdr(skb, conn->handle, flags | ACL_CONT); + hci_add_acl_hdr(skb, conn->handle, flags); BT_DBG("%s frag %p len %d", hdev->name, skb, skb->len); diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index c791fcd..ff191b9 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -362,13 +362,19 @@ static inline u8 l2cap_get_ident(struct l2cap_conn *conn) static inline void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data) { struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data); + u8 flags; BT_DBG("code 0x%2.2x", code); if (!skb) return; - hci_send_acl(conn->hcon, skb, 0); + if (lmp_no_flush_capable(conn->hcon->hdev)) + flags = ACL_START_NO_FLUSH; + else + flags = ACL_START; + + hci_send_acl(conn->hcon, skb, flags); } static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control) @@ -378,6 +384,7 @@ static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control) struct l2cap_conn *conn = pi->conn; struct sock *sk = (struct sock *)pi; int count, hlen = L2CAP_HDR_SIZE + 2; + u8 flags; if (sk->sk_state != BT_CONNECTED) return; @@ -414,7 +421,12 @@ static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control) put_unaligned_le16(fcs, skb_put(skb, 2)); } - hci_send_acl(pi->conn->hcon, skb, 0); + if (lmp_no_flush_capable(conn->hcon->hdev)) + flags = ACL_START_NO_FLUSH; + else + flags = ACL_START; + + hci_send_acl(pi->conn->hcon, skb, flags); } static inline void l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control) @@ -900,6 +912,7 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) pi->sec_level = l2cap_pi(parent)->sec_level; pi->role_switch = l2cap_pi(parent)->role_switch; pi->force_reliable = l2cap_pi(parent)->force_reliable; + pi->flushable = l2cap_pi(parent)->flushable; } else { pi->imtu = L2CAP_DEFAULT_MTU; pi->omtu = 0; @@ -915,6 +928,7 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) pi->sec_level = BT_SECURITY_LOW; pi->role_switch = 0; pi->force_reliable = 0; + pi->flushable = BT_FLUSHABLE_OFF; } /* Default config options */ @@ -1450,10 +1464,17 @@ static void l2cap_drop_acked_frames(struct sock *sk) static inline void l2cap_do_send(struct sock *sk, struct sk_buff *skb) { struct l2cap_pinfo *pi = l2cap_pi(sk); + struct hci_conn *hcon = pi->conn->hcon; + u16 flags; BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len); - hci_send_acl(pi->conn->hcon, skb, 0); + if (!pi->flushable && lmp_no_flush_capable(hcon->hdev)) + flags = ACL_START_NO_FLUSH; + else + flags = ACL_START; + + hci_send_acl(hcon, skb, flags); } static void l2cap_streaming_send(struct sock *sk) @@ -2098,6 +2119,30 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch bt_sk(sk)->defer_setup = opt; break; + case BT_FLUSHABLE: + if (get_user(opt, (u32 __user *) optval)) { + err = -EFAULT; + break; + } + + if (opt > BT_FLUSHABLE_ON) { + err = -EINVAL; + break; + } + + if (opt == BT_FLUSHABLE_OFF) { + struct l2cap_conn *conn = l2cap_pi(sk)->conn; + /* proceed futher only when we have l2cap_conn and + No Flush support in the LM */ + if (!conn || !lmp_no_flush_capable(conn->hcon->hdev)) { + err = -EINVAL; + break; + } + } + + l2cap_pi(sk)->flushable = opt; + break; + default: err = -ENOPROTOOPT; break; @@ -2237,6 +2282,12 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch break; + case BT_FLUSHABLE: + if (put_user(l2cap_pi(sk)->flushable, (u32 __user *) optval)) + err = -EFAULT; + + break; + default: err = -ENOPROTOOPT; break; @@ -4697,7 +4748,7 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags); - if (flags & ACL_START) { + if (!(flags & ACL_CONT)) { struct l2cap_hdr *hdr; struct sock *sk; u16 cid; -- 1.7.1 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCHv4] Bluetooth: Use non-flushable by default L2CAP data packets 2011-01-03 9:14 ` Emeltchenko Andrei @ 2011-01-07 11:08 ` Andrei Emeltchenko 2011-01-10 15:16 ` Andrei Emeltchenko 2011-01-10 16:38 ` Anderson Lizardo 2011-01-21 17:10 ` Gustavo F. Padovan 2 siblings, 1 reply; 7+ messages in thread From: Andrei Emeltchenko @ 2011-01-07 11:08 UTC (permalink / raw) To: linux-bluetooth On Mon, Jan 3, 2011 at 11:14 AM, Emeltchenko Andrei <Andrei.Emeltchenko.news@gmail.com> wrote: > From: Andrei Emeltchenko <andrei.emeltchenko@nokia.com> > > Modification of Nick Pelly <npelly@google.com> patch. > > With Bluetooth 2.1 ACL packets can be flushable or non-flushable. This commit > makes ACL data packets non-flushable by default on compatible chipsets, and > adds the BT_FLUSHABLE socket option to explicitly request flushable ACL > data packets for a given L2CAP socket. This is useful for A2DP data which can > be safely discarded if it can not be delivered within a short time (while > other ACL data should not be discarded). > > Note that making ACL data flushable has no effect unless the automatic flush > timeout for that ACL link is changed from its default of 0 (infinite). > > Default packet types (for compatible chipsets): > Frame 34: 13 bytes on wire (104 bits), 13 bytes captured (104 bits) > Bluetooth HCI H4 > Bluetooth HCI ACL Packet > .... 0000 0000 0010 = Connection Handle: 0x0002 > ..00 .... .... .... = PB Flag: First Non-automatically Flushable Packet (0) > 00.. .... .... .... = BC Flag: Point-To-Point (0) > Data Total Length: 8 > Bluetooth L2CAP Packet > > After setting BT_FLUSHABLE > (sock.setsockopt(274 /*SOL_BLUETOOTH*/, 8 /* BT_FLUSHABLE */, 1 /* flush */)) > Frame 34: 13 bytes on wire (104 bits), 13 bytes captured (104 bits) > Bluetooth HCI H4 > Bluetooth HCI ACL Packet > .... 0000 0000 0010 = Connection Handle: 0x0002 > ..10 .... .... .... = PB Flag: First Automatically Flushable Packet (2) > 00.. .... .... .... = BC Flag: Point-To-Point (0) > Data Total Length: 8 > Bluetooth L2CAP Packet > > Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@nokia. > --- > include/net/bluetooth/bluetooth.h | 5 +++ > include/net/bluetooth/hci.h | 2 + > include/net/bluetooth/hci_core.h | 1 + > include/net/bluetooth/l2cap.h | 1 + > net/bluetooth/hci_core.c | 7 +++- > net/bluetooth/l2cap.c | 59 ++++++++++++++++++++++++++++++++++-- > 6 files changed, 69 insertions(+), 6 deletions(-) > > diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h > index 0c5e725..ed7d775 100644 > --- a/include/net/bluetooth/bluetooth.h > +++ b/include/net/bluetooth/bluetooth.h > @@ -64,6 +64,11 @@ struct bt_security { > > #define BT_DEFER_SETUP 7 > > +#define BT_FLUSHABLE 8 > + > +#define BT_FLUSHABLE_OFF 0 > +#define BT_FLUSHABLE_ON 1 > + > #define BT_INFO(fmt, arg...) printk(KERN_INFO "Bluetooth: " fmt "\n" , ## arg) > #define BT_ERR(fmt, arg...) printk(KERN_ERR "%s: " fmt "\n" , __func__ , ## arg) > #define BT_DBG(fmt, arg...) pr_debug("%s: " fmt "\n" , __func__ , ## arg) > diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h > index 29a7a8c..5d033dc 100644 > --- a/include/net/bluetooth/hci.h > +++ b/include/net/bluetooth/hci.h > @@ -150,6 +150,7 @@ enum { > #define EDR_ESCO_MASK (ESCO_2EV3 | ESCO_3EV3 | ESCO_2EV5 | ESCO_3EV5) > > /* ACL flags */ > +#define ACL_START_NO_FLUSH 0x00 > #define ACL_CONT 0x01 > #define ACL_START 0x02 > #define ACL_ACTIVE_BCAST 0x04 > @@ -194,6 +195,7 @@ enum { > #define LMP_EDR_3S_ESCO 0x80 > > #define LMP_SIMPLE_PAIR 0x08 > +#define LMP_NO_FLUSH 0x40 > > /* Connection modes */ > #define HCI_CM_ACTIVE 0x0000 > diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h > index a29feb0..59135a6 100644 > --- a/include/net/bluetooth/hci_core.h > +++ b/include/net/bluetooth/hci_core.h > @@ -457,6 +457,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn); > #define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR) > #define lmp_esco_capable(dev) ((dev)->features[3] & LMP_ESCO) > #define lmp_ssp_capable(dev) ((dev)->features[6] & LMP_SIMPLE_PAIR) > +#define lmp_no_flush_capable(dev) ((dev)->features[6] & LMP_NO_FLUSH) > > /* ----- HCI protocols ----- */ > struct hci_proto { > diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h > index 7ad25ca..7f88a87 100644 > --- a/include/net/bluetooth/l2cap.h > +++ b/include/net/bluetooth/l2cap.h > @@ -327,6 +327,7 @@ struct l2cap_pinfo { > __u8 sec_level; > __u8 role_switch; > __u8 force_reliable; > + __u8 flushable; > > __u8 conf_req[64]; > __u8 conf_len; > diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c > index 8b602d8..3c0990d 100644 > --- a/net/bluetooth/hci_core.c > +++ b/net/bluetooth/hci_core.c > @@ -1391,7 +1391,7 @@ void hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags) > > skb->dev = (void *) hdev; > bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT; > - hci_add_acl_hdr(skb, conn->handle, flags | ACL_START); > + hci_add_acl_hdr(skb, conn->handle, flags); > > list = skb_shinfo(skb)->frag_list; > if (!list) { > @@ -1409,12 +1409,15 @@ void hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags) > spin_lock_bh(&conn->data_q.lock); > > __skb_queue_tail(&conn->data_q, skb); > + > + flags &= ~ACL_START; > + flags |= ACL_CONT; > do { > skb = list; list = list->next; > > skb->dev = (void *) hdev; > bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT; > - hci_add_acl_hdr(skb, conn->handle, flags | ACL_CONT); > + hci_add_acl_hdr(skb, conn->handle, flags); > > BT_DBG("%s frag %p len %d", hdev->name, skb, skb->len); > > diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c > index c791fcd..ff191b9 100644 > --- a/net/bluetooth/l2cap.c > +++ b/net/bluetooth/l2cap.c > @@ -362,13 +362,19 @@ static inline u8 l2cap_get_ident(struct l2cap_conn *conn) > static inline void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data) > { > struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data); > + u8 flags; > > BT_DBG("code 0x%2.2x", code); > > if (!skb) > return; > > - hci_send_acl(conn->hcon, skb, 0); > + if (lmp_no_flush_capable(conn->hcon->hdev)) > + flags = ACL_START_NO_FLUSH; > + else > + flags = ACL_START; > + > + hci_send_acl(conn->hcon, skb, flags); > } > > static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control) > @@ -378,6 +384,7 @@ static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control) > struct l2cap_conn *conn = pi->conn; > struct sock *sk = (struct sock *)pi; > int count, hlen = L2CAP_HDR_SIZE + 2; > + u8 flags; > > if (sk->sk_state != BT_CONNECTED) > return; > @@ -414,7 +421,12 @@ static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control) > put_unaligned_le16(fcs, skb_put(skb, 2)); > } > > - hci_send_acl(pi->conn->hcon, skb, 0); > + if (lmp_no_flush_capable(conn->hcon->hdev)) > + flags = ACL_START_NO_FLUSH; > + else > + flags = ACL_START; > + > + hci_send_acl(pi->conn->hcon, skb, flags); > } > > static inline void l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control) > @@ -900,6 +912,7 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) > pi->sec_level = l2cap_pi(parent)->sec_level; > pi->role_switch = l2cap_pi(parent)->role_switch; > pi->force_reliable = l2cap_pi(parent)->force_reliable; > + pi->flushable = l2cap_pi(parent)->flushable; > } else { > pi->imtu = L2CAP_DEFAULT_MTU; > pi->omtu = 0; > @@ -915,6 +928,7 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) > pi->sec_level = BT_SECURITY_LOW; > pi->role_switch = 0; > pi->force_reliable = 0; > + pi->flushable = BT_FLUSHABLE_OFF; > } > > /* Default config options */ > @@ -1450,10 +1464,17 @@ static void l2cap_drop_acked_frames(struct sock *sk) > static inline void l2cap_do_send(struct sock *sk, struct sk_buff *skb) > { > struct l2cap_pinfo *pi = l2cap_pi(sk); > + struct hci_conn *hcon = pi->conn->hcon; > + u16 flags; > > BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len); > > - hci_send_acl(pi->conn->hcon, skb, 0); > + if (!pi->flushable && lmp_no_flush_capable(hcon->hdev)) > + flags = ACL_START_NO_FLUSH; > + else > + flags = ACL_START; > + > + hci_send_acl(hcon, skb, flags); > } > > static void l2cap_streaming_send(struct sock *sk) > @@ -2098,6 +2119,30 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch > bt_sk(sk)->defer_setup = opt; > break; > > + case BT_FLUSHABLE: > + if (get_user(opt, (u32 __user *) optval)) { > + err = -EFAULT; > + break; > + } > + > + if (opt > BT_FLUSHABLE_ON) { > + err = -EINVAL; > + break; > + } > + > + if (opt == BT_FLUSHABLE_OFF) { > + struct l2cap_conn *conn = l2cap_pi(sk)->conn; > + /* proceed futher only when we have l2cap_conn and > + No Flush support in the LM */ > + if (!conn || !lmp_no_flush_capable(conn->hcon->hdev)) { > + err = -EINVAL; > + break; > + } > + } > + > + l2cap_pi(sk)->flushable = opt; > + break; > + > default: > err = -ENOPROTOOPT; > break; > @@ -2237,6 +2282,12 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch > > break; > > + case BT_FLUSHABLE: > + if (put_user(l2cap_pi(sk)->flushable, (u32 __user *) optval)) > + err = -EFAULT; > + > + break; > + > default: > err = -ENOPROTOOPT; > break; > @@ -4697,7 +4748,7 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl > > BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags); > > - if (flags & ACL_START) { > + if (!(flags & ACL_CONT)) { > struct l2cap_hdr *hdr; > struct sock *sk; > u16 cid; > -- > 1.7.1 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > ping ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCHv4] Bluetooth: Use non-flushable by default L2CAP data packets 2011-01-07 11:08 ` Andrei Emeltchenko @ 2011-01-10 15:16 ` Andrei Emeltchenko 0 siblings, 0 replies; 7+ messages in thread From: Andrei Emeltchenko @ 2011-01-10 15:16 UTC (permalink / raw) To: linux-bluetooth On Fri, Jan 7, 2011 at 1:08 PM, Andrei Emeltchenko <andrei.emeltchenko.news@gmail.com> wrote: > On Mon, Jan 3, 2011 at 11:14 AM, Emeltchenko Andrei > <Andrei.Emeltchenko.news@gmail.com> wrote: >> From: Andrei Emeltchenko <andrei.emeltchenko@nokia.com> >> >> Modification of Nick Pelly <npelly@google.com> patch. >> >> With Bluetooth 2.1 ACL packets can be flushable or non-flushable. This commit >> makes ACL data packets non-flushable by default on compatible chipsets, and >> adds the BT_FLUSHABLE socket option to explicitly request flushable ACL >> data packets for a given L2CAP socket. This is useful for A2DP data which can >> be safely discarded if it can not be delivered within a short time (while >> other ACL data should not be discarded). >> >> Note that making ACL data flushable has no effect unless the automatic flush >> timeout for that ACL link is changed from its default of 0 (infinite). >> >> Default packet types (for compatible chipsets): >> Frame 34: 13 bytes on wire (104 bits), 13 bytes captured (104 bits) >> Bluetooth HCI H4 >> Bluetooth HCI ACL Packet >> .... 0000 0000 0010 = Connection Handle: 0x0002 >> ..00 .... .... .... = PB Flag: First Non-automatically Flushable Packet (0) >> 00.. .... .... .... = BC Flag: Point-To-Point (0) >> Data Total Length: 8 >> Bluetooth L2CAP Packet >> >> After setting BT_FLUSHABLE >> (sock.setsockopt(274 /*SOL_BLUETOOTH*/, 8 /* BT_FLUSHABLE */, 1 /* flush */)) >> Frame 34: 13 bytes on wire (104 bits), 13 bytes captured (104 bits) >> Bluetooth HCI H4 >> Bluetooth HCI ACL Packet >> .... 0000 0000 0010 = Connection Handle: 0x0002 >> ..10 .... .... .... = PB Flag: First Automatically Flushable Packet (2) >> 00.. .... .... .... = BC Flag: Point-To-Point (0) >> Data Total Length: 8 >> Bluetooth L2CAP Packet >> >> Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@nokia. >> --- >> include/net/bluetooth/bluetooth.h | 5 +++ >> include/net/bluetooth/hci.h | 2 + >> include/net/bluetooth/hci_core.h | 1 + >> include/net/bluetooth/l2cap.h | 1 + >> net/bluetooth/hci_core.c | 7 +++- >> net/bluetooth/l2cap.c | 59 ++++++++++++++++++++++++++++++++++-- >> 6 files changed, 69 insertions(+), 6 deletions(-) >> >> diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h >> index 0c5e725..ed7d775 100644 >> --- a/include/net/bluetooth/bluetooth.h >> +++ b/include/net/bluetooth/bluetooth.h >> @@ -64,6 +64,11 @@ struct bt_security { >> >> #define BT_DEFER_SETUP 7 >> >> +#define BT_FLUSHABLE 8 >> + >> +#define BT_FLUSHABLE_OFF 0 >> +#define BT_FLUSHABLE_ON 1 >> + >> #define BT_INFO(fmt, arg...) printk(KERN_INFO "Bluetooth: " fmt "\n" , ## arg) >> #define BT_ERR(fmt, arg...) printk(KERN_ERR "%s: " fmt "\n" , __func__ , ## arg) >> #define BT_DBG(fmt, arg...) pr_debug("%s: " fmt "\n" , __func__ , ## arg) >> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h >> index 29a7a8c..5d033dc 100644 >> --- a/include/net/bluetooth/hci.h >> +++ b/include/net/bluetooth/hci.h >> @@ -150,6 +150,7 @@ enum { >> #define EDR_ESCO_MASK (ESCO_2EV3 | ESCO_3EV3 | ESCO_2EV5 | ESCO_3EV5) >> >> /* ACL flags */ >> +#define ACL_START_NO_FLUSH 0x00 >> #define ACL_CONT 0x01 >> #define ACL_START 0x02 >> #define ACL_ACTIVE_BCAST 0x04 >> @@ -194,6 +195,7 @@ enum { >> #define LMP_EDR_3S_ESCO 0x80 >> >> #define LMP_SIMPLE_PAIR 0x08 >> +#define LMP_NO_FLUSH 0x40 >> >> /* Connection modes */ >> #define HCI_CM_ACTIVE 0x0000 >> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h >> index a29feb0..59135a6 100644 >> --- a/include/net/bluetooth/hci_core.h >> +++ b/include/net/bluetooth/hci_core.h >> @@ -457,6 +457,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn); >> #define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR) >> #define lmp_esco_capable(dev) ((dev)->features[3] & LMP_ESCO) >> #define lmp_ssp_capable(dev) ((dev)->features[6] & LMP_SIMPLE_PAIR) >> +#define lmp_no_flush_capable(dev) ((dev)->features[6] & LMP_NO_FLUSH) >> >> /* ----- HCI protocols ----- */ >> struct hci_proto { >> diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h >> index 7ad25ca..7f88a87 100644 >> --- a/include/net/bluetooth/l2cap.h >> +++ b/include/net/bluetooth/l2cap.h >> @@ -327,6 +327,7 @@ struct l2cap_pinfo { >> __u8 sec_level; >> __u8 role_switch; >> __u8 force_reliable; >> + __u8 flushable; >> >> __u8 conf_req[64]; >> __u8 conf_len; >> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c >> index 8b602d8..3c0990d 100644 >> --- a/net/bluetooth/hci_core.c >> +++ b/net/bluetooth/hci_core.c >> @@ -1391,7 +1391,7 @@ void hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags) >> >> skb->dev = (void *) hdev; >> bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT; >> - hci_add_acl_hdr(skb, conn->handle, flags | ACL_START); >> + hci_add_acl_hdr(skb, conn->handle, flags); >> >> list = skb_shinfo(skb)->frag_list; >> if (!list) { >> @@ -1409,12 +1409,15 @@ void hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags) >> spin_lock_bh(&conn->data_q.lock); >> >> __skb_queue_tail(&conn->data_q, skb); >> + >> + flags &= ~ACL_START; >> + flags |= ACL_CONT; >> do { >> skb = list; list = list->next; >> >> skb->dev = (void *) hdev; >> bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT; >> - hci_add_acl_hdr(skb, conn->handle, flags | ACL_CONT); >> + hci_add_acl_hdr(skb, conn->handle, flags); >> >> BT_DBG("%s frag %p len %d", hdev->name, skb, skb->len); >> >> diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c >> index c791fcd..ff191b9 100644 >> --- a/net/bluetooth/l2cap.c >> +++ b/net/bluetooth/l2cap.c >> @@ -362,13 +362,19 @@ static inline u8 l2cap_get_ident(struct l2cap_conn *conn) >> static inline void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data) >> { >> struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data); >> + u8 flags; >> >> BT_DBG("code 0x%2.2x", code); >> >> if (!skb) >> return; >> >> - hci_send_acl(conn->hcon, skb, 0); >> + if (lmp_no_flush_capable(conn->hcon->hdev)) >> + flags = ACL_START_NO_FLUSH; >> + else >> + flags = ACL_START; >> + >> + hci_send_acl(conn->hcon, skb, flags); >> } >> >> static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control) >> @@ -378,6 +384,7 @@ static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control) >> struct l2cap_conn *conn = pi->conn; >> struct sock *sk = (struct sock *)pi; >> int count, hlen = L2CAP_HDR_SIZE + 2; >> + u8 flags; >> >> if (sk->sk_state != BT_CONNECTED) >> return; >> @@ -414,7 +421,12 @@ static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control) >> put_unaligned_le16(fcs, skb_put(skb, 2)); >> } >> >> - hci_send_acl(pi->conn->hcon, skb, 0); >> + if (lmp_no_flush_capable(conn->hcon->hdev)) >> + flags = ACL_START_NO_FLUSH; >> + else >> + flags = ACL_START; >> + >> + hci_send_acl(pi->conn->hcon, skb, flags); >> } >> >> static inline void l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control) >> @@ -900,6 +912,7 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) >> pi->sec_level = l2cap_pi(parent)->sec_level; >> pi->role_switch = l2cap_pi(parent)->role_switch; >> pi->force_reliable = l2cap_pi(parent)->force_reliable; >> + pi->flushable = l2cap_pi(parent)->flushable; >> } else { >> pi->imtu = L2CAP_DEFAULT_MTU; >> pi->omtu = 0; >> @@ -915,6 +928,7 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) >> pi->sec_level = BT_SECURITY_LOW; >> pi->role_switch = 0; >> pi->force_reliable = 0; >> + pi->flushable = BT_FLUSHABLE_OFF; >> } >> >> /* Default config options */ >> @@ -1450,10 +1464,17 @@ static void l2cap_drop_acked_frames(struct sock *sk) >> static inline void l2cap_do_send(struct sock *sk, struct sk_buff *skb) >> { >> struct l2cap_pinfo *pi = l2cap_pi(sk); >> + struct hci_conn *hcon = pi->conn->hcon; >> + u16 flags; >> >> BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len); >> >> - hci_send_acl(pi->conn->hcon, skb, 0); >> + if (!pi->flushable && lmp_no_flush_capable(hcon->hdev)) >> + flags = ACL_START_NO_FLUSH; >> + else >> + flags = ACL_START; >> + >> + hci_send_acl(hcon, skb, flags); >> } >> >> static void l2cap_streaming_send(struct sock *sk) >> @@ -2098,6 +2119,30 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch >> bt_sk(sk)->defer_setup = opt; >> break; >> >> + case BT_FLUSHABLE: >> + if (get_user(opt, (u32 __user *) optval)) { >> + err = -EFAULT; >> + break; >> + } >> + >> + if (opt > BT_FLUSHABLE_ON) { >> + err = -EINVAL; >> + break; >> + } >> + >> + if (opt == BT_FLUSHABLE_OFF) { >> + struct l2cap_conn *conn = l2cap_pi(sk)->conn; >> + /* proceed futher only when we have l2cap_conn and >> + No Flush support in the LM */ >> + if (!conn || !lmp_no_flush_capable(conn->hcon->hdev)) { >> + err = -EINVAL; >> + break; >> + } >> + } >> + >> + l2cap_pi(sk)->flushable = opt; >> + break; >> + >> default: >> err = -ENOPROTOOPT; >> break; >> @@ -2237,6 +2282,12 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch >> >> break; >> >> + case BT_FLUSHABLE: >> + if (put_user(l2cap_pi(sk)->flushable, (u32 __user *) optval)) >> + err = -EFAULT; >> + >> + break; >> + >> default: >> err = -ENOPROTOOPT; >> break; >> @@ -4697,7 +4748,7 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl >> >> BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags); >> >> - if (flags & ACL_START) { >> + if (!(flags & ACL_CONT)) { >> struct l2cap_hdr *hdr; >> struct sock *sk; >> u16 cid; >> -- >> 1.7.1 >> >> -- >> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in >> the body of a message to majordomo@vger.kernel.org >> More majordomo info at http://vger.kernel.org/majordomo-info.html >> > > ping > any comments? ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCHv4] Bluetooth: Use non-flushable by default L2CAP data packets 2011-01-03 9:14 ` Emeltchenko Andrei 2011-01-07 11:08 ` Andrei Emeltchenko @ 2011-01-10 16:38 ` Anderson Lizardo 2011-01-11 8:40 ` Andrei Emeltchenko 2011-01-21 17:10 ` Gustavo F. Padovan 2 siblings, 1 reply; 7+ messages in thread From: Anderson Lizardo @ 2011-01-10 16:38 UTC (permalink / raw) To: Emeltchenko Andrei; +Cc: linux-bluetooth Hi Andrei, On Mon, Jan 3, 2011 at 5:14 AM, Emeltchenko Andrei <Andrei.Emeltchenko.news@gmail.com> wrote: > diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c > index c791fcd..ff191b9 100644 > --- a/net/bluetooth/l2cap.c > +++ b/net/bluetooth/l2cap.c > @@ -362,13 +362,19 @@ static inline u8 l2cap_get_ident(struct l2cap_conn *conn) > static inline void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data) > { > struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data); > + u8 flags; > > BT_DBG("code 0x%2.2x", code); > > if (!skb) > return; > > - hci_send_acl(conn->hcon, skb, 0); > + if (lmp_no_flush_capable(conn->hcon->hdev)) > + flags = ACL_START_NO_FLUSH; > + else > + flags = ACL_START; > + > + hci_send_acl(conn->hcon, skb, flags); > } Looks like you can't control the "no flush" flag here using the new BT_FLUSHABLE setsockopt() option. > @@ -414,7 +421,12 @@ static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control) > put_unaligned_le16(fcs, skb_put(skb, 2)); > } > > - hci_send_acl(pi->conn->hcon, skb, 0); > + if (lmp_no_flush_capable(conn->hcon->hdev)) > + flags = ACL_START_NO_FLUSH; > + else > + flags = ACL_START; > + > + hci_send_acl(pi->conn->hcon, skb, flags); > } Same here. Regards, -- Anderson Lizardo OpenBossa Labs - INdT Manaus - Brazil ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCHv4] Bluetooth: Use non-flushable by default L2CAP data packets 2011-01-10 16:38 ` Anderson Lizardo @ 2011-01-11 8:40 ` Andrei Emeltchenko 0 siblings, 0 replies; 7+ messages in thread From: Andrei Emeltchenko @ 2011-01-11 8:40 UTC (permalink / raw) To: Anderson Lizardo; +Cc: linux-bluetooth Hi Anderson, On Mon, Jan 10, 2011 at 6:38 PM, Anderson Lizardo <anderson.lizardo@openbossa.org> wrote: > Hi Andrei, > > On Mon, Jan 3, 2011 at 5:14 AM, Emeltchenko Andrei > <Andrei.Emeltchenko.news@gmail.com> wrote: >> diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c >> index c791fcd..ff191b9 100644 >> --- a/net/bluetooth/l2cap.c >> +++ b/net/bluetooth/l2cap.c >> @@ -362,13 +362,19 @@ static inline u8 l2cap_get_ident(struct l2cap_conn *conn) >> static inline void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data) >> { >> struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data); >> + u8 flags; >> >> BT_DBG("code 0x%2.2x", code); >> >> if (!skb) >> return; >> >> - hci_send_acl(conn->hcon, skb, 0); >> + if (lmp_no_flush_capable(conn->hcon->hdev)) >> + flags = ACL_START_NO_FLUSH; >> + else >> + flags = ACL_START; >> + >> + hci_send_acl(conn->hcon, skb, flags); >> } > > Looks like you can't control the "no flush" flag here using the new > BT_FLUSHABLE setsockopt() option. The flag is used when sending data packets, when sending l2cap commands we set ACL_START_NO_FLUSH when host supports it. Regards, Andrei >> @@ -414,7 +421,12 @@ static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control) >> put_unaligned_le16(fcs, skb_put(skb, 2)); >> } >> >> - hci_send_acl(pi->conn->hcon, skb, 0); >> + if (lmp_no_flush_capable(conn->hcon->hdev)) >> + flags = ACL_START_NO_FLUSH; >> + else >> + flags = ACL_START; >> + >> + hci_send_acl(pi->conn->hcon, skb, flags); >> } > > Same here. > > Regards, > -- > Anderson Lizardo > OpenBossa Labs - INdT > Manaus - Brazil > ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCHv4] Bluetooth: Use non-flushable by default L2CAP data packets 2011-01-03 9:14 ` Emeltchenko Andrei 2011-01-07 11:08 ` Andrei Emeltchenko 2011-01-10 16:38 ` Anderson Lizardo @ 2011-01-21 17:10 ` Gustavo F. Padovan 2 siblings, 0 replies; 7+ messages in thread From: Gustavo F. Padovan @ 2011-01-21 17:10 UTC (permalink / raw) To: Emeltchenko Andrei; +Cc: linux-bluetooth Hi Andrei, * Emeltchenko Andrei <Andrei.Emeltchenko.news@gmail.com> [2011-01-03 11:14:36 +0200]: > From: Andrei Emeltchenko <andrei.emeltchenko@nokia.com> > > Modification of Nick Pelly <npelly@google.com> patch. > > With Bluetooth 2.1 ACL packets can be flushable or non-flushable. This commit > makes ACL data packets non-flushable by default on compatible chipsets, and > adds the BT_FLUSHABLE socket option to explicitly request flushable ACL > data packets for a given L2CAP socket. This is useful for A2DP data which can > be safely discarded if it can not be delivered within a short time (while > other ACL data should not be discarded). > > Note that making ACL data flushable has no effect unless the automatic flush > timeout for that ACL link is changed from its default of 0 (infinite). > > Default packet types (for compatible chipsets): > Frame 34: 13 bytes on wire (104 bits), 13 bytes captured (104 bits) > Bluetooth HCI H4 > Bluetooth HCI ACL Packet > .... 0000 0000 0010 = Connection Handle: 0x0002 > ..00 .... .... .... = PB Flag: First Non-automatically Flushable Packet (0) > 00.. .... .... .... = BC Flag: Point-To-Point (0) > Data Total Length: 8 > Bluetooth L2CAP Packet > > After setting BT_FLUSHABLE > (sock.setsockopt(274 /*SOL_BLUETOOTH*/, 8 /* BT_FLUSHABLE */, 1 /* flush */)) > Frame 34: 13 bytes on wire (104 bits), 13 bytes captured (104 bits) > Bluetooth HCI H4 > Bluetooth HCI ACL Packet > .... 0000 0000 0010 = Connection Handle: 0x0002 > ..10 .... .... .... = PB Flag: First Automatically Flushable Packet (2) > 00.. .... .... .... = BC Flag: Point-To-Point (0) > Data Total Length: 8 > Bluetooth L2CAP Packet > > Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@nokia.com> > --- > include/net/bluetooth/bluetooth.h | 5 +++ > include/net/bluetooth/hci.h | 2 + > include/net/bluetooth/hci_core.h | 1 + > include/net/bluetooth/l2cap.h | 1 + > net/bluetooth/hci_core.c | 7 +++- > net/bluetooth/l2cap.c | 59 ++++++++++++++++++++++++++++++++++-- > 6 files changed, 69 insertions(+), 6 deletions(-) Patch has been applied to bluetooth-next-2.6. Thanks. -- Gustavo F. Padovan http://profusion.mobi ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2011-01-21 17:10 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2011-01-03 9:14 [PATCHv4] Bluetooth: Use non-flushable by default L2CAP data packets Emeltchenko Andrei 2011-01-03 9:14 ` Emeltchenko Andrei 2011-01-07 11:08 ` Andrei Emeltchenko 2011-01-10 15:16 ` Andrei Emeltchenko 2011-01-10 16:38 ` Anderson Lizardo 2011-01-11 8:40 ` Andrei Emeltchenko 2011-01-21 17:10 ` Gustavo F. Padovan
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox