aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrédéric Dalleau <frederic.dalleau@linux.intel.com>2013-08-19 08:23:56 -0400
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>2013-08-21 10:47:09 -0400
commitad10b1a48754b1381582d96f070a39832e41382d (patch)
tree7111567e3b1e7b283ec7d2617136f244660487ad
parent33f2404823f000f9b5fc570b0a08b1008e241578 (diff)
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>
-rw-r--r--include/net/bluetooth/bluetooth.h8
-rw-r--r--include/net/bluetooth/sco.h1
-rw-r--r--net/bluetooth/sco.c40
3 files changed, 48 insertions, 1 deletions
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index 10eb9b389014..10d43d8c7037 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -107,6 +107,14 @@ struct bt_power {
107 */ 107 */
108#define BT_CHANNEL_POLICY_AMP_PREFERRED 2 108#define BT_CHANNEL_POLICY_AMP_PREFERRED 2
109 109
110#define BT_VOICE 11
111struct bt_voice {
112 __u16 setting;
113};
114
115#define BT_VOICE_TRANSPARENT 0x0003
116#define BT_VOICE_CVSD_16BIT 0x0060
117
110__printf(1, 2) 118__printf(1, 2)
111int bt_info(const char *fmt, ...); 119int bt_info(const char *fmt, ...);
112__printf(1, 2) 120__printf(1, 2)
diff --git a/include/net/bluetooth/sco.h b/include/net/bluetooth/sco.h
index 1e35c43657c8..e252a31ee6b6 100644
--- a/include/net/bluetooth/sco.h
+++ b/include/net/bluetooth/sco.h
@@ -73,6 +73,7 @@ struct sco_conn {
73struct sco_pinfo { 73struct sco_pinfo {
74 struct bt_sock bt; 74 struct bt_sock bt;
75 __u32 flags; 75 __u32 flags;
76 __u16 setting;
76 struct sco_conn *conn; 77 struct sco_conn *conn;
77}; 78};
78 79
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index acdca68806db..678747e2e389 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -416,6 +416,8 @@ static struct sock *sco_sock_alloc(struct net *net, struct socket *sock, int pro
416 sk->sk_protocol = proto; 416 sk->sk_protocol = proto;
417 sk->sk_state = BT_OPEN; 417 sk->sk_state = BT_OPEN;
418 418
419 sco_pi(sk)->setting = BT_VOICE_CVSD_16BIT;
420
419 setup_timer(&sk->sk_timer, sco_sock_timeout, (unsigned long)sk); 421 setup_timer(&sk->sk_timer, sco_sock_timeout, (unsigned long)sk);
420 422
421 bt_sock_link(&sco_sk_list, sk); 423 bt_sock_link(&sco_sk_list, sk);
@@ -709,7 +711,8 @@ static int sco_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
709static int sco_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen) 711static int sco_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
710{ 712{
711 struct sock *sk = sock->sk; 713 struct sock *sk = sock->sk;
712 int err = 0; 714 int len, err = 0;
715 struct bt_voice voice;
713 u32 opt; 716 u32 opt;
714 717
715 BT_DBG("sk %p", sk); 718 BT_DBG("sk %p", sk);
@@ -735,6 +738,31 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname, char
735 clear_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags); 738 clear_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
736 break; 739 break;
737 740
741 case BT_VOICE:
742 if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND &&
743 sk->sk_state != BT_CONNECT2) {
744 err = -EINVAL;
745 break;
746 }
747
748 voice.setting = sco_pi(sk)->setting;
749
750 len = min_t(unsigned int, sizeof(voice), optlen);
751 if (copy_from_user((char *) &voice, optval, len)) {
752 err = -EFAULT;
753 break;
754 }
755
756 /* Explicitly check for these values */
757 if (voice.setting != BT_VOICE_TRANSPARENT &&
758 voice.setting != BT_VOICE_CVSD_16BIT) {
759 err = -EINVAL;
760 break;
761 }
762
763 sco_pi(sk)->setting = voice.setting;
764 break;
765
738 default: 766 default:
739 err = -ENOPROTOOPT; 767 err = -ENOPROTOOPT;
740 break; 768 break;
@@ -808,6 +836,7 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname, char
808{ 836{
809 struct sock *sk = sock->sk; 837 struct sock *sk = sock->sk;
810 int len, err = 0; 838 int len, err = 0;
839 struct bt_voice voice;
811 840
812 BT_DBG("sk %p", sk); 841 BT_DBG("sk %p", sk);
813 842
@@ -833,6 +862,15 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname, char
833 862
834 break; 863 break;
835 864
865 case BT_VOICE:
866 voice.setting = sco_pi(sk)->setting;
867
868 len = min_t(unsigned int, len, sizeof(voice));
869 if (copy_to_user(optval, (char *)&voice, len))
870 err = -EFAULT;
871
872 break;
873
836 default: 874 default:
837 err = -ENOPROTOOPT; 875 err = -ENOPROTOOPT;
838 break; 876 break;