Re: [PATCH] Bluetooth: Add BT_POWER L2CAP socket option.

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

 



* Jaikumar Ganesh <jaikumarg@xxxxxxxxx> [2011-05-31 18:53:51 -0700]:

> Gustavo,
> 
> On Mon, May 30, 2011 at 3:11 PM, Gustavo F. Padovan
> <padovan@xxxxxxxxxxxxxx> wrote:
> > Hi Jaikumar,
> >
> > * Jaikumar Ganesh <jaikumar@xxxxxxxxxx> [2011-05-23 18:06:04 -0700]:
> >
> >> Add BT_POWER socket option used to control the power
> >> characteristics of the underlying ACL link. When the remote end
> >> has put the link in sniff mode and the host stack wants to send
> >> data we need need to explicitly exit sniff mode to work well with
> >> certain devices (For example, A2DP on Plantronics Voyager 855).
> >> However, this causes problems with HID devices.
> >>
> >> Hence, moving into active mode when sending data, irrespective
> >> of who set the sniff mode has been made as a socket option. By
> >> default, we will move into active mode. HID devices can set the
> >> L2CAP socket option to prevent this from happening.
> >>
> >> Currently, this has been implemented for L2CAP sockets. This has been
> >> tested with incoming and outgoing L2CAP sockets for HID and A2DP.
> >>
> >> Based on discussions on linux-bluetooth and patches submitted by
> >> Andrei Emeltchenko.
> >>
> >> Signed-off-by: Jaikumar Ganesh <jaikumar@xxxxxxxxxx>
> >> ---
> >>  include/net/bluetooth/bluetooth.h |    8 ++++++++
> >>  include/net/bluetooth/hci_core.h  |    2 +-
> >>  include/net/bluetooth/l2cap.h     |    1 +
> >>  net/bluetooth/hci_conn.c          |    9 ++++++---
> >>  net/bluetooth/hci_core.c          |    4 ++--
> >>  net/bluetooth/l2cap_core.c        |    5 +++++
> >>  net/bluetooth/l2cap_sock.c        |   36 ++++++++++++++++++++++++++++++++++++
> >>  7 files changed, 59 insertions(+), 6 deletions(-)
> >>
> >> diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
> >> index 4375043..af930a3 100644
> >> --- a/include/net/bluetooth/bluetooth.h
> >> +++ b/include/net/bluetooth/bluetooth.h
> >> @@ -69,6 +69,13 @@ struct bt_security {
> >>  #define BT_FLUSHABLE_OFF     0
> >>  #define BT_FLUSHABLE_ON              1
> >>
> >> +#define BT_POWER     9
> >> +struct bt_power {
> >> +     __u8 force_active;
> >> +};
> >> +#define BT_POWER_FORCE_ACTIVE_OFF 0
> >> +#define BT_POWER_FORCE_ACTIVE_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)
> >> @@ -150,6 +157,7 @@ struct bt_skb_cb {
> >>       __u8 retries;
> >>       __u8 sar;
> >>       unsigned short channel;
> >> +     __u8 force_active;
> >>  };
> >>  #define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb))
> >>
> >> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> >> index 6c994c0..0747841 100644
> >> --- a/include/net/bluetooth/hci_core.h
> >> +++ b/include/net/bluetooth/hci_core.h
> >> @@ -427,7 +427,7 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type);
> >>  int hci_conn_change_link_key(struct hci_conn *conn);
> >>  int hci_conn_switch_role(struct hci_conn *conn, __u8 role);
> >>
> >> -void hci_conn_enter_active_mode(struct hci_conn *conn);
> >> +void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active);
> >>  void hci_conn_enter_sniff_mode(struct hci_conn *conn);
> >>
> >>  void hci_conn_hold_device(struct hci_conn *conn);
> >> diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
> >> index d09c9b1..942970d 100644
> >> --- a/include/net/bluetooth/l2cap.h
> >> +++ b/include/net/bluetooth/l2cap.h
> >> @@ -302,6 +302,7 @@ struct l2cap_chan {
> >>       __u8            role_switch;
> >>       __u8            force_reliable;
> >>       __u8            flushable;
> >> +     __u8            force_active;
> >>
> >>       __u8            ident;
> >>
> >> diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
> >> index 3163330..5195715 100644
> >> --- a/net/bluetooth/hci_conn.c
> >> +++ b/net/bluetooth/hci_conn.c
> >> @@ -497,7 +497,7 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8
> >>       if (acl->state == BT_CONNECTED &&
> >>                       (sco->state == BT_OPEN || sco->state == BT_CLOSED)) {
> >>               acl->power_save = 1;
> >> -             hci_conn_enter_active_mode(acl);
> >> +             hci_conn_enter_active_mode(acl, BT_POWER_FORCE_ACTIVE_ON);
> >>
> >>               if (test_bit(HCI_CONN_MODE_CHANGE_PEND, &acl->pend)) {
> >>                       /* defer SCO setup until mode change completed */
> >> @@ -676,7 +676,7 @@ int hci_conn_switch_role(struct hci_conn *conn, __u8 role)
> >>  EXPORT_SYMBOL(hci_conn_switch_role);
> >>
> >>  /* Enter active mode */
> >> -void hci_conn_enter_active_mode(struct hci_conn *conn)
> >> +void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active)
> >>  {
> >>       struct hci_dev *hdev = conn->hdev;
> >>
> >> @@ -685,7 +685,10 @@ void hci_conn_enter_active_mode(struct hci_conn *conn)
> >>       if (test_bit(HCI_RAW, &hdev->flags))
> >>               return;
> >>
> >> -     if (conn->mode != HCI_CM_SNIFF || !conn->power_save)
> >> +     if (conn->mode != HCI_CM_SNIFF)
> >> +             goto timer;
> >> +
> >> +     if (!conn->power_save && !force_active)
> >>               goto timer;
> >>
> >>       if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
> >> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> >> index b6bda3f..be68e7d 100644
> >> --- a/net/bluetooth/hci_core.c
> >> +++ b/net/bluetooth/hci_core.c
> >> @@ -1893,7 +1893,7 @@ static inline void hci_sched_acl(struct hci_dev *hdev)
> >>               while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
> >>                       BT_DBG("skb %p len %d", skb, skb->len);
> >>
> >> -                     hci_conn_enter_active_mode(conn);
> >> +                     hci_conn_enter_active_mode(conn, bt_cb(skb)->force_active);
> >>
> >>                       hci_send_frame(skb);
> >>                       hdev->acl_last_tx = jiffies;
> >> @@ -2032,7 +2032,7 @@ static inline void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb)
> >>       if (conn) {
> >>               register struct hci_proto *hp;
> >>
> >> -             hci_conn_enter_active_mode(conn);
> >> +             hci_conn_enter_active_mode(conn, bt_cb(skb)->force_active);
> >>
> >>               /* Send to upper protocol */
> >>               hp = hci_proto[HCI_PROTO_L2CAP];
> >> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> >> index 7c0e571..2a80a91 100644
> >> --- a/net/bluetooth/l2cap_core.c
> >> +++ b/net/bluetooth/l2cap_core.c
> >> @@ -408,6 +408,8 @@ void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *d
> >>       else
> >>               flags = ACL_START;
> >>
> >> +     bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
> >> +
> >>       hci_send_acl(conn->hcon, skb, flags);
> >>  }
> >>
> >> @@ -461,6 +463,8 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
> >>       else
> >>               flags = ACL_START;
> >>
> >> +     bt_cb(skb)->force_active = chan->force_active;
> >> +
> >>       hci_send_acl(chan->conn->hcon, skb, flags);
> >>  }
> >>
> >> @@ -1089,6 +1093,7 @@ void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
> >>       else
> >>               flags = ACL_START;
> >>
> >> +     bt_cb(skb)->force_active = chan->force_active;
> >>       hci_send_acl(hcon, skb, flags);
> >>  }
> >>
> >> diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
> >> index c98360d..9f99e1d 100644
> >> --- a/net/bluetooth/l2cap_sock.c
> >> +++ b/net/bluetooth/l2cap_sock.c
> >> @@ -436,6 +436,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
> >>       struct sock *sk = sock->sk;
> >>       struct l2cap_chan *chan = l2cap_pi(sk)->chan;
> >>       struct bt_security sec;
> >> +     struct bt_power pwr;
> >>       int len, err = 0;
> >>
> >>       BT_DBG("sk %p", sk);
> >> @@ -484,6 +485,21 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
> >>
> >>               break;
> >>
> >> +     case BT_POWER:
> >> +             if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
> >> +                             && sk->sk_type != SOCK_RAW) {
> >> +                     err = -EINVAL;
> >> +                     break;
> >> +             }
> >> +
> >> +             pwr.force_active = chan->force_active;
> >> +
> >> +             len = min_t(unsigned int, len, sizeof(pwr));
> >> +             if (copy_to_user(optval, (char *) &pwr, len))
> >> +                     err = -EFAULT;
> >> +
> >> +             break;
> >> +
> >>       default:
> >>               err = -ENOPROTOOPT;
> >>               break;
> >> @@ -584,6 +600,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
> >>       struct sock *sk = sock->sk;
> >>       struct l2cap_chan *chan = l2cap_pi(sk)->chan;
> >>       struct bt_security sec;
> >> +     struct bt_power pwr;
> >>       int len, err = 0;
> >>       u32 opt;
> >>
> >> @@ -660,6 +677,23 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
> >>               chan->flushable = opt;
> >>               break;
> >>
> >> +     case BT_POWER:
> >> +             if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
> >> +                             && sk->sk_type != SOCK_RAW) {
> >> +                     err = -EINVAL;
> >
> > This need to be rebased against bluetooth-next. Not sure, but this seems to be
> > the only place of conflict.
> 
> Rebased patch attached.
> 
> Thanks
> 
> >
> > --
> > Gustavo F. Padovan
> > http://profusion.mobi
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> > the body of a message to majordomo@xxxxxxxxxxxxxxx
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> >

> From 74e9a75ef48b633aa82e28ec775bb04b630d51ac Mon Sep 17 00:00:00 2001
> From: Jaikumar Ganesh <jaikumar@xxxxxxxxxx>
> Date: Mon, 23 May 2011 18:06:04 -0700
> Subject: [PATCH] Bluetooth: Add BT_POWER L2CAP socket option.
> 
> Add BT_POWER socket option used to control the power
> characteristics of the underlying ACL link. When the remote end
> has put the link in sniff mode and the host stack wants to send
> data we need need to explicitly exit sniff mode to work well with
> certain devices (For example, A2DP on Plantronics Voyager 855).
> However, this causes problems with HID devices.
> 
> Hence, moving into active mode when sending data, irrespective
> of who set the sniff mode has been made as a socket option. By
> default, we will move into active mode. HID devices can set the
> L2CAP socket option to prevent this from happening.
> 
> Currently, this has been implemented for L2CAP sockets. This has been
> tested with incoming and outgoing L2CAP sockets for HID and A2DP.
> 
> Based on discussions on linux-bluetooth and patches submitted by
> Andrei Emeltchenko.
> 
> Signed-off-by: Jaikumar Ganesh <jaikumar@xxxxxxxxxx>
> ---
>  include/net/bluetooth/bluetooth.h |    8 ++++++++
>  include/net/bluetooth/hci_core.h  |    2 +-
>  include/net/bluetooth/l2cap.h     |    1 +
>  net/bluetooth/hci_conn.c          |    9 ++++++---
>  net/bluetooth/hci_core.c          |    4 ++--
>  net/bluetooth/l2cap_core.c        |    5 +++++
>  net/bluetooth/l2cap_sock.c        |   36 ++++++++++++++++++++++++++++++++++++
>  7 files changed, 59 insertions(+), 6 deletions(-)

I applied it, but please next time send a inline patch. Thanks.

-- 
Gustavo F. Padovan
http://profusion.mobi
--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[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