Linux Audio

Check our new training course

Loading...
v6.8
  1/*
  2   CMTP implementation for Linux Bluetooth stack (BlueZ).
  3   Copyright (C) 2002-2003 Marcel Holtmann <marcel@holtmann.org>
  4
  5   This program is free software; you can redistribute it and/or modify
  6   it under the terms of the GNU General Public License version 2 as
  7   published by the Free Software Foundation;
  8
  9   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 10   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 11   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
 12   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
 13   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
 14   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 15   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 16   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 17
 18   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
 19   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
 20   SOFTWARE IS DISCLAIMED.
 21*/
 22
 23#include <linux/module.h>
 24
 25#include <linux/types.h>
 26#include <linux/errno.h>
 27#include <linux/kernel.h>
 28#include <linux/sched.h>
 29#include <linux/slab.h>
 30#include <linux/poll.h>
 31#include <linux/fcntl.h>
 32#include <linux/freezer.h>
 33#include <linux/skbuff.h>
 34#include <linux/socket.h>
 35#include <linux/ioctl.h>
 36#include <linux/file.h>
 37#include <linux/init.h>
 38#include <linux/kthread.h>
 39#include <net/sock.h>
 40
 41#include <linux/isdn/capilli.h>
 42
 43#include <net/bluetooth/bluetooth.h>
 44#include <net/bluetooth/l2cap.h>
 45
 46#include "cmtp.h"
 47
 48#define VERSION "1.0"
 49
 50static DECLARE_RWSEM(cmtp_session_sem);
 51static LIST_HEAD(cmtp_session_list);
 52
 53static struct cmtp_session *__cmtp_get_session(bdaddr_t *bdaddr)
 54{
 55	struct cmtp_session *session;
 
 56
 57	BT_DBG("");
 58
 59	list_for_each_entry(session, &cmtp_session_list, list)
 
 60		if (!bacmp(bdaddr, &session->bdaddr))
 61			return session;
 62
 63	return NULL;
 64}
 65
 66static void __cmtp_link_session(struct cmtp_session *session)
 67{
 
 68	list_add(&session->list, &cmtp_session_list);
 69}
 70
 71static void __cmtp_unlink_session(struct cmtp_session *session)
 72{
 73	list_del(&session->list);
 
 74}
 75
 76static void __cmtp_copy_session(struct cmtp_session *session, struct cmtp_conninfo *ci)
 77{
 78	u32 valid_flags = BIT(CMTP_LOOPBACK);
 79	memset(ci, 0, sizeof(*ci));
 80	bacpy(&ci->bdaddr, &session->bdaddr);
 81
 82	ci->flags = session->flags & valid_flags;
 83	ci->state = session->state;
 84
 85	ci->num = session->num;
 86}
 87
 88
 89static inline int cmtp_alloc_block_id(struct cmtp_session *session)
 90{
 91	int i, id = -1;
 92
 93	for (i = 0; i < 16; i++)
 94		if (!test_and_set_bit(i, &session->blockids)) {
 95			id = i;
 96			break;
 97		}
 98
 99	return id;
100}
101
102static inline void cmtp_free_block_id(struct cmtp_session *session, int id)
103{
104	clear_bit(id, &session->blockids);
105}
106
107static inline void cmtp_add_msgpart(struct cmtp_session *session, int id, const unsigned char *buf, int count)
108{
109	struct sk_buff *skb = session->reassembly[id], *nskb;
110	int size;
111
112	BT_DBG("session %p buf %p count %d", session, buf, count);
113
114	size = (skb) ? skb->len + count : count;
115
116	nskb = alloc_skb(size, GFP_ATOMIC);
117	if (!nskb) {
118		BT_ERR("Can't allocate memory for CAPI message");
119		return;
120	}
121
122	if (skb && (skb->len > 0))
123		skb_copy_from_linear_data(skb, skb_put(nskb, skb->len), skb->len);
124
125	skb_put_data(nskb, buf, count);
126
127	session->reassembly[id] = nskb;
128
129	kfree_skb(skb);
130}
131
132static inline int cmtp_recv_frame(struct cmtp_session *session, struct sk_buff *skb)
133{
134	__u8 hdr, hdrlen, id;
135	__u16 len;
136
137	BT_DBG("session %p skb %p len %d", session, skb, skb->len);
138
139	while (skb->len > 0) {
140		hdr = skb->data[0];
141
142		switch (hdr & 0xc0) {
143		case 0x40:
144			hdrlen = 2;
145			len = skb->data[1];
146			break;
147		case 0x80:
148			hdrlen = 3;
149			len = skb->data[1] | (skb->data[2] << 8);
150			break;
151		default:
152			hdrlen = 1;
153			len = 0;
154			break;
155		}
156
157		id = (hdr & 0x3c) >> 2;
158
159		BT_DBG("hdr 0x%02x hdrlen %d len %d id %d", hdr, hdrlen, len, id);
160
161		if (hdrlen + len > skb->len) {
162			BT_ERR("Wrong size or header information in CMTP frame");
163			break;
164		}
165
166		if (len == 0) {
167			skb_pull(skb, hdrlen);
168			continue;
169		}
170
171		switch (hdr & 0x03) {
172		case 0x00:
173			cmtp_add_msgpart(session, id, skb->data + hdrlen, len);
174			cmtp_recv_capimsg(session, session->reassembly[id]);
175			session->reassembly[id] = NULL;
176			break;
177		case 0x01:
178			cmtp_add_msgpart(session, id, skb->data + hdrlen, len);
179			break;
180		default:
181			kfree_skb(session->reassembly[id]);
 
182			session->reassembly[id] = NULL;
183			break;
184		}
185
186		skb_pull(skb, hdrlen + len);
187	}
188
189	kfree_skb(skb);
190	return 0;
191}
192
193static int cmtp_send_frame(struct cmtp_session *session, unsigned char *data, int len)
194{
195	struct socket *sock = session->sock;
196	struct kvec iv = { data, len };
197	struct msghdr msg;
198
199	BT_DBG("session %p data %p len %d", session, data, len);
200
201	if (!len)
202		return 0;
203
204	memset(&msg, 0, sizeof(msg));
205
206	return kernel_sendmsg(sock, &msg, &iv, 1, len);
207}
208
209static void cmtp_process_transmit(struct cmtp_session *session)
210{
211	struct sk_buff *skb, *nskb;
212	unsigned char *hdr;
213	unsigned int size, tail;
214
215	BT_DBG("session %p", session);
216
217	nskb = alloc_skb(session->mtu, GFP_ATOMIC);
218	if (!nskb) {
219		BT_ERR("Can't allocate memory for new frame");
220		return;
221	}
222
223	while ((skb = skb_dequeue(&session->transmit))) {
224		struct cmtp_scb *scb = (void *) skb->cb;
225
226		tail = session->mtu - nskb->len;
227		if (tail < 5) {
228			cmtp_send_frame(session, nskb->data, nskb->len);
229			skb_trim(nskb, 0);
230			tail = session->mtu;
231		}
232
233		size = min_t(uint, ((tail < 258) ? (tail - 2) : (tail - 3)), skb->len);
234
235		if (scb->id < 0) {
236			scb->id = cmtp_alloc_block_id(session);
237			if (scb->id < 0) {
238				skb_queue_head(&session->transmit, skb);
239				break;
240			}
241		}
242
243		if (size < 256) {
244			hdr = skb_put(nskb, 2);
245			hdr[0] = 0x40
246				| ((scb->id << 2) & 0x3c)
247				| ((skb->len == size) ? 0x00 : 0x01);
248			hdr[1] = size;
249		} else {
250			hdr = skb_put(nskb, 3);
251			hdr[0] = 0x80
252				| ((scb->id << 2) & 0x3c)
253				| ((skb->len == size) ? 0x00 : 0x01);
254			hdr[1] = size & 0xff;
255			hdr[2] = size >> 8;
256		}
257
258		skb_copy_from_linear_data(skb, skb_put(nskb, size), size);
259		skb_pull(skb, size);
260
261		if (skb->len > 0) {
262			skb_queue_head(&session->transmit, skb);
263		} else {
264			cmtp_free_block_id(session, scb->id);
265			if (scb->data) {
266				cmtp_send_frame(session, nskb->data, nskb->len);
267				skb_trim(nskb, 0);
268			}
269			kfree_skb(skb);
270		}
271	}
272
273	cmtp_send_frame(session, nskb->data, nskb->len);
274
275	kfree_skb(nskb);
276}
277
278static int cmtp_session(void *arg)
279{
280	struct cmtp_session *session = arg;
281	struct sock *sk = session->sock->sk;
282	struct sk_buff *skb;
283	DEFINE_WAIT_FUNC(wait, woken_wake_function);
284
285	BT_DBG("session %p", session);
286
287	set_user_nice(current, -15);
288
 
289	add_wait_queue(sk_sleep(sk), &wait);
290	while (1) {
 
 
291		if (atomic_read(&session->terminate))
292			break;
293		if (sk->sk_state != BT_CONNECTED)
294			break;
295
296		while ((skb = skb_dequeue(&sk->sk_receive_queue))) {
297			skb_orphan(skb);
298			if (!skb_linearize(skb))
299				cmtp_recv_frame(session, skb);
300			else
301				kfree_skb(skb);
302		}
303
304		cmtp_process_transmit(session);
305
306		/*
307		 * wait_woken() performs the necessary memory barriers
308		 * for us; see the header comment for this primitive.
309		 */
310		wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
311	}
 
312	remove_wait_queue(sk_sleep(sk), &wait);
313
314	down_write(&cmtp_session_sem);
315
316	if (!(session->flags & BIT(CMTP_LOOPBACK)))
317		cmtp_detach_device(session);
318
319	fput(session->sock->file);
320
321	__cmtp_unlink_session(session);
322
323	up_write(&cmtp_session_sem);
324
325	kfree(session);
326	module_put_and_kthread_exit(0);
327	return 0;
328}
329
330int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock)
331{
332	u32 valid_flags = BIT(CMTP_LOOPBACK);
333	struct cmtp_session *session, *s;
334	int i, err;
335
336	BT_DBG("");
337
338	if (!l2cap_is_socket(sock))
339		return -EBADFD;
340
341	if (req->flags & ~valid_flags)
342		return -EINVAL;
343
344	session = kzalloc(sizeof(struct cmtp_session), GFP_KERNEL);
345	if (!session)
346		return -ENOMEM;
347
348	down_write(&cmtp_session_sem);
349
350	s = __cmtp_get_session(&l2cap_pi(sock->sk)->chan->dst);
351	if (s && s->state == BT_CONNECTED) {
352		err = -EEXIST;
353		goto failed;
354	}
355
356	bacpy(&session->bdaddr, &l2cap_pi(sock->sk)->chan->dst);
357
358	session->mtu = min_t(uint, l2cap_pi(sock->sk)->chan->omtu,
359					l2cap_pi(sock->sk)->chan->imtu);
360
361	BT_DBG("mtu %d", session->mtu);
362
363	sprintf(session->name, "%pMR", &session->bdaddr);
364
365	session->sock  = sock;
366	session->state = BT_CONFIG;
367
368	init_waitqueue_head(&session->wait);
369
370	session->msgnum = CMTP_INITIAL_MSGNUM;
371
372	INIT_LIST_HEAD(&session->applications);
373
374	skb_queue_head_init(&session->transmit);
375
376	for (i = 0; i < 16; i++)
377		session->reassembly[i] = NULL;
378
379	session->flags = req->flags;
380
381	__cmtp_link_session(session);
382
383	__module_get(THIS_MODULE);
384	session->task = kthread_run(cmtp_session, session, "kcmtpd_ctr_%d",
385								session->num);
386	if (IS_ERR(session->task)) {
387		module_put(THIS_MODULE);
388		err = PTR_ERR(session->task);
389		goto unlink;
390	}
391
392	if (!(session->flags & BIT(CMTP_LOOPBACK))) {
393		err = cmtp_attach_device(session);
394		if (err < 0) {
395			/* Caller will call fput in case of failure, and so
396			 * will cmtp_session kthread.
397			 */
398			get_file(session->sock->file);
399
400			atomic_inc(&session->terminate);
401			wake_up_interruptible(sk_sleep(session->sock->sk));
402			up_write(&cmtp_session_sem);
403			return err;
404		}
405	}
406
407	up_write(&cmtp_session_sem);
408	return 0;
409
410unlink:
411	__cmtp_unlink_session(session);
412
413failed:
414	up_write(&cmtp_session_sem);
415	kfree(session);
416	return err;
417}
418
419int cmtp_del_connection(struct cmtp_conndel_req *req)
420{
421	u32 valid_flags = 0;
422	struct cmtp_session *session;
423	int err = 0;
424
425	BT_DBG("");
426
427	if (req->flags & ~valid_flags)
428		return -EINVAL;
429
430	down_read(&cmtp_session_sem);
431
432	session = __cmtp_get_session(&req->bdaddr);
433	if (session) {
434		/* Flush the transmit queue */
435		skb_queue_purge(&session->transmit);
436
437		/* Stop session thread */
438		atomic_inc(&session->terminate);
439
440		/*
441		 * See the comment preceding the call to wait_woken()
442		 * in cmtp_session().
443		 */
444		wake_up_interruptible(sk_sleep(session->sock->sk));
445	} else
446		err = -ENOENT;
447
448	up_read(&cmtp_session_sem);
449	return err;
450}
451
452int cmtp_get_connlist(struct cmtp_connlist_req *req)
453{
454	struct cmtp_session *session;
455	int err = 0, n = 0;
456
457	BT_DBG("");
458
459	down_read(&cmtp_session_sem);
460
461	list_for_each_entry(session, &cmtp_session_list, list) {
 
462		struct cmtp_conninfo ci;
463
 
 
464		__cmtp_copy_session(session, &ci);
465
466		if (copy_to_user(req->ci, &ci, sizeof(ci))) {
467			err = -EFAULT;
468			break;
469		}
470
471		if (++n >= req->cnum)
472			break;
473
474		req->ci++;
475	}
476	req->cnum = n;
477
478	up_read(&cmtp_session_sem);
479	return err;
480}
481
482int cmtp_get_conninfo(struct cmtp_conninfo *ci)
483{
484	struct cmtp_session *session;
485	int err = 0;
486
487	down_read(&cmtp_session_sem);
488
489	session = __cmtp_get_session(&ci->bdaddr);
490	if (session)
491		__cmtp_copy_session(session, ci);
492	else
493		err = -ENOENT;
494
495	up_read(&cmtp_session_sem);
496	return err;
497}
498
499
500static int __init cmtp_init(void)
501{
502	BT_INFO("CMTP (CAPI Emulation) ver %s", VERSION);
503
504	return cmtp_init_sockets();
 
 
505}
506
507static void __exit cmtp_exit(void)
508{
509	cmtp_cleanup_sockets();
510}
511
512module_init(cmtp_init);
513module_exit(cmtp_exit);
514
515MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
516MODULE_DESCRIPTION("Bluetooth CMTP ver " VERSION);
517MODULE_VERSION(VERSION);
518MODULE_LICENSE("GPL");
519MODULE_ALIAS("bt-proto-5");
v3.1
  1/*
  2   CMTP implementation for Linux Bluetooth stack (BlueZ).
  3   Copyright (C) 2002-2003 Marcel Holtmann <marcel@holtmann.org>
  4
  5   This program is free software; you can redistribute it and/or modify
  6   it under the terms of the GNU General Public License version 2 as
  7   published by the Free Software Foundation;
  8
  9   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 10   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 11   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
 12   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
 13   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
 14   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 15   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 16   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 17
 18   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
 19   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
 20   SOFTWARE IS DISCLAIMED.
 21*/
 22
 23#include <linux/module.h>
 24
 25#include <linux/types.h>
 26#include <linux/errno.h>
 27#include <linux/kernel.h>
 28#include <linux/sched.h>
 29#include <linux/slab.h>
 30#include <linux/poll.h>
 31#include <linux/fcntl.h>
 32#include <linux/freezer.h>
 33#include <linux/skbuff.h>
 34#include <linux/socket.h>
 35#include <linux/ioctl.h>
 36#include <linux/file.h>
 37#include <linux/init.h>
 38#include <linux/kthread.h>
 39#include <net/sock.h>
 40
 41#include <linux/isdn/capilli.h>
 42
 43#include <net/bluetooth/bluetooth.h>
 44#include <net/bluetooth/l2cap.h>
 45
 46#include "cmtp.h"
 47
 48#define VERSION "1.0"
 49
 50static DECLARE_RWSEM(cmtp_session_sem);
 51static LIST_HEAD(cmtp_session_list);
 52
 53static struct cmtp_session *__cmtp_get_session(bdaddr_t *bdaddr)
 54{
 55	struct cmtp_session *session;
 56	struct list_head *p;
 57
 58	BT_DBG("");
 59
 60	list_for_each(p, &cmtp_session_list) {
 61		session = list_entry(p, struct cmtp_session, list);
 62		if (!bacmp(bdaddr, &session->bdaddr))
 63			return session;
 64	}
 65	return NULL;
 66}
 67
 68static void __cmtp_link_session(struct cmtp_session *session)
 69{
 70	__module_get(THIS_MODULE);
 71	list_add(&session->list, &cmtp_session_list);
 72}
 73
 74static void __cmtp_unlink_session(struct cmtp_session *session)
 75{
 76	list_del(&session->list);
 77	module_put(THIS_MODULE);
 78}
 79
 80static void __cmtp_copy_session(struct cmtp_session *session, struct cmtp_conninfo *ci)
 81{
 
 82	memset(ci, 0, sizeof(*ci));
 83	bacpy(&ci->bdaddr, &session->bdaddr);
 84
 85	ci->flags = session->flags;
 86	ci->state = session->state;
 87
 88	ci->num = session->num;
 89}
 90
 91
 92static inline int cmtp_alloc_block_id(struct cmtp_session *session)
 93{
 94	int i, id = -1;
 95
 96	for (i = 0; i < 16; i++)
 97		if (!test_and_set_bit(i, &session->blockids)) {
 98			id = i;
 99			break;
100		}
101
102	return id;
103}
104
105static inline void cmtp_free_block_id(struct cmtp_session *session, int id)
106{
107	clear_bit(id, &session->blockids);
108}
109
110static inline void cmtp_add_msgpart(struct cmtp_session *session, int id, const unsigned char *buf, int count)
111{
112	struct sk_buff *skb = session->reassembly[id], *nskb;
113	int size;
114
115	BT_DBG("session %p buf %p count %d", session, buf, count);
116
117	size = (skb) ? skb->len + count : count;
118
119	nskb = alloc_skb(size, GFP_ATOMIC);
120	if (!nskb) {
121		BT_ERR("Can't allocate memory for CAPI message");
122		return;
123	}
124
125	if (skb && (skb->len > 0))
126		skb_copy_from_linear_data(skb, skb_put(nskb, skb->len), skb->len);
127
128	memcpy(skb_put(nskb, count), buf, count);
129
130	session->reassembly[id] = nskb;
131
132	kfree_skb(skb);
133}
134
135static inline int cmtp_recv_frame(struct cmtp_session *session, struct sk_buff *skb)
136{
137	__u8 hdr, hdrlen, id;
138	__u16 len;
139
140	BT_DBG("session %p skb %p len %d", session, skb, skb->len);
141
142	while (skb->len > 0) {
143		hdr = skb->data[0];
144
145		switch (hdr & 0xc0) {
146		case 0x40:
147			hdrlen = 2;
148			len = skb->data[1];
149			break;
150		case 0x80:
151			hdrlen = 3;
152			len = skb->data[1] | (skb->data[2] << 8);
153			break;
154		default:
155			hdrlen = 1;
156			len = 0;
157			break;
158		}
159
160		id = (hdr & 0x3c) >> 2;
161
162		BT_DBG("hdr 0x%02x hdrlen %d len %d id %d", hdr, hdrlen, len, id);
163
164		if (hdrlen + len > skb->len) {
165			BT_ERR("Wrong size or header information in CMTP frame");
166			break;
167		}
168
169		if (len == 0) {
170			skb_pull(skb, hdrlen);
171			continue;
172		}
173
174		switch (hdr & 0x03) {
175		case 0x00:
176			cmtp_add_msgpart(session, id, skb->data + hdrlen, len);
177			cmtp_recv_capimsg(session, session->reassembly[id]);
178			session->reassembly[id] = NULL;
179			break;
180		case 0x01:
181			cmtp_add_msgpart(session, id, skb->data + hdrlen, len);
182			break;
183		default:
184			if (session->reassembly[id] != NULL)
185				kfree_skb(session->reassembly[id]);
186			session->reassembly[id] = NULL;
187			break;
188		}
189
190		skb_pull(skb, hdrlen + len);
191	}
192
193	kfree_skb(skb);
194	return 0;
195}
196
197static int cmtp_send_frame(struct cmtp_session *session, unsigned char *data, int len)
198{
199	struct socket *sock = session->sock;
200	struct kvec iv = { data, len };
201	struct msghdr msg;
202
203	BT_DBG("session %p data %p len %d", session, data, len);
204
205	if (!len)
206		return 0;
207
208	memset(&msg, 0, sizeof(msg));
209
210	return kernel_sendmsg(sock, &msg, &iv, 1, len);
211}
212
213static void cmtp_process_transmit(struct cmtp_session *session)
214{
215	struct sk_buff *skb, *nskb;
216	unsigned char *hdr;
217	unsigned int size, tail;
218
219	BT_DBG("session %p", session);
220
221	nskb = alloc_skb(session->mtu, GFP_ATOMIC);
222	if (!nskb) {
223		BT_ERR("Can't allocate memory for new frame");
224		return;
225	}
226
227	while ((skb = skb_dequeue(&session->transmit))) {
228		struct cmtp_scb *scb = (void *) skb->cb;
229
230		tail = session->mtu - nskb->len;
231		if (tail < 5) {
232			cmtp_send_frame(session, nskb->data, nskb->len);
233			skb_trim(nskb, 0);
234			tail = session->mtu;
235		}
236
237		size = min_t(uint, ((tail < 258) ? (tail - 2) : (tail - 3)), skb->len);
238
239		if (scb->id < 0) {
240			scb->id = cmtp_alloc_block_id(session);
241			if (scb->id < 0) {
242				skb_queue_head(&session->transmit, skb);
243				break;
244			}
245		}
246
247		if (size < 256) {
248			hdr = skb_put(nskb, 2);
249			hdr[0] = 0x40
250				| ((scb->id << 2) & 0x3c)
251				| ((skb->len == size) ? 0x00 : 0x01);
252			hdr[1] = size;
253		} else {
254			hdr = skb_put(nskb, 3);
255			hdr[0] = 0x80
256				| ((scb->id << 2) & 0x3c)
257				| ((skb->len == size) ? 0x00 : 0x01);
258			hdr[1] = size & 0xff;
259			hdr[2] = size >> 8;
260		}
261
262		skb_copy_from_linear_data(skb, skb_put(nskb, size), size);
263		skb_pull(skb, size);
264
265		if (skb->len > 0) {
266			skb_queue_head(&session->transmit, skb);
267		} else {
268			cmtp_free_block_id(session, scb->id);
269			if (scb->data) {
270				cmtp_send_frame(session, nskb->data, nskb->len);
271				skb_trim(nskb, 0);
272			}
273			kfree_skb(skb);
274		}
275	}
276
277	cmtp_send_frame(session, nskb->data, nskb->len);
278
279	kfree_skb(nskb);
280}
281
282static int cmtp_session(void *arg)
283{
284	struct cmtp_session *session = arg;
285	struct sock *sk = session->sock->sk;
286	struct sk_buff *skb;
287	wait_queue_t wait;
288
289	BT_DBG("session %p", session);
290
291	set_user_nice(current, -15);
292
293	init_waitqueue_entry(&wait, current);
294	add_wait_queue(sk_sleep(sk), &wait);
295	while (1) {
296		set_current_state(TASK_INTERRUPTIBLE);
297
298		if (atomic_read(&session->terminate))
299			break;
300		if (sk->sk_state != BT_CONNECTED)
301			break;
302
303		while ((skb = skb_dequeue(&sk->sk_receive_queue))) {
304			skb_orphan(skb);
305			cmtp_recv_frame(session, skb);
 
 
 
306		}
307
308		cmtp_process_transmit(session);
309
310		schedule();
 
 
 
 
311	}
312	__set_current_state(TASK_RUNNING);
313	remove_wait_queue(sk_sleep(sk), &wait);
314
315	down_write(&cmtp_session_sem);
316
317	if (!(session->flags & (1 << CMTP_LOOPBACK)))
318		cmtp_detach_device(session);
319
320	fput(session->sock->file);
321
322	__cmtp_unlink_session(session);
323
324	up_write(&cmtp_session_sem);
325
326	kfree(session);
 
327	return 0;
328}
329
330int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock)
331{
 
332	struct cmtp_session *session, *s;
333	int i, err;
334
335	BT_DBG("");
336
 
 
 
 
 
 
337	session = kzalloc(sizeof(struct cmtp_session), GFP_KERNEL);
338	if (!session)
339		return -ENOMEM;
340
341	down_write(&cmtp_session_sem);
342
343	s = __cmtp_get_session(&bt_sk(sock->sk)->dst);
344	if (s && s->state == BT_CONNECTED) {
345		err = -EEXIST;
346		goto failed;
347	}
348
349	bacpy(&session->bdaddr, &bt_sk(sock->sk)->dst);
350
351	session->mtu = min_t(uint, l2cap_pi(sock->sk)->chan->omtu,
352					l2cap_pi(sock->sk)->chan->imtu);
353
354	BT_DBG("mtu %d", session->mtu);
355
356	sprintf(session->name, "%s", batostr(&bt_sk(sock->sk)->dst));
357
358	session->sock  = sock;
359	session->state = BT_CONFIG;
360
361	init_waitqueue_head(&session->wait);
362
363	session->msgnum = CMTP_INITIAL_MSGNUM;
364
365	INIT_LIST_HEAD(&session->applications);
366
367	skb_queue_head_init(&session->transmit);
368
369	for (i = 0; i < 16; i++)
370		session->reassembly[i] = NULL;
371
372	session->flags = req->flags;
373
374	__cmtp_link_session(session);
375
 
376	session->task = kthread_run(cmtp_session, session, "kcmtpd_ctr_%d",
377								session->num);
378	if (IS_ERR(session->task)) {
 
379		err = PTR_ERR(session->task);
380		goto unlink;
381	}
382
383	if (!(session->flags & (1 << CMTP_LOOPBACK))) {
384		err = cmtp_attach_device(session);
385		if (err < 0) {
 
 
 
 
 
386			atomic_inc(&session->terminate);
387			wake_up_process(session->task);
388			up_write(&cmtp_session_sem);
389			return err;
390		}
391	}
392
393	up_write(&cmtp_session_sem);
394	return 0;
395
396unlink:
397	__cmtp_unlink_session(session);
398
399failed:
400	up_write(&cmtp_session_sem);
401	kfree(session);
402	return err;
403}
404
405int cmtp_del_connection(struct cmtp_conndel_req *req)
406{
 
407	struct cmtp_session *session;
408	int err = 0;
409
410	BT_DBG("");
411
 
 
 
412	down_read(&cmtp_session_sem);
413
414	session = __cmtp_get_session(&req->bdaddr);
415	if (session) {
416		/* Flush the transmit queue */
417		skb_queue_purge(&session->transmit);
418
419		/* Stop session thread */
420		atomic_inc(&session->terminate);
421		wake_up_process(session->task);
 
 
 
 
 
422	} else
423		err = -ENOENT;
424
425	up_read(&cmtp_session_sem);
426	return err;
427}
428
429int cmtp_get_connlist(struct cmtp_connlist_req *req)
430{
431	struct list_head *p;
432	int err = 0, n = 0;
433
434	BT_DBG("");
435
436	down_read(&cmtp_session_sem);
437
438	list_for_each(p, &cmtp_session_list) {
439		struct cmtp_session *session;
440		struct cmtp_conninfo ci;
441
442		session = list_entry(p, struct cmtp_session, list);
443
444		__cmtp_copy_session(session, &ci);
445
446		if (copy_to_user(req->ci, &ci, sizeof(ci))) {
447			err = -EFAULT;
448			break;
449		}
450
451		if (++n >= req->cnum)
452			break;
453
454		req->ci++;
455	}
456	req->cnum = n;
457
458	up_read(&cmtp_session_sem);
459	return err;
460}
461
462int cmtp_get_conninfo(struct cmtp_conninfo *ci)
463{
464	struct cmtp_session *session;
465	int err = 0;
466
467	down_read(&cmtp_session_sem);
468
469	session = __cmtp_get_session(&ci->bdaddr);
470	if (session)
471		__cmtp_copy_session(session, ci);
472	else
473		err = -ENOENT;
474
475	up_read(&cmtp_session_sem);
476	return err;
477}
478
479
480static int __init cmtp_init(void)
481{
482	BT_INFO("CMTP (CAPI Emulation) ver %s", VERSION);
483
484	cmtp_init_sockets();
485
486	return 0;
487}
488
489static void __exit cmtp_exit(void)
490{
491	cmtp_cleanup_sockets();
492}
493
494module_init(cmtp_init);
495module_exit(cmtp_exit);
496
497MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
498MODULE_DESCRIPTION("Bluetooth CMTP ver " VERSION);
499MODULE_VERSION(VERSION);
500MODULE_LICENSE("GPL");
501MODULE_ALIAS("bt-proto-5");