Bluetooth: Add new BT_SNDMTU and BT_RCVMTU socket options
authorJohan Hedberg <johan.hedberg@intel.com>
Mon, 2 Dec 2013 14:34:18 +0000 (16:34 +0200)
committerMarcel Holtmann <marcel@holtmann.org>
Thu, 5 Dec 2013 15:05:34 +0000 (07:05 -0800)
This patch adds new socket options for LE sockets since the existing
L2CAP_OPTIONS socket option is not usable for LE. For now, the new
socket options also require LE CoC support to be explicitly enabled to
leave some playroom in case something needs to be changed in a backwards
incompatible way.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
include/net/bluetooth/bluetooth.h
net/bluetooth/l2cap_sock.c

index 2a628b28249ffd00f8b4bd36d4e024583599ad67..f4f9ee466791a9b9fc0b0d7f74f22e2cf3660ac2 100644 (file)
@@ -115,6 +115,9 @@ struct bt_voice {
 #define BT_VOICE_TRANSPARENT                   0x0003
 #define BT_VOICE_CVSD_16BIT                    0x0060
 
+#define BT_SNDMTU              12
+#define BT_RCVMTU              13
+
 __printf(1, 2)
 int bt_info(const char *fmt, ...);
 __printf(1, 2)
index a20fcc3ddcd974457c55e28265901172888b0e48..01d65bc99b0cf15f645f302cb495f9940406aca1 100644 (file)
@@ -534,6 +534,41 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname,
                        err = -EFAULT;
                break;
 
+       case BT_SNDMTU:
+               if (!enable_lecoc) {
+                       err = -EPROTONOSUPPORT;
+                       break;
+               }
+
+               if (!bdaddr_type_is_le(chan->src_type)) {
+                       err = -EINVAL;
+                       break;
+               }
+
+               if (sk->sk_state != BT_CONNECTED) {
+                       err = -ENOTCONN;
+                       break;
+               }
+
+               if (put_user(chan->omtu, (u16 __user *) optval))
+                       err = -EFAULT;
+               break;
+
+       case BT_RCVMTU:
+               if (!enable_lecoc) {
+                       err = -EPROTONOSUPPORT;
+                       break;
+               }
+
+               if (!bdaddr_type_is_le(chan->src_type)) {
+                       err = -EINVAL;
+                       break;
+               }
+
+               if (put_user(chan->imtu, (u16 __user *) optval))
+                       err = -EFAULT;
+               break;
+
        default:
                err = -ENOPROTOOPT;
                break;
@@ -834,6 +869,47 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
 
                break;
 
+       case BT_SNDMTU:
+               if (!enable_lecoc) {
+                       err = -EPROTONOSUPPORT;
+                       break;
+               }
+
+               if (!bdaddr_type_is_le(chan->src_type)) {
+                       err = -EINVAL;
+                       break;
+               }
+
+               /* Setting is not supported as it's the remote side that
+                * decides this.
+                */
+               err = -EPERM;
+               break;
+
+       case BT_RCVMTU:
+               if (!enable_lecoc) {
+                       err = -EPROTONOSUPPORT;
+                       break;
+               }
+
+               if (!bdaddr_type_is_le(chan->src_type)) {
+                       err = -EINVAL;
+                       break;
+               }
+
+               if (sk->sk_state == BT_CONNECTED) {
+                       err = -EISCONN;
+                       break;
+               }
+
+               if (get_user(opt, (u32 __user *) optval)) {
+                       err = -EFAULT;
+                       break;
+               }
+
+               chan->imtu = opt;
+               break;
+
        default:
                err = -ENOPROTOOPT;
                break;