Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[pandora-kernel.git] / net / bluetooth / l2cap_sock.c
index e829236..e2e785c 100644 (file)
@@ -27,6 +27,7 @@
 /* Bluetooth L2CAP sockets. */
 
 #include <linux/security.h>
+#include <linux/export.h>
 
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
@@ -333,7 +334,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us
                opts.mode     = chan->mode;
                opts.fcs      = chan->fcs;
                opts.max_tx   = chan->max_tx;
-               opts.txwin_size = (__u16)chan->tx_win;
+               opts.txwin_size = chan->tx_win;
 
                len = min_t(unsigned int, len, sizeof(opts));
                if (copy_to_user(optval, (char *) &opts, len))
@@ -358,10 +359,10 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us
                        break;
                }
 
-               if (chan->role_switch)
+               if (test_bit(FLAG_ROLE_SWITCH, &chan->flags))
                        opt |= L2CAP_LM_MASTER;
 
-               if (chan->force_reliable)
+               if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
                        opt |= L2CAP_LM_RELIABLE;
 
                if (put_user(opt, (u32 __user *) optval))
@@ -448,7 +449,8 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
                break;
 
        case BT_FLUSHABLE:
-               if (put_user(chan->flushable, (u32 __user *) optval))
+               if (put_user(test_bit(FLAG_FLUSHABLE, &chan->flags),
+                                               (u32 __user *) optval))
                        err = -EFAULT;
 
                break;
@@ -460,7 +462,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
                        break;
                }
 
-               pwr.force_active = chan->force_active;
+               pwr.force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
 
                len = min_t(unsigned int, len, sizeof(pwr));
                if (copy_to_user(optval, (char *) &pwr, len))
@@ -468,6 +470,16 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
 
                break;
 
+       case BT_CHANNEL_POLICY:
+               if (!enable_hs) {
+                       err = -ENOPROTOOPT;
+                       break;
+               }
+
+               if (put_user(chan->chan_policy, (u32 __user *) optval))
+                       err = -EFAULT;
+               break;
+
        default:
                err = -ENOPROTOOPT;
                break;
@@ -502,7 +514,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
                opts.mode     = chan->mode;
                opts.fcs      = chan->fcs;
                opts.max_tx   = chan->max_tx;
-               opts.txwin_size = (__u16)chan->tx_win;
+               opts.txwin_size = chan->tx_win;
 
                len = min_t(unsigned int, sizeof(opts), optlen);
                if (copy_from_user((char *) &opts, optval, len)) {
@@ -510,7 +522,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
                        break;
                }
 
-               if (opts.txwin_size > L2CAP_DEFAULT_TX_WINDOW) {
+               if (opts.txwin_size > L2CAP_DEFAULT_EXT_WINDOW) {
                        err = -EINVAL;
                        break;
                }
@@ -534,7 +546,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
                chan->omtu = opts.omtu;
                chan->fcs  = opts.fcs;
                chan->max_tx = opts.max_tx;
-               chan->tx_win = (__u8)opts.txwin_size;
+               chan->tx_win = opts.txwin_size;
                break;
 
        case L2CAP_LM:
@@ -550,8 +562,15 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
                if (opt & L2CAP_LM_SECURE)
                        chan->sec_level = BT_SECURITY_HIGH;
 
-               chan->role_switch    = (opt & L2CAP_LM_MASTER);
-               chan->force_reliable = (opt & L2CAP_LM_RELIABLE);
+               if (opt & L2CAP_LM_MASTER)
+                       set_bit(FLAG_ROLE_SWITCH, &chan->flags);
+               else
+                       clear_bit(FLAG_ROLE_SWITCH, &chan->flags);
+
+               if (opt & L2CAP_LM_RELIABLE)
+                       set_bit(FLAG_FORCE_RELIABLE, &chan->flags);
+               else
+                       clear_bit(FLAG_FORCE_RELIABLE, &chan->flags);
                break;
 
        default:
@@ -657,7 +676,10 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
                        }
                }
 
-               chan->flushable = opt;
+               if (opt)
+                       set_bit(FLAG_FLUSHABLE, &chan->flags);
+               else
+                       clear_bit(FLAG_FLUSHABLE, &chan->flags);
                break;
 
        case BT_POWER:
@@ -674,7 +696,36 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
                        err = -EFAULT;
                        break;
                }
-               chan->force_active = pwr.force_active;
+
+               if (pwr.force_active)
+                       set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
+               else
+                       clear_bit(FLAG_FORCE_ACTIVE, &chan->flags);
+               break;
+
+       case BT_CHANNEL_POLICY:
+               if (!enable_hs) {
+                       err = -ENOPROTOOPT;
+                       break;
+               }
+
+               if (get_user(opt, (u32 __user *) optval)) {
+                       err = -EFAULT;
+                       break;
+               }
+
+               if (opt > BT_CHANNEL_POLICY_AMP_PREFERRED) {
+                       err = -EINVAL;
+                       break;
+               }
+
+               if (chan->mode != L2CAP_MODE_ERTM &&
+                               chan->mode != L2CAP_MODE_STREAMING) {
+                       err = -EOPNOTSUPP;
+                       break;
+               }
+
+               chan->chan_policy = (u8) opt;
                break;
 
        default:
@@ -708,7 +759,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
                return -ENOTCONN;
        }
 
-       err = l2cap_chan_send(chan, msg, len);
+       err = l2cap_chan_send(chan, msg, len, sk->sk_priority);
 
        release_sock(sk);
        return err;
@@ -930,11 +981,9 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent)
                chan->fcs  = pchan->fcs;
                chan->max_tx = pchan->max_tx;
                chan->tx_win = pchan->tx_win;
+               chan->tx_win_max = pchan->tx_win_max;
                chan->sec_level = pchan->sec_level;
-               chan->role_switch = pchan->role_switch;
-               chan->force_reliable = pchan->force_reliable;
-               chan->flushable = pchan->flushable;
-               chan->force_active = pchan->force_active;
+               chan->flags = pchan->flags;
 
                security_sk_clone(parent, sk);
        } else {
@@ -963,12 +1012,10 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent)
                chan->max_tx = L2CAP_DEFAULT_MAX_TX;
                chan->fcs  = L2CAP_FCS_CRC16;
                chan->tx_win = L2CAP_DEFAULT_TX_WINDOW;
+               chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
                chan->sec_level = BT_SECURITY_LOW;
-               chan->role_switch = 0;
-               chan->force_reliable = 0;
-               chan->flushable = BT_FLUSHABLE_OFF;
-               chan->force_active = BT_POWER_FORCE_ACTIVE_ON;
-
+               chan->flags = 0;
+               set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
        }
 
        /* Default config options */