xref: /linux/net/bluetooth/sco.c (revision d44cd8226449114780a8554fd253c7e3d171a0a6)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds    BlueZ - Bluetooth protocol stack for Linux
31da177e4SLinus Torvalds    Copyright (C) 2000-2001 Qualcomm Incorporated
41da177e4SLinus Torvalds 
51da177e4SLinus Torvalds    Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
61da177e4SLinus Torvalds 
71da177e4SLinus Torvalds    This program is free software; you can redistribute it and/or modify
81da177e4SLinus Torvalds    it under the terms of the GNU General Public License version 2 as
91da177e4SLinus Torvalds    published by the Free Software Foundation;
101da177e4SLinus Torvalds 
111da177e4SLinus Torvalds    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
121da177e4SLinus Torvalds    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
131da177e4SLinus Torvalds    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
141da177e4SLinus Torvalds    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
151da177e4SLinus Torvalds    CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
161da177e4SLinus Torvalds    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
171da177e4SLinus Torvalds    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
181da177e4SLinus Torvalds    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
191da177e4SLinus Torvalds 
201da177e4SLinus Torvalds    ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
211da177e4SLinus Torvalds    COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
221da177e4SLinus Torvalds    SOFTWARE IS DISCLAIMED.
231da177e4SLinus Torvalds */
241da177e4SLinus Torvalds 
251da177e4SLinus Torvalds /* Bluetooth SCO sockets. */
261da177e4SLinus Torvalds 
271da177e4SLinus Torvalds #include <linux/module.h>
28aef7d97cSMarcel Holtmann #include <linux/debugfs.h>
29aef7d97cSMarcel Holtmann #include <linux/seq_file.h>
30174cd4b1SIngo Molnar #include <linux/sched/signal.h>
311da177e4SLinus Torvalds 
321da177e4SLinus Torvalds #include <net/bluetooth/bluetooth.h>
331da177e4SLinus Torvalds #include <net/bluetooth/hci_core.h>
341da177e4SLinus Torvalds #include <net/bluetooth/sco.h>
351da177e4SLinus Torvalds 
36eb939922SRusty Russell static bool disable_esco;
371da177e4SLinus Torvalds 
3890ddc4f0SEric Dumazet static const struct proto_ops sco_sock_ops;
391da177e4SLinus Torvalds 
401da177e4SLinus Torvalds static struct bt_sock_list sco_sk_list = {
41d5fb2962SRobert P. J. Day 	.lock = __RW_LOCK_UNLOCKED(sco_sk_list.lock)
421da177e4SLinus Torvalds };
431da177e4SLinus Torvalds 
44fc8f525aSMarcel Holtmann /* ---- SCO connections ---- */
45fc8f525aSMarcel Holtmann struct sco_conn {
46fc8f525aSMarcel Holtmann 	struct hci_conn	*hcon;
47fc8f525aSMarcel Holtmann 
48fc8f525aSMarcel Holtmann 	spinlock_t	lock;
49fc8f525aSMarcel Holtmann 	struct sock	*sk;
50fc8f525aSMarcel Holtmann 
51ba316be1SDesmond Cheong Zhi Xi 	struct delayed_work	timeout_work;
52ba316be1SDesmond Cheong Zhi Xi 
53fc8f525aSMarcel Holtmann 	unsigned int    mtu;
54fc8f525aSMarcel Holtmann };
55fc8f525aSMarcel Holtmann 
560f90d320SMeng Yu #define sco_conn_lock(c)	spin_lock(&c->lock)
570f90d320SMeng Yu #define sco_conn_unlock(c)	spin_unlock(&c->lock)
58fc8f525aSMarcel Holtmann 
591da177e4SLinus Torvalds static void sco_sock_close(struct sock *sk);
601da177e4SLinus Torvalds static void sco_sock_kill(struct sock *sk);
611da177e4SLinus Torvalds 
622a0dccb3SMarcel Holtmann /* ----- SCO socket info ----- */
632a0dccb3SMarcel Holtmann #define sco_pi(sk) ((struct sco_pinfo *) sk)
642a0dccb3SMarcel Holtmann 
652a0dccb3SMarcel Holtmann struct sco_pinfo {
662a0dccb3SMarcel Holtmann 	struct bt_sock	bt;
672a0dccb3SMarcel Holtmann 	bdaddr_t	src;
682a0dccb3SMarcel Holtmann 	bdaddr_t	dst;
692a0dccb3SMarcel Holtmann 	__u32		flags;
702a0dccb3SMarcel Holtmann 	__u16		setting;
71f6873401SKiran K 	struct bt_codec codec;
722a0dccb3SMarcel Holtmann 	struct sco_conn	*conn;
732a0dccb3SMarcel Holtmann };
742a0dccb3SMarcel Holtmann 
751da177e4SLinus Torvalds /* ---- SCO timers ---- */
76068d69e5SMarcel Holtmann #define SCO_CONN_TIMEOUT	(HZ * 40)
77068d69e5SMarcel Holtmann #define SCO_DISCONN_TIMEOUT	(HZ * 2)
78068d69e5SMarcel Holtmann 
sco_sock_hold(struct sco_conn * conn)79*1bf4470aSLuiz Augusto von Dentz static struct sock *sco_sock_hold(struct sco_conn *conn)
80*1bf4470aSLuiz Augusto von Dentz {
81*1bf4470aSLuiz Augusto von Dentz 	if (!conn || !bt_sock_linked(&sco_sk_list, conn->sk))
82*1bf4470aSLuiz Augusto von Dentz 		return NULL;
83*1bf4470aSLuiz Augusto von Dentz 
84*1bf4470aSLuiz Augusto von Dentz 	sock_hold(conn->sk);
85*1bf4470aSLuiz Augusto von Dentz 
86*1bf4470aSLuiz Augusto von Dentz 	return conn->sk;
87*1bf4470aSLuiz Augusto von Dentz }
88*1bf4470aSLuiz Augusto von Dentz 
sco_sock_timeout(struct work_struct * work)89ba316be1SDesmond Cheong Zhi Xi static void sco_sock_timeout(struct work_struct *work)
901da177e4SLinus Torvalds {
91ba316be1SDesmond Cheong Zhi Xi 	struct sco_conn *conn = container_of(work, struct sco_conn,
92ba316be1SDesmond Cheong Zhi Xi 					     timeout_work.work);
93ba316be1SDesmond Cheong Zhi Xi 	struct sock *sk;
94ba316be1SDesmond Cheong Zhi Xi 
95ba316be1SDesmond Cheong Zhi Xi 	sco_conn_lock(conn);
96483bc081SDuoming Zhou 	if (!conn->hcon) {
97483bc081SDuoming Zhou 		sco_conn_unlock(conn);
98483bc081SDuoming Zhou 		return;
99483bc081SDuoming Zhou 	}
100*1bf4470aSLuiz Augusto von Dentz 	sk = sco_sock_hold(conn);
101ba316be1SDesmond Cheong Zhi Xi 	sco_conn_unlock(conn);
102ba316be1SDesmond Cheong Zhi Xi 
103ba316be1SDesmond Cheong Zhi Xi 	if (!sk)
104ba316be1SDesmond Cheong Zhi Xi 		return;
1051da177e4SLinus Torvalds 
1061da177e4SLinus Torvalds 	BT_DBG("sock %p state %d", sk, sk->sk_state);
1071da177e4SLinus Torvalds 
10827c24fdaSDesmond Cheong Zhi Xi 	lock_sock(sk);
1091da177e4SLinus Torvalds 	sk->sk_err = ETIMEDOUT;
1101da177e4SLinus Torvalds 	sk->sk_state_change(sk);
11127c24fdaSDesmond Cheong Zhi Xi 	release_sock(sk);
1121da177e4SLinus Torvalds 	sock_put(sk);
1131da177e4SLinus Torvalds }
1141da177e4SLinus Torvalds 
sco_sock_set_timer(struct sock * sk,long timeout)1151da177e4SLinus Torvalds static void sco_sock_set_timer(struct sock *sk, long timeout)
1161da177e4SLinus Torvalds {
117ba316be1SDesmond Cheong Zhi Xi 	if (!sco_pi(sk)->conn)
118ba316be1SDesmond Cheong Zhi Xi 		return;
119ba316be1SDesmond Cheong Zhi Xi 
1201da177e4SLinus Torvalds 	BT_DBG("sock %p state %d timeout %ld", sk, sk->sk_state, timeout);
121ba316be1SDesmond Cheong Zhi Xi 	cancel_delayed_work(&sco_pi(sk)->conn->timeout_work);
122ba316be1SDesmond Cheong Zhi Xi 	schedule_delayed_work(&sco_pi(sk)->conn->timeout_work, timeout);
1231da177e4SLinus Torvalds }
1241da177e4SLinus Torvalds 
sco_sock_clear_timer(struct sock * sk)1251da177e4SLinus Torvalds static void sco_sock_clear_timer(struct sock *sk)
1261da177e4SLinus Torvalds {
127ba316be1SDesmond Cheong Zhi Xi 	if (!sco_pi(sk)->conn)
128ba316be1SDesmond Cheong Zhi Xi 		return;
129ba316be1SDesmond Cheong Zhi Xi 
1301da177e4SLinus Torvalds 	BT_DBG("sock %p state %d", sk, sk->sk_state);
131ba316be1SDesmond Cheong Zhi Xi 	cancel_delayed_work(&sco_pi(sk)->conn->timeout_work);
1321da177e4SLinus Torvalds }
1331da177e4SLinus Torvalds 
1341da177e4SLinus Torvalds /* ---- SCO connections ---- */
sco_conn_add(struct hci_conn * hcon)135519e42b3SLukasz Rymanowski static struct sco_conn *sco_conn_add(struct hci_conn *hcon)
1361da177e4SLinus Torvalds {
13725ea6db0SMarcel Holtmann 	struct sco_conn *conn = hcon->sco_data;
1381da177e4SLinus Torvalds 
1393dcaa192SPauli Virtanen 	if (conn) {
1403dcaa192SPauli Virtanen 		if (!conn->hcon)
1413dcaa192SPauli Virtanen 			conn->hcon = hcon;
1421da177e4SLinus Torvalds 		return conn;
1433dcaa192SPauli Virtanen 	}
1441da177e4SLinus Torvalds 
145c10cc5a9SClaudio Takahasi 	conn = kzalloc(sizeof(struct sco_conn), GFP_KERNEL);
14625ea6db0SMarcel Holtmann 	if (!conn)
1471da177e4SLinus Torvalds 		return NULL;
1481da177e4SLinus Torvalds 
1491da177e4SLinus Torvalds 	spin_lock_init(&conn->lock);
15049d8a560SDesmond Cheong Zhi Xi 	INIT_DELAYED_WORK(&conn->timeout_work, sco_sock_timeout);
1511da177e4SLinus Torvalds 
1521da177e4SLinus Torvalds 	hcon->sco_data = conn;
1531da177e4SLinus Torvalds 	conn->hcon = hcon;
154a5b862c6SSungwoo Kim 	conn->mtu = hcon->mtu;
1551da177e4SLinus Torvalds 
156a5b862c6SSungwoo Kim 	if (hcon->mtu > 0)
157a5b862c6SSungwoo Kim 		conn->mtu = hcon->mtu;
1581da177e4SLinus Torvalds 	else
1591da177e4SLinus Torvalds 		conn->mtu = 60;
1601da177e4SLinus Torvalds 
1611da177e4SLinus Torvalds 	BT_DBG("hcon %p conn %p", hcon, conn);
16225ea6db0SMarcel Holtmann 
1631da177e4SLinus Torvalds 	return conn;
1641da177e4SLinus Torvalds }
1651da177e4SLinus Torvalds 
166e03ab519SMarcel Holtmann /* Delete channel.
167e03ab519SMarcel Holtmann  * Must be called on the locked socket. */
sco_chan_del(struct sock * sk,int err)168e03ab519SMarcel Holtmann static void sco_chan_del(struct sock *sk, int err)
169e03ab519SMarcel Holtmann {
170e03ab519SMarcel Holtmann 	struct sco_conn *conn;
171e03ab519SMarcel Holtmann 
172e03ab519SMarcel Holtmann 	conn = sco_pi(sk)->conn;
173e03ab519SMarcel Holtmann 
174e03ab519SMarcel Holtmann 	BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
175e03ab519SMarcel Holtmann 
176e03ab519SMarcel Holtmann 	if (conn) {
177e03ab519SMarcel Holtmann 		sco_conn_lock(conn);
178e03ab519SMarcel Holtmann 		conn->sk = NULL;
179e03ab519SMarcel Holtmann 		sco_pi(sk)->conn = NULL;
180e03ab519SMarcel Holtmann 		sco_conn_unlock(conn);
181e03ab519SMarcel Holtmann 
182e03ab519SMarcel Holtmann 		if (conn->hcon)
183e03ab519SMarcel Holtmann 			hci_conn_drop(conn->hcon);
184e03ab519SMarcel Holtmann 	}
185e03ab519SMarcel Holtmann 
186e03ab519SMarcel Holtmann 	sk->sk_state = BT_CLOSED;
187e03ab519SMarcel Holtmann 	sk->sk_err   = err;
188e03ab519SMarcel Holtmann 	sk->sk_state_change(sk);
189e03ab519SMarcel Holtmann 
190e03ab519SMarcel Holtmann 	sock_set_flag(sk, SOCK_ZAPPED);
191e03ab519SMarcel Holtmann }
192e03ab519SMarcel Holtmann 
sco_conn_del(struct hci_conn * hcon,int err)193df945360SNicholas Krause static void sco_conn_del(struct hci_conn *hcon, int err)
1941da177e4SLinus Torvalds {
195735cbc47SAndrei Emeltchenko 	struct sco_conn *conn = hcon->sco_data;
1961da177e4SLinus Torvalds 	struct sock *sk;
1971da177e4SLinus Torvalds 
198735cbc47SAndrei Emeltchenko 	if (!conn)
199df945360SNicholas Krause 		return;
2001da177e4SLinus Torvalds 
2011da177e4SLinus Torvalds 	BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
2021da177e4SLinus Torvalds 
2031da177e4SLinus Torvalds 	/* Kill socket */
204eb5a4de8SMarcel Holtmann 	sco_conn_lock(conn);
205*1bf4470aSLuiz Augusto von Dentz 	sk = sco_sock_hold(conn);
206eb5a4de8SMarcel Holtmann 	sco_conn_unlock(conn);
207eb5a4de8SMarcel Holtmann 
208735cbc47SAndrei Emeltchenko 	if (sk) {
20927c24fdaSDesmond Cheong Zhi Xi 		lock_sock(sk);
2101da177e4SLinus Torvalds 		sco_sock_clear_timer(sk);
2111da177e4SLinus Torvalds 		sco_chan_del(sk, err);
21227c24fdaSDesmond Cheong Zhi Xi 		release_sock(sk);
21375e34f5cSKuba Pawlak 		sock_put(sk);
21449d8a560SDesmond Cheong Zhi Xi 	}
215ba316be1SDesmond Cheong Zhi Xi 
216ba316be1SDesmond Cheong Zhi Xi 	/* Ensure no more work items will run before freeing conn. */
217ba316be1SDesmond Cheong Zhi Xi 	cancel_delayed_work_sync(&conn->timeout_work);
2181da177e4SLinus Torvalds 
2191da177e4SLinus Torvalds 	hcon->sco_data = NULL;
2201da177e4SLinus Torvalds 	kfree(conn);
2211da177e4SLinus Torvalds }
2221da177e4SLinus Torvalds 
__sco_chan_add(struct sco_conn * conn,struct sock * sk,struct sock * parent)223c4297e8fSMarcel Holtmann static void __sco_chan_add(struct sco_conn *conn, struct sock *sk,
224c4297e8fSMarcel Holtmann 			   struct sock *parent)
225015b01cbSMarcel Holtmann {
226015b01cbSMarcel Holtmann 	BT_DBG("conn %p", conn);
227015b01cbSMarcel Holtmann 
228015b01cbSMarcel Holtmann 	sco_pi(sk)->conn = conn;
229015b01cbSMarcel Holtmann 	conn->sk = sk;
230015b01cbSMarcel Holtmann 
231015b01cbSMarcel Holtmann 	if (parent)
232c4f5627fSMatthias Kaehlcke 		bt_accept_enqueue(parent, sk, true);
233015b01cbSMarcel Holtmann }
234015b01cbSMarcel Holtmann 
sco_chan_add(struct sco_conn * conn,struct sock * sk,struct sock * parent)2356039aa73SGustavo Padovan static int sco_chan_add(struct sco_conn *conn, struct sock *sk,
2366039aa73SGustavo Padovan 			struct sock *parent)
2371da177e4SLinus Torvalds {
2381da177e4SLinus Torvalds 	int err = 0;
2391da177e4SLinus Torvalds 
2401da177e4SLinus Torvalds 	sco_conn_lock(conn);
241b9dbdbc1SGustavo F. Padovan 	if (conn->sk)
2421da177e4SLinus Torvalds 		err = -EBUSY;
243b9dbdbc1SGustavo F. Padovan 	else
2441da177e4SLinus Torvalds 		__sco_chan_add(conn, sk, parent);
245b9dbdbc1SGustavo F. Padovan 
2461da177e4SLinus Torvalds 	sco_conn_unlock(conn);
2471da177e4SLinus Torvalds 	return err;
2481da177e4SLinus Torvalds }
2491da177e4SLinus Torvalds 
sco_connect(struct sock * sk)2509a8ec9e8SLuiz Augusto von Dentz static int sco_connect(struct sock *sk)
2511da177e4SLinus Torvalds {
2521da177e4SLinus Torvalds 	struct sco_conn *conn;
2531da177e4SLinus Torvalds 	struct hci_conn *hcon;
2549a8ec9e8SLuiz Augusto von Dentz 	struct hci_dev  *hdev;
255b6a0dc82SMarcel Holtmann 	int err, type;
2561da177e4SLinus Torvalds 
257eea96364SMarcel Holtmann 	BT_DBG("%pMR -> %pMR", &sco_pi(sk)->src, &sco_pi(sk)->dst);
2581da177e4SLinus Torvalds 
2599a8ec9e8SLuiz Augusto von Dentz 	hdev = hci_get_route(&sco_pi(sk)->dst, &sco_pi(sk)->src, BDADDR_BREDR);
2609a8ec9e8SLuiz Augusto von Dentz 	if (!hdev)
2619a8ec9e8SLuiz Augusto von Dentz 		return -EHOSTUNREACH;
2629a8ec9e8SLuiz Augusto von Dentz 
2639a8ec9e8SLuiz Augusto von Dentz 	hci_dev_lock(hdev);
2649a8ec9e8SLuiz Augusto von Dentz 
2657cb127d5SMarcel Holtmann 	if (lmp_esco_capable(hdev) && !disable_esco)
2667cb127d5SMarcel Holtmann 		type = ESCO_LINK;
2677cb127d5SMarcel Holtmann 	else
2687cb127d5SMarcel Holtmann 		type = SCO_LINK;
269b6a0dc82SMarcel Holtmann 
27079dc0087SFrédéric Dalleau 	if (sco_pi(sk)->setting == BT_VOICE_TRANSPARENT &&
2719a8ec9e8SLuiz Augusto von Dentz 	    (!lmp_transp_capable(hdev) || !lmp_esco_capable(hdev))) {
2729a8ec9e8SLuiz Augusto von Dentz 		err = -EOPNOTSUPP;
2739a8ec9e8SLuiz Augusto von Dentz 		goto unlock;
2749a8ec9e8SLuiz Augusto von Dentz 	}
27579dc0087SFrédéric Dalleau 
276eea96364SMarcel Holtmann 	hcon = hci_connect_sco(hdev, type, &sco_pi(sk)->dst,
277bf98feeaSLuiz Augusto von Dentz 			       sco_pi(sk)->setting, &sco_pi(sk)->codec,
278bf98feeaSLuiz Augusto von Dentz 			       sk->sk_sndtimeo);
2799a8ec9e8SLuiz Augusto von Dentz 	if (IS_ERR(hcon)) {
2809a8ec9e8SLuiz Augusto von Dentz 		err = PTR_ERR(hcon);
2819a8ec9e8SLuiz Augusto von Dentz 		goto unlock;
2829a8ec9e8SLuiz Augusto von Dentz 	}
2839a8ec9e8SLuiz Augusto von Dentz 
284519e42b3SLukasz Rymanowski 	conn = sco_conn_add(hcon);
2851da177e4SLinus Torvalds 	if (!conn) {
28676a68ba0SDavid Herrmann 		hci_conn_drop(hcon);
2873dcaa192SPauli Virtanen 		err = -ENOMEM;
2883dcaa192SPauli Virtanen 		goto unlock;
2891da177e4SLinus Torvalds 	}
2901da177e4SLinus Torvalds 
2919a8ec9e8SLuiz Augusto von Dentz 	lock_sock(sk);
2929a8ec9e8SLuiz Augusto von Dentz 
2933dcaa192SPauli Virtanen 	err = sco_chan_add(conn, sk, NULL);
2943dcaa192SPauli Virtanen 	if (err) {
2953dcaa192SPauli Virtanen 		release_sock(sk);
2963dcaa192SPauli Virtanen 		goto unlock;
2973dcaa192SPauli Virtanen 	}
2983dcaa192SPauli Virtanen 
2999a8ec9e8SLuiz Augusto von Dentz 	/* Update source addr of the socket */
3009a8ec9e8SLuiz Augusto von Dentz 	bacpy(&sco_pi(sk)->src, &hcon->src);
3019a8ec9e8SLuiz Augusto von Dentz 
3021da177e4SLinus Torvalds 	if (hcon->state == BT_CONNECTED) {
3031da177e4SLinus Torvalds 		sco_sock_clear_timer(sk);
3041da177e4SLinus Torvalds 		sk->sk_state = BT_CONNECTED;
3051da177e4SLinus Torvalds 	} else {
3061da177e4SLinus Torvalds 		sk->sk_state = BT_CONNECT;
3071da177e4SLinus Torvalds 		sco_sock_set_timer(sk, sk->sk_sndtimeo);
3081da177e4SLinus Torvalds 	}
309b6a0dc82SMarcel Holtmann 
3109a8ec9e8SLuiz Augusto von Dentz 	release_sock(sk);
3119a8ec9e8SLuiz Augusto von Dentz 
3129a8ec9e8SLuiz Augusto von Dentz unlock:
3139a8ec9e8SLuiz Augusto von Dentz 	hci_dev_unlock(hdev);
3149a8ec9e8SLuiz Augusto von Dentz 	hci_dev_put(hdev);
3151da177e4SLinus Torvalds 	return err;
3161da177e4SLinus Torvalds }
3171da177e4SLinus Torvalds 
sco_send_frame(struct sock * sk,struct sk_buff * skb)3180771cbb3SLuiz Augusto von Dentz static int sco_send_frame(struct sock *sk, struct sk_buff *skb)
3191da177e4SLinus Torvalds {
3201da177e4SLinus Torvalds 	struct sco_conn *conn = sco_pi(sk)->conn;
321037ce005SLuiz Augusto von Dentz 	int len = skb->len;
3221da177e4SLinus Torvalds 
3231da177e4SLinus Torvalds 	/* Check outgoing MTU */
324037ce005SLuiz Augusto von Dentz 	if (len > conn->mtu)
3251da177e4SLinus Torvalds 		return -EINVAL;
3261da177e4SLinus Torvalds 
327037ce005SLuiz Augusto von Dentz 	BT_DBG("sk %p len %d", sk, len);
3281da177e4SLinus Torvalds 
3290d861d8bSGustavo F. Padovan 	hci_send_sco(conn->hcon, skb);
3301da177e4SLinus Torvalds 
331037ce005SLuiz Augusto von Dentz 	return len;
3321da177e4SLinus Torvalds }
3331da177e4SLinus Torvalds 
sco_recv_frame(struct sco_conn * conn,struct sk_buff * skb)3346039aa73SGustavo Padovan static void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb)
3351da177e4SLinus Torvalds {
336eb5a4de8SMarcel Holtmann 	struct sock *sk;
337eb5a4de8SMarcel Holtmann 
338eb5a4de8SMarcel Holtmann 	sco_conn_lock(conn);
339eb5a4de8SMarcel Holtmann 	sk = conn->sk;
340eb5a4de8SMarcel Holtmann 	sco_conn_unlock(conn);
3411da177e4SLinus Torvalds 
3421da177e4SLinus Torvalds 	if (!sk)
3431da177e4SLinus Torvalds 		goto drop;
3441da177e4SLinus Torvalds 
34579dbeafeSKai Ye 	BT_DBG("sk %p len %u", sk, skb->len);
3461da177e4SLinus Torvalds 
3471da177e4SLinus Torvalds 	if (sk->sk_state != BT_CONNECTED)
3481da177e4SLinus Torvalds 		goto drop;
3491da177e4SLinus Torvalds 
3501da177e4SLinus Torvalds 	if (!sock_queue_rcv_skb(sk, skb))
3511da177e4SLinus Torvalds 		return;
3521da177e4SLinus Torvalds 
3531da177e4SLinus Torvalds drop:
3541da177e4SLinus Torvalds 	kfree_skb(skb);
3551da177e4SLinus Torvalds }
3561da177e4SLinus Torvalds 
3571da177e4SLinus Torvalds /* -------- Socket interface ---------- */
__sco_get_sock_listen_by_addr(bdaddr_t * ba)358fb334059SMarcel Holtmann static struct sock *__sco_get_sock_listen_by_addr(bdaddr_t *ba)
3591da177e4SLinus Torvalds {
360fb334059SMarcel Holtmann 	struct sock *sk;
3611da177e4SLinus Torvalds 
362b67bfe0dSSasha Levin 	sk_for_each(sk, &sco_sk_list.head) {
363fb334059SMarcel Holtmann 		if (sk->sk_state != BT_LISTEN)
364fb334059SMarcel Holtmann 			continue;
365fb334059SMarcel Holtmann 
366eea96364SMarcel Holtmann 		if (!bacmp(&sco_pi(sk)->src, ba))
3671da177e4SLinus Torvalds 			return sk;
3681da177e4SLinus Torvalds 	}
3691da177e4SLinus Torvalds 
370fb334059SMarcel Holtmann 	return NULL;
371fb334059SMarcel Holtmann }
372fb334059SMarcel Holtmann 
3731da177e4SLinus Torvalds /* Find socket listening on source bdaddr.
3741da177e4SLinus Torvalds  * Returns closest match.
3751da177e4SLinus Torvalds  */
sco_get_sock_listen(bdaddr_t * src)3761da177e4SLinus Torvalds static struct sock *sco_get_sock_listen(bdaddr_t *src)
3771da177e4SLinus Torvalds {
3781da177e4SLinus Torvalds 	struct sock *sk = NULL, *sk1 = NULL;
3791da177e4SLinus Torvalds 
3801da177e4SLinus Torvalds 	read_lock(&sco_sk_list.lock);
3811da177e4SLinus Torvalds 
382b67bfe0dSSasha Levin 	sk_for_each(sk, &sco_sk_list.head) {
3831da177e4SLinus Torvalds 		if (sk->sk_state != BT_LISTEN)
3841da177e4SLinus Torvalds 			continue;
3851da177e4SLinus Torvalds 
3861da177e4SLinus Torvalds 		/* Exact match. */
387eea96364SMarcel Holtmann 		if (!bacmp(&sco_pi(sk)->src, src))
3881da177e4SLinus Torvalds 			break;
3891da177e4SLinus Torvalds 
3901da177e4SLinus Torvalds 		/* Closest match */
391eea96364SMarcel Holtmann 		if (!bacmp(&sco_pi(sk)->src, BDADDR_ANY))
3921da177e4SLinus Torvalds 			sk1 = sk;
3931da177e4SLinus Torvalds 	}
3941da177e4SLinus Torvalds 
3951da177e4SLinus Torvalds 	read_unlock(&sco_sk_list.lock);
3961da177e4SLinus Torvalds 
397b67bfe0dSSasha Levin 	return sk ? sk : sk1;
3981da177e4SLinus Torvalds }
3991da177e4SLinus Torvalds 
sco_sock_destruct(struct sock * sk)4001da177e4SLinus Torvalds static void sco_sock_destruct(struct sock *sk)
4011da177e4SLinus Torvalds {
4021da177e4SLinus Torvalds 	BT_DBG("sk %p", sk);
4031da177e4SLinus Torvalds 
4041da177e4SLinus Torvalds 	skb_queue_purge(&sk->sk_receive_queue);
4051da177e4SLinus Torvalds 	skb_queue_purge(&sk->sk_write_queue);
4061da177e4SLinus Torvalds }
4071da177e4SLinus Torvalds 
sco_sock_cleanup_listen(struct sock * parent)4081da177e4SLinus Torvalds static void sco_sock_cleanup_listen(struct sock *parent)
4091da177e4SLinus Torvalds {
4101da177e4SLinus Torvalds 	struct sock *sk;
4111da177e4SLinus Torvalds 
4121da177e4SLinus Torvalds 	BT_DBG("parent %p", parent);
4131da177e4SLinus Torvalds 
4141da177e4SLinus Torvalds 	/* Close not yet accepted channels */
4151da177e4SLinus Torvalds 	while ((sk = bt_accept_dequeue(parent, NULL))) {
4161da177e4SLinus Torvalds 		sco_sock_close(sk);
4171da177e4SLinus Torvalds 		sco_sock_kill(sk);
4181da177e4SLinus Torvalds 	}
4191da177e4SLinus Torvalds 
4201da177e4SLinus Torvalds 	parent->sk_state  = BT_CLOSED;
4211da177e4SLinus Torvalds 	sock_set_flag(parent, SOCK_ZAPPED);
4221da177e4SLinus Torvalds }
4231da177e4SLinus Torvalds 
4241da177e4SLinus Torvalds /* Kill socket (only if zapped and orphan)
4251da177e4SLinus Torvalds  * Must be called on unlocked socket.
4261da177e4SLinus Torvalds  */
sco_sock_kill(struct sock * sk)4271da177e4SLinus Torvalds static void sco_sock_kill(struct sock *sk)
4281da177e4SLinus Torvalds {
429e1dee2c1SDesmond Cheong Zhi Xi 	if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket)
4301da177e4SLinus Torvalds 		return;
4311da177e4SLinus Torvalds 
4321da177e4SLinus Torvalds 	BT_DBG("sk %p state %d", sk, sk->sk_state);
4331da177e4SLinus Torvalds 
4341da177e4SLinus Torvalds 	/* Kill poor orphan */
4351da177e4SLinus Torvalds 	bt_sock_unlink(&sco_sk_list, sk);
4361da177e4SLinus Torvalds 	sock_set_flag(sk, SOCK_DEAD);
4371da177e4SLinus Torvalds 	sock_put(sk);
4381da177e4SLinus Torvalds }
4391da177e4SLinus Torvalds 
__sco_sock_close(struct sock * sk)440fd0b3ff7SMarcel Holtmann static void __sco_sock_close(struct sock *sk)
4411da177e4SLinus Torvalds {
442fd0b3ff7SMarcel Holtmann 	BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket);
4431da177e4SLinus Torvalds 
4441da177e4SLinus Torvalds 	switch (sk->sk_state) {
4451da177e4SLinus Torvalds 	case BT_LISTEN:
4461da177e4SLinus Torvalds 		sco_sock_cleanup_listen(sk);
4471da177e4SLinus Torvalds 		break;
4481da177e4SLinus Torvalds 
4491da177e4SLinus Torvalds 	case BT_CONNECTED:
4501da177e4SLinus Torvalds 	case BT_CONFIG:
451b7e98b51SGustavo Padovan 		if (sco_pi(sk)->conn->hcon) {
4524a77708bSLuiz Augusto von Dentz 			sk->sk_state = BT_DISCONN;
4534a77708bSLuiz Augusto von Dentz 			sco_sock_set_timer(sk, SCO_DISCONN_TIMEOUT);
454435c5133SKuba Pawlak 			sco_conn_lock(sco_pi(sk)->conn);
45576a68ba0SDavid Herrmann 			hci_conn_drop(sco_pi(sk)->conn->hcon);
4564a77708bSLuiz Augusto von Dentz 			sco_pi(sk)->conn->hcon = NULL;
457435c5133SKuba Pawlak 			sco_conn_unlock(sco_pi(sk)->conn);
4584a77708bSLuiz Augusto von Dentz 		} else
4594a77708bSLuiz Augusto von Dentz 			sco_chan_del(sk, ECONNRESET);
4604a77708bSLuiz Augusto von Dentz 		break;
4614a77708bSLuiz Augusto von Dentz 
462eb20ff9cSVinicius Costa Gomes 	case BT_CONNECT2:
4631da177e4SLinus Torvalds 	case BT_CONNECT:
4641da177e4SLinus Torvalds 	case BT_DISCONN:
4651da177e4SLinus Torvalds 		sco_chan_del(sk, ECONNRESET);
4661da177e4SLinus Torvalds 		break;
4671da177e4SLinus Torvalds 
4681da177e4SLinus Torvalds 	default:
4691da177e4SLinus Torvalds 		sock_set_flag(sk, SOCK_ZAPPED);
4701da177e4SLinus Torvalds 		break;
4713ff50b79SStephen Hemminger 	}
472f6873401SKiran K 
473fd0b3ff7SMarcel Holtmann }
4741da177e4SLinus Torvalds 
475fd0b3ff7SMarcel Holtmann /* Must be called on unlocked socket. */
sco_sock_close(struct sock * sk)476fd0b3ff7SMarcel Holtmann static void sco_sock_close(struct sock *sk)
477fd0b3ff7SMarcel Holtmann {
478fd0b3ff7SMarcel Holtmann 	lock_sock(sk);
4793f2c89fbSDesmond Cheong Zhi Xi 	sco_sock_clear_timer(sk);
480fd0b3ff7SMarcel Holtmann 	__sco_sock_close(sk);
4811da177e4SLinus Torvalds 	release_sock(sk);
4821da177e4SLinus Torvalds }
4831da177e4SLinus Torvalds 
sco_sock_init(struct sock * sk,struct sock * parent)4841da177e4SLinus Torvalds static void sco_sock_init(struct sock *sk, struct sock *parent)
4851da177e4SLinus Torvalds {
4861da177e4SLinus Torvalds 	BT_DBG("sk %p", sk);
4871da177e4SLinus Torvalds 
4886230c9b4SPaul Moore 	if (parent) {
4891da177e4SLinus Torvalds 		sk->sk_type = parent->sk_type;
49020714bfeSFrédéric Dalleau 		bt_sk(sk)->flags = bt_sk(parent)->flags;
4916230c9b4SPaul Moore 		security_sk_clone(parent, sk);
4926230c9b4SPaul Moore 	}
4931da177e4SLinus Torvalds }
4941da177e4SLinus Torvalds 
4951da177e4SLinus Torvalds static struct proto sco_proto = {
4961da177e4SLinus Torvalds 	.name		= "SCO",
4971da177e4SLinus Torvalds 	.owner		= THIS_MODULE,
4981da177e4SLinus Torvalds 	.obj_size	= sizeof(struct sco_pinfo)
4991da177e4SLinus Torvalds };
5001da177e4SLinus Torvalds 
sco_sock_alloc(struct net * net,struct socket * sock,int proto,gfp_t prio,int kern)501c4297e8fSMarcel Holtmann static struct sock *sco_sock_alloc(struct net *net, struct socket *sock,
502c4297e8fSMarcel Holtmann 				   int proto, gfp_t prio, int kern)
5031da177e4SLinus Torvalds {
5041da177e4SLinus Torvalds 	struct sock *sk;
5051da177e4SLinus Torvalds 
5066bfa273eSLuiz Augusto von Dentz 	sk = bt_sock_alloc(net, sock, &sco_proto, proto, prio, kern);
5071da177e4SLinus Torvalds 	if (!sk)
5081da177e4SLinus Torvalds 		return NULL;
5091da177e4SLinus Torvalds 
5101da177e4SLinus Torvalds 	sk->sk_destruct = sco_sock_destruct;
5111da177e4SLinus Torvalds 	sk->sk_sndtimeo = SCO_CONN_TIMEOUT;
5121da177e4SLinus Torvalds 
513ad10b1a4SFrédéric Dalleau 	sco_pi(sk)->setting = BT_VOICE_CVSD_16BIT;
514f6873401SKiran K 	sco_pi(sk)->codec.id = BT_CODEC_CVSD;
515f6873401SKiran K 	sco_pi(sk)->codec.cid = 0xffff;
516f6873401SKiran K 	sco_pi(sk)->codec.vid = 0xffff;
517f6873401SKiran K 	sco_pi(sk)->codec.data_path = 0x00;
518ad10b1a4SFrédéric Dalleau 
5191da177e4SLinus Torvalds 	bt_sock_link(&sco_sk_list, sk);
5201da177e4SLinus Torvalds 	return sk;
5211da177e4SLinus Torvalds }
5221da177e4SLinus Torvalds 
sco_sock_create(struct net * net,struct socket * sock,int protocol,int kern)5233f378b68SEric Paris static int sco_sock_create(struct net *net, struct socket *sock, int protocol,
5243f378b68SEric Paris 			   int kern)
5251da177e4SLinus Torvalds {
5261da177e4SLinus Torvalds 	struct sock *sk;
5271da177e4SLinus Torvalds 
5281da177e4SLinus Torvalds 	BT_DBG("sock %p", sock);
5291da177e4SLinus Torvalds 
5301da177e4SLinus Torvalds 	sock->state = SS_UNCONNECTED;
5311da177e4SLinus Torvalds 
5321da177e4SLinus Torvalds 	if (sock->type != SOCK_SEQPACKET)
5331da177e4SLinus Torvalds 		return -ESOCKTNOSUPPORT;
5341da177e4SLinus Torvalds 
5351da177e4SLinus Torvalds 	sock->ops = &sco_sock_ops;
5361da177e4SLinus Torvalds 
53711aa9c28SEric W. Biederman 	sk = sco_sock_alloc(net, sock, protocol, GFP_ATOMIC, kern);
53874da626aSMarcel Holtmann 	if (!sk)
5391da177e4SLinus Torvalds 		return -ENOMEM;
5401da177e4SLinus Torvalds 
5411da177e4SLinus Torvalds 	sco_sock_init(sk, NULL);
5421da177e4SLinus Torvalds 	return 0;
5431da177e4SLinus Torvalds }
5441da177e4SLinus Torvalds 
sco_sock_bind(struct socket * sock,struct sockaddr * addr,int addr_len)545c4297e8fSMarcel Holtmann static int sco_sock_bind(struct socket *sock, struct sockaddr *addr,
546c4297e8fSMarcel Holtmann 			 int addr_len)
5471da177e4SLinus Torvalds {
5481da177e4SLinus Torvalds 	struct sockaddr_sco *sa = (struct sockaddr_sco *) addr;
5491da177e4SLinus Torvalds 	struct sock *sk = sock->sk;
5501da177e4SLinus Torvalds 	int err = 0;
5511da177e4SLinus Torvalds 
552d2ecfa76SMateusz Jurczyk 	if (!addr || addr_len < sizeof(struct sockaddr_sco) ||
553d2ecfa76SMateusz Jurczyk 	    addr->sa_family != AF_BLUETOOTH)
5545233252fSDavid S. Miller 		return -EINVAL;
5555233252fSDavid S. Miller 
556bd7d46ddSTetsuo Handa 	BT_DBG("sk %p %pMR", sk, &sa->sco_bdaddr);
557bd7d46ddSTetsuo Handa 
5581da177e4SLinus Torvalds 	lock_sock(sk);
5591da177e4SLinus Torvalds 
5601da177e4SLinus Torvalds 	if (sk->sk_state != BT_OPEN) {
5611da177e4SLinus Torvalds 		err = -EBADFD;
5621da177e4SLinus Torvalds 		goto done;
5631da177e4SLinus Torvalds 	}
5641da177e4SLinus Torvalds 
5658ed21f7eSMarcel Holtmann 	if (sk->sk_type != SOCK_SEQPACKET) {
5668ed21f7eSMarcel Holtmann 		err = -EINVAL;
5678ed21f7eSMarcel Holtmann 		goto done;
5681da177e4SLinus Torvalds 	}
5691da177e4SLinus Torvalds 
570eea96364SMarcel Holtmann 	bacpy(&sco_pi(sk)->src, &sa->sco_bdaddr);
5718ed21f7eSMarcel Holtmann 
5728ed21f7eSMarcel Holtmann 	sk->sk_state = BT_BOUND;
5731da177e4SLinus Torvalds 
5741da177e4SLinus Torvalds done:
5751da177e4SLinus Torvalds 	release_sock(sk);
5761da177e4SLinus Torvalds 	return err;
5771da177e4SLinus Torvalds }
5781da177e4SLinus Torvalds 
sco_sock_connect(struct socket * sock,struct sockaddr * addr,int alen,int flags)5791da177e4SLinus Torvalds static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags)
5801da177e4SLinus Torvalds {
5811da177e4SLinus Torvalds 	struct sockaddr_sco *sa = (struct sockaddr_sco *) addr;
5821da177e4SLinus Torvalds 	struct sock *sk = sock->sk;
58392f185c8SClaudio Takahasi 	int err;
5841da177e4SLinus Torvalds 
5851da177e4SLinus Torvalds 	BT_DBG("sk %p", sk);
5861da177e4SLinus Torvalds 
5876503d961SChangli Gao 	if (alen < sizeof(struct sockaddr_sco) ||
5886503d961SChangli Gao 	    addr->sa_family != AF_BLUETOOTH)
5891da177e4SLinus Torvalds 		return -EINVAL;
5901da177e4SLinus Torvalds 
5919a8ec9e8SLuiz Augusto von Dentz 	if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND)
5929a8ec9e8SLuiz Augusto von Dentz 		return -EBADFD;
5931da177e4SLinus Torvalds 
5949a8ec9e8SLuiz Augusto von Dentz 	if (sk->sk_type != SOCK_SEQPACKET)
5957aa1e7d1SYing Hsu 		err = -EINVAL;
5961da177e4SLinus Torvalds 
5979a8ec9e8SLuiz Augusto von Dentz 	lock_sock(sk);
5981da177e4SLinus Torvalds 	/* Set destination address and psm */
599eea96364SMarcel Holtmann 	bacpy(&sco_pi(sk)->dst, &sa->sco_bdaddr);
6009a8ec9e8SLuiz Augusto von Dentz 	release_sock(sk);
6011da177e4SLinus Torvalds 
6029a8ec9e8SLuiz Augusto von Dentz 	err = sco_connect(sk);
603735cbc47SAndrei Emeltchenko 	if (err)
6049a8ec9e8SLuiz Augusto von Dentz 		return err;
6059a8ec9e8SLuiz Augusto von Dentz 
6069a8ec9e8SLuiz Augusto von Dentz 	lock_sock(sk);
6071da177e4SLinus Torvalds 
6081da177e4SLinus Torvalds 	err = bt_sock_wait_state(sk, BT_CONNECTED,
6091da177e4SLinus Torvalds 				 sock_sndtimeo(sk, flags & O_NONBLOCK));
6101da177e4SLinus Torvalds 
6111da177e4SLinus Torvalds 	release_sock(sk);
6121da177e4SLinus Torvalds 	return err;
6131da177e4SLinus Torvalds }
6141da177e4SLinus Torvalds 
sco_sock_listen(struct socket * sock,int backlog)6151da177e4SLinus Torvalds static int sco_sock_listen(struct socket *sock, int backlog)
6161da177e4SLinus Torvalds {
6171da177e4SLinus Torvalds 	struct sock *sk = sock->sk;
618eea96364SMarcel Holtmann 	bdaddr_t *src = &sco_pi(sk)->src;
6191da177e4SLinus Torvalds 	int err = 0;
6201da177e4SLinus Torvalds 
6211da177e4SLinus Torvalds 	BT_DBG("sk %p backlog %d", sk, backlog);
6221da177e4SLinus Torvalds 
6231da177e4SLinus Torvalds 	lock_sock(sk);
6241da177e4SLinus Torvalds 
6257d5d775aSMarcel Holtmann 	if (sk->sk_state != BT_BOUND) {
6261da177e4SLinus Torvalds 		err = -EBADFD;
6271da177e4SLinus Torvalds 		goto done;
6281da177e4SLinus Torvalds 	}
6291da177e4SLinus Torvalds 
6307d5d775aSMarcel Holtmann 	if (sk->sk_type != SOCK_SEQPACKET) {
6317d5d775aSMarcel Holtmann 		err = -EINVAL;
6327d5d775aSMarcel Holtmann 		goto done;
6337d5d775aSMarcel Holtmann 	}
6347d5d775aSMarcel Holtmann 
635fb334059SMarcel Holtmann 	write_lock(&sco_sk_list.lock);
636fb334059SMarcel Holtmann 
637fb334059SMarcel Holtmann 	if (__sco_get_sock_listen_by_addr(src)) {
638fb334059SMarcel Holtmann 		err = -EADDRINUSE;
639fb334059SMarcel Holtmann 		goto unlock;
640fb334059SMarcel Holtmann 	}
641fb334059SMarcel Holtmann 
6421da177e4SLinus Torvalds 	sk->sk_max_ack_backlog = backlog;
6431da177e4SLinus Torvalds 	sk->sk_ack_backlog = 0;
644fb334059SMarcel Holtmann 
6451da177e4SLinus Torvalds 	sk->sk_state = BT_LISTEN;
6461da177e4SLinus Torvalds 
647fb334059SMarcel Holtmann unlock:
648fb334059SMarcel Holtmann 	write_unlock(&sco_sk_list.lock);
649fb334059SMarcel Holtmann 
6501da177e4SLinus Torvalds done:
6511da177e4SLinus Torvalds 	release_sock(sk);
6521da177e4SLinus Torvalds 	return err;
6531da177e4SLinus Torvalds }
6541da177e4SLinus Torvalds 
sco_sock_accept(struct socket * sock,struct socket * newsock,struct proto_accept_arg * arg)655c4297e8fSMarcel Holtmann static int sco_sock_accept(struct socket *sock, struct socket *newsock,
65692ef0fd5SJens Axboe 			   struct proto_accept_arg *arg)
6571da177e4SLinus Torvalds {
658dfb2fae7SPeter Hurley 	DEFINE_WAIT_FUNC(wait, woken_wake_function);
6591da177e4SLinus Torvalds 	struct sock *sk = sock->sk, *ch;
6601da177e4SLinus Torvalds 	long timeo;
6611da177e4SLinus Torvalds 	int err = 0;
6621da177e4SLinus Torvalds 
6631da177e4SLinus Torvalds 	lock_sock(sk);
6641da177e4SLinus Torvalds 
66592ef0fd5SJens Axboe 	timeo = sock_rcvtimeo(sk, arg->flags & O_NONBLOCK);
6661da177e4SLinus Torvalds 
6671da177e4SLinus Torvalds 	BT_DBG("sk %p timeo %ld", sk, timeo);
6681da177e4SLinus Torvalds 
6691da177e4SLinus Torvalds 	/* Wait for an incoming connection. (wake-one). */
670aa395145SEric Dumazet 	add_wait_queue_exclusive(sk_sleep(sk), &wait);
671552b0d3cSPeter Hurley 	while (1) {
6721da177e4SLinus Torvalds 		if (sk->sk_state != BT_LISTEN) {
6731da177e4SLinus Torvalds 			err = -EBADFD;
6741da177e4SLinus Torvalds 			break;
6751da177e4SLinus Torvalds 		}
6761da177e4SLinus Torvalds 
677552b0d3cSPeter Hurley 		ch = bt_accept_dequeue(sk, newsock);
678552b0d3cSPeter Hurley 		if (ch)
679552b0d3cSPeter Hurley 			break;
680552b0d3cSPeter Hurley 
681552b0d3cSPeter Hurley 		if (!timeo) {
682552b0d3cSPeter Hurley 			err = -EAGAIN;
683552b0d3cSPeter Hurley 			break;
684552b0d3cSPeter Hurley 		}
685552b0d3cSPeter Hurley 
6861da177e4SLinus Torvalds 		if (signal_pending(current)) {
6871da177e4SLinus Torvalds 			err = sock_intr_errno(timeo);
6881da177e4SLinus Torvalds 			break;
6891da177e4SLinus Torvalds 		}
690552b0d3cSPeter Hurley 
691552b0d3cSPeter Hurley 		release_sock(sk);
692dfb2fae7SPeter Hurley 
693dfb2fae7SPeter Hurley 		timeo = wait_woken(&wait, TASK_INTERRUPTIBLE, timeo);
694552b0d3cSPeter Hurley 		lock_sock(sk);
6951da177e4SLinus Torvalds 	}
696aa395145SEric Dumazet 	remove_wait_queue(sk_sleep(sk), &wait);
6971da177e4SLinus Torvalds 
6981da177e4SLinus Torvalds 	if (err)
6991da177e4SLinus Torvalds 		goto done;
7001da177e4SLinus Torvalds 
7011da177e4SLinus Torvalds 	newsock->state = SS_CONNECTED;
7021da177e4SLinus Torvalds 
7031da177e4SLinus Torvalds 	BT_DBG("new socket %p", ch);
7041da177e4SLinus Torvalds 
7051da177e4SLinus Torvalds done:
7061da177e4SLinus Torvalds 	release_sock(sk);
7071da177e4SLinus Torvalds 	return err;
7081da177e4SLinus Torvalds }
7091da177e4SLinus Torvalds 
sco_sock_getname(struct socket * sock,struct sockaddr * addr,int peer)710c4297e8fSMarcel Holtmann static int sco_sock_getname(struct socket *sock, struct sockaddr *addr,
7119b2c45d4SDenys Vlasenko 			    int peer)
7121da177e4SLinus Torvalds {
7131da177e4SLinus Torvalds 	struct sockaddr_sco *sa = (struct sockaddr_sco *) addr;
7141da177e4SLinus Torvalds 	struct sock *sk = sock->sk;
7151da177e4SLinus Torvalds 
7161da177e4SLinus Torvalds 	BT_DBG("sock %p, sk %p", sock, sk);
7171da177e4SLinus Torvalds 
7181da177e4SLinus Torvalds 	addr->sa_family = AF_BLUETOOTH;
7191da177e4SLinus Torvalds 
7201da177e4SLinus Torvalds 	if (peer)
721eea96364SMarcel Holtmann 		bacpy(&sa->sco_bdaddr, &sco_pi(sk)->dst);
7221da177e4SLinus Torvalds 	else
723eea96364SMarcel Holtmann 		bacpy(&sa->sco_bdaddr, &sco_pi(sk)->src);
7241da177e4SLinus Torvalds 
7259b2c45d4SDenys Vlasenko 	return sizeof(struct sockaddr_sco);
7261da177e4SLinus Torvalds }
7271da177e4SLinus Torvalds 
sco_sock_sendmsg(struct socket * sock,struct msghdr * msg,size_t len)7281b784140SYing Xue static int sco_sock_sendmsg(struct socket *sock, struct msghdr *msg,
7291b784140SYing Xue 			    size_t len)
7301da177e4SLinus Torvalds {
7311da177e4SLinus Torvalds 	struct sock *sk = sock->sk;
7320771cbb3SLuiz Augusto von Dentz 	struct sk_buff *skb;
733b9dbdbc1SGustavo F. Padovan 	int err;
7341da177e4SLinus Torvalds 
7351da177e4SLinus Torvalds 	BT_DBG("sock %p, sk %p", sock, sk);
7361da177e4SLinus Torvalds 
737c1cbe4b7SBenjamin LaHaise 	err = sock_error(sk);
738c1cbe4b7SBenjamin LaHaise 	if (err)
739c1cbe4b7SBenjamin LaHaise 		return err;
7401da177e4SLinus Torvalds 
7411da177e4SLinus Torvalds 	if (msg->msg_flags & MSG_OOB)
7421da177e4SLinus Torvalds 		return -EOPNOTSUPP;
7431da177e4SLinus Torvalds 
7440771cbb3SLuiz Augusto von Dentz 	skb = bt_skb_sendmsg(sk, msg, len, len, 0, 0);
745266191aaSLuiz Augusto von Dentz 	if (IS_ERR(skb))
7460771cbb3SLuiz Augusto von Dentz 		return PTR_ERR(skb);
74799c23da0STakashi Iwai 
7481da177e4SLinus Torvalds 	lock_sock(sk);
7491da177e4SLinus Torvalds 
7501da177e4SLinus Torvalds 	if (sk->sk_state == BT_CONNECTED)
7510771cbb3SLuiz Augusto von Dentz 		err = sco_send_frame(sk, skb);
7521da177e4SLinus Torvalds 	else
7531da177e4SLinus Torvalds 		err = -ENOTCONN;
7541da177e4SLinus Torvalds 
7551da177e4SLinus Torvalds 	release_sock(sk);
756037ce005SLuiz Augusto von Dentz 
757037ce005SLuiz Augusto von Dentz 	if (err < 0)
7580771cbb3SLuiz Augusto von Dentz 		kfree_skb(skb);
7591da177e4SLinus Torvalds 	return err;
7601da177e4SLinus Torvalds }
7611da177e4SLinus Torvalds 
sco_conn_defer_accept(struct hci_conn * conn,u16 setting)7622f69a82aSFrédéric Dalleau static void sco_conn_defer_accept(struct hci_conn *conn, u16 setting)
763fa5513beSFrédéric Dalleau {
764fa5513beSFrédéric Dalleau 	struct hci_dev *hdev = conn->hdev;
765fa5513beSFrédéric Dalleau 
766fa5513beSFrédéric Dalleau 	BT_DBG("conn %p", conn);
767fa5513beSFrédéric Dalleau 
768fa5513beSFrédéric Dalleau 	conn->state = BT_CONFIG;
769fa5513beSFrédéric Dalleau 
770fa5513beSFrédéric Dalleau 	if (!lmp_esco_capable(hdev)) {
771fa5513beSFrédéric Dalleau 		struct hci_cp_accept_conn_req cp;
772fa5513beSFrédéric Dalleau 
773fa5513beSFrédéric Dalleau 		bacpy(&cp.bdaddr, &conn->dst);
77433f24048SFrédéric Dalleau 		cp.role = 0x00; /* Ignored */
775fa5513beSFrédéric Dalleau 
776fa5513beSFrédéric Dalleau 		hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp);
777fa5513beSFrédéric Dalleau 	} else {
778fa5513beSFrédéric Dalleau 		struct hci_cp_accept_sync_conn_req cp;
779fa5513beSFrédéric Dalleau 
780fa5513beSFrédéric Dalleau 		bacpy(&cp.bdaddr, &conn->dst);
781fa5513beSFrédéric Dalleau 		cp.pkt_type = cpu_to_le16(conn->pkt_type);
782fa5513beSFrédéric Dalleau 
783dcf4adbfSJoe Perches 		cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
784dcf4adbfSJoe Perches 		cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
7852f69a82aSFrédéric Dalleau 		cp.content_format = cpu_to_le16(setting);
7862f69a82aSFrédéric Dalleau 
7872f69a82aSFrédéric Dalleau 		switch (setting & SCO_AIRMODE_MASK) {
7882f69a82aSFrédéric Dalleau 		case SCO_AIRMODE_TRANSP:
7892f69a82aSFrédéric Dalleau 			if (conn->pkt_type & ESCO_2EV3)
790dcf4adbfSJoe Perches 				cp.max_latency = cpu_to_le16(0x0008);
7912f69a82aSFrédéric Dalleau 			else
792dcf4adbfSJoe Perches 				cp.max_latency = cpu_to_le16(0x000D);
7932f69a82aSFrédéric Dalleau 			cp.retrans_effort = 0x02;
7942f69a82aSFrédéric Dalleau 			break;
7952f69a82aSFrédéric Dalleau 		case SCO_AIRMODE_CVSD:
796dcf4adbfSJoe Perches 			cp.max_latency = cpu_to_le16(0xffff);
797fa5513beSFrédéric Dalleau 			cp.retrans_effort = 0xff;
7982f69a82aSFrédéric Dalleau 			break;
79959da0b38SDan Carpenter 		default:
80059da0b38SDan Carpenter 			/* use CVSD settings as fallback */
80159da0b38SDan Carpenter 			cp.max_latency = cpu_to_le16(0xffff);
80259da0b38SDan Carpenter 			cp.retrans_effort = 0xff;
80359da0b38SDan Carpenter 			break;
8042f69a82aSFrédéric Dalleau 		}
805fa5513beSFrédéric Dalleau 
806fa5513beSFrédéric Dalleau 		hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
807fa5513beSFrédéric Dalleau 			     sizeof(cp), &cp);
808fa5513beSFrédéric Dalleau 	}
809fa5513beSFrédéric Dalleau }
810fa5513beSFrédéric Dalleau 
sco_sock_recvmsg(struct socket * sock,struct msghdr * msg,size_t len,int flags)8111b784140SYing Xue static int sco_sock_recvmsg(struct socket *sock, struct msghdr *msg,
8121b784140SYing Xue 			    size_t len, int flags)
81320714bfeSFrédéric Dalleau {
81420714bfeSFrédéric Dalleau 	struct sock *sk = sock->sk;
81520714bfeSFrédéric Dalleau 	struct sco_pinfo *pi = sco_pi(sk);
81620714bfeSFrédéric Dalleau 
81720714bfeSFrédéric Dalleau 	lock_sock(sk);
81820714bfeSFrédéric Dalleau 
81920714bfeSFrédéric Dalleau 	if (sk->sk_state == BT_CONNECT2 &&
82020714bfeSFrédéric Dalleau 	    test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
8212f69a82aSFrédéric Dalleau 		sco_conn_defer_accept(pi->conn->hcon, pi->setting);
82220714bfeSFrédéric Dalleau 		sk->sk_state = BT_CONFIG;
82320714bfeSFrédéric Dalleau 
82420714bfeSFrédéric Dalleau 		release_sock(sk);
82520714bfeSFrédéric Dalleau 		return 0;
82620714bfeSFrédéric Dalleau 	}
82720714bfeSFrédéric Dalleau 
82820714bfeSFrédéric Dalleau 	release_sock(sk);
82920714bfeSFrédéric Dalleau 
8301b784140SYing Xue 	return bt_sock_recvmsg(sock, msg, len, flags);
83120714bfeSFrédéric Dalleau }
83220714bfeSFrédéric Dalleau 
sco_sock_setsockopt(struct socket * sock,int level,int optname,sockptr_t optval,unsigned int optlen)833c4297e8fSMarcel Holtmann static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
834a7b75c5aSChristoph Hellwig 			       sockptr_t optval, unsigned int optlen)
8351da177e4SLinus Torvalds {
8361da177e4SLinus Torvalds 	struct sock *sk = sock->sk;
83751eda36dSLuiz Augusto von Dentz 	int err = 0;
838ad10b1a4SFrédéric Dalleau 	struct bt_voice voice;
839b96e9c67SFrédéric Dalleau 	u32 opt;
840f6873401SKiran K 	struct bt_codecs *codecs;
841f6873401SKiran K 	struct hci_dev *hdev;
842f6873401SKiran K 	__u8 buffer[255];
8431da177e4SLinus Torvalds 
8441da177e4SLinus Torvalds 	BT_DBG("sk %p", sk);
8451da177e4SLinus Torvalds 
8461da177e4SLinus Torvalds 	lock_sock(sk);
8471da177e4SLinus Torvalds 
8481da177e4SLinus Torvalds 	switch (optname) {
849b96e9c67SFrédéric Dalleau 
850b96e9c67SFrédéric Dalleau 	case BT_DEFER_SETUP:
851b96e9c67SFrédéric Dalleau 		if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
852b96e9c67SFrédéric Dalleau 			err = -EINVAL;
853b96e9c67SFrédéric Dalleau 			break;
854b96e9c67SFrédéric Dalleau 		}
855b96e9c67SFrédéric Dalleau 
85651eda36dSLuiz Augusto von Dentz 		err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
85751eda36dSLuiz Augusto von Dentz 		if (err)
858b96e9c67SFrédéric Dalleau 			break;
859b96e9c67SFrédéric Dalleau 
860b96e9c67SFrédéric Dalleau 		if (opt)
861b96e9c67SFrédéric Dalleau 			set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
862b96e9c67SFrédéric Dalleau 		else
863b96e9c67SFrédéric Dalleau 			clear_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
864b96e9c67SFrédéric Dalleau 		break;
865b96e9c67SFrédéric Dalleau 
866ad10b1a4SFrédéric Dalleau 	case BT_VOICE:
867ad10b1a4SFrédéric Dalleau 		if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND &&
868ad10b1a4SFrédéric Dalleau 		    sk->sk_state != BT_CONNECT2) {
869ad10b1a4SFrédéric Dalleau 			err = -EINVAL;
870ad10b1a4SFrédéric Dalleau 			break;
871ad10b1a4SFrédéric Dalleau 		}
872ad10b1a4SFrédéric Dalleau 
873ad10b1a4SFrédéric Dalleau 		voice.setting = sco_pi(sk)->setting;
874ad10b1a4SFrédéric Dalleau 
87551eda36dSLuiz Augusto von Dentz 		err = bt_copy_from_sockptr(&voice, sizeof(voice), optval,
87651eda36dSLuiz Augusto von Dentz 					   optlen);
87751eda36dSLuiz Augusto von Dentz 		if (err)
878ad10b1a4SFrédéric Dalleau 			break;
879ad10b1a4SFrédéric Dalleau 
880ad10b1a4SFrédéric Dalleau 		/* Explicitly check for these values */
881ad10b1a4SFrédéric Dalleau 		if (voice.setting != BT_VOICE_TRANSPARENT &&
882ad10b1a4SFrédéric Dalleau 		    voice.setting != BT_VOICE_CVSD_16BIT) {
883ad10b1a4SFrédéric Dalleau 			err = -EINVAL;
884ad10b1a4SFrédéric Dalleau 			break;
885ad10b1a4SFrédéric Dalleau 		}
886ad10b1a4SFrédéric Dalleau 
887ad10b1a4SFrédéric Dalleau 		sco_pi(sk)->setting = voice.setting;
888b2af264aSKiran K 		hdev = hci_get_route(&sco_pi(sk)->dst, &sco_pi(sk)->src,
889b2af264aSKiran K 				     BDADDR_BREDR);
890b2af264aSKiran K 		if (!hdev) {
891b2af264aSKiran K 			err = -EBADFD;
892b2af264aSKiran K 			break;
893b2af264aSKiran K 		}
89405abad85SLuiz Augusto von Dentz 		if (enhanced_sync_conn_capable(hdev) &&
895b2af264aSKiran K 		    voice.setting == BT_VOICE_TRANSPARENT)
896b2af264aSKiran K 			sco_pi(sk)->codec.id = BT_CODEC_TRANSPARENT;
897b2af264aSKiran K 		hci_dev_put(hdev);
898ad10b1a4SFrédéric Dalleau 		break;
899ad10b1a4SFrédéric Dalleau 
90000398e1dSAlain Michaud 	case BT_PKT_STATUS:
90151eda36dSLuiz Augusto von Dentz 		err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
90251eda36dSLuiz Augusto von Dentz 		if (err)
90300398e1dSAlain Michaud 			break;
90400398e1dSAlain Michaud 
90500398e1dSAlain Michaud 		if (opt)
9063f19ffb2SLuiz Augusto von Dentz 			set_bit(BT_SK_PKT_STATUS, &bt_sk(sk)->flags);
90700398e1dSAlain Michaud 		else
9083f19ffb2SLuiz Augusto von Dentz 			clear_bit(BT_SK_PKT_STATUS, &bt_sk(sk)->flags);
90900398e1dSAlain Michaud 		break;
91000398e1dSAlain Michaud 
911f6873401SKiran K 	case BT_CODEC:
912f6873401SKiran K 		if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND &&
913f6873401SKiran K 		    sk->sk_state != BT_CONNECT2) {
914f6873401SKiran K 			err = -EINVAL;
915f6873401SKiran K 			break;
916f6873401SKiran K 		}
917f6873401SKiran K 
918f6873401SKiran K 		hdev = hci_get_route(&sco_pi(sk)->dst, &sco_pi(sk)->src,
919f6873401SKiran K 				     BDADDR_BREDR);
920f6873401SKiran K 		if (!hdev) {
921f6873401SKiran K 			err = -EBADFD;
922f6873401SKiran K 			break;
923f6873401SKiran K 		}
924f6873401SKiran K 
925f6873401SKiran K 		if (!hci_dev_test_flag(hdev, HCI_OFFLOAD_CODECS_ENABLED)) {
926f6873401SKiran K 			hci_dev_put(hdev);
927f6873401SKiran K 			err = -EOPNOTSUPP;
928f6873401SKiran K 			break;
929f6873401SKiran K 		}
930f6873401SKiran K 
931f6873401SKiran K 		if (!hdev->get_data_path_id) {
932f6873401SKiran K 			hci_dev_put(hdev);
933f6873401SKiran K 			err = -EOPNOTSUPP;
934f6873401SKiran K 			break;
935f6873401SKiran K 		}
936f6873401SKiran K 
937f6873401SKiran K 		if (optlen < sizeof(struct bt_codecs) ||
938f6873401SKiran K 		    optlen > sizeof(buffer)) {
939f6873401SKiran K 			hci_dev_put(hdev);
940f6873401SKiran K 			err = -EINVAL;
941f6873401SKiran K 			break;
942f6873401SKiran K 		}
943f6873401SKiran K 
94451eda36dSLuiz Augusto von Dentz 		err = bt_copy_from_sockptr(buffer, optlen, optval, optlen);
94551eda36dSLuiz Augusto von Dentz 		if (err) {
946f6873401SKiran K 			hci_dev_put(hdev);
947f6873401SKiran K 			break;
948f6873401SKiran K 		}
949f6873401SKiran K 
950f6873401SKiran K 		codecs = (void *)buffer;
951f6873401SKiran K 
952f6873401SKiran K 		if (codecs->num_codecs > 1) {
953f6873401SKiran K 			hci_dev_put(hdev);
954f6873401SKiran K 			err = -EINVAL;
955f6873401SKiran K 			break;
956f6873401SKiran K 		}
957f6873401SKiran K 
958f6873401SKiran K 		sco_pi(sk)->codec = codecs->codecs[0];
959f6873401SKiran K 		hci_dev_put(hdev);
960f6873401SKiran K 		break;
961f6873401SKiran K 
9621da177e4SLinus Torvalds 	default:
9631da177e4SLinus Torvalds 		err = -ENOPROTOOPT;
9641da177e4SLinus Torvalds 		break;
9651da177e4SLinus Torvalds 	}
9661da177e4SLinus Torvalds 
9671da177e4SLinus Torvalds 	release_sock(sk);
9681da177e4SLinus Torvalds 	return err;
9691da177e4SLinus Torvalds }
9701da177e4SLinus Torvalds 
sco_sock_getsockopt_old(struct socket * sock,int optname,char __user * optval,int __user * optlen)971c4297e8fSMarcel Holtmann static int sco_sock_getsockopt_old(struct socket *sock, int optname,
972c4297e8fSMarcel Holtmann 				   char __user *optval, int __user *optlen)
9731da177e4SLinus Torvalds {
9741da177e4SLinus Torvalds 	struct sock *sk = sock->sk;
9751da177e4SLinus Torvalds 	struct sco_options opts;
9761da177e4SLinus Torvalds 	struct sco_conninfo cinfo;
9779bf4e919SNathan Chancellor 	int err = 0;
9789bf4e919SNathan Chancellor 	size_t len;
9791da177e4SLinus Torvalds 
9801da177e4SLinus Torvalds 	BT_DBG("sk %p", sk);
9811da177e4SLinus Torvalds 
9821da177e4SLinus Torvalds 	if (get_user(len, optlen))
9831da177e4SLinus Torvalds 		return -EFAULT;
9841da177e4SLinus Torvalds 
9851da177e4SLinus Torvalds 	lock_sock(sk);
9861da177e4SLinus Torvalds 
9871da177e4SLinus Torvalds 	switch (optname) {
9881da177e4SLinus Torvalds 	case SCO_OPTIONS:
9899d225d22SJohan Hedberg 		if (sk->sk_state != BT_CONNECTED &&
9909d225d22SJohan Hedberg 		    !(sk->sk_state == BT_CONNECT2 &&
9919d225d22SJohan Hedberg 		      test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags))) {
9921da177e4SLinus Torvalds 			err = -ENOTCONN;
9931da177e4SLinus Torvalds 			break;
9941da177e4SLinus Torvalds 		}
9951da177e4SLinus Torvalds 
9961da177e4SLinus Torvalds 		opts.mtu = sco_pi(sk)->conn->mtu;
9971da177e4SLinus Torvalds 
99879dbeafeSKai Ye 		BT_DBG("mtu %u", opts.mtu);
9991da177e4SLinus Torvalds 
10009bf4e919SNathan Chancellor 		len = min(len, sizeof(opts));
10011da177e4SLinus Torvalds 		if (copy_to_user(optval, (char *)&opts, len))
10021da177e4SLinus Torvalds 			err = -EFAULT;
10031da177e4SLinus Torvalds 
10041da177e4SLinus Torvalds 		break;
10051da177e4SLinus Torvalds 
10061da177e4SLinus Torvalds 	case SCO_CONNINFO:
10079d225d22SJohan Hedberg 		if (sk->sk_state != BT_CONNECTED &&
10089d225d22SJohan Hedberg 		    !(sk->sk_state == BT_CONNECT2 &&
10099d225d22SJohan Hedberg 		      test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags))) {
10101da177e4SLinus Torvalds 			err = -ENOTCONN;
10111da177e4SLinus Torvalds 			break;
10121da177e4SLinus Torvalds 		}
10131da177e4SLinus Torvalds 
1014c4c896e1SVasiliy Kulikov 		memset(&cinfo, 0, sizeof(cinfo));
10151da177e4SLinus Torvalds 		cinfo.hci_handle = sco_pi(sk)->conn->hcon->handle;
10161da177e4SLinus Torvalds 		memcpy(cinfo.dev_class, sco_pi(sk)->conn->hcon->dev_class, 3);
10171da177e4SLinus Torvalds 
10189bf4e919SNathan Chancellor 		len = min(len, sizeof(cinfo));
10191da177e4SLinus Torvalds 		if (copy_to_user(optval, (char *)&cinfo, len))
10201da177e4SLinus Torvalds 			err = -EFAULT;
10211da177e4SLinus Torvalds 
10221da177e4SLinus Torvalds 		break;
10231da177e4SLinus Torvalds 
10241da177e4SLinus Torvalds 	default:
10251da177e4SLinus Torvalds 		err = -ENOPROTOOPT;
10261da177e4SLinus Torvalds 		break;
10271da177e4SLinus Torvalds 	}
10281da177e4SLinus Torvalds 
10291da177e4SLinus Torvalds 	release_sock(sk);
10301da177e4SLinus Torvalds 	return err;
10311da177e4SLinus Torvalds }
10321da177e4SLinus Torvalds 
sco_sock_getsockopt(struct socket * sock,int level,int optname,char __user * optval,int __user * optlen)1033c4297e8fSMarcel Holtmann static int sco_sock_getsockopt(struct socket *sock, int level, int optname,
1034c4297e8fSMarcel Holtmann 			       char __user *optval, int __user *optlen)
1035d58daf42SMarcel Holtmann {
1036d58daf42SMarcel Holtmann 	struct sock *sk = sock->sk;
1037d58daf42SMarcel Holtmann 	int len, err = 0;
1038ad10b1a4SFrédéric Dalleau 	struct bt_voice voice;
1039eab2404bSLuiz Augusto von Dentz 	u32 phys;
1040248733e8SKiran K 	int buf_len;
1041248733e8SKiran K 	struct codec_list *c;
1042248733e8SKiran K 	u8 num_codecs, i, __user *ptr;
1043248733e8SKiran K 	struct hci_dev *hdev;
1044248733e8SKiran K 	struct hci_codec_caps *caps;
1045248733e8SKiran K 	struct bt_codec codec;
1046d58daf42SMarcel Holtmann 
1047d58daf42SMarcel Holtmann 	BT_DBG("sk %p", sk);
1048d58daf42SMarcel Holtmann 
1049d58daf42SMarcel Holtmann 	if (level == SOL_SCO)
1050d58daf42SMarcel Holtmann 		return sco_sock_getsockopt_old(sock, optname, optval, optlen);
1051d58daf42SMarcel Holtmann 
1052d58daf42SMarcel Holtmann 	if (get_user(len, optlen))
1053d58daf42SMarcel Holtmann 		return -EFAULT;
1054d58daf42SMarcel Holtmann 
1055d58daf42SMarcel Holtmann 	lock_sock(sk);
1056d58daf42SMarcel Holtmann 
1057d58daf42SMarcel Holtmann 	switch (optname) {
1058b96e9c67SFrédéric Dalleau 
1059b96e9c67SFrédéric Dalleau 	case BT_DEFER_SETUP:
1060b96e9c67SFrédéric Dalleau 		if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
1061b96e9c67SFrédéric Dalleau 			err = -EINVAL;
1062b96e9c67SFrédéric Dalleau 			break;
1063b96e9c67SFrédéric Dalleau 		}
1064b96e9c67SFrédéric Dalleau 
1065b96e9c67SFrédéric Dalleau 		if (put_user(test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags),
1066b96e9c67SFrédéric Dalleau 			     (u32 __user *)optval))
1067b96e9c67SFrédéric Dalleau 			err = -EFAULT;
1068b96e9c67SFrédéric Dalleau 
1069b96e9c67SFrédéric Dalleau 		break;
1070b96e9c67SFrédéric Dalleau 
1071ad10b1a4SFrédéric Dalleau 	case BT_VOICE:
1072ad10b1a4SFrédéric Dalleau 		voice.setting = sco_pi(sk)->setting;
1073ad10b1a4SFrédéric Dalleau 
1074ad10b1a4SFrédéric Dalleau 		len = min_t(unsigned int, len, sizeof(voice));
1075ad10b1a4SFrédéric Dalleau 		if (copy_to_user(optval, (char *)&voice, len))
1076ad10b1a4SFrédéric Dalleau 			err = -EFAULT;
1077ad10b1a4SFrédéric Dalleau 
1078ad10b1a4SFrédéric Dalleau 		break;
1079ad10b1a4SFrédéric Dalleau 
1080eab2404bSLuiz Augusto von Dentz 	case BT_PHY:
1081a2a8b0b4SLuiz Augusto von Dentz 		if (sk->sk_state != BT_CONNECTED) {
1082eab2404bSLuiz Augusto von Dentz 			err = -ENOTCONN;
1083eab2404bSLuiz Augusto von Dentz 			break;
1084eab2404bSLuiz Augusto von Dentz 		}
1085eab2404bSLuiz Augusto von Dentz 
1086eab2404bSLuiz Augusto von Dentz 		phys = hci_conn_get_phy(sco_pi(sk)->conn->hcon);
1087eab2404bSLuiz Augusto von Dentz 
1088eab2404bSLuiz Augusto von Dentz 		if (put_user(phys, (u32 __user *) optval))
1089eab2404bSLuiz Augusto von Dentz 			err = -EFAULT;
1090eab2404bSLuiz Augusto von Dentz 		break;
1091eab2404bSLuiz Augusto von Dentz 
109200398e1dSAlain Michaud 	case BT_PKT_STATUS:
10933f19ffb2SLuiz Augusto von Dentz 		if (put_user(test_bit(BT_SK_PKT_STATUS, &bt_sk(sk)->flags),
10943f19ffb2SLuiz Augusto von Dentz 			     (int __user *)optval))
109500398e1dSAlain Michaud 			err = -EFAULT;
109600398e1dSAlain Michaud 		break;
109700398e1dSAlain Michaud 
10980fc1a726SJoseph Hwang 	case BT_SNDMTU:
10990fc1a726SJoseph Hwang 	case BT_RCVMTU:
1100f6b8c6b5SWei Yongjun 		if (sk->sk_state != BT_CONNECTED) {
1101f6b8c6b5SWei Yongjun 			err = -ENOTCONN;
1102f6b8c6b5SWei Yongjun 			break;
1103f6b8c6b5SWei Yongjun 		}
1104f6b8c6b5SWei Yongjun 
11050fc1a726SJoseph Hwang 		if (put_user(sco_pi(sk)->conn->mtu, (u32 __user *)optval))
11060fc1a726SJoseph Hwang 			err = -EFAULT;
11070fc1a726SJoseph Hwang 		break;
11080fc1a726SJoseph Hwang 
1109248733e8SKiran K 	case BT_CODEC:
1110248733e8SKiran K 		num_codecs = 0;
1111248733e8SKiran K 		buf_len = 0;
1112248733e8SKiran K 
1113248733e8SKiran K 		hdev = hci_get_route(&sco_pi(sk)->dst, &sco_pi(sk)->src, BDADDR_BREDR);
1114248733e8SKiran K 		if (!hdev) {
1115248733e8SKiran K 			err = -EBADFD;
1116248733e8SKiran K 			break;
1117248733e8SKiran K 		}
1118248733e8SKiran K 
1119248733e8SKiran K 		if (!hci_dev_test_flag(hdev, HCI_OFFLOAD_CODECS_ENABLED)) {
1120248733e8SKiran K 			hci_dev_put(hdev);
1121248733e8SKiran K 			err = -EOPNOTSUPP;
1122248733e8SKiran K 			break;
1123248733e8SKiran K 		}
1124248733e8SKiran K 
1125248733e8SKiran K 		if (!hdev->get_data_path_id) {
1126248733e8SKiran K 			hci_dev_put(hdev);
1127248733e8SKiran K 			err = -EOPNOTSUPP;
1128248733e8SKiran K 			break;
1129248733e8SKiran K 		}
1130248733e8SKiran K 
1131975abc0cSLuiz Augusto von Dentz 		release_sock(sk);
1132975abc0cSLuiz Augusto von Dentz 
1133248733e8SKiran K 		/* find total buffer size required to copy codec + caps */
1134248733e8SKiran K 		hci_dev_lock(hdev);
1135248733e8SKiran K 		list_for_each_entry(c, &hdev->local_codecs, list) {
1136248733e8SKiran K 			if (c->transport != HCI_TRANSPORT_SCO_ESCO)
1137248733e8SKiran K 				continue;
1138248733e8SKiran K 			num_codecs++;
1139248733e8SKiran K 			for (i = 0, caps = c->caps; i < c->num_caps; i++) {
1140248733e8SKiran K 				buf_len += 1 + caps->len;
1141248733e8SKiran K 				caps = (void *)&caps->data[caps->len];
1142248733e8SKiran K 			}
1143248733e8SKiran K 			buf_len += sizeof(struct bt_codec);
1144248733e8SKiran K 		}
1145248733e8SKiran K 		hci_dev_unlock(hdev);
1146248733e8SKiran K 
1147248733e8SKiran K 		buf_len += sizeof(struct bt_codecs);
1148248733e8SKiran K 		if (buf_len > len) {
1149248733e8SKiran K 			hci_dev_put(hdev);
1150975abc0cSLuiz Augusto von Dentz 			return -ENOBUFS;
1151248733e8SKiran K 		}
1152248733e8SKiran K 		ptr = optval;
1153248733e8SKiran K 
1154248733e8SKiran K 		if (put_user(num_codecs, ptr)) {
1155248733e8SKiran K 			hci_dev_put(hdev);
1156975abc0cSLuiz Augusto von Dentz 			return -EFAULT;
1157248733e8SKiran K 		}
1158248733e8SKiran K 		ptr += sizeof(num_codecs);
1159248733e8SKiran K 
1160248733e8SKiran K 		/* Iterate all the codecs supported over SCO and populate
1161248733e8SKiran K 		 * codec data
1162248733e8SKiran K 		 */
1163248733e8SKiran K 		hci_dev_lock(hdev);
1164248733e8SKiran K 		list_for_each_entry(c, &hdev->local_codecs, list) {
1165248733e8SKiran K 			if (c->transport != HCI_TRANSPORT_SCO_ESCO)
1166248733e8SKiran K 				continue;
1167248733e8SKiran K 
1168248733e8SKiran K 			codec.id = c->id;
1169248733e8SKiran K 			codec.cid = c->cid;
1170248733e8SKiran K 			codec.vid = c->vid;
1171248733e8SKiran K 			err = hdev->get_data_path_id(hdev, &codec.data_path);
1172248733e8SKiran K 			if (err < 0)
1173248733e8SKiran K 				break;
1174248733e8SKiran K 			codec.num_caps = c->num_caps;
1175248733e8SKiran K 			if (copy_to_user(ptr, &codec, sizeof(codec))) {
1176248733e8SKiran K 				err = -EFAULT;
1177248733e8SKiran K 				break;
1178248733e8SKiran K 			}
1179248733e8SKiran K 			ptr += sizeof(codec);
1180248733e8SKiran K 
1181248733e8SKiran K 			/* find codec capabilities data length */
1182248733e8SKiran K 			len = 0;
1183248733e8SKiran K 			for (i = 0, caps = c->caps; i < c->num_caps; i++) {
1184248733e8SKiran K 				len += 1 + caps->len;
1185248733e8SKiran K 				caps = (void *)&caps->data[caps->len];
1186248733e8SKiran K 			}
1187248733e8SKiran K 
1188248733e8SKiran K 			/* copy codec capabilities data */
1189248733e8SKiran K 			if (len && copy_to_user(ptr, c->caps, len)) {
1190248733e8SKiran K 				err = -EFAULT;
1191248733e8SKiran K 				break;
1192248733e8SKiran K 			}
1193248733e8SKiran K 			ptr += len;
1194248733e8SKiran K 		}
1195248733e8SKiran K 
1196248733e8SKiran K 		hci_dev_unlock(hdev);
1197248733e8SKiran K 		hci_dev_put(hdev);
1198248733e8SKiran K 
1199975abc0cSLuiz Augusto von Dentz 		lock_sock(sk);
1200975abc0cSLuiz Augusto von Dentz 
1201975abc0cSLuiz Augusto von Dentz 		if (!err && put_user(buf_len, optlen))
1202975abc0cSLuiz Augusto von Dentz 			err = -EFAULT;
1203975abc0cSLuiz Augusto von Dentz 
1204248733e8SKiran K 		break;
1205248733e8SKiran K 
1206d58daf42SMarcel Holtmann 	default:
1207d58daf42SMarcel Holtmann 		err = -ENOPROTOOPT;
1208d58daf42SMarcel Holtmann 		break;
1209d58daf42SMarcel Holtmann 	}
1210d58daf42SMarcel Holtmann 
1211d58daf42SMarcel Holtmann 	release_sock(sk);
1212d58daf42SMarcel Holtmann 	return err;
1213d58daf42SMarcel Holtmann }
1214d58daf42SMarcel Holtmann 
sco_sock_shutdown(struct socket * sock,int how)1215fd0b3ff7SMarcel Holtmann static int sco_sock_shutdown(struct socket *sock, int how)
1216fd0b3ff7SMarcel Holtmann {
1217fd0b3ff7SMarcel Holtmann 	struct sock *sk = sock->sk;
1218fd0b3ff7SMarcel Holtmann 	int err = 0;
1219fd0b3ff7SMarcel Holtmann 
1220fd0b3ff7SMarcel Holtmann 	BT_DBG("sock %p, sk %p", sock, sk);
1221fd0b3ff7SMarcel Holtmann 
1222fd0b3ff7SMarcel Holtmann 	if (!sk)
1223fd0b3ff7SMarcel Holtmann 		return 0;
1224fd0b3ff7SMarcel Holtmann 
12251da5537eSKuba Pawlak 	sock_hold(sk);
1226fd0b3ff7SMarcel Holtmann 	lock_sock(sk);
12271da5537eSKuba Pawlak 
1228fd0b3ff7SMarcel Holtmann 	if (!sk->sk_shutdown) {
1229fd0b3ff7SMarcel Holtmann 		sk->sk_shutdown = SHUTDOWN_MASK;
1230fd0b3ff7SMarcel Holtmann 		sco_sock_clear_timer(sk);
1231fd0b3ff7SMarcel Holtmann 		__sco_sock_close(sk);
1232fd0b3ff7SMarcel Holtmann 
1233093facf3SVladimir Davydov 		if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime &&
1234093facf3SVladimir Davydov 		    !(current->flags & PF_EXITING))
1235fd0b3ff7SMarcel Holtmann 			err = bt_sock_wait_state(sk, BT_CLOSED,
1236fd0b3ff7SMarcel Holtmann 						 sk->sk_lingertime);
1237fd0b3ff7SMarcel Holtmann 	}
12381da5537eSKuba Pawlak 
1239fd0b3ff7SMarcel Holtmann 	release_sock(sk);
12401da5537eSKuba Pawlak 	sock_put(sk);
12411da5537eSKuba Pawlak 
1242fd0b3ff7SMarcel Holtmann 	return err;
1243fd0b3ff7SMarcel Holtmann }
1244fd0b3ff7SMarcel Holtmann 
sco_sock_release(struct socket * sock)12451da177e4SLinus Torvalds static int sco_sock_release(struct socket *sock)
12461da177e4SLinus Torvalds {
12471da177e4SLinus Torvalds 	struct sock *sk = sock->sk;
12481da177e4SLinus Torvalds 	int err = 0;
12491da177e4SLinus Torvalds 
12501da177e4SLinus Torvalds 	BT_DBG("sock %p, sk %p", sock, sk);
12511da177e4SLinus Torvalds 
12521da177e4SLinus Torvalds 	if (!sk)
12531da177e4SLinus Torvalds 		return 0;
12541da177e4SLinus Torvalds 
12551da177e4SLinus Torvalds 	sco_sock_close(sk);
12561da177e4SLinus Torvalds 
1257bc1fb82aSEric Dumazet 	if (sock_flag(sk, SOCK_LINGER) && READ_ONCE(sk->sk_lingertime) &&
1258093facf3SVladimir Davydov 	    !(current->flags & PF_EXITING)) {
12591da177e4SLinus Torvalds 		lock_sock(sk);
12601da177e4SLinus Torvalds 		err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime);
12611da177e4SLinus Torvalds 		release_sock(sk);
12621da177e4SLinus Torvalds 	}
12631da177e4SLinus Torvalds 
12641da177e4SLinus Torvalds 	sock_orphan(sk);
12651da177e4SLinus Torvalds 	sco_sock_kill(sk);
12661da177e4SLinus Torvalds 	return err;
12671da177e4SLinus Torvalds }
12681da177e4SLinus Torvalds 
sco_conn_ready(struct sco_conn * conn)12691da177e4SLinus Torvalds static void sco_conn_ready(struct sco_conn *conn)
12701da177e4SLinus Torvalds {
1271735cbc47SAndrei Emeltchenko 	struct sock *parent;
1272735cbc47SAndrei Emeltchenko 	struct sock *sk = conn->sk;
12731da177e4SLinus Torvalds 
12741da177e4SLinus Torvalds 	BT_DBG("conn %p", conn);
12751da177e4SLinus Torvalds 
1276735cbc47SAndrei Emeltchenko 	if (sk) {
127727c24fdaSDesmond Cheong Zhi Xi 		lock_sock(sk);
12783f2c89fbSDesmond Cheong Zhi Xi 		sco_sock_clear_timer(sk);
12791da177e4SLinus Torvalds 		sk->sk_state = BT_CONNECTED;
12801da177e4SLinus Torvalds 		sk->sk_state_change(sk);
128127c24fdaSDesmond Cheong Zhi Xi 		release_sock(sk);
12821da177e4SLinus Torvalds 	} else {
128340528088SAndre Guedes 		sco_conn_lock(conn);
128440528088SAndre Guedes 
12852c501cddSKuba Pawlak 		if (!conn->hcon) {
12862c501cddSKuba Pawlak 			sco_conn_unlock(conn);
12872c501cddSKuba Pawlak 			return;
12882c501cddSKuba Pawlak 		}
12892c501cddSKuba Pawlak 
1290041987cfSMarcel Holtmann 		parent = sco_get_sock_listen(&conn->hcon->src);
129140528088SAndre Guedes 		if (!parent) {
129240528088SAndre Guedes 			sco_conn_unlock(conn);
129340528088SAndre Guedes 			return;
129440528088SAndre Guedes 		}
12951da177e4SLinus Torvalds 
129627c24fdaSDesmond Cheong Zhi Xi 		lock_sock(parent);
12971da177e4SLinus Torvalds 
1298b9dbdbc1SGustavo F. Padovan 		sk = sco_sock_alloc(sock_net(parent), NULL,
129911aa9c28SEric W. Biederman 				    BTPROTO_SCO, GFP_ATOMIC, 0);
13001da177e4SLinus Torvalds 		if (!sk) {
130127c24fdaSDesmond Cheong Zhi Xi 			release_sock(parent);
130240528088SAndre Guedes 			sco_conn_unlock(conn);
130340528088SAndre Guedes 			return;
13041da177e4SLinus Torvalds 		}
13051da177e4SLinus Torvalds 
13061da177e4SLinus Torvalds 		sco_sock_init(sk, parent);
13071da177e4SLinus Torvalds 
1308eea96364SMarcel Holtmann 		bacpy(&sco_pi(sk)->src, &conn->hcon->src);
1309eea96364SMarcel Holtmann 		bacpy(&sco_pi(sk)->dst, &conn->hcon->dst);
13101da177e4SLinus Torvalds 
13111da177e4SLinus Torvalds 		hci_conn_hold(conn->hcon);
13121da177e4SLinus Torvalds 		__sco_chan_add(conn, sk, parent);
13131da177e4SLinus Torvalds 
131420714bfeSFrédéric Dalleau 		if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags))
131520714bfeSFrédéric Dalleau 			sk->sk_state = BT_CONNECT2;
131620714bfeSFrédéric Dalleau 		else
13171da177e4SLinus Torvalds 			sk->sk_state = BT_CONNECTED;
13181da177e4SLinus Torvalds 
13191da177e4SLinus Torvalds 		/* Wake up parent */
1320676d2369SDavid S. Miller 		parent->sk_data_ready(parent);
13211da177e4SLinus Torvalds 
132227c24fdaSDesmond Cheong Zhi Xi 		release_sock(parent);
13231da177e4SLinus Torvalds 
13241da177e4SLinus Torvalds 		sco_conn_unlock(conn);
13251da177e4SLinus Torvalds 	}
132640528088SAndre Guedes }
13271da177e4SLinus Torvalds 
13281da177e4SLinus Torvalds /* ----- SCO interface with lower layer (HCI) ----- */
sco_connect_ind(struct hci_dev * hdev,bdaddr_t * bdaddr,__u8 * flags)132920714bfeSFrédéric Dalleau int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
13301da177e4SLinus Torvalds {
1331fc5fef61SGustavo Padovan 	struct sock *sk;
133271aeeaa1SMarcel Holtmann 	int lm = 0;
133371aeeaa1SMarcel Holtmann 
13346ed93dc6SAndrei Emeltchenko 	BT_DBG("hdev %s, bdaddr %pMR", hdev->name, bdaddr);
13351da177e4SLinus Torvalds 
133671aeeaa1SMarcel Holtmann 	/* Find listening sockets */
133771aeeaa1SMarcel Holtmann 	read_lock(&sco_sk_list.lock);
1338b67bfe0dSSasha Levin 	sk_for_each(sk, &sco_sk_list.head) {
133971aeeaa1SMarcel Holtmann 		if (sk->sk_state != BT_LISTEN)
134071aeeaa1SMarcel Holtmann 			continue;
134171aeeaa1SMarcel Holtmann 
1342eea96364SMarcel Holtmann 		if (!bacmp(&sco_pi(sk)->src, &hdev->bdaddr) ||
1343eea96364SMarcel Holtmann 		    !bacmp(&sco_pi(sk)->src, BDADDR_ANY)) {
134471aeeaa1SMarcel Holtmann 			lm |= HCI_LM_ACCEPT;
134520714bfeSFrédéric Dalleau 
134620714bfeSFrédéric Dalleau 			if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags))
134720714bfeSFrédéric Dalleau 				*flags |= HCI_PROTO_DEFER;
134871aeeaa1SMarcel Holtmann 			break;
134971aeeaa1SMarcel Holtmann 		}
135071aeeaa1SMarcel Holtmann 	}
135171aeeaa1SMarcel Holtmann 	read_unlock(&sco_sk_list.lock);
135271aeeaa1SMarcel Holtmann 
135371aeeaa1SMarcel Holtmann 	return lm;
13541da177e4SLinus Torvalds }
13551da177e4SLinus Torvalds 
sco_connect_cfm(struct hci_conn * hcon,__u8 status)1356539c496dSJohan Hedberg static void sco_connect_cfm(struct hci_conn *hcon, __u8 status)
13571da177e4SLinus Torvalds {
1358539c496dSJohan Hedberg 	if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
1359539c496dSJohan Hedberg 		return;
1360539c496dSJohan Hedberg 
136179dbeafeSKai Ye 	BT_DBG("hcon %p bdaddr %pMR status %u", hcon, &hcon->dst, status);
1362539c496dSJohan Hedberg 
13631da177e4SLinus Torvalds 	if (!status) {
13641da177e4SLinus Torvalds 		struct sco_conn *conn;
13651da177e4SLinus Torvalds 
1366519e42b3SLukasz Rymanowski 		conn = sco_conn_add(hcon);
13671da177e4SLinus Torvalds 		if (conn)
13681da177e4SLinus Torvalds 			sco_conn_ready(conn);
13691da177e4SLinus Torvalds 	} else
1370e175072fSJoe Perches 		sco_conn_del(hcon, bt_to_errno(status));
13711da177e4SLinus Torvalds }
13721da177e4SLinus Torvalds 
sco_disconn_cfm(struct hci_conn * hcon,__u8 reason)13733a6d576bSJohan Hedberg static void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason)
13741da177e4SLinus Torvalds {
13753a6d576bSJohan Hedberg 	if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
13763a6d576bSJohan Hedberg 		return;
13773a6d576bSJohan Hedberg 
13781da177e4SLinus Torvalds 	BT_DBG("hcon %p reason %d", hcon, reason);
13791da177e4SLinus Torvalds 
1380e175072fSJoe Perches 	sco_conn_del(hcon, bt_to_errno(reason));
13811da177e4SLinus Torvalds }
13821da177e4SLinus Torvalds 
sco_recv_scodata(struct hci_conn * hcon,struct sk_buff * skb)13839b4c3336SArron Wang void sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb)
13841da177e4SLinus Torvalds {
13851da177e4SLinus Torvalds 	struct sco_conn *conn = hcon->sco_data;
13861da177e4SLinus Torvalds 
13871da177e4SLinus Torvalds 	if (!conn)
13881da177e4SLinus Torvalds 		goto drop;
13891da177e4SLinus Torvalds 
139079dbeafeSKai Ye 	BT_DBG("conn %p len %u", conn, skb->len);
13911da177e4SLinus Torvalds 
13921da177e4SLinus Torvalds 	if (skb->len) {
13931da177e4SLinus Torvalds 		sco_recv_frame(conn, skb);
13949b4c3336SArron Wang 		return;
13951da177e4SLinus Torvalds 	}
13961da177e4SLinus Torvalds 
13971da177e4SLinus Torvalds drop:
13981da177e4SLinus Torvalds 	kfree_skb(skb);
13991da177e4SLinus Torvalds }
14001da177e4SLinus Torvalds 
1401539c496dSJohan Hedberg static struct hci_cb sco_cb = {
1402539c496dSJohan Hedberg 	.name		= "SCO",
1403539c496dSJohan Hedberg 	.connect_cfm	= sco_connect_cfm,
14043a6d576bSJohan Hedberg 	.disconn_cfm	= sco_disconn_cfm,
1405539c496dSJohan Hedberg };
1406539c496dSJohan Hedberg 
sco_debugfs_show(struct seq_file * f,void * p)1407aef7d97cSMarcel Holtmann static int sco_debugfs_show(struct seq_file *f, void *p)
14081da177e4SLinus Torvalds {
14091da177e4SLinus Torvalds 	struct sock *sk;
14101da177e4SLinus Torvalds 
1411ee65d19eSGustavo F. Padovan 	read_lock(&sco_sk_list.lock);
14121da177e4SLinus Torvalds 
1413b67bfe0dSSasha Levin 	sk_for_each(sk, &sco_sk_list.head) {
1414eea96364SMarcel Holtmann 		seq_printf(f, "%pMR %pMR %d\n", &sco_pi(sk)->src,
1415eea96364SMarcel Holtmann 			   &sco_pi(sk)->dst, sk->sk_state);
14161da177e4SLinus Torvalds 	}
14171da177e4SLinus Torvalds 
1418ee65d19eSGustavo F. Padovan 	read_unlock(&sco_sk_list.lock);
1419be9d1227SMarcel Holtmann 
1420aef7d97cSMarcel Holtmann 	return 0;
14211da177e4SLinus Torvalds }
14221da177e4SLinus Torvalds 
14238e2924e3SYangtao Li DEFINE_SHOW_ATTRIBUTE(sco_debugfs);
1424aef7d97cSMarcel Holtmann 
1425aef7d97cSMarcel Holtmann static struct dentry *sco_debugfs;
14261da177e4SLinus Torvalds 
142790ddc4f0SEric Dumazet static const struct proto_ops sco_sock_ops = {
14281da177e4SLinus Torvalds 	.family		= PF_BLUETOOTH,
14291da177e4SLinus Torvalds 	.owner		= THIS_MODULE,
14301da177e4SLinus Torvalds 	.release	= sco_sock_release,
14311da177e4SLinus Torvalds 	.bind		= sco_sock_bind,
14321da177e4SLinus Torvalds 	.connect	= sco_sock_connect,
14331da177e4SLinus Torvalds 	.listen		= sco_sock_listen,
14341da177e4SLinus Torvalds 	.accept		= sco_sock_accept,
14351da177e4SLinus Torvalds 	.getname	= sco_sock_getname,
14361da177e4SLinus Torvalds 	.sendmsg	= sco_sock_sendmsg,
143720714bfeSFrédéric Dalleau 	.recvmsg	= sco_sock_recvmsg,
1438a11e1d43SLinus Torvalds 	.poll		= bt_sock_poll,
14393241ad82SMarcel Holtmann 	.ioctl		= bt_sock_ioctl,
1440c7cbdbf2SArnd Bergmann 	.gettstamp	= sock_gettstamp,
14411da177e4SLinus Torvalds 	.mmap		= sock_no_mmap,
14421da177e4SLinus Torvalds 	.socketpair	= sock_no_socketpair,
1443fd0b3ff7SMarcel Holtmann 	.shutdown	= sco_sock_shutdown,
14441da177e4SLinus Torvalds 	.setsockopt	= sco_sock_setsockopt,
14451da177e4SLinus Torvalds 	.getsockopt	= sco_sock_getsockopt
14461da177e4SLinus Torvalds };
14471da177e4SLinus Torvalds 
1448ec1b4cf7SStephen Hemminger static const struct net_proto_family sco_sock_family_ops = {
14491da177e4SLinus Torvalds 	.family	= PF_BLUETOOTH,
14501da177e4SLinus Torvalds 	.owner	= THIS_MODULE,
14511da177e4SLinus Torvalds 	.create	= sco_sock_create,
14521da177e4SLinus Torvalds };
14531da177e4SLinus Torvalds 
sco_init(void)145464274518SGustavo F. Padovan int __init sco_init(void)
14551da177e4SLinus Torvalds {
14561da177e4SLinus Torvalds 	int err;
14571da177e4SLinus Torvalds 
145815762fa7SMarcel Holtmann 	BUILD_BUG_ON(sizeof(struct sockaddr_sco) > sizeof(struct sockaddr));
145915762fa7SMarcel Holtmann 
14601da177e4SLinus Torvalds 	err = proto_register(&sco_proto, 0);
14611da177e4SLinus Torvalds 	if (err < 0)
14621da177e4SLinus Torvalds 		return err;
14631da177e4SLinus Torvalds 
14641da177e4SLinus Torvalds 	err = bt_sock_register(BTPROTO_SCO, &sco_sock_family_ops);
14651da177e4SLinus Torvalds 	if (err < 0) {
14661da177e4SLinus Torvalds 		BT_ERR("SCO socket registration failed");
14671da177e4SLinus Torvalds 		goto error;
14681da177e4SLinus Torvalds 	}
14691da177e4SLinus Torvalds 
1470b0316615SAl Viro 	err = bt_procfs_init(&init_net, "sco", &sco_sk_list, NULL);
1471de9b9212SMasatake YAMATO 	if (err < 0) {
1472de9b9212SMasatake YAMATO 		BT_ERR("Failed to create SCO proc file");
1473de9b9212SMasatake YAMATO 		bt_sock_unregister(BTPROTO_SCO);
1474de9b9212SMasatake YAMATO 		goto error;
1475de9b9212SMasatake YAMATO 	}
1476de9b9212SMasatake YAMATO 
14771120e4bfSMarcel Holtmann 	BT_INFO("SCO socket layer initialized");
14781120e4bfSMarcel Holtmann 
1479539c496dSJohan Hedberg 	hci_register_cb(&sco_cb);
1480539c496dSJohan Hedberg 
14811120e4bfSMarcel Holtmann 	if (IS_ERR_OR_NULL(bt_debugfs))
14821120e4bfSMarcel Holtmann 		return 0;
14831120e4bfSMarcel Holtmann 
1484be7c2b99SGustavo Padovan 	sco_debugfs = debugfs_create_file("sco", 0444, bt_debugfs,
1485be7c2b99SGustavo Padovan 					  NULL, &sco_debugfs_fops);
14861da177e4SLinus Torvalds 
14871da177e4SLinus Torvalds 	return 0;
14881da177e4SLinus Torvalds 
14891da177e4SLinus Torvalds error:
14901da177e4SLinus Torvalds 	proto_unregister(&sco_proto);
14911da177e4SLinus Torvalds 	return err;
14921da177e4SLinus Torvalds }
14931da177e4SLinus Torvalds 
sco_exit(void)14940402d9f2SAlexander Aring void sco_exit(void)
14951da177e4SLinus Torvalds {
1496de9b9212SMasatake YAMATO 	bt_procfs_cleanup(&init_net, "sco");
1497de9b9212SMasatake YAMATO 
1498aef7d97cSMarcel Holtmann 	debugfs_remove(sco_debugfs);
14991da177e4SLinus Torvalds 
1500539c496dSJohan Hedberg 	hci_unregister_cb(&sco_cb);
1501539c496dSJohan Hedberg 
15025e9d7f86SDavid Herrmann 	bt_sock_unregister(BTPROTO_SCO);
15031da177e4SLinus Torvalds 
15041da177e4SLinus Torvalds 	proto_unregister(&sco_proto);
15051da177e4SLinus Torvalds }
15061da177e4SLinus Torvalds 
15077cb127d5SMarcel Holtmann module_param(disable_esco, bool, 0644);
15087cb127d5SMarcel Holtmann MODULE_PARM_DESC(disable_esco, "Disable eSCO connection creation");
1509