浏览代码

Bluetooth: Add Bluetooth socket voice option

This patch extends the current Bluetooth socket options with BT_VOICE.
This is intended to choose voice data type at runtime. It only applies
to SCO sockets. Incoming connections shall be setup during deferred
setup. Outgoing connections shall be setup before connect(). The desired
setting is stored in the SCO socket info. This patch declares needed
members, modifies getsockopt() and setsockopt().

Signed-off-by: Frédéric Dalleau <frederic.dalleau@linux.intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Frédéric Dalleau 12 年之前
父节点
当前提交
ad10b1a487
共有 3 个文件被更改,包括 48 次插入1 次删除
  1. 8 0
      include/net/bluetooth/bluetooth.h
  2. 1 0
      include/net/bluetooth/sco.h
  3. 39 1
      net/bluetooth/sco.c

+ 8 - 0
include/net/bluetooth/bluetooth.h

@@ -107,6 +107,14 @@ struct bt_power {
  */
  */
 #define BT_CHANNEL_POLICY_AMP_PREFERRED		2
 #define BT_CHANNEL_POLICY_AMP_PREFERRED		2
 
 
+#define BT_VOICE		11
+struct bt_voice {
+	__u16 setting;
+};
+
+#define BT_VOICE_TRANSPARENT			0x0003
+#define BT_VOICE_CVSD_16BIT			0x0060
+
 __printf(1, 2)
 __printf(1, 2)
 int bt_info(const char *fmt, ...);
 int bt_info(const char *fmt, ...);
 __printf(1, 2)
 __printf(1, 2)

+ 1 - 0
include/net/bluetooth/sco.h

@@ -73,6 +73,7 @@ struct sco_conn {
 struct sco_pinfo {
 struct sco_pinfo {
 	struct bt_sock	bt;
 	struct bt_sock	bt;
 	__u32		flags;
 	__u32		flags;
+	__u16		setting;
 	struct sco_conn	*conn;
 	struct sco_conn	*conn;
 };
 };
 
 

+ 39 - 1
net/bluetooth/sco.c

@@ -416,6 +416,8 @@ static struct sock *sco_sock_alloc(struct net *net, struct socket *sock, int pro
 	sk->sk_protocol = proto;
 	sk->sk_protocol = proto;
 	sk->sk_state    = BT_OPEN;
 	sk->sk_state    = BT_OPEN;
 
 
+	sco_pi(sk)->setting = BT_VOICE_CVSD_16BIT;
+
 	setup_timer(&sk->sk_timer, sco_sock_timeout, (unsigned long)sk);
 	setup_timer(&sk->sk_timer, sco_sock_timeout, (unsigned long)sk);
 
 
 	bt_sock_link(&sco_sk_list, sk);
 	bt_sock_link(&sco_sk_list, sk);
@@ -709,7 +711,8 @@ static int sco_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
 static int sco_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
 static int sco_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
 {
 {
 	struct sock *sk = sock->sk;
 	struct sock *sk = sock->sk;
-	int err = 0;
+	int len, err = 0;
+	struct bt_voice voice;
 	u32 opt;
 	u32 opt;
 
 
 	BT_DBG("sk %p", sk);
 	BT_DBG("sk %p", sk);
@@ -735,6 +738,31 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname, char
 			clear_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
 			clear_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
 		break;
 		break;
 
 
+	case BT_VOICE:
+		if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND &&
+		    sk->sk_state != BT_CONNECT2) {
+			err = -EINVAL;
+			break;
+		}
+
+		voice.setting = sco_pi(sk)->setting;
+
+		len = min_t(unsigned int, sizeof(voice), optlen);
+		if (copy_from_user((char *) &voice, optval, len)) {
+			err = -EFAULT;
+			break;
+		}
+
+		/* Explicitly check for these values */
+		if (voice.setting != BT_VOICE_TRANSPARENT &&
+		    voice.setting != BT_VOICE_CVSD_16BIT) {
+			err = -EINVAL;
+			break;
+		}
+
+		sco_pi(sk)->setting = voice.setting;
+		break;
+
 	default:
 	default:
 		err = -ENOPROTOOPT;
 		err = -ENOPROTOOPT;
 		break;
 		break;
@@ -808,6 +836,7 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname, char
 {
 {
 	struct sock *sk = sock->sk;
 	struct sock *sk = sock->sk;
 	int len, err = 0;
 	int len, err = 0;
+	struct bt_voice voice;
 
 
 	BT_DBG("sk %p", sk);
 	BT_DBG("sk %p", sk);
 
 
@@ -833,6 +862,15 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname, char
 
 
 		break;
 		break;
 
 
+	case BT_VOICE:
+		voice.setting = sco_pi(sk)->setting;
+
+		len = min_t(unsigned int, len, sizeof(voice));
+		if (copy_to_user(optval, (char *)&voice, len))
+			err = -EFAULT;
+
+		break;
+
 	default:
 	default:
 		err = -ENOPROTOOPT;
 		err = -ENOPROTOOPT;
 		break;
 		break;