Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ad10b1a4 authored by Frédéric Dalleau's avatar Frédéric Dalleau Committed by Gustavo Padovan
Browse files

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: default avatarFrédéric Dalleau <frederic.dalleau@linux.intel.com>
Acked-by: default avatarMarcel Holtmann <marcel@holtmann.org>
Signed-off-by: default avatarJohan Hedberg <johan.hedberg@intel.com>
Signed-off-by: default avatarGustavo Padovan <gustavo.padovan@collabora.co.uk>
parent 33f24048
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -107,6 +107,14 @@ struct bt_power {
 */
#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)
int bt_info(const char *fmt, ...);
__printf(1, 2)
+1 −0
Original line number Diff line number Diff line
@@ -73,6 +73,7 @@ struct sco_conn {
struct sco_pinfo {
	struct bt_sock	bt;
	__u32		flags;
	__u16		setting;
	struct sco_conn	*conn;
};

+39 −1
Original line number Diff line number Diff line
@@ -416,6 +416,8 @@ static struct sock *sco_sock_alloc(struct net *net, struct socket *sock, int pro
	sk->sk_protocol = proto;
	sk->sk_state    = BT_OPEN;

	sco_pi(sk)->setting = BT_VOICE_CVSD_16BIT;

	setup_timer(&sk->sk_timer, sco_sock_timeout, (unsigned long)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)
{
	struct sock *sk = sock->sk;
	int err = 0;
	int len, err = 0;
	struct bt_voice voice;
	u32 opt;

	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);
		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:
		err = -ENOPROTOOPT;
		break;
@@ -808,6 +836,7 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname, char
{
	struct sock *sk = sock->sk;
	int len, err = 0;
	struct bt_voice voice;

	BT_DBG("sk %p", sk);

@@ -833,6 +862,15 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname, char

		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:
		err = -ENOPROTOOPT;
		break;