Blame view

net/bluetooth/sco.c 25.6 KB
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
1
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
6
7
8
9
10
11
12
13
14
     BlueZ - Bluetooth protocol stack for Linux
     Copyright (C) 2000-2001 Qualcomm Incorporated
  
     Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
  
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License version 2 as
     published by the Free Software Foundation;
  
     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
     IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
15
16
17
     CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
     WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
19
20
     ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
     COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21
22
23
24
     SOFTWARE IS DISCLAIMED.
  */
  
  /* Bluetooth SCO sockets. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
  #include <linux/module.h>
aef7d97cc   Marcel Holtmann   Bluetooth: Conver...
26
27
  #include <linux/debugfs.h>
  #include <linux/seq_file.h>
174cd4b1e   Ingo Molnar   sched/headers: Pr...
28
  #include <linux/sched/signal.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
30
31
32
  
  #include <net/bluetooth/bluetooth.h>
  #include <net/bluetooth/hci_core.h>
  #include <net/bluetooth/sco.h>
eb9399220   Rusty Russell   module_param: mak...
33
  static bool disable_esco;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34

90ddc4f04   Eric Dumazet   [NET]: move struc...
35
  static const struct proto_ops sco_sock_ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
37
  
  static struct bt_sock_list sco_sk_list = {
d5fb2962c   Robert P. J. Day   bluetooth: replac...
38
  	.lock = __RW_LOCK_UNLOCKED(sco_sk_list.lock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39
  };
fc8f525a6   Marcel Holtmann   Bluetooth: Move s...
40
41
42
43
44
45
46
47
48
49
50
51
  /* ---- SCO connections ---- */
  struct sco_conn {
  	struct hci_conn	*hcon;
  
  	spinlock_t	lock;
  	struct sock	*sk;
  
  	unsigned int    mtu;
  };
  
  #define sco_conn_lock(c)	spin_lock(&c->lock);
  #define sco_conn_unlock(c)	spin_unlock(&c->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52
53
  static void sco_sock_close(struct sock *sk);
  static void sco_sock_kill(struct sock *sk);
2a0dccb3d   Marcel Holtmann   Bluetooth: Move s...
54
55
56
57
58
59
60
61
62
  /* ----- SCO socket info ----- */
  #define sco_pi(sk) ((struct sco_pinfo *) sk)
  
  struct sco_pinfo {
  	struct bt_sock	bt;
  	bdaddr_t	src;
  	bdaddr_t	dst;
  	__u32		flags;
  	__u16		setting;
00398e1d5   Alain Michaud   Bluetooth: Add su...
63
  	__u8		cmsg_mask;
2a0dccb3d   Marcel Holtmann   Bluetooth: Move s...
64
65
  	struct sco_conn	*conn;
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
  /* ---- SCO timers ---- */
068d69e5b   Marcel Holtmann   Bluetooth: Move S...
67
68
  #define SCO_CONN_TIMEOUT	(HZ * 40)
  #define SCO_DISCONN_TIMEOUT	(HZ * 2)
e99e88a9d   Kees Cook   treewide: setup_t...
69
  static void sco_sock_timeout(struct timer_list *t)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
  {
e99e88a9d   Kees Cook   treewide: setup_t...
71
  	struct sock *sk = from_timer(sk, t, sk_timer);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
  
  	BT_DBG("sock %p state %d", sk, sk->sk_state);
  
  	bh_lock_sock(sk);
  	sk->sk_err = ETIMEDOUT;
  	sk->sk_state_change(sk);
  	bh_unlock_sock(sk);
  
  	sco_sock_kill(sk);
  	sock_put(sk);
  }
  
  static void sco_sock_set_timer(struct sock *sk, long timeout)
  {
  	BT_DBG("sock %p state %d timeout %ld", sk, sk->sk_state, timeout);
  	sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout);
  }
  
  static void sco_sock_clear_timer(struct sock *sk)
  {
  	BT_DBG("sock %p state %d", sk, sk->sk_state);
  	sk_stop_timer(sk, &sk->sk_timer);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
  /* ---- SCO connections ---- */
519e42b38   Lukasz Rymanowski   Bluetooth: Remove...
96
  static struct sco_conn *sco_conn_add(struct hci_conn *hcon)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97
98
  {
  	struct hci_dev *hdev = hcon->hdev;
25ea6db04   Marcel Holtmann   [Bluetooth] Remai...
99
  	struct sco_conn *conn = hcon->sco_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100

519e42b38   Lukasz Rymanowski   Bluetooth: Remove...
101
  	if (conn)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102
  		return conn;
c10cc5a9d   Claudio Takahasi   Bluetooth: Use GF...
103
  	conn = kzalloc(sizeof(struct sco_conn), GFP_KERNEL);
25ea6db04   Marcel Holtmann   [Bluetooth] Remai...
104
  	if (!conn)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105
  		return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
106
107
108
109
110
  
  	spin_lock_init(&conn->lock);
  
  	hcon->sco_data = conn;
  	conn->hcon = hcon;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
112
113
114
115
116
  	if (hdev->sco_mtu > 0)
  		conn->mtu = hdev->sco_mtu;
  	else
  		conn->mtu = 60;
  
  	BT_DBG("hcon %p conn %p", hcon, conn);
25ea6db04   Marcel Holtmann   [Bluetooth] Remai...
117

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
118
119
  	return conn;
  }
e03ab5199   Marcel Holtmann   Bluetooth: Remove...
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
  /* Delete channel.
   * Must be called on the locked socket. */
  static void sco_chan_del(struct sock *sk, int err)
  {
  	struct sco_conn *conn;
  
  	conn = sco_pi(sk)->conn;
  
  	BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
  
  	if (conn) {
  		sco_conn_lock(conn);
  		conn->sk = NULL;
  		sco_pi(sk)->conn = NULL;
  		sco_conn_unlock(conn);
  
  		if (conn->hcon)
  			hci_conn_drop(conn->hcon);
  	}
  
  	sk->sk_state = BT_CLOSED;
  	sk->sk_err   = err;
  	sk->sk_state_change(sk);
  
  	sock_set_flag(sk, SOCK_ZAPPED);
  }
df945360c   Nicholas Krause   Bluetooth: Make t...
146
  static void sco_conn_del(struct hci_conn *hcon, int err)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147
  {
735cbc478   Andrei Emeltchenko   Bluetooth: clean ...
148
  	struct sco_conn *conn = hcon->sco_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
149
  	struct sock *sk;
735cbc478   Andrei Emeltchenko   Bluetooth: clean ...
150
  	if (!conn)
df945360c   Nicholas Krause   Bluetooth: Make t...
151
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
152
153
154
155
  
  	BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
  
  	/* Kill socket */
eb5a4de80   Marcel Holtmann   Bluetooth: Remove...
156
157
158
  	sco_conn_lock(conn);
  	sk = conn->sk;
  	sco_conn_unlock(conn);
735cbc478   Andrei Emeltchenko   Bluetooth: clean ...
159
  	if (sk) {
75e34f5cf   Kuba Pawlak   Bluetooth: Fix cr...
160
  		sock_hold(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
161
162
163
164
165
  		bh_lock_sock(sk);
  		sco_sock_clear_timer(sk);
  		sco_chan_del(sk, err);
  		bh_unlock_sock(sk);
  		sco_sock_kill(sk);
75e34f5cf   Kuba Pawlak   Bluetooth: Fix cr...
166
  		sock_put(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
167
168
169
170
  	}
  
  	hcon->sco_data = NULL;
  	kfree(conn);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
171
  }
c4297e8f7   Marcel Holtmann   Bluetooth: Fix so...
172
173
  static void __sco_chan_add(struct sco_conn *conn, struct sock *sk,
  			   struct sock *parent)
015b01cbc   Marcel Holtmann   Bluetooth: Remove...
174
175
176
177
178
179
180
  {
  	BT_DBG("conn %p", conn);
  
  	sco_pi(sk)->conn = conn;
  	conn->sk = sk;
  
  	if (parent)
c4f5627f7   Matthias Kaehlcke   Bluetooth: Fix lo...
181
  		bt_accept_enqueue(parent, sk, true);
015b01cbc   Marcel Holtmann   Bluetooth: Remove...
182
  }
6039aa73a   Gustavo Padovan   Bluetooth: Remove...
183
184
  static int sco_chan_add(struct sco_conn *conn, struct sock *sk,
  			struct sock *parent)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185
186
187
188
  {
  	int err = 0;
  
  	sco_conn_lock(conn);
b9dbdbc1f   Gustavo F. Padovan   Bluetooth: Trivia...
189
  	if (conn->sk)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190
  		err = -EBUSY;
b9dbdbc1f   Gustavo F. Padovan   Bluetooth: Trivia...
191
  	else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192
  		__sco_chan_add(conn, sk, parent);
b9dbdbc1f   Gustavo F. Padovan   Bluetooth: Trivia...
193

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194
195
196
197
198
199
  	sco_conn_unlock(conn);
  	return err;
  }
  
  static int sco_connect(struct sock *sk)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
200
201
202
  	struct sco_conn *conn;
  	struct hci_conn *hcon;
  	struct hci_dev  *hdev;
b6a0dc822   Marcel Holtmann   [Bluetooth] Add s...
203
  	int err, type;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
204

eea963641   Marcel Holtmann   Bluetooth: Store ...
205
  	BT_DBG("%pMR -> %pMR", &sco_pi(sk)->src, &sco_pi(sk)->dst);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
206

39385cb5f   Johan Hedberg   Bluetooth: Fix us...
207
  	hdev = hci_get_route(&sco_pi(sk)->dst, &sco_pi(sk)->src, BDADDR_BREDR);
735cbc478   Andrei Emeltchenko   Bluetooth: clean ...
208
  	if (!hdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
209
  		return -EHOSTUNREACH;
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
210
  	hci_dev_lock(hdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211

7cb127d5b   Marcel Holtmann   [Bluetooth] Add o...
212
213
214
215
  	if (lmp_esco_capable(hdev) && !disable_esco)
  		type = ESCO_LINK;
  	else
  		type = SCO_LINK;
b6a0dc822   Marcel Holtmann   [Bluetooth] Add s...
216

79dc0087c   Frédéric Dalleau   Bluetooth: Preven...
217
218
219
220
221
  	if (sco_pi(sk)->setting == BT_VOICE_TRANSPARENT &&
  	    (!lmp_transp_capable(hdev) || !lmp_esco_capable(hdev))) {
  		err = -EOPNOTSUPP;
  		goto done;
  	}
eea963641   Marcel Holtmann   Bluetooth: Store ...
222
  	hcon = hci_connect_sco(hdev, type, &sco_pi(sk)->dst,
041987cff   Marcel Holtmann   Bluetooth: Use SC...
223
  			       sco_pi(sk)->setting);
30e762721   Ville Tervo   Bluetooth: Use ER...
224
225
  	if (IS_ERR(hcon)) {
  		err = PTR_ERR(hcon);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
226
  		goto done;
30e762721   Ville Tervo   Bluetooth: Use ER...
227
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
228

519e42b38   Lukasz Rymanowski   Bluetooth: Remove...
229
  	conn = sco_conn_add(hcon);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230
  	if (!conn) {
76a68ba0a   David Herrmann   Bluetooth: rename...
231
  		hci_conn_drop(hcon);
30e762721   Ville Tervo   Bluetooth: Use ER...
232
  		err = -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
233
234
235
236
  		goto done;
  	}
  
  	/* Update source addr of the socket */
eea963641   Marcel Holtmann   Bluetooth: Store ...
237
  	bacpy(&sco_pi(sk)->src, &hcon->src);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
239
240
241
242
243
244
245
246
247
248
249
  
  	err = sco_chan_add(conn, sk, NULL);
  	if (err)
  		goto done;
  
  	if (hcon->state == BT_CONNECTED) {
  		sco_sock_clear_timer(sk);
  		sk->sk_state = BT_CONNECTED;
  	} else {
  		sk->sk_state = BT_CONNECT;
  		sco_sock_set_timer(sk, sk->sk_sndtimeo);
  	}
b6a0dc822   Marcel Holtmann   [Bluetooth] Add s...
250

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
251
  done:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
252
  	hci_dev_unlock(hdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253
254
255
  	hci_dev_put(hdev);
  	return err;
  }
6039aa73a   Gustavo Padovan   Bluetooth: Remove...
256
  static int sco_send_frame(struct sock *sk, struct msghdr *msg, int len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
257
258
259
  {
  	struct sco_conn *conn = sco_pi(sk)->conn;
  	struct sk_buff *skb;
088ce088e   Mikel Astiz   Bluetooth: Remove...
260
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
261
262
263
264
265
266
  
  	/* Check outgoing MTU */
  	if (len > conn->mtu)
  		return -EINVAL;
  
  	BT_DBG("sk %p len %d", sk, len);
088ce088e   Mikel Astiz   Bluetooth: Remove...
267
  	skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err);
b9dbdbc1f   Gustavo F. Padovan   Bluetooth: Trivia...
268
  	if (!skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269
  		return err;
6ce8e9ce5   Al Viro   new helper: memcp...
270
  	if (memcpy_from_msg(skb_put(skb, len), msg, len)) {
b9dbdbc1f   Gustavo F. Padovan   Bluetooth: Trivia...
271
272
  		kfree_skb(skb);
  		return -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
273
  	}
0d861d8b8   Gustavo F. Padovan   Bluetooth: Make h...
274
  	hci_send_sco(conn->hcon, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
275

088ce088e   Mikel Astiz   Bluetooth: Remove...
276
  	return len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
277
  }
6039aa73a   Gustavo Padovan   Bluetooth: Remove...
278
  static void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279
  {
eb5a4de80   Marcel Holtmann   Bluetooth: Remove...
280
281
282
283
284
  	struct sock *sk;
  
  	sco_conn_lock(conn);
  	sk = conn->sk;
  	sco_conn_unlock(conn);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
285
286
287
288
289
290
291
292
293
294
295
296
297
298
  
  	if (!sk)
  		goto drop;
  
  	BT_DBG("sk %p len %d", sk, skb->len);
  
  	if (sk->sk_state != BT_CONNECTED)
  		goto drop;
  
  	if (!sock_queue_rcv_skb(sk, skb))
  		return;
  
  drop:
  	kfree_skb(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
299
300
301
  }
  
  /* -------- Socket interface ---------- */
fb3340594   Marcel Holtmann   Bluetooth: Restri...
302
  static struct sock *__sco_get_sock_listen_by_addr(bdaddr_t *ba)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
303
  {
fb3340594   Marcel Holtmann   Bluetooth: Restri...
304
  	struct sock *sk;
b67bfe0d4   Sasha Levin   hlist: drop the n...
305
  	sk_for_each(sk, &sco_sk_list.head) {
fb3340594   Marcel Holtmann   Bluetooth: Restri...
306
307
  		if (sk->sk_state != BT_LISTEN)
  			continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
308

eea963641   Marcel Holtmann   Bluetooth: Store ...
309
  		if (!bacmp(&sco_pi(sk)->src, ba))
fb3340594   Marcel Holtmann   Bluetooth: Restri...
310
311
312
313
  			return sk;
  	}
  
  	return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
314
315
316
317
318
319
320
321
  }
  
  /* Find socket listening on source bdaddr.
   * Returns closest match.
   */
  static struct sock *sco_get_sock_listen(bdaddr_t *src)
  {
  	struct sock *sk = NULL, *sk1 = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
322
323
  
  	read_lock(&sco_sk_list.lock);
b67bfe0d4   Sasha Levin   hlist: drop the n...
324
  	sk_for_each(sk, &sco_sk_list.head) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325
326
327
328
  		if (sk->sk_state != BT_LISTEN)
  			continue;
  
  		/* Exact match. */
eea963641   Marcel Holtmann   Bluetooth: Store ...
329
  		if (!bacmp(&sco_pi(sk)->src, src))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
330
331
332
  			break;
  
  		/* Closest match */
eea963641   Marcel Holtmann   Bluetooth: Store ...
333
  		if (!bacmp(&sco_pi(sk)->src, BDADDR_ANY))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
334
335
336
337
  			sk1 = sk;
  	}
  
  	read_unlock(&sco_sk_list.lock);
b67bfe0d4   Sasha Levin   hlist: drop the n...
338
  	return sk ? sk : sk1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
  }
  
  static void sco_sock_destruct(struct sock *sk)
  {
  	BT_DBG("sk %p", sk);
  
  	skb_queue_purge(&sk->sk_receive_queue);
  	skb_queue_purge(&sk->sk_write_queue);
  }
  
  static void sco_sock_cleanup_listen(struct sock *parent)
  {
  	struct sock *sk;
  
  	BT_DBG("parent %p", parent);
  
  	/* Close not yet accepted channels */
  	while ((sk = bt_accept_dequeue(parent, NULL))) {
  		sco_sock_close(sk);
  		sco_sock_kill(sk);
  	}
  
  	parent->sk_state  = BT_CLOSED;
  	sock_set_flag(parent, SOCK_ZAPPED);
  }
  
  /* Kill socket (only if zapped and orphan)
   * Must be called on unlocked socket.
   */
  static void sco_sock_kill(struct sock *sk)
  {
4e1a720d0   Sudip Mukherjee   Bluetooth: avoid ...
370
371
  	if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket ||
  	    sock_flag(sk, SOCK_DEAD))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
372
373
374
375
376
377
378
379
380
  		return;
  
  	BT_DBG("sk %p state %d", sk, sk->sk_state);
  
  	/* Kill poor orphan */
  	bt_sock_unlink(&sco_sk_list, sk);
  	sock_set_flag(sk, SOCK_DEAD);
  	sock_put(sk);
  }
fd0b3ff70   Marcel Holtmann   Bluetooth: Add pr...
381
  static void __sco_sock_close(struct sock *sk)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
382
  {
fd0b3ff70   Marcel Holtmann   Bluetooth: Add pr...
383
  	BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
384
385
386
387
388
389
390
391
  
  	switch (sk->sk_state) {
  	case BT_LISTEN:
  		sco_sock_cleanup_listen(sk);
  		break;
  
  	case BT_CONNECTED:
  	case BT_CONFIG:
b7e98b510   Gustavo Padovan   Bluetooth: Check ...
392
  		if (sco_pi(sk)->conn->hcon) {
4a77708b0   Luiz Augusto von Dentz   Bluetooth: fix sh...
393
394
  			sk->sk_state = BT_DISCONN;
  			sco_sock_set_timer(sk, SCO_DISCONN_TIMEOUT);
435c51336   Kuba Pawlak   Bluetooth: Fix lo...
395
  			sco_conn_lock(sco_pi(sk)->conn);
76a68ba0a   David Herrmann   Bluetooth: rename...
396
  			hci_conn_drop(sco_pi(sk)->conn->hcon);
4a77708b0   Luiz Augusto von Dentz   Bluetooth: fix sh...
397
  			sco_pi(sk)->conn->hcon = NULL;
435c51336   Kuba Pawlak   Bluetooth: Fix lo...
398
  			sco_conn_unlock(sco_pi(sk)->conn);
4a77708b0   Luiz Augusto von Dentz   Bluetooth: fix sh...
399
400
401
  		} else
  			sco_chan_del(sk, ECONNRESET);
  		break;
eb20ff9c9   Vinicius Costa Gomes   Bluetooth: Fix no...
402
  	case BT_CONNECT2:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403
404
405
406
407
408
409
410
  	case BT_CONNECT:
  	case BT_DISCONN:
  		sco_chan_del(sk, ECONNRESET);
  		break;
  
  	default:
  		sock_set_flag(sk, SOCK_ZAPPED);
  		break;
3ff50b799   Stephen Hemminger   [NET]: cleanup ex...
411
  	}
fd0b3ff70   Marcel Holtmann   Bluetooth: Add pr...
412
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
413

fd0b3ff70   Marcel Holtmann   Bluetooth: Add pr...
414
415
416
417
418
419
  /* Must be called on unlocked socket. */
  static void sco_sock_close(struct sock *sk)
  {
  	sco_sock_clear_timer(sk);
  	lock_sock(sk);
  	__sco_sock_close(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
420
  	release_sock(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
421
422
  	sco_sock_kill(sk);
  }
00398e1d5   Alain Michaud   Bluetooth: Add su...
423
424
425
426
427
428
429
430
  static void sco_skb_put_cmsg(struct sk_buff *skb, struct msghdr *msg,
  			     struct sock *sk)
  {
  	if (sco_pi(sk)->cmsg_mask & SCO_CMSG_PKT_STATUS)
  		put_cmsg(msg, SOL_BLUETOOTH, BT_SCM_PKT_STATUS,
  			 sizeof(bt_cb(skb)->sco.pkt_status),
  			 &bt_cb(skb)->sco.pkt_status);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
431
432
433
  static void sco_sock_init(struct sock *sk, struct sock *parent)
  {
  	BT_DBG("sk %p", sk);
6230c9b4f   Paul Moore   bluetooth: Proper...
434
  	if (parent) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
435
  		sk->sk_type = parent->sk_type;
20714bfef   Frédéric Dalleau   Bluetooth: Implem...
436
  		bt_sk(sk)->flags = bt_sk(parent)->flags;
6230c9b4f   Paul Moore   bluetooth: Proper...
437
  		security_sk_clone(parent, sk);
00398e1d5   Alain Michaud   Bluetooth: Add su...
438
439
  	} else {
  		bt_sk(sk)->skb_put_cmsg = sco_skb_put_cmsg;
6230c9b4f   Paul Moore   bluetooth: Proper...
440
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
441
442
443
444
445
446
447
  }
  
  static struct proto sco_proto = {
  	.name		= "SCO",
  	.owner		= THIS_MODULE,
  	.obj_size	= sizeof(struct sco_pinfo)
  };
c4297e8f7   Marcel Holtmann   Bluetooth: Fix so...
448
449
  static struct sock *sco_sock_alloc(struct net *net, struct socket *sock,
  				   int proto, gfp_t prio, int kern)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
450
451
  {
  	struct sock *sk;
11aa9c28b   Eric W. Biederman   net: Pass kern fr...
452
  	sk = sk_alloc(net, PF_BLUETOOTH, prio, &sco_proto, kern);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
453
454
455
456
457
458
459
460
461
462
463
464
465
  	if (!sk)
  		return NULL;
  
  	sock_init_data(sock, sk);
  	INIT_LIST_HEAD(&bt_sk(sk)->accept_q);
  
  	sk->sk_destruct = sco_sock_destruct;
  	sk->sk_sndtimeo = SCO_CONN_TIMEOUT;
  
  	sock_reset_flag(sk, SOCK_ZAPPED);
  
  	sk->sk_protocol = proto;
  	sk->sk_state    = BT_OPEN;
ad10b1a48   Frédéric Dalleau   Bluetooth: Add Bl...
466
  	sco_pi(sk)->setting = BT_VOICE_CVSD_16BIT;
e99e88a9d   Kees Cook   treewide: setup_t...
467
  	timer_setup(&sk->sk_timer, sco_sock_timeout, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
468
469
470
471
  
  	bt_sock_link(&sco_sk_list, sk);
  	return sk;
  }
3f378b684   Eric Paris   net: pass kern to...
472
473
  static int sco_sock_create(struct net *net, struct socket *sock, int protocol,
  			   int kern)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474
475
476
477
478
479
480
481
482
483
484
  {
  	struct sock *sk;
  
  	BT_DBG("sock %p", sock);
  
  	sock->state = SS_UNCONNECTED;
  
  	if (sock->type != SOCK_SEQPACKET)
  		return -ESOCKTNOSUPPORT;
  
  	sock->ops = &sco_sock_ops;
11aa9c28b   Eric W. Biederman   net: Pass kern fr...
485
  	sk = sco_sock_alloc(net, sock, protocol, GFP_ATOMIC, kern);
74da626a1   Marcel Holtmann   [Bluetooth] Add l...
486
  	if (!sk)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
487
488
489
490
491
  		return -ENOMEM;
  
  	sco_sock_init(sk, NULL);
  	return 0;
  }
c4297e8f7   Marcel Holtmann   Bluetooth: Fix so...
492
493
  static int sco_sock_bind(struct socket *sock, struct sockaddr *addr,
  			 int addr_len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
494
495
496
  {
  	struct sockaddr_sco *sa = (struct sockaddr_sco *) addr;
  	struct sock *sk = sock->sk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
497
  	int err = 0;
d2ecfa765   Mateusz Jurczyk   Bluetooth: Add so...
498
499
  	if (!addr || addr_len < sizeof(struct sockaddr_sco) ||
  	    addr->sa_family != AF_BLUETOOTH)
5233252fc   David S. Miller   bluetooth: Valida...
500
  		return -EINVAL;
bd7d46ddc   Tetsuo Handa   Bluetooth: Check ...
501
  	BT_DBG("sk %p %pMR", sk, &sa->sco_bdaddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
502
503
504
505
506
507
  	lock_sock(sk);
  
  	if (sk->sk_state != BT_OPEN) {
  		err = -EBADFD;
  		goto done;
  	}
8ed21f7ee   Marcel Holtmann   Bluetooth: Don't ...
508
509
510
  	if (sk->sk_type != SOCK_SEQPACKET) {
  		err = -EINVAL;
  		goto done;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
511
  	}
eea963641   Marcel Holtmann   Bluetooth: Store ...
512
  	bacpy(&sco_pi(sk)->src, &sa->sco_bdaddr);
8ed21f7ee   Marcel Holtmann   Bluetooth: Don't ...
513
514
  
  	sk->sk_state = BT_BOUND;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
515
516
517
518
519
520
521
522
523
524
  
  done:
  	release_sock(sk);
  	return err;
  }
  
  static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags)
  {
  	struct sockaddr_sco *sa = (struct sockaddr_sco *) addr;
  	struct sock *sk = sock->sk;
92f185c89   Claudio Takahasi   Bluetooth: Minor ...
525
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
526
527
  
  	BT_DBG("sk %p", sk);
6503d9616   Changli Gao   net: check the le...
528
529
  	if (alen < sizeof(struct sockaddr_sco) ||
  	    addr->sa_family != AF_BLUETOOTH)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
530
531
532
533
534
535
536
537
538
539
540
  		return -EINVAL;
  
  	if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND)
  		return -EBADFD;
  
  	if (sk->sk_type != SOCK_SEQPACKET)
  		return -EINVAL;
  
  	lock_sock(sk);
  
  	/* Set destination address and psm */
eea963641   Marcel Holtmann   Bluetooth: Store ...
541
  	bacpy(&sco_pi(sk)->dst, &sa->sco_bdaddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
542

735cbc478   Andrei Emeltchenko   Bluetooth: clean ...
543
544
  	err = sco_connect(sk);
  	if (err)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
545
  		goto done;
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
546
  	err = bt_sock_wait_state(sk, BT_CONNECTED,
be7c2b99e   Gustavo Padovan   Bluetooth: Fix co...
547
  				 sock_sndtimeo(sk, flags & O_NONBLOCK));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
548
549
550
551
552
553
554
555
556
  
  done:
  	release_sock(sk);
  	return err;
  }
  
  static int sco_sock_listen(struct socket *sock, int backlog)
  {
  	struct sock *sk = sock->sk;
eea963641   Marcel Holtmann   Bluetooth: Store ...
557
  	bdaddr_t *src = &sco_pi(sk)->src;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
558
559
560
561
562
  	int err = 0;
  
  	BT_DBG("sk %p backlog %d", sk, backlog);
  
  	lock_sock(sk);
7d5d775a5   Marcel Holtmann   Bluetooth: Split ...
563
  	if (sk->sk_state != BT_BOUND) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
564
565
566
  		err = -EBADFD;
  		goto done;
  	}
7d5d775a5   Marcel Holtmann   Bluetooth: Split ...
567
568
569
570
  	if (sk->sk_type != SOCK_SEQPACKET) {
  		err = -EINVAL;
  		goto done;
  	}
fb3340594   Marcel Holtmann   Bluetooth: Restri...
571
572
573
574
575
576
  	write_lock(&sco_sk_list.lock);
  
  	if (__sco_get_sock_listen_by_addr(src)) {
  		err = -EADDRINUSE;
  		goto unlock;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
577
578
  	sk->sk_max_ack_backlog = backlog;
  	sk->sk_ack_backlog = 0;
fb3340594   Marcel Holtmann   Bluetooth: Restri...
579

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580
  	sk->sk_state = BT_LISTEN;
fb3340594   Marcel Holtmann   Bluetooth: Restri...
581
582
  unlock:
  	write_unlock(&sco_sk_list.lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
583
584
585
586
  done:
  	release_sock(sk);
  	return err;
  }
c4297e8f7   Marcel Holtmann   Bluetooth: Fix so...
587
  static int sco_sock_accept(struct socket *sock, struct socket *newsock,
cdfbabfb2   David Howells   net: Work around ...
588
  			   int flags, bool kern)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
589
  {
dfb2fae7c   Peter Hurley   Bluetooth: Fix ne...
590
  	DEFINE_WAIT_FUNC(wait, woken_wake_function);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
591
592
593
594
595
  	struct sock *sk = sock->sk, *ch;
  	long timeo;
  	int err = 0;
  
  	lock_sock(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
596
597
598
599
600
  	timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
  
  	BT_DBG("sk %p timeo %ld", sk, timeo);
  
  	/* Wait for an incoming connection. (wake-one). */
aa3951451   Eric Dumazet   net: sk_sleep() h...
601
  	add_wait_queue_exclusive(sk_sleep(sk), &wait);
552b0d3cb   Peter Hurley   Bluetooth: sco: F...
602
  	while (1) {
552b0d3cb   Peter Hurley   Bluetooth: sco: F...
603
604
  		if (sk->sk_state != BT_LISTEN) {
  			err = -EBADFD;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
605
606
  			break;
  		}
552b0d3cb   Peter Hurley   Bluetooth: sco: F...
607
608
609
  		ch = bt_accept_dequeue(sk, newsock);
  		if (ch)
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
610

552b0d3cb   Peter Hurley   Bluetooth: sco: F...
611
612
  		if (!timeo) {
  			err = -EAGAIN;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
613
614
615
616
617
618
619
  			break;
  		}
  
  		if (signal_pending(current)) {
  			err = sock_intr_errno(timeo);
  			break;
  		}
552b0d3cb   Peter Hurley   Bluetooth: sco: F...
620
621
  
  		release_sock(sk);
dfb2fae7c   Peter Hurley   Bluetooth: Fix ne...
622
623
  
  		timeo = wait_woken(&wait, TASK_INTERRUPTIBLE, timeo);
552b0d3cb   Peter Hurley   Bluetooth: sco: F...
624
  		lock_sock(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
625
  	}
aa3951451   Eric Dumazet   net: sk_sleep() h...
626
  	remove_wait_queue(sk_sleep(sk), &wait);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
627
628
629
630
631
632
633
634
635
636
637
638
  
  	if (err)
  		goto done;
  
  	newsock->state = SS_CONNECTED;
  
  	BT_DBG("new socket %p", ch);
  
  done:
  	release_sock(sk);
  	return err;
  }
c4297e8f7   Marcel Holtmann   Bluetooth: Fix so...
639
  static int sco_sock_getname(struct socket *sock, struct sockaddr *addr,
9b2c45d47   Denys Vlasenko   net: make getname...
640
  			    int peer)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
641
642
643
644
645
646
647
  {
  	struct sockaddr_sco *sa = (struct sockaddr_sco *) addr;
  	struct sock *sk = sock->sk;
  
  	BT_DBG("sock %p, sk %p", sock, sk);
  
  	addr->sa_family = AF_BLUETOOTH;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
648
649
  
  	if (peer)
eea963641   Marcel Holtmann   Bluetooth: Store ...
650
  		bacpy(&sa->sco_bdaddr, &sco_pi(sk)->dst);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
651
  	else
eea963641   Marcel Holtmann   Bluetooth: Store ...
652
  		bacpy(&sa->sco_bdaddr, &sco_pi(sk)->src);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
653

9b2c45d47   Denys Vlasenko   net: make getname...
654
  	return sizeof(struct sockaddr_sco);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
655
  }
1b7841404   Ying Xue   net: Remove iocb ...
656
657
  static int sco_sock_sendmsg(struct socket *sock, struct msghdr *msg,
  			    size_t len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
658
659
  {
  	struct sock *sk = sock->sk;
b9dbdbc1f   Gustavo F. Padovan   Bluetooth: Trivia...
660
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
661
662
  
  	BT_DBG("sock %p, sk %p", sock, sk);
c1cbe4b7a   Benjamin LaHaise   [NET]: Avoid atom...
663
664
665
  	err = sock_error(sk);
  	if (err)
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
666
667
668
669
670
671
672
673
674
675
676
677
678
679
  
  	if (msg->msg_flags & MSG_OOB)
  		return -EOPNOTSUPP;
  
  	lock_sock(sk);
  
  	if (sk->sk_state == BT_CONNECTED)
  		err = sco_send_frame(sk, msg, len);
  	else
  		err = -ENOTCONN;
  
  	release_sock(sk);
  	return err;
  }
2f69a82ac   Frédéric Dalleau   Bluetooth: Use vo...
680
  static void sco_conn_defer_accept(struct hci_conn *conn, u16 setting)
fa5513be2   Frédéric Dalleau   Bluetooth: Move a...
681
682
683
684
685
686
687
688
689
690
691
  {
  	struct hci_dev *hdev = conn->hdev;
  
  	BT_DBG("conn %p", conn);
  
  	conn->state = BT_CONFIG;
  
  	if (!lmp_esco_capable(hdev)) {
  		struct hci_cp_accept_conn_req cp;
  
  		bacpy(&cp.bdaddr, &conn->dst);
33f240482   Frédéric Dalleau   Bluetooth: Remove...
692
  		cp.role = 0x00; /* Ignored */
fa5513be2   Frédéric Dalleau   Bluetooth: Move a...
693
694
695
696
697
698
699
  
  		hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp);
  	} else {
  		struct hci_cp_accept_sync_conn_req cp;
  
  		bacpy(&cp.bdaddr, &conn->dst);
  		cp.pkt_type = cpu_to_le16(conn->pkt_type);
dcf4adbfd   Joe Perches   Bluetooth: Conver...
700
701
  		cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
  		cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
2f69a82ac   Frédéric Dalleau   Bluetooth: Use vo...
702
703
704
705
706
  		cp.content_format = cpu_to_le16(setting);
  
  		switch (setting & SCO_AIRMODE_MASK) {
  		case SCO_AIRMODE_TRANSP:
  			if (conn->pkt_type & ESCO_2EV3)
dcf4adbfd   Joe Perches   Bluetooth: Conver...
707
  				cp.max_latency = cpu_to_le16(0x0008);
2f69a82ac   Frédéric Dalleau   Bluetooth: Use vo...
708
  			else
dcf4adbfd   Joe Perches   Bluetooth: Conver...
709
  				cp.max_latency = cpu_to_le16(0x000D);
2f69a82ac   Frédéric Dalleau   Bluetooth: Use vo...
710
711
712
  			cp.retrans_effort = 0x02;
  			break;
  		case SCO_AIRMODE_CVSD:
dcf4adbfd   Joe Perches   Bluetooth: Conver...
713
  			cp.max_latency = cpu_to_le16(0xffff);
2f69a82ac   Frédéric Dalleau   Bluetooth: Use vo...
714
715
716
  			cp.retrans_effort = 0xff;
  			break;
  		}
fa5513be2   Frédéric Dalleau   Bluetooth: Move a...
717
718
719
720
721
  
  		hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
  			     sizeof(cp), &cp);
  	}
  }
1b7841404   Ying Xue   net: Remove iocb ...
722
723
  static int sco_sock_recvmsg(struct socket *sock, struct msghdr *msg,
  			    size_t len, int flags)
20714bfef   Frédéric Dalleau   Bluetooth: Implem...
724
725
726
727
728
729
730
731
  {
  	struct sock *sk = sock->sk;
  	struct sco_pinfo *pi = sco_pi(sk);
  
  	lock_sock(sk);
  
  	if (sk->sk_state == BT_CONNECT2 &&
  	    test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
2f69a82ac   Frédéric Dalleau   Bluetooth: Use vo...
732
  		sco_conn_defer_accept(pi->conn->hcon, pi->setting);
20714bfef   Frédéric Dalleau   Bluetooth: Implem...
733
734
735
736
737
738
739
  		sk->sk_state = BT_CONFIG;
  
  		release_sock(sk);
  		return 0;
  	}
  
  	release_sock(sk);
1b7841404   Ying Xue   net: Remove iocb ...
740
  	return bt_sock_recvmsg(sock, msg, len, flags);
20714bfef   Frédéric Dalleau   Bluetooth: Implem...
741
  }
c4297e8f7   Marcel Holtmann   Bluetooth: Fix so...
742
  static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
a7b75c5a8   Christoph Hellwig   net: pass a sockp...
743
  			       sockptr_t optval, unsigned int optlen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
744
745
  {
  	struct sock *sk = sock->sk;
ad10b1a48   Frédéric Dalleau   Bluetooth: Add Bl...
746
747
  	int len, err = 0;
  	struct bt_voice voice;
b96e9c671   Frédéric Dalleau   Bluetooth: Add BT...
748
  	u32 opt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
749
750
751
752
753
754
  
  	BT_DBG("sk %p", sk);
  
  	lock_sock(sk);
  
  	switch (optname) {
b96e9c671   Frédéric Dalleau   Bluetooth: Add BT...
755
756
757
758
759
760
  
  	case BT_DEFER_SETUP:
  		if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
  			err = -EINVAL;
  			break;
  		}
a7b75c5a8   Christoph Hellwig   net: pass a sockp...
761
  		if (copy_from_sockptr(&opt, optval, sizeof(u32))) {
b96e9c671   Frédéric Dalleau   Bluetooth: Add BT...
762
763
764
765
766
767
768
769
770
  			err = -EFAULT;
  			break;
  		}
  
  		if (opt)
  			set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
  		else
  			clear_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
  		break;
ad10b1a48   Frédéric Dalleau   Bluetooth: Add Bl...
771
772
773
774
775
776
777
778
779
780
  	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);
a7b75c5a8   Christoph Hellwig   net: pass a sockp...
781
  		if (copy_from_sockptr(&voice, optval, len)) {
ad10b1a48   Frédéric Dalleau   Bluetooth: Add Bl...
782
783
784
785
786
787
788
789
790
791
792
793
794
  			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;
00398e1d5   Alain Michaud   Bluetooth: Add su...
795
  	case BT_PKT_STATUS:
83a33b248   David S. Miller   bluetooth: sco: F...
796
  		if (copy_from_sockptr(&opt, optval, sizeof(u32))) {
00398e1d5   Alain Michaud   Bluetooth: Add su...
797
798
799
800
801
802
803
804
805
  			err = -EFAULT;
  			break;
  		}
  
  		if (opt)
  			sco_pi(sk)->cmsg_mask |= SCO_CMSG_PKT_STATUS;
  		else
  			sco_pi(sk)->cmsg_mask &= SCO_CMSG_PKT_STATUS;
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
806
807
808
809
810
811
812
813
  	default:
  		err = -ENOPROTOOPT;
  		break;
  	}
  
  	release_sock(sk);
  	return err;
  }
c4297e8f7   Marcel Holtmann   Bluetooth: Fix so...
814
815
  static int sco_sock_getsockopt_old(struct socket *sock, int optname,
  				   char __user *optval, int __user *optlen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
816
817
818
819
  {
  	struct sock *sk = sock->sk;
  	struct sco_options opts;
  	struct sco_conninfo cinfo;
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
820
  	int len, err = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
821
822
823
824
825
826
827
828
829
830
  
  	BT_DBG("sk %p", sk);
  
  	if (get_user(len, optlen))
  		return -EFAULT;
  
  	lock_sock(sk);
  
  	switch (optname) {
  	case SCO_OPTIONS:
9d225d220   Johan Hedberg   Bluetooth: Fix ge...
831
832
833
  		if (sk->sk_state != BT_CONNECTED &&
  		    !(sk->sk_state == BT_CONNECT2 &&
  		      test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
  			err = -ENOTCONN;
  			break;
  		}
  
  		opts.mtu = sco_pi(sk)->conn->mtu;
  
  		BT_DBG("mtu %d", opts.mtu);
  
  		len = min_t(unsigned int, len, sizeof(opts));
  		if (copy_to_user(optval, (char *)&opts, len))
  			err = -EFAULT;
  
  		break;
  
  	case SCO_CONNINFO:
9d225d220   Johan Hedberg   Bluetooth: Fix ge...
849
850
851
  		if (sk->sk_state != BT_CONNECTED &&
  		    !(sk->sk_state == BT_CONNECT2 &&
  		      test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
852
853
854
  			err = -ENOTCONN;
  			break;
  		}
c4c896e14   Vasiliy Kulikov   Bluetooth: sco: f...
855
  		memset(&cinfo, 0, sizeof(cinfo));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
  		cinfo.hci_handle = sco_pi(sk)->conn->hcon->handle;
  		memcpy(cinfo.dev_class, sco_pi(sk)->conn->hcon->dev_class, 3);
  
  		len = min_t(unsigned int, len, sizeof(cinfo));
  		if (copy_to_user(optval, (char *)&cinfo, len))
  			err = -EFAULT;
  
  		break;
  
  	default:
  		err = -ENOPROTOOPT;
  		break;
  	}
  
  	release_sock(sk);
  	return err;
  }
c4297e8f7   Marcel Holtmann   Bluetooth: Fix so...
873
874
  static int sco_sock_getsockopt(struct socket *sock, int level, int optname,
  			       char __user *optval, int __user *optlen)
d58daf42d   Marcel Holtmann   Bluetooth: Prepar...
875
876
877
  {
  	struct sock *sk = sock->sk;
  	int len, err = 0;
ad10b1a48   Frédéric Dalleau   Bluetooth: Add Bl...
878
  	struct bt_voice voice;
eab2404ba   Luiz Augusto von Dentz   Bluetooth: Add BT...
879
  	u32 phys;
00398e1d5   Alain Michaud   Bluetooth: Add su...
880
  	int pkt_status;
d58daf42d   Marcel Holtmann   Bluetooth: Prepar...
881
882
883
884
885
886
887
888
889
890
891
892
  
  	BT_DBG("sk %p", sk);
  
  	if (level == SOL_SCO)
  		return sco_sock_getsockopt_old(sock, optname, optval, optlen);
  
  	if (get_user(len, optlen))
  		return -EFAULT;
  
  	lock_sock(sk);
  
  	switch (optname) {
b96e9c671   Frédéric Dalleau   Bluetooth: Add BT...
893
894
895
896
897
898
899
900
  
  	case BT_DEFER_SETUP:
  		if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
  			err = -EINVAL;
  			break;
  		}
  
  		if (put_user(test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags),
c4297e8f7   Marcel Holtmann   Bluetooth: Fix so...
901
  			     (u32 __user *)optval))
b96e9c671   Frédéric Dalleau   Bluetooth: Add BT...
902
903
904
  			err = -EFAULT;
  
  		break;
ad10b1a48   Frédéric Dalleau   Bluetooth: Add Bl...
905
906
907
908
909
910
911
912
  	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;
eab2404ba   Luiz Augusto von Dentz   Bluetooth: Add BT...
913
  	case BT_PHY:
a2a8b0b4a   Luiz Augusto von Dentz   Bluetooth: Fix cr...
914
  		if (sk->sk_state != BT_CONNECTED) {
eab2404ba   Luiz Augusto von Dentz   Bluetooth: Add BT...
915
916
917
918
919
920
921
922
923
  			err = -ENOTCONN;
  			break;
  		}
  
  		phys = hci_conn_get_phy(sco_pi(sk)->conn->hcon);
  
  		if (put_user(phys, (u32 __user *) optval))
  			err = -EFAULT;
  		break;
00398e1d5   Alain Michaud   Bluetooth: Add su...
924
925
926
927
928
929
  	case BT_PKT_STATUS:
  		pkt_status = (sco_pi(sk)->cmsg_mask & SCO_CMSG_PKT_STATUS);
  
  		if (put_user(pkt_status, (int __user *)optval))
  			err = -EFAULT;
  		break;
0fc1a726f   Joseph Hwang   Bluetooth: sco: n...
930
931
932
933
934
  	case BT_SNDMTU:
  	case BT_RCVMTU:
  		if (put_user(sco_pi(sk)->conn->mtu, (u32 __user *)optval))
  			err = -EFAULT;
  		break;
d58daf42d   Marcel Holtmann   Bluetooth: Prepar...
935
936
937
938
939
940
941
942
  	default:
  		err = -ENOPROTOOPT;
  		break;
  	}
  
  	release_sock(sk);
  	return err;
  }
fd0b3ff70   Marcel Holtmann   Bluetooth: Add pr...
943
944
945
946
947
948
949
950
951
  static int sco_sock_shutdown(struct socket *sock, int how)
  {
  	struct sock *sk = sock->sk;
  	int err = 0;
  
  	BT_DBG("sock %p, sk %p", sock, sk);
  
  	if (!sk)
  		return 0;
1da5537ec   Kuba Pawlak   Bluetooth: Fix lo...
952
  	sock_hold(sk);
fd0b3ff70   Marcel Holtmann   Bluetooth: Add pr...
953
  	lock_sock(sk);
1da5537ec   Kuba Pawlak   Bluetooth: Fix lo...
954

fd0b3ff70   Marcel Holtmann   Bluetooth: Add pr...
955
956
957
958
  	if (!sk->sk_shutdown) {
  		sk->sk_shutdown = SHUTDOWN_MASK;
  		sco_sock_clear_timer(sk);
  		__sco_sock_close(sk);
093facf36   Vladimir Davydov   Bluetooth: never ...
959
960
  		if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime &&
  		    !(current->flags & PF_EXITING))
fd0b3ff70   Marcel Holtmann   Bluetooth: Add pr...
961
  			err = bt_sock_wait_state(sk, BT_CLOSED,
be7c2b99e   Gustavo Padovan   Bluetooth: Fix co...
962
  						 sk->sk_lingertime);
fd0b3ff70   Marcel Holtmann   Bluetooth: Add pr...
963
  	}
1da5537ec   Kuba Pawlak   Bluetooth: Fix lo...
964

fd0b3ff70   Marcel Holtmann   Bluetooth: Add pr...
965
  	release_sock(sk);
1da5537ec   Kuba Pawlak   Bluetooth: Fix lo...
966
  	sock_put(sk);
fd0b3ff70   Marcel Holtmann   Bluetooth: Add pr...
967
968
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
969
970
971
972
973
974
975
976
977
978
979
  static int sco_sock_release(struct socket *sock)
  {
  	struct sock *sk = sock->sk;
  	int err = 0;
  
  	BT_DBG("sock %p, sk %p", sock, sk);
  
  	if (!sk)
  		return 0;
  
  	sco_sock_close(sk);
093facf36   Vladimir Davydov   Bluetooth: never ...
980
981
  	if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime &&
  	    !(current->flags & PF_EXITING)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
982
983
984
985
986
987
988
989
990
  		lock_sock(sk);
  		err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime);
  		release_sock(sk);
  	}
  
  	sock_orphan(sk);
  	sco_sock_kill(sk);
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
991
992
  static void sco_conn_ready(struct sco_conn *conn)
  {
735cbc478   Andrei Emeltchenko   Bluetooth: clean ...
993
994
  	struct sock *parent;
  	struct sock *sk = conn->sk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
995
996
  
  	BT_DBG("conn %p", conn);
735cbc478   Andrei Emeltchenko   Bluetooth: clean ...
997
  	if (sk) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
998
999
1000
1001
1002
1003
  		sco_sock_clear_timer(sk);
  		bh_lock_sock(sk);
  		sk->sk_state = BT_CONNECTED;
  		sk->sk_state_change(sk);
  		bh_unlock_sock(sk);
  	} else {
405280887   Andre Guedes   Bluetooth: Reduce...
1004
  		sco_conn_lock(conn);
2c501cdd6   Kuba Pawlak   Bluetooth: Fix cr...
1005
1006
1007
1008
  		if (!conn->hcon) {
  			sco_conn_unlock(conn);
  			return;
  		}
041987cff   Marcel Holtmann   Bluetooth: Use SC...
1009
  		parent = sco_get_sock_listen(&conn->hcon->src);
405280887   Andre Guedes   Bluetooth: Reduce...
1010
1011
1012
1013
  		if (!parent) {
  			sco_conn_unlock(conn);
  			return;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1014
1015
  
  		bh_lock_sock(parent);
b9dbdbc1f   Gustavo F. Padovan   Bluetooth: Trivia...
1016
  		sk = sco_sock_alloc(sock_net(parent), NULL,
11aa9c28b   Eric W. Biederman   net: Pass kern fr...
1017
  				    BTPROTO_SCO, GFP_ATOMIC, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1018
1019
  		if (!sk) {
  			bh_unlock_sock(parent);
405280887   Andre Guedes   Bluetooth: Reduce...
1020
1021
  			sco_conn_unlock(conn);
  			return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1022
1023
1024
  		}
  
  		sco_sock_init(sk, parent);
eea963641   Marcel Holtmann   Bluetooth: Store ...
1025
1026
  		bacpy(&sco_pi(sk)->src, &conn->hcon->src);
  		bacpy(&sco_pi(sk)->dst, &conn->hcon->dst);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1027
1028
1029
  
  		hci_conn_hold(conn->hcon);
  		__sco_chan_add(conn, sk, parent);
20714bfef   Frédéric Dalleau   Bluetooth: Implem...
1030
1031
1032
1033
  		if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags))
  			sk->sk_state = BT_CONNECT2;
  		else
  			sk->sk_state = BT_CONNECTED;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1034
1035
  
  		/* Wake up parent */
676d23690   David S. Miller   net: Fix use afte...
1036
  		parent->sk_data_ready(parent);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1037
1038
  
  		bh_unlock_sock(parent);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1039

405280887   Andre Guedes   Bluetooth: Reduce...
1040
1041
  		sco_conn_unlock(conn);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1042
1043
1044
  }
  
  /* ----- SCO interface with lower layer (HCI) ----- */
20714bfef   Frédéric Dalleau   Bluetooth: Implem...
1045
  int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1046
  {
fc5fef615   Gustavo Padovan   Bluetooth: Remove...
1047
  	struct sock *sk;
71aeeaa1f   Marcel Holtmann   Bluetooth: Reject...
1048
  	int lm = 0;
6ed93dc64   Andrei Emeltchenko   Bluetooth: Use %p...
1049
  	BT_DBG("hdev %s, bdaddr %pMR", hdev->name, bdaddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1050

71aeeaa1f   Marcel Holtmann   Bluetooth: Reject...
1051
1052
  	/* Find listening sockets */
  	read_lock(&sco_sk_list.lock);
b67bfe0d4   Sasha Levin   hlist: drop the n...
1053
  	sk_for_each(sk, &sco_sk_list.head) {
71aeeaa1f   Marcel Holtmann   Bluetooth: Reject...
1054
1055
  		if (sk->sk_state != BT_LISTEN)
  			continue;
eea963641   Marcel Holtmann   Bluetooth: Store ...
1056
1057
  		if (!bacmp(&sco_pi(sk)->src, &hdev->bdaddr) ||
  		    !bacmp(&sco_pi(sk)->src, BDADDR_ANY)) {
71aeeaa1f   Marcel Holtmann   Bluetooth: Reject...
1058
  			lm |= HCI_LM_ACCEPT;
20714bfef   Frédéric Dalleau   Bluetooth: Implem...
1059
1060
1061
  
  			if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags))
  				*flags |= HCI_PROTO_DEFER;
71aeeaa1f   Marcel Holtmann   Bluetooth: Reject...
1062
1063
1064
1065
1066
1067
  			break;
  		}
  	}
  	read_unlock(&sco_sk_list.lock);
  
  	return lm;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1068
  }
539c496d8   Johan Hedberg   Bluetooth: Conver...
1069
  static void sco_connect_cfm(struct hci_conn *hcon, __u8 status)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1070
  {
539c496d8   Johan Hedberg   Bluetooth: Conver...
1071
1072
  	if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
  		return;
6ed93dc64   Andrei Emeltchenko   Bluetooth: Use %p...
1073
  	BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status);
539c496d8   Johan Hedberg   Bluetooth: Conver...
1074

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1075
1076
  	if (!status) {
  		struct sco_conn *conn;
519e42b38   Lukasz Rymanowski   Bluetooth: Remove...
1077
  		conn = sco_conn_add(hcon);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1078
1079
  		if (conn)
  			sco_conn_ready(conn);
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
1080
  	} else
e175072f3   Joe Perches   Bluetooth: Rename...
1081
  		sco_conn_del(hcon, bt_to_errno(status));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1082
  }
3a6d576be   Johan Hedberg   Bluetooth: Conver...
1083
  static void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1084
  {
3a6d576be   Johan Hedberg   Bluetooth: Conver...
1085
1086
  	if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1087
  	BT_DBG("hcon %p reason %d", hcon, reason);
e175072f3   Joe Perches   Bluetooth: Rename...
1088
  	sco_conn_del(hcon, bt_to_errno(reason));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1089
  }
9b4c33364   Arron Wang   Bluetooth: Make l...
1090
  void sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
  {
  	struct sco_conn *conn = hcon->sco_data;
  
  	if (!conn)
  		goto drop;
  
  	BT_DBG("conn %p len %d", conn, skb->len);
  
  	if (skb->len) {
  		sco_recv_frame(conn, skb);
9b4c33364   Arron Wang   Bluetooth: Make l...
1101
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1102
1103
1104
  	}
  
  drop:
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
1105
  	kfree_skb(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1106
  }
539c496d8   Johan Hedberg   Bluetooth: Conver...
1107
1108
1109
  static struct hci_cb sco_cb = {
  	.name		= "SCO",
  	.connect_cfm	= sco_connect_cfm,
3a6d576be   Johan Hedberg   Bluetooth: Conver...
1110
  	.disconn_cfm	= sco_disconn_cfm,
539c496d8   Johan Hedberg   Bluetooth: Conver...
1111
  };
aef7d97cc   Marcel Holtmann   Bluetooth: Conver...
1112
  static int sco_debugfs_show(struct seq_file *f, void *p)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1113
1114
  {
  	struct sock *sk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1115

ee65d19e2   Gustavo F. Padovan   Bluetooth: Remove...
1116
  	read_lock(&sco_sk_list.lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1117

b67bfe0d4   Sasha Levin   hlist: drop the n...
1118
  	sk_for_each(sk, &sco_sk_list.head) {
eea963641   Marcel Holtmann   Bluetooth: Store ...
1119
1120
1121
  		seq_printf(f, "%pMR %pMR %d
  ", &sco_pi(sk)->src,
  			   &sco_pi(sk)->dst, sk->sk_state);
be9d12273   Marcel Holtmann   [Bluetooth]: Remo...
1122
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1123

ee65d19e2   Gustavo F. Padovan   Bluetooth: Remove...
1124
  	read_unlock(&sco_sk_list.lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1125

aef7d97cc   Marcel Holtmann   Bluetooth: Conver...
1126
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1127
  }
8e2924e38   Yangtao Li   Bluetooth: Change...
1128
  DEFINE_SHOW_ATTRIBUTE(sco_debugfs);
aef7d97cc   Marcel Holtmann   Bluetooth: Conver...
1129
1130
  
  static struct dentry *sco_debugfs;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1131

90ddc4f04   Eric Dumazet   [NET]: move struc...
1132
  static const struct proto_ops sco_sock_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1133
1134
1135
1136
1137
1138
1139
1140
1141
  	.family		= PF_BLUETOOTH,
  	.owner		= THIS_MODULE,
  	.release	= sco_sock_release,
  	.bind		= sco_sock_bind,
  	.connect	= sco_sock_connect,
  	.listen		= sco_sock_listen,
  	.accept		= sco_sock_accept,
  	.getname	= sco_sock_getname,
  	.sendmsg	= sco_sock_sendmsg,
20714bfef   Frédéric Dalleau   Bluetooth: Implem...
1142
  	.recvmsg	= sco_sock_recvmsg,
a11e1d432   Linus Torvalds   Revert changes to...
1143
  	.poll		= bt_sock_poll,
3241ad820   Marcel Holtmann   [Bluetooth] Add t...
1144
  	.ioctl		= bt_sock_ioctl,
c7cbdbf29   Arnd Bergmann   net: rework SIOCG...
1145
  	.gettstamp	= sock_gettstamp,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1146
1147
  	.mmap		= sock_no_mmap,
  	.socketpair	= sock_no_socketpair,
fd0b3ff70   Marcel Holtmann   Bluetooth: Add pr...
1148
  	.shutdown	= sco_sock_shutdown,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1149
1150
1151
  	.setsockopt	= sco_sock_setsockopt,
  	.getsockopt	= sco_sock_getsockopt
  };
ec1b4cf74   Stephen Hemminger   net: mark net_pro...
1152
  static const struct net_proto_family sco_sock_family_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1153
1154
1155
1156
  	.family	= PF_BLUETOOTH,
  	.owner	= THIS_MODULE,
  	.create	= sco_sock_create,
  };
642745184   Gustavo F. Padovan   Bluetooth: Merge ...
1157
  int __init sco_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1158
1159
  {
  	int err;
15762fa77   Marcel Holtmann   Bluetooth: Add BU...
1160
  	BUILD_BUG_ON(sizeof(struct sockaddr_sco) > sizeof(struct sockaddr));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1161
1162
1163
1164
1165
1166
1167
1168
1169
  	err = proto_register(&sco_proto, 0);
  	if (err < 0)
  		return err;
  
  	err = bt_sock_register(BTPROTO_SCO, &sco_sock_family_ops);
  	if (err < 0) {
  		BT_ERR("SCO socket registration failed");
  		goto error;
  	}
b03166152   Al Viro   bluetooth: kill u...
1170
  	err = bt_procfs_init(&init_net, "sco", &sco_sk_list, NULL);
de9b9212c   Masatake YAMATO   Bluetooth: Added ...
1171
1172
1173
1174
1175
  	if (err < 0) {
  		BT_ERR("Failed to create SCO proc file");
  		bt_sock_unregister(BTPROTO_SCO);
  		goto error;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1176
  	BT_INFO("SCO socket layer initialized");
539c496d8   Johan Hedberg   Bluetooth: Conver...
1177
  	hci_register_cb(&sco_cb);
1120e4bfa   Marcel Holtmann   Bluetooth: Use IS...
1178
1179
1180
1181
1182
  	if (IS_ERR_OR_NULL(bt_debugfs))
  		return 0;
  
  	sco_debugfs = debugfs_create_file("sco", 0444, bt_debugfs,
  					  NULL, &sco_debugfs_fops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1183
1184
1185
1186
1187
1188
  	return 0;
  
  error:
  	proto_unregister(&sco_proto);
  	return err;
  }
0402d9f23   Alexander Aring   Bluetooth: fix sc...
1189
  void sco_exit(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1190
  {
de9b9212c   Masatake YAMATO   Bluetooth: Added ...
1191
  	bt_procfs_cleanup(&init_net, "sco");
aef7d97cc   Marcel Holtmann   Bluetooth: Conver...
1192
  	debugfs_remove(sco_debugfs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1193

539c496d8   Johan Hedberg   Bluetooth: Conver...
1194
  	hci_unregister_cb(&sco_cb);
5e9d7f868   David Herrmann   Bluetooth: discar...
1195
  	bt_sock_unregister(BTPROTO_SCO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1196

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1197
1198
  	proto_unregister(&sco_proto);
  }
7cb127d5b   Marcel Holtmann   [Bluetooth] Add o...
1199
1200
  module_param(disable_esco, bool, 0644);
  MODULE_PARM_DESC(disable_esco, "Disable eSCO connection creation");