diff options
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/hci_conn.c | 9 | ||||
-rw-r--r-- | net/bluetooth/hci_core.c | 4 | ||||
-rw-r--r-- | net/bluetooth/l2cap_core.c | 5 | ||||
-rw-r--r-- | net/bluetooth/l2cap_sock.c | 36 |
4 files changed, 49 insertions, 5 deletions
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index ce67d0ff486f..0408a93570d6 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -507,7 +507,7 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 | |||
507 | if (acl->state == BT_CONNECTED && | 507 | if (acl->state == BT_CONNECTED && |
508 | (sco->state == BT_OPEN || sco->state == BT_CLOSED)) { | 508 | (sco->state == BT_OPEN || sco->state == BT_CLOSED)) { |
509 | acl->power_save = 1; | 509 | acl->power_save = 1; |
510 | hci_conn_enter_active_mode(acl); | 510 | hci_conn_enter_active_mode(acl, BT_POWER_FORCE_ACTIVE_ON); |
511 | 511 | ||
512 | if (test_bit(HCI_CONN_MODE_CHANGE_PEND, &acl->pend)) { | 512 | if (test_bit(HCI_CONN_MODE_CHANGE_PEND, &acl->pend)) { |
513 | /* defer SCO setup until mode change completed */ | 513 | /* defer SCO setup until mode change completed */ |
@@ -688,7 +688,7 @@ int hci_conn_switch_role(struct hci_conn *conn, __u8 role) | |||
688 | EXPORT_SYMBOL(hci_conn_switch_role); | 688 | EXPORT_SYMBOL(hci_conn_switch_role); |
689 | 689 | ||
690 | /* Enter active mode */ | 690 | /* Enter active mode */ |
691 | void hci_conn_enter_active_mode(struct hci_conn *conn) | 691 | void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active) |
692 | { | 692 | { |
693 | struct hci_dev *hdev = conn->hdev; | 693 | struct hci_dev *hdev = conn->hdev; |
694 | 694 | ||
@@ -697,7 +697,10 @@ void hci_conn_enter_active_mode(struct hci_conn *conn) | |||
697 | if (test_bit(HCI_RAW, &hdev->flags)) | 697 | if (test_bit(HCI_RAW, &hdev->flags)) |
698 | return; | 698 | return; |
699 | 699 | ||
700 | if (conn->mode != HCI_CM_SNIFF || !conn->power_save) | 700 | if (conn->mode != HCI_CM_SNIFF) |
701 | goto timer; | ||
702 | |||
703 | if (!conn->power_save && !force_active) | ||
701 | goto timer; | 704 | goto timer; |
702 | 705 | ||
703 | if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) { | 706 | 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 ff6b784c58c5..e14e8a1cb04e 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -1969,7 +1969,7 @@ static inline void hci_sched_acl(struct hci_dev *hdev) | |||
1969 | while (quote-- && (skb = skb_dequeue(&conn->data_q))) { | 1969 | while (quote-- && (skb = skb_dequeue(&conn->data_q))) { |
1970 | BT_DBG("skb %p len %d", skb, skb->len); | 1970 | BT_DBG("skb %p len %d", skb, skb->len); |
1971 | 1971 | ||
1972 | hci_conn_enter_active_mode(conn); | 1972 | hci_conn_enter_active_mode(conn, bt_cb(skb)->force_active); |
1973 | 1973 | ||
1974 | hci_send_frame(skb); | 1974 | hci_send_frame(skb); |
1975 | hdev->acl_last_tx = jiffies; | 1975 | hdev->acl_last_tx = jiffies; |
@@ -2108,7 +2108,7 @@ static inline void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb) | |||
2108 | if (conn) { | 2108 | if (conn) { |
2109 | register struct hci_proto *hp; | 2109 | register struct hci_proto *hp; |
2110 | 2110 | ||
2111 | hci_conn_enter_active_mode(conn); | 2111 | hci_conn_enter_active_mode(conn, bt_cb(skb)->force_active); |
2112 | 2112 | ||
2113 | /* Send to upper protocol */ | 2113 | /* Send to upper protocol */ |
2114 | hp = hci_proto[HCI_PROTO_L2CAP]; | 2114 | hp = hci_proto[HCI_PROTO_L2CAP]; |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index bb6be6377891..6908a835a7a3 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -537,6 +537,8 @@ static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, | |||
537 | else | 537 | else |
538 | flags = ACL_START; | 538 | flags = ACL_START; |
539 | 539 | ||
540 | bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON; | ||
541 | |||
540 | hci_send_acl(conn->hcon, skb, flags); | 542 | hci_send_acl(conn->hcon, skb, flags); |
541 | } | 543 | } |
542 | 544 | ||
@@ -590,6 +592,8 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control) | |||
590 | else | 592 | else |
591 | flags = ACL_START; | 593 | flags = ACL_START; |
592 | 594 | ||
595 | bt_cb(skb)->force_active = chan->force_active; | ||
596 | |||
593 | hci_send_acl(chan->conn->hcon, skb, flags); | 597 | hci_send_acl(chan->conn->hcon, skb, flags); |
594 | } | 598 | } |
595 | 599 | ||
@@ -1215,6 +1219,7 @@ void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb) | |||
1215 | else | 1219 | else |
1216 | flags = ACL_START; | 1220 | flags = ACL_START; |
1217 | 1221 | ||
1222 | bt_cb(skb)->force_active = chan->force_active; | ||
1218 | hci_send_acl(hcon, skb, flags); | 1223 | hci_send_acl(hcon, skb, flags); |
1219 | } | 1224 | } |
1220 | 1225 | ||
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index b79fb7561836..bec3e043b254 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -390,6 +390,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch | |||
390 | struct sock *sk = sock->sk; | 390 | struct sock *sk = sock->sk; |
391 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; | 391 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; |
392 | struct bt_security sec; | 392 | struct bt_security sec; |
393 | struct bt_power pwr; | ||
393 | int len, err = 0; | 394 | int len, err = 0; |
394 | 395 | ||
395 | BT_DBG("sk %p", sk); | 396 | BT_DBG("sk %p", sk); |
@@ -438,6 +439,21 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch | |||
438 | 439 | ||
439 | break; | 440 | break; |
440 | 441 | ||
442 | case BT_POWER: | ||
443 | if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM | ||
444 | && sk->sk_type != SOCK_RAW) { | ||
445 | err = -EINVAL; | ||
446 | break; | ||
447 | } | ||
448 | |||
449 | pwr.force_active = chan->force_active; | ||
450 | |||
451 | len = min_t(unsigned int, len, sizeof(pwr)); | ||
452 | if (copy_to_user(optval, (char *) &pwr, len)) | ||
453 | err = -EFAULT; | ||
454 | |||
455 | break; | ||
456 | |||
441 | default: | 457 | default: |
442 | err = -ENOPROTOOPT; | 458 | err = -ENOPROTOOPT; |
443 | break; | 459 | break; |
@@ -538,6 +554,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch | |||
538 | struct sock *sk = sock->sk; | 554 | struct sock *sk = sock->sk; |
539 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; | 555 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; |
540 | struct bt_security sec; | 556 | struct bt_security sec; |
557 | struct bt_power pwr; | ||
541 | int len, err = 0; | 558 | int len, err = 0; |
542 | u32 opt; | 559 | u32 opt; |
543 | 560 | ||
@@ -614,6 +631,23 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch | |||
614 | chan->flushable = opt; | 631 | chan->flushable = opt; |
615 | break; | 632 | break; |
616 | 633 | ||
634 | case BT_POWER: | ||
635 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED && | ||
636 | chan->chan_type != L2CAP_CHAN_RAW) { | ||
637 | err = -EINVAL; | ||
638 | break; | ||
639 | } | ||
640 | |||
641 | pwr.force_active = BT_POWER_FORCE_ACTIVE_ON; | ||
642 | |||
643 | len = min_t(unsigned int, sizeof(pwr), optlen); | ||
644 | if (copy_from_user((char *) &pwr, optval, len)) { | ||
645 | err = -EFAULT; | ||
646 | break; | ||
647 | } | ||
648 | chan->force_active = pwr.force_active; | ||
649 | break; | ||
650 | |||
617 | default: | 651 | default: |
618 | err = -ENOPROTOOPT; | 652 | err = -ENOPROTOOPT; |
619 | break; | 653 | break; |
@@ -771,6 +805,7 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent) | |||
771 | chan->role_switch = pchan->role_switch; | 805 | chan->role_switch = pchan->role_switch; |
772 | chan->force_reliable = pchan->force_reliable; | 806 | chan->force_reliable = pchan->force_reliable; |
773 | chan->flushable = pchan->flushable; | 807 | chan->flushable = pchan->flushable; |
808 | chan->force_active = pchan->force_active; | ||
774 | } else { | 809 | } else { |
775 | 810 | ||
776 | switch (sk->sk_type) { | 811 | switch (sk->sk_type) { |
@@ -801,6 +836,7 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent) | |||
801 | chan->role_switch = 0; | 836 | chan->role_switch = 0; |
802 | chan->force_reliable = 0; | 837 | chan->force_reliable = 0; |
803 | chan->flushable = BT_FLUSHABLE_OFF; | 838 | chan->flushable = BT_FLUSHABLE_OFF; |
839 | chan->force_active = BT_POWER_FORCE_ACTIVE_ON; | ||
804 | } | 840 | } |
805 | 841 | ||
806 | /* Default config options */ | 842 | /* Default config options */ |