diff options
Diffstat (limited to 'net/bluetooth/l2cap_sock.c')
-rw-r--r-- | net/bluetooth/l2cap_sock.c | 36 |
1 files changed, 36 insertions, 0 deletions
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 */ |