Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e702112f authored by Andrei Emeltchenko's avatar Andrei Emeltchenko Committed by Gustavo Padovan
Browse files

Bluetooth: Use non-flushable by default L2CAP data packets



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: default avatarAndrei Emeltchenko <andrei.emeltchenko@nokia.com>
Signed-off-by: default avatarGustavo F. Padovan <padovan@profusion.mobi>
parent b2c60d42
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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)
+2 −0
Original line number Diff line number Diff line
@@ -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
+1 −0
Original line number Diff line number Diff line
@@ -458,6 +458,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 {
+1 −0
Original line number Diff line number Diff line
@@ -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;
+5 −2
Original line number Diff line number Diff line
@@ -1395,7 +1395,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) {
@@ -1413,12 +1413,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);

Loading