Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 237302
b: refs/heads/master
c: e702112
h: refs/heads/master
v: v3
  • Loading branch information
Andrei Emeltchenko authored and Gustavo F. Padovan committed Feb 8, 2011
1 parent b36624c commit 9cbc35a
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 7 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b2c60d42db0fea1e6c4345739601024863566a13
refs/heads/master: e702112ff68a554bcac16bb03ddc2b8e5425bcbf
5 changes: 5 additions & 0 deletions trunk/include/net/bluetooth/bluetooth.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions trunk/include/net/bluetooth/hci.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions trunk/include/net/bluetooth/hci_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
1 change: 1 addition & 0 deletions trunk/include/net/bluetooth/l2cap.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
7 changes: 5 additions & 2 deletions trunk/net/bluetooth/hci_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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);

Expand Down
59 changes: 55 additions & 4 deletions trunk/net/bluetooth/l2cap.c
Original file line number Diff line number Diff line change
Expand Up @@ -373,13 +373,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)
Expand All @@ -389,6 +395,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;
Expand Down Expand Up @@ -425,7 +432,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)
Expand Down Expand Up @@ -912,6 +924,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;
Expand All @@ -927,6 +940,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 */
Expand Down Expand Up @@ -1431,10 +1445,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)
Expand Down Expand Up @@ -2079,6 +2100,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;
Expand Down Expand Up @@ -2218,6 +2263,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;
Expand Down Expand Up @@ -4678,7 +4729,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;
Expand Down

0 comments on commit 9cbc35a

Please sign in to comment.