#define BT_DEFER_SETUP 7
+#define BT_POWER 8
+struct bt_power {
+ __u8 force_active;
+};
+
#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)
__u8 tx_seq;
__u8 retries;
__u8 sar;
+ __u8 force_active;
};
#define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb))
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);
__u8 role_switch;
__u8 force_reliable;
__u8 flushable;
+ __u8 force_active;
__u8 conf_req[64];
__u8 conf_len;
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, 1);
if (test_bit(HCI_CONN_MODE_CHANGE_PEND, &acl->pend)) {
/* defer SCO setup until mode change completed */
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;
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)) {
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;
if (conn) {
register struct hci_proto *hp;
- hci_conn_enter_active_mode(conn);
+ hci_conn_enter_active_mode(conn, 1);
/* Send to upper protocol */
if ((hp = hci_proto[HCI_PROTO_L2CAP]) && hp->recv_acldata) {
else
flags = ACL_START;
+ bt_cb(skb)->force_active = 1;
+
hci_send_acl(conn->hcon, skb, flags);
}
put_unaligned_le16(fcs, skb_put(skb, 2));
}
+ bt_cb(skb)->force_active = l2cap_pi(sk)->force_active;
+
hci_send_acl(pi->conn->hcon, skb, 0);
}
pi->role_switch = l2cap_pi(parent)->role_switch;
pi->force_reliable = l2cap_pi(parent)->force_reliable;
pi->flushable = l2cap_pi(parent)->flushable;
+ pi->force_active = l2cap_pi(parent)->force_active;
} else {
pi->imtu = L2CAP_DEFAULT_MTU;
pi->omtu = 0;
pi->role_switch = 0;
pi->force_reliable = 0;
pi->flushable = 0;
+ pi->force_active = 1;
}
/* Default config options */
else
flags = ACL_START;
+ bt_cb(skb)->force_active = pi->force_active;
hci_send_acl(hcon, skb, flags);
}
{
struct sock *sk = sock->sk;
struct bt_security sec;
+ struct bt_power pwr;
int len, err = 0;
u32 opt;
bt_sk(sk)->defer_setup = opt;
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 = 1;
+
+ len = min_t(unsigned int, sizeof(pwr), optlen);
+ if (copy_from_user((char *) &pwr, optval, len)) {
+ err = -EFAULT;
+ break;
+ }
+ l2cap_pi(sk)->force_active = pwr.force_active;
+ break;
+
default:
err = -ENOPROTOOPT;
break;
{
struct sock *sk = sock->sk;
struct bt_security sec;
+ struct bt_power pwr;
int len, err = 0;
BT_DBG("sk %p", sk);
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 = l2cap_pi(sk)->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;