Blame view

net/bluetooth/sco.c 24.7 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
63
64
  /* ----- 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;
  	struct sco_conn	*conn;
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65
  /* ---- SCO timers ---- */
068d69e5b   Marcel Holtmann   Bluetooth: Move S...
66
67
  #define SCO_CONN_TIMEOUT	(HZ * 40)
  #define SCO_DISCONN_TIMEOUT	(HZ * 2)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68
69
  static void sco_sock_timeout(unsigned long arg)
  {
c4297e8f7   Marcel Holtmann   Bluetooth: Fix so...
70
  	struct sock *sk = (struct sock *)arg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
  
  	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
94
  /* ---- SCO connections ---- */
519e42b38   Lukasz Rymanowski   Bluetooth: Remove...
95
  static struct sco_conn *sco_conn_add(struct hci_conn *hcon)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
96
97
  {
  	struct hci_dev *hdev = hcon->hdev;
25ea6db04   Marcel Holtmann   [Bluetooth] Remai...
98
  	struct sco_conn *conn = hcon->sco_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99

519e42b38   Lukasz Rymanowski   Bluetooth: Remove...
100
  	if (conn)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
101
  		return conn;
c10cc5a9d   Claudio Takahasi   Bluetooth: Use GF...
102
  	conn = kzalloc(sizeof(struct sco_conn), GFP_KERNEL);
25ea6db04   Marcel Holtmann   [Bluetooth] Remai...
103
  	if (!conn)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
  		return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105
106
107
108
109
  
  	spin_lock_init(&conn->lock);
  
  	hcon->sco_data = conn;
  	conn->hcon = hcon;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110
111
112
113
114
115
  	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...
116

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
117
118
  	return conn;
  }
e03ab5199   Marcel Holtmann   Bluetooth: Remove...
119
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
  /* 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...
145
  static void sco_conn_del(struct hci_conn *hcon, int err)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146
  {
735cbc478   Andrei Emeltchenko   Bluetooth: clean ...
147
  	struct sco_conn *conn = hcon->sco_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
148
  	struct sock *sk;
735cbc478   Andrei Emeltchenko   Bluetooth: clean ...
149
  	if (!conn)
df945360c   Nicholas Krause   Bluetooth: Make t...
150
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
151
152
153
154
  
  	BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
  
  	/* Kill socket */
eb5a4de80   Marcel Holtmann   Bluetooth: Remove...
155
156
157
  	sco_conn_lock(conn);
  	sk = conn->sk;
  	sco_conn_unlock(conn);
735cbc478   Andrei Emeltchenko   Bluetooth: clean ...
158
  	if (sk) {
75e34f5cf   Kuba Pawlak   Bluetooth: Fix cr...
159
  		sock_hold(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
160
161
162
163
164
  		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...
165
  		sock_put(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
166
167
168
169
  	}
  
  	hcon->sco_data = NULL;
  	kfree(conn);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170
  }
c4297e8f7   Marcel Holtmann   Bluetooth: Fix so...
171
172
  static void __sco_chan_add(struct sco_conn *conn, struct sock *sk,
  			   struct sock *parent)
015b01cbc   Marcel Holtmann   Bluetooth: Remove...
173
174
175
176
177
178
179
180
181
  {
  	BT_DBG("conn %p", conn);
  
  	sco_pi(sk)->conn = conn;
  	conn->sk = sk;
  
  	if (parent)
  		bt_accept_enqueue(parent, sk);
  }
6039aa73a   Gustavo Padovan   Bluetooth: Remove...
182
183
  static int sco_chan_add(struct sco_conn *conn, struct sock *sk,
  			struct sock *parent)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
184
185
186
187
  {
  	int err = 0;
  
  	sco_conn_lock(conn);
b9dbdbc1f   Gustavo F. Padovan   Bluetooth: Trivia...
188
  	if (conn->sk)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
189
  		err = -EBUSY;
b9dbdbc1f   Gustavo F. Padovan   Bluetooth: Trivia...
190
  	else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
191
  		__sco_chan_add(conn, sk, parent);
b9dbdbc1f   Gustavo F. Padovan   Bluetooth: Trivia...
192

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

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

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

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

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

519e42b38   Lukasz Rymanowski   Bluetooth: Remove...
228
  	conn = sco_conn_add(hcon);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
229
  	if (!conn) {
76a68ba0a   David Herrmann   Bluetooth: rename...
230
  		hci_conn_drop(hcon);
30e762721   Ville Tervo   Bluetooth: Use ER...
231
  		err = -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
232
233
234
235
  		goto done;
  	}
  
  	/* Update source addr of the socket */
eea963641   Marcel Holtmann   Bluetooth: Store ...
236
  	bacpy(&sco_pi(sk)->src, &hcon->src);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237
238
239
240
241
242
243
244
245
246
247
248
  
  	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...
249

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

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

eea963641   Marcel Holtmann   Bluetooth: Store ...
308
  		if (!bacmp(&sco_pi(sk)->src, ba))
fb3340594   Marcel Holtmann   Bluetooth: Restri...
309
310
311
312
  			return sk;
  	}
  
  	return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
313
314
315
316
317
318
319
320
  }
  
  /* 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
321
322
  
  	read_lock(&sco_sk_list.lock);
b67bfe0d4   Sasha Levin   hlist: drop the n...
323
  	sk_for_each(sk, &sco_sk_list.head) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
324
325
326
327
  		if (sk->sk_state != BT_LISTEN)
  			continue;
  
  		/* Exact match. */
eea963641   Marcel Holtmann   Bluetooth: Store ...
328
  		if (!bacmp(&sco_pi(sk)->src, src))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
329
330
331
  			break;
  
  		/* Closest match */
eea963641   Marcel Holtmann   Bluetooth: Store ...
332
  		if (!bacmp(&sco_pi(sk)->src, BDADDR_ANY))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
333
334
335
336
  			sk1 = sk;
  	}
  
  	read_unlock(&sco_sk_list.lock);
b67bfe0d4   Sasha Levin   hlist: drop the n...
337
  	return sk ? sk : sk1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
338
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
  }
  
  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)
  {
f276e2efb   Sudip Mukherjee   Bluetooth: avoid ...
369
370
  	if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket ||
  	    sock_flag(sk, SOCK_DEAD))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
371
372
373
374
375
376
377
378
379
  		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...
380
  static void __sco_sock_close(struct sock *sk)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
381
  {
fd0b3ff70   Marcel Holtmann   Bluetooth: Add pr...
382
  	BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
383
384
385
386
387
388
389
390
  
  	switch (sk->sk_state) {
  	case BT_LISTEN:
  		sco_sock_cleanup_listen(sk);
  		break;
  
  	case BT_CONNECTED:
  	case BT_CONFIG:
b7e98b510   Gustavo Padovan   Bluetooth: Check ...
391
  		if (sco_pi(sk)->conn->hcon) {
4a77708b0   Luiz Augusto von Dentz   Bluetooth: fix sh...
392
393
  			sk->sk_state = BT_DISCONN;
  			sco_sock_set_timer(sk, SCO_DISCONN_TIMEOUT);
435c51336   Kuba Pawlak   Bluetooth: Fix lo...
394
  			sco_conn_lock(sco_pi(sk)->conn);
76a68ba0a   David Herrmann   Bluetooth: rename...
395
  			hci_conn_drop(sco_pi(sk)->conn->hcon);
4a77708b0   Luiz Augusto von Dentz   Bluetooth: fix sh...
396
  			sco_pi(sk)->conn->hcon = NULL;
435c51336   Kuba Pawlak   Bluetooth: Fix lo...
397
  			sco_conn_unlock(sco_pi(sk)->conn);
4a77708b0   Luiz Augusto von Dentz   Bluetooth: fix sh...
398
399
400
  		} else
  			sco_chan_del(sk, ECONNRESET);
  		break;
eb20ff9c9   Vinicius Costa Gomes   Bluetooth: Fix no...
401
  	case BT_CONNECT2:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
402
403
404
405
406
407
408
409
  	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...
410
  	}
fd0b3ff70   Marcel Holtmann   Bluetooth: Add pr...
411
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
412

fd0b3ff70   Marcel Holtmann   Bluetooth: Add pr...
413
414
415
416
417
418
  /* 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
419
  	release_sock(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
420
421
422
423
424
425
  	sco_sock_kill(sk);
  }
  
  static void sco_sock_init(struct sock *sk, struct sock *parent)
  {
  	BT_DBG("sk %p", sk);
6230c9b4f   Paul Moore   bluetooth: Proper...
426
  	if (parent) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
427
  		sk->sk_type = parent->sk_type;
20714bfef   Frédéric Dalleau   Bluetooth: Implem...
428
  		bt_sk(sk)->flags = bt_sk(parent)->flags;
6230c9b4f   Paul Moore   bluetooth: Proper...
429
430
  		security_sk_clone(parent, sk);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
431
432
433
434
435
436
437
  }
  
  static struct proto sco_proto = {
  	.name		= "SCO",
  	.owner		= THIS_MODULE,
  	.obj_size	= sizeof(struct sco_pinfo)
  };
c4297e8f7   Marcel Holtmann   Bluetooth: Fix so...
438
439
  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
440
441
  {
  	struct sock *sk;
11aa9c28b   Eric W. Biederman   net: Pass kern fr...
442
  	sk = sk_alloc(net, PF_BLUETOOTH, prio, &sco_proto, kern);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
443
444
445
446
447
448
449
450
451
452
453
454
455
  	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...
456
  	sco_pi(sk)->setting = BT_VOICE_CVSD_16BIT;
b24b8a247   Pavel Emelyanov   [NET]: Convert in...
457
  	setup_timer(&sk->sk_timer, sco_sock_timeout, (unsigned long)sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
458
459
460
461
  
  	bt_sock_link(&sco_sk_list, sk);
  	return sk;
  }
3f378b684   Eric Paris   net: pass kern to...
462
463
  static int sco_sock_create(struct net *net, struct socket *sock, int protocol,
  			   int kern)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
464
465
466
467
468
469
470
471
472
473
474
  {
  	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...
475
  	sk = sco_sock_alloc(net, sock, protocol, GFP_ATOMIC, kern);
74da626a1   Marcel Holtmann   [Bluetooth] Add l...
476
  	if (!sk)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
477
478
479
480
481
  		return -ENOMEM;
  
  	sco_sock_init(sk, NULL);
  	return 0;
  }
c4297e8f7   Marcel Holtmann   Bluetooth: Fix so...
482
483
  static int sco_sock_bind(struct socket *sock, struct sockaddr *addr,
  			 int addr_len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
484
485
486
  {
  	struct sockaddr_sco *sa = (struct sockaddr_sco *) addr;
  	struct sock *sk = sock->sk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
487
  	int err = 0;
6ed93dc64   Andrei Emeltchenko   Bluetooth: Use %p...
488
  	BT_DBG("sk %p %pMR", sk, &sa->sco_bdaddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
489

d2ecfa765   Mateusz Jurczyk   Bluetooth: Add so...
490
491
  	if (!addr || addr_len < sizeof(struct sockaddr_sco) ||
  	    addr->sa_family != AF_BLUETOOTH)
5233252fc   David S. Miller   bluetooth: Valida...
492
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
493
494
495
496
497
498
  	lock_sock(sk);
  
  	if (sk->sk_state != BT_OPEN) {
  		err = -EBADFD;
  		goto done;
  	}
8ed21f7ee   Marcel Holtmann   Bluetooth: Don't ...
499
500
501
  	if (sk->sk_type != SOCK_SEQPACKET) {
  		err = -EINVAL;
  		goto done;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
502
  	}
eea963641   Marcel Holtmann   Bluetooth: Store ...
503
  	bacpy(&sco_pi(sk)->src, &sa->sco_bdaddr);
8ed21f7ee   Marcel Holtmann   Bluetooth: Don't ...
504
505
  
  	sk->sk_state = BT_BOUND;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
506
507
508
509
510
511
512
513
514
515
  
  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 ...
516
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
517
518
  
  	BT_DBG("sk %p", sk);
6503d9616   Changli Gao   net: check the le...
519
520
  	if (alen < sizeof(struct sockaddr_sco) ||
  	    addr->sa_family != AF_BLUETOOTH)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
521
522
523
524
525
526
527
528
529
530
531
  		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 ...
532
  	bacpy(&sco_pi(sk)->dst, &sa->sco_bdaddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
533

735cbc478   Andrei Emeltchenko   Bluetooth: clean ...
534
535
  	err = sco_connect(sk);
  	if (err)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
536
  		goto done;
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
537
  	err = bt_sock_wait_state(sk, BT_CONNECTED,
be7c2b99e   Gustavo Padovan   Bluetooth: Fix co...
538
  				 sock_sndtimeo(sk, flags & O_NONBLOCK));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
539
540
541
542
543
544
545
546
547
  
  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 ...
548
  	bdaddr_t *src = &sco_pi(sk)->src;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
549
550
551
552
553
  	int err = 0;
  
  	BT_DBG("sk %p backlog %d", sk, backlog);
  
  	lock_sock(sk);
7d5d775a5   Marcel Holtmann   Bluetooth: Split ...
554
  	if (sk->sk_state != BT_BOUND) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
555
556
557
  		err = -EBADFD;
  		goto done;
  	}
7d5d775a5   Marcel Holtmann   Bluetooth: Split ...
558
559
560
561
  	if (sk->sk_type != SOCK_SEQPACKET) {
  		err = -EINVAL;
  		goto done;
  	}
fb3340594   Marcel Holtmann   Bluetooth: Restri...
562
563
564
565
566
567
  	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
568
569
  	sk->sk_max_ack_backlog = backlog;
  	sk->sk_ack_backlog = 0;
fb3340594   Marcel Holtmann   Bluetooth: Restri...
570

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
571
  	sk->sk_state = BT_LISTEN;
fb3340594   Marcel Holtmann   Bluetooth: Restri...
572
573
  unlock:
  	write_unlock(&sco_sk_list.lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
574
575
576
577
  done:
  	release_sock(sk);
  	return err;
  }
c4297e8f7   Marcel Holtmann   Bluetooth: Fix so...
578
  static int sco_sock_accept(struct socket *sock, struct socket *newsock,
cdfbabfb2   David Howells   net: Work around ...
579
  			   int flags, bool kern)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580
  {
dfb2fae7c   Peter Hurley   Bluetooth: Fix ne...
581
  	DEFINE_WAIT_FUNC(wait, woken_wake_function);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
582
583
584
585
586
  	struct sock *sk = sock->sk, *ch;
  	long timeo;
  	int err = 0;
  
  	lock_sock(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
587
588
589
590
591
  	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...
592
  	add_wait_queue_exclusive(sk_sleep(sk), &wait);
552b0d3cb   Peter Hurley   Bluetooth: sco: F...
593
  	while (1) {
552b0d3cb   Peter Hurley   Bluetooth: sco: F...
594
595
  		if (sk->sk_state != BT_LISTEN) {
  			err = -EBADFD;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
596
597
  			break;
  		}
552b0d3cb   Peter Hurley   Bluetooth: sco: F...
598
599
600
  		ch = bt_accept_dequeue(sk, newsock);
  		if (ch)
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
601

552b0d3cb   Peter Hurley   Bluetooth: sco: F...
602
603
  		if (!timeo) {
  			err = -EAGAIN;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
604
605
606
607
608
609
610
  			break;
  		}
  
  		if (signal_pending(current)) {
  			err = sock_intr_errno(timeo);
  			break;
  		}
552b0d3cb   Peter Hurley   Bluetooth: sco: F...
611
612
  
  		release_sock(sk);
dfb2fae7c   Peter Hurley   Bluetooth: Fix ne...
613
614
  
  		timeo = wait_woken(&wait, TASK_INTERRUPTIBLE, timeo);
552b0d3cb   Peter Hurley   Bluetooth: sco: F...
615
  		lock_sock(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
616
  	}
aa3951451   Eric Dumazet   net: sk_sleep() h...
617
  	remove_wait_queue(sk_sleep(sk), &wait);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
618
619
620
621
622
623
624
625
626
627
628
629
  
  	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...
630
631
  static int sco_sock_getname(struct socket *sock, struct sockaddr *addr,
  			    int *len, int peer)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
632
633
634
635
636
637
638
639
640
641
  {
  	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;
  	*len = sizeof(struct sockaddr_sco);
  
  	if (peer)
eea963641   Marcel Holtmann   Bluetooth: Store ...
642
  		bacpy(&sa->sco_bdaddr, &sco_pi(sk)->dst);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
643
  	else
eea963641   Marcel Holtmann   Bluetooth: Store ...
644
  		bacpy(&sa->sco_bdaddr, &sco_pi(sk)->src);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
645
646
647
  
  	return 0;
  }
1b7841404   Ying Xue   net: Remove iocb ...
648
649
  static int sco_sock_sendmsg(struct socket *sock, struct msghdr *msg,
  			    size_t len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
650
651
  {
  	struct sock *sk = sock->sk;
b9dbdbc1f   Gustavo F. Padovan   Bluetooth: Trivia...
652
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
653
654
  
  	BT_DBG("sock %p, sk %p", sock, sk);
c1cbe4b7a   Benjamin LaHaise   [NET]: Avoid atom...
655
656
657
  	err = sock_error(sk);
  	if (err)
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
658
659
660
661
662
663
664
665
666
667
668
669
670
671
  
  	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...
672
  static void sco_conn_defer_accept(struct hci_conn *conn, u16 setting)
fa5513be2   Frédéric Dalleau   Bluetooth: Move a...
673
674
675
676
677
678
679
680
681
682
683
  {
  	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...
684
  		cp.role = 0x00; /* Ignored */
fa5513be2   Frédéric Dalleau   Bluetooth: Move a...
685
686
687
688
689
690
691
  
  		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...
692
693
  		cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
  		cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
2f69a82ac   Frédéric Dalleau   Bluetooth: Use vo...
694
695
696
697
698
  		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...
699
  				cp.max_latency = cpu_to_le16(0x0008);
2f69a82ac   Frédéric Dalleau   Bluetooth: Use vo...
700
  			else
dcf4adbfd   Joe Perches   Bluetooth: Conver...
701
  				cp.max_latency = cpu_to_le16(0x000D);
2f69a82ac   Frédéric Dalleau   Bluetooth: Use vo...
702
703
704
  			cp.retrans_effort = 0x02;
  			break;
  		case SCO_AIRMODE_CVSD:
dcf4adbfd   Joe Perches   Bluetooth: Conver...
705
  			cp.max_latency = cpu_to_le16(0xffff);
2f69a82ac   Frédéric Dalleau   Bluetooth: Use vo...
706
707
708
  			cp.retrans_effort = 0xff;
  			break;
  		}
fa5513be2   Frédéric Dalleau   Bluetooth: Move a...
709
710
711
712
713
  
  		hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
  			     sizeof(cp), &cp);
  	}
  }
1b7841404   Ying Xue   net: Remove iocb ...
714
715
  static int sco_sock_recvmsg(struct socket *sock, struct msghdr *msg,
  			    size_t len, int flags)
20714bfef   Frédéric Dalleau   Bluetooth: Implem...
716
717
718
719
720
721
722
723
  {
  	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...
724
  		sco_conn_defer_accept(pi->conn->hcon, pi->setting);
20714bfef   Frédéric Dalleau   Bluetooth: Implem...
725
726
727
728
729
730
731
  		sk->sk_state = BT_CONFIG;
  
  		release_sock(sk);
  		return 0;
  	}
  
  	release_sock(sk);
1b7841404   Ying Xue   net: Remove iocb ...
732
  	return bt_sock_recvmsg(sock, msg, len, flags);
20714bfef   Frédéric Dalleau   Bluetooth: Implem...
733
  }
c4297e8f7   Marcel Holtmann   Bluetooth: Fix so...
734
735
  static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
  			       char __user *optval, unsigned int optlen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
736
737
  {
  	struct sock *sk = sock->sk;
ad10b1a48   Frédéric Dalleau   Bluetooth: Add Bl...
738
739
  	int len, err = 0;
  	struct bt_voice voice;
b96e9c671   Frédéric Dalleau   Bluetooth: Add BT...
740
  	u32 opt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
741
742
743
744
745
746
  
  	BT_DBG("sk %p", sk);
  
  	lock_sock(sk);
  
  	switch (optname) {
b96e9c671   Frédéric Dalleau   Bluetooth: Add BT...
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
  
  	case BT_DEFER_SETUP:
  		if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
  			err = -EINVAL;
  			break;
  		}
  
  		if (get_user(opt, (u32 __user *) optval)) {
  			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...
764
765
766
767
768
769
770
771
772
773
  	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);
c4297e8f7   Marcel Holtmann   Bluetooth: Fix so...
774
  		if (copy_from_user((char *)&voice, optval, len)) {
ad10b1a48   Frédéric Dalleau   Bluetooth: Add Bl...
775
776
777
778
779
780
781
782
783
784
785
786
787
  			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;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
788
789
790
791
792
793
794
795
  	default:
  		err = -ENOPROTOOPT;
  		break;
  	}
  
  	release_sock(sk);
  	return err;
  }
c4297e8f7   Marcel Holtmann   Bluetooth: Fix so...
796
797
  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
798
799
800
801
  {
  	struct sock *sk = sock->sk;
  	struct sco_options opts;
  	struct sco_conninfo cinfo;
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
802
  	int len, err = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
803
804
805
806
807
808
809
810
811
812
  
  	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...
813
814
815
  		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
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
  			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...
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
  			err = -ENOTCONN;
  			break;
  		}
c4c896e14   Vasiliy Kulikov   Bluetooth: sco: f...
837
  		memset(&cinfo, 0, sizeof(cinfo));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
  		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...
855
856
  static int sco_sock_getsockopt(struct socket *sock, int level, int optname,
  			       char __user *optval, int __user *optlen)
d58daf42d   Marcel Holtmann   Bluetooth: Prepar...
857
858
859
  {
  	struct sock *sk = sock->sk;
  	int len, err = 0;
ad10b1a48   Frédéric Dalleau   Bluetooth: Add Bl...
860
  	struct bt_voice voice;
d58daf42d   Marcel Holtmann   Bluetooth: Prepar...
861
862
863
864
865
866
867
868
869
870
871
872
  
  	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...
873
874
875
876
877
878
879
880
  
  	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...
881
  			     (u32 __user *)optval))
b96e9c671   Frédéric Dalleau   Bluetooth: Add BT...
882
883
884
  			err = -EFAULT;
  
  		break;
ad10b1a48   Frédéric Dalleau   Bluetooth: Add Bl...
885
886
887
888
889
890
891
892
  	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;
d58daf42d   Marcel Holtmann   Bluetooth: Prepar...
893
894
895
896
897
898
899
900
  	default:
  		err = -ENOPROTOOPT;
  		break;
  	}
  
  	release_sock(sk);
  	return err;
  }
fd0b3ff70   Marcel Holtmann   Bluetooth: Add pr...
901
902
903
904
905
906
907
908
909
  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...
910
  	sock_hold(sk);
fd0b3ff70   Marcel Holtmann   Bluetooth: Add pr...
911
  	lock_sock(sk);
1da5537ec   Kuba Pawlak   Bluetooth: Fix lo...
912

fd0b3ff70   Marcel Holtmann   Bluetooth: Add pr...
913
914
915
916
  	if (!sk->sk_shutdown) {
  		sk->sk_shutdown = SHUTDOWN_MASK;
  		sco_sock_clear_timer(sk);
  		__sco_sock_close(sk);
093facf36   Vladimir Davydov   Bluetooth: never ...
917
918
  		if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime &&
  		    !(current->flags & PF_EXITING))
fd0b3ff70   Marcel Holtmann   Bluetooth: Add pr...
919
  			err = bt_sock_wait_state(sk, BT_CLOSED,
be7c2b99e   Gustavo Padovan   Bluetooth: Fix co...
920
  						 sk->sk_lingertime);
fd0b3ff70   Marcel Holtmann   Bluetooth: Add pr...
921
  	}
1da5537ec   Kuba Pawlak   Bluetooth: Fix lo...
922

fd0b3ff70   Marcel Holtmann   Bluetooth: Add pr...
923
  	release_sock(sk);
1da5537ec   Kuba Pawlak   Bluetooth: Fix lo...
924
  	sock_put(sk);
fd0b3ff70   Marcel Holtmann   Bluetooth: Add pr...
925
926
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
927
928
929
930
931
932
933
934
935
936
937
  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 ...
938
939
  	if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime &&
  	    !(current->flags & PF_EXITING)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
940
941
942
943
944
945
946
947
948
  		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
949
950
  static void sco_conn_ready(struct sco_conn *conn)
  {
735cbc478   Andrei Emeltchenko   Bluetooth: clean ...
951
952
  	struct sock *parent;
  	struct sock *sk = conn->sk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
953
954
  
  	BT_DBG("conn %p", conn);
735cbc478   Andrei Emeltchenko   Bluetooth: clean ...
955
  	if (sk) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
956
957
958
959
960
961
  		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...
962
  		sco_conn_lock(conn);
2c501cdd6   Kuba Pawlak   Bluetooth: Fix cr...
963
964
965
966
  		if (!conn->hcon) {
  			sco_conn_unlock(conn);
  			return;
  		}
041987cff   Marcel Holtmann   Bluetooth: Use SC...
967
  		parent = sco_get_sock_listen(&conn->hcon->src);
405280887   Andre Guedes   Bluetooth: Reduce...
968
969
970
971
  		if (!parent) {
  			sco_conn_unlock(conn);
  			return;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
972
973
  
  		bh_lock_sock(parent);
b9dbdbc1f   Gustavo F. Padovan   Bluetooth: Trivia...
974
  		sk = sco_sock_alloc(sock_net(parent), NULL,
11aa9c28b   Eric W. Biederman   net: Pass kern fr...
975
  				    BTPROTO_SCO, GFP_ATOMIC, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
976
977
  		if (!sk) {
  			bh_unlock_sock(parent);
405280887   Andre Guedes   Bluetooth: Reduce...
978
979
  			sco_conn_unlock(conn);
  			return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
980
981
982
  		}
  
  		sco_sock_init(sk, parent);
eea963641   Marcel Holtmann   Bluetooth: Store ...
983
984
  		bacpy(&sco_pi(sk)->src, &conn->hcon->src);
  		bacpy(&sco_pi(sk)->dst, &conn->hcon->dst);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
985
986
987
  
  		hci_conn_hold(conn->hcon);
  		__sco_chan_add(conn, sk, parent);
20714bfef   Frédéric Dalleau   Bluetooth: Implem...
988
989
990
991
  		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
992
993
  
  		/* Wake up parent */
676d23690   David S. Miller   net: Fix use afte...
994
  		parent->sk_data_ready(parent);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
995
996
  
  		bh_unlock_sock(parent);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
997

405280887   Andre Guedes   Bluetooth: Reduce...
998
999
  		sco_conn_unlock(conn);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1000
1001
1002
  }
  
  /* ----- SCO interface with lower layer (HCI) ----- */
20714bfef   Frédéric Dalleau   Bluetooth: Implem...
1003
  int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1004
  {
fc5fef615   Gustavo Padovan   Bluetooth: Remove...
1005
  	struct sock *sk;
71aeeaa1f   Marcel Holtmann   Bluetooth: Reject...
1006
  	int lm = 0;
6ed93dc64   Andrei Emeltchenko   Bluetooth: Use %p...
1007
  	BT_DBG("hdev %s, bdaddr %pMR", hdev->name, bdaddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1008

71aeeaa1f   Marcel Holtmann   Bluetooth: Reject...
1009
1010
  	/* Find listening sockets */
  	read_lock(&sco_sk_list.lock);
b67bfe0d4   Sasha Levin   hlist: drop the n...
1011
  	sk_for_each(sk, &sco_sk_list.head) {
71aeeaa1f   Marcel Holtmann   Bluetooth: Reject...
1012
1013
  		if (sk->sk_state != BT_LISTEN)
  			continue;
eea963641   Marcel Holtmann   Bluetooth: Store ...
1014
1015
  		if (!bacmp(&sco_pi(sk)->src, &hdev->bdaddr) ||
  		    !bacmp(&sco_pi(sk)->src, BDADDR_ANY)) {
71aeeaa1f   Marcel Holtmann   Bluetooth: Reject...
1016
  			lm |= HCI_LM_ACCEPT;
20714bfef   Frédéric Dalleau   Bluetooth: Implem...
1017
1018
1019
  
  			if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags))
  				*flags |= HCI_PROTO_DEFER;
71aeeaa1f   Marcel Holtmann   Bluetooth: Reject...
1020
1021
1022
1023
1024
1025
  			break;
  		}
  	}
  	read_unlock(&sco_sk_list.lock);
  
  	return lm;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1026
  }
539c496d8   Johan Hedberg   Bluetooth: Conver...
1027
  static void sco_connect_cfm(struct hci_conn *hcon, __u8 status)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1028
  {
539c496d8   Johan Hedberg   Bluetooth: Conver...
1029
1030
  	if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
  		return;
6ed93dc64   Andrei Emeltchenko   Bluetooth: Use %p...
1031
  	BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status);
539c496d8   Johan Hedberg   Bluetooth: Conver...
1032

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1033
1034
  	if (!status) {
  		struct sco_conn *conn;
519e42b38   Lukasz Rymanowski   Bluetooth: Remove...
1035
  		conn = sco_conn_add(hcon);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1036
1037
  		if (conn)
  			sco_conn_ready(conn);
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
1038
  	} else
e175072f3   Joe Perches   Bluetooth: Rename...
1039
  		sco_conn_del(hcon, bt_to_errno(status));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1040
  }
3a6d576be   Johan Hedberg   Bluetooth: Conver...
1041
  static void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1042
  {
3a6d576be   Johan Hedberg   Bluetooth: Conver...
1043
1044
  	if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1045
  	BT_DBG("hcon %p reason %d", hcon, reason);
e175072f3   Joe Perches   Bluetooth: Rename...
1046
  	sco_conn_del(hcon, bt_to_errno(reason));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1047
  }
9b4c33364   Arron Wang   Bluetooth: Make l...
1048
  void sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
  {
  	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...
1059
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1060
1061
1062
  	}
  
  drop:
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
1063
  	kfree_skb(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1064
  }
539c496d8   Johan Hedberg   Bluetooth: Conver...
1065
1066
1067
  static struct hci_cb sco_cb = {
  	.name		= "SCO",
  	.connect_cfm	= sco_connect_cfm,
3a6d576be   Johan Hedberg   Bluetooth: Conver...
1068
  	.disconn_cfm	= sco_disconn_cfm,
539c496d8   Johan Hedberg   Bluetooth: Conver...
1069
  };
aef7d97cc   Marcel Holtmann   Bluetooth: Conver...
1070
  static int sco_debugfs_show(struct seq_file *f, void *p)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1071
1072
  {
  	struct sock *sk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1073

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

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

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

aef7d97cc   Marcel Holtmann   Bluetooth: Conver...
1084
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1085
  }
aef7d97cc   Marcel Holtmann   Bluetooth: Conver...
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
  static int sco_debugfs_open(struct inode *inode, struct file *file)
  {
  	return single_open(file, sco_debugfs_show, inode->i_private);
  }
  
  static const struct file_operations sco_debugfs_fops = {
  	.open		= sco_debugfs_open,
  	.read		= seq_read,
  	.llseek		= seq_lseek,
  	.release	= single_release,
  };
  
  static struct dentry *sco_debugfs;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1099

90ddc4f04   Eric Dumazet   [NET]: move struc...
1100
  static const struct proto_ops sco_sock_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1101
1102
1103
1104
1105
1106
1107
1108
1109
  	.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...
1110
  	.recvmsg	= sco_sock_recvmsg,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1111
  	.poll		= bt_sock_poll,
3241ad820   Marcel Holtmann   [Bluetooth] Add t...
1112
  	.ioctl		= bt_sock_ioctl,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1113
1114
  	.mmap		= sock_no_mmap,
  	.socketpair	= sock_no_socketpair,
fd0b3ff70   Marcel Holtmann   Bluetooth: Add pr...
1115
  	.shutdown	= sco_sock_shutdown,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1116
1117
1118
  	.setsockopt	= sco_sock_setsockopt,
  	.getsockopt	= sco_sock_getsockopt
  };
ec1b4cf74   Stephen Hemminger   net: mark net_pro...
1119
  static const struct net_proto_family sco_sock_family_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1120
1121
1122
1123
  	.family	= PF_BLUETOOTH,
  	.owner	= THIS_MODULE,
  	.create	= sco_sock_create,
  };
642745184   Gustavo F. Padovan   Bluetooth: Merge ...
1124
  int __init sco_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1125
1126
  {
  	int err;
15762fa77   Marcel Holtmann   Bluetooth: Add BU...
1127
  	BUILD_BUG_ON(sizeof(struct sockaddr_sco) > sizeof(struct sockaddr));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1128
1129
1130
1131
1132
1133
1134
1135
1136
  	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...
1137
  	err = bt_procfs_init(&init_net, "sco", &sco_sk_list, NULL);
de9b9212c   Masatake YAMATO   Bluetooth: Added ...
1138
1139
1140
1141
1142
  	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
1143
  	BT_INFO("SCO socket layer initialized");
539c496d8   Johan Hedberg   Bluetooth: Conver...
1144
  	hci_register_cb(&sco_cb);
1120e4bfa   Marcel Holtmann   Bluetooth: Use IS...
1145
1146
1147
1148
1149
  	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
1150
1151
1152
1153
1154
1155
  	return 0;
  
  error:
  	proto_unregister(&sco_proto);
  	return err;
  }
0402d9f23   Alexander Aring   Bluetooth: fix sc...
1156
  void sco_exit(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1157
  {
de9b9212c   Masatake YAMATO   Bluetooth: Added ...
1158
  	bt_procfs_cleanup(&init_net, "sco");
aef7d97cc   Marcel Holtmann   Bluetooth: Conver...
1159
  	debugfs_remove(sco_debugfs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1160

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

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