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/export.h>
24#include <linux/proc_fs.h>
25#include <linux/seq_file.h>
26#include <linux/types.h>
27#include <linux/errno.h>
28#include <linux/kernel.h>
29#include <linux/sched.h>
30#include <linux/slab.h>
31#include <linux/poll.h>
32#include <linux/fcntl.h>
33#include <linux/skbuff.h>
34#include <linux/socket.h>
35#include <linux/ioctl.h>
36#include <linux/file.h>
37#include <linux/wait.h>
38#include <linux/kthread.h>
39#include <net/sock.h>
40
41#include <linux/isdn/capilli.h>
42#include <linux/isdn/capicmd.h>
43#include <linux/isdn/capiutil.h>
44
45#include "cmtp.h"
46
47#define CAPI_INTEROPERABILITY		0x20
48
49#define CAPI_INTEROPERABILITY_REQ	CAPICMD(CAPI_INTEROPERABILITY, CAPI_REQ)
50#define CAPI_INTEROPERABILITY_CONF	CAPICMD(CAPI_INTEROPERABILITY, CAPI_CONF)
51#define CAPI_INTEROPERABILITY_IND	CAPICMD(CAPI_INTEROPERABILITY, CAPI_IND)
52#define CAPI_INTEROPERABILITY_RESP	CAPICMD(CAPI_INTEROPERABILITY, CAPI_RESP)
53
54#define CAPI_INTEROPERABILITY_REQ_LEN	(CAPI_MSG_BASELEN + 2)
55#define CAPI_INTEROPERABILITY_CONF_LEN	(CAPI_MSG_BASELEN + 4)
56#define CAPI_INTEROPERABILITY_IND_LEN	(CAPI_MSG_BASELEN + 2)
57#define CAPI_INTEROPERABILITY_RESP_LEN	(CAPI_MSG_BASELEN + 2)
58
59#define CAPI_FUNCTION_REGISTER		0
60#define CAPI_FUNCTION_RELEASE		1
61#define CAPI_FUNCTION_GET_PROFILE	2
62#define CAPI_FUNCTION_GET_MANUFACTURER	3
63#define CAPI_FUNCTION_GET_VERSION	4
64#define CAPI_FUNCTION_GET_SERIAL_NUMBER	5
65#define CAPI_FUNCTION_MANUFACTURER	6
66#define CAPI_FUNCTION_LOOPBACK		7
67
68
69#define CMTP_MSGNUM	1
70#define CMTP_APPLID	2
71#define CMTP_MAPPING	3
72
73static struct cmtp_application *cmtp_application_add(struct cmtp_session *session, __u16 appl)
74{
75	struct cmtp_application *app = kzalloc(sizeof(*app), GFP_KERNEL);
76
77	BT_DBG("session %p application %p appl %d", session, app, appl);
78
79	if (!app)
80		return NULL;
81
82	app->state = BT_OPEN;
83	app->appl = appl;
84
85	list_add_tail(&app->list, &session->applications);
86
87	return app;
88}
89
90static void cmtp_application_del(struct cmtp_session *session, struct cmtp_application *app)
91{
92	BT_DBG("session %p application %p", session, app);
93
94	if (app) {
95		list_del(&app->list);
96		kfree(app);
97	}
98}
99
100static struct cmtp_application *cmtp_application_get(struct cmtp_session *session, int pattern, __u16 value)
101{
102	struct cmtp_application *app;
103	struct list_head *p, *n;
104
105	list_for_each_safe(p, n, &session->applications) {
106		app = list_entry(p, struct cmtp_application, list);
107		switch (pattern) {
108		case CMTP_MSGNUM:
109			if (app->msgnum == value)
110				return app;
111			break;
112		case CMTP_APPLID:
113			if (app->appl == value)
114				return app;
115			break;
116		case CMTP_MAPPING:
117			if (app->mapping == value)
118				return app;
119			break;
120		}
121	}
122
123	return NULL;
124}
125
126static int cmtp_msgnum_get(struct cmtp_session *session)
127{
128	session->msgnum++;
129
130	if ((session->msgnum & 0xff) > 200)
131		session->msgnum = CMTP_INITIAL_MSGNUM + 1;
132
133	return session->msgnum;
134}
135
136static void cmtp_send_capimsg(struct cmtp_session *session, struct sk_buff *skb)
137{
138	struct cmtp_scb *scb = (void *) skb->cb;
139
140	BT_DBG("session %p skb %p len %d", session, skb, skb->len);
141
142	scb->id = -1;
143	scb->data = (CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3);
144
145	skb_queue_tail(&session->transmit, skb);
146
147	wake_up_interruptible(sk_sleep(session->sock->sk));
148}
149
150static void cmtp_send_interopmsg(struct cmtp_session *session,
151					__u8 subcmd, __u16 appl, __u16 msgnum,
152					__u16 function, unsigned char *buf, int len)
153{
154	struct sk_buff *skb;
155	unsigned char *s;
156
157	BT_DBG("session %p subcmd 0x%02x appl %d msgnum %d", session, subcmd, appl, msgnum);
158
159	skb = alloc_skb(CAPI_MSG_BASELEN + 6 + len, GFP_ATOMIC);
160	if (!skb) {
161		BT_ERR("Can't allocate memory for interoperability packet");
162		return;
163	}
164
165	s = skb_put(skb, CAPI_MSG_BASELEN + 6 + len);
166
167	capimsg_setu16(s, 0, CAPI_MSG_BASELEN + 6 + len);
168	capimsg_setu16(s, 2, appl);
169	capimsg_setu8 (s, 4, CAPI_INTEROPERABILITY);
170	capimsg_setu8 (s, 5, subcmd);
171	capimsg_setu16(s, 6, msgnum);
172
173	/* Interoperability selector (Bluetooth Device Management) */
174	capimsg_setu16(s, 8, 0x0001);
175
176	capimsg_setu8 (s, 10, 3 + len);
177	capimsg_setu16(s, 11, function);
178	capimsg_setu8 (s, 13, len);
179
180	if (len > 0)
181		memcpy(s + 14, buf, len);
182
183	cmtp_send_capimsg(session, skb);
184}
185
186static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *skb)
187{
188	struct capi_ctr *ctrl = &session->ctrl;
189	struct cmtp_application *application;
190	__u16 appl, msgnum, func, info;
191	__u32 controller;
192
193	BT_DBG("session %p skb %p len %d", session, skb, skb->len);
194
195	switch (CAPIMSG_SUBCOMMAND(skb->data)) {
196	case CAPI_CONF:
197		if (skb->len < CAPI_MSG_BASELEN + 10)
198			break;
199
200		func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 5);
201		info = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 8);
202
203		switch (func) {
204		case CAPI_FUNCTION_REGISTER:
205			msgnum = CAPIMSG_MSGID(skb->data);
206
207			application = cmtp_application_get(session, CMTP_MSGNUM, msgnum);
208			if (application) {
209				application->state = BT_CONNECTED;
210				application->msgnum = 0;
211				application->mapping = CAPIMSG_APPID(skb->data);
212				wake_up_interruptible(&session->wait);
213			}
214
215			break;
216
217		case CAPI_FUNCTION_RELEASE:
218			appl = CAPIMSG_APPID(skb->data);
219
220			application = cmtp_application_get(session, CMTP_MAPPING, appl);
221			if (application) {
222				application->state = BT_CLOSED;
223				application->msgnum = 0;
224				wake_up_interruptible(&session->wait);
225			}
226
227			break;
228
229		case CAPI_FUNCTION_GET_PROFILE:
230			if (skb->len < CAPI_MSG_BASELEN + 11 + sizeof(capi_profile))
231				break;
232
233			controller = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 11);
234			msgnum = CAPIMSG_MSGID(skb->data);
235
236			if (!info && (msgnum == CMTP_INITIAL_MSGNUM)) {
237				session->ncontroller = controller;
238				wake_up_interruptible(&session->wait);
239				break;
240			}
241
242			if (!info && ctrl) {
243				memcpy(&ctrl->profile,
244					skb->data + CAPI_MSG_BASELEN + 11,
245					sizeof(capi_profile));
246				session->state = BT_CONNECTED;
247				capi_ctr_ready(ctrl);
248			}
249
250			break;
251
252		case CAPI_FUNCTION_GET_MANUFACTURER:
253			if (skb->len < CAPI_MSG_BASELEN + 15)
254				break;
255
256			controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 10);
257
258			if (!info && ctrl) {
259				int len = min_t(uint, CAPI_MANUFACTURER_LEN,
260						skb->data[CAPI_MSG_BASELEN + 14]);
261
262				memset(ctrl->manu, 0, CAPI_MANUFACTURER_LEN);
263				strncpy(ctrl->manu,
264					skb->data + CAPI_MSG_BASELEN + 15, len);
265			}
266
267			break;
268
269		case CAPI_FUNCTION_GET_VERSION:
270			if (skb->len < CAPI_MSG_BASELEN + 32)
271				break;
272
273			controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12);
274
275			if (!info && ctrl) {
276				ctrl->version.majorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 16);
277				ctrl->version.minorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 20);
278				ctrl->version.majormanuversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 24);
279				ctrl->version.minormanuversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 28);
280			}
281
282			break;
283
284		case CAPI_FUNCTION_GET_SERIAL_NUMBER:
285			if (skb->len < CAPI_MSG_BASELEN + 17)
286				break;
287
288			controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12);
289
290			if (!info && ctrl) {
291				int len = min_t(uint, CAPI_SERIAL_LEN,
292						skb->data[CAPI_MSG_BASELEN + 16]);
293
294				memset(ctrl->serial, 0, CAPI_SERIAL_LEN);
295				strncpy(ctrl->serial,
296					skb->data + CAPI_MSG_BASELEN + 17, len);
297			}
298
299			break;
300		}
301
302		break;
303
304	case CAPI_IND:
305		if (skb->len < CAPI_MSG_BASELEN + 6)
306			break;
307
308		func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 3);
309
310		if (func == CAPI_FUNCTION_LOOPBACK) {
311			int len = min_t(uint, skb->len - CAPI_MSG_BASELEN - 6,
312						skb->data[CAPI_MSG_BASELEN + 5]);
313			appl = CAPIMSG_APPID(skb->data);
314			msgnum = CAPIMSG_MSGID(skb->data);
315			cmtp_send_interopmsg(session, CAPI_RESP, appl, msgnum, func,
316						skb->data + CAPI_MSG_BASELEN + 6, len);
317		}
318
319		break;
320	}
321
322	kfree_skb(skb);
323}
324
325void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb)
326{
327	struct capi_ctr *ctrl = &session->ctrl;
328	struct cmtp_application *application;
329	__u16 appl;
330	__u32 contr;
331
332	BT_DBG("session %p skb %p len %d", session, skb, skb->len);
333
334	if (skb->len < CAPI_MSG_BASELEN)
335		return;
336
337	if (CAPIMSG_COMMAND(skb->data) == CAPI_INTEROPERABILITY) {
338		cmtp_recv_interopmsg(session, skb);
339		return;
340	}
341
342	if (session->flags & (1 << CMTP_LOOPBACK)) {
343		kfree_skb(skb);
344		return;
345	}
346
347	appl = CAPIMSG_APPID(skb->data);
348	contr = CAPIMSG_CONTROL(skb->data);
349
350	application = cmtp_application_get(session, CMTP_MAPPING, appl);
351	if (application) {
352		appl = application->appl;
353		CAPIMSG_SETAPPID(skb->data, appl);
354	} else {
355		BT_ERR("Can't find application with id %d", appl);
356		kfree_skb(skb);
357		return;
358	}
359
360	if ((contr & 0x7f) == 0x01) {
361		contr = (contr & 0xffffff80) | session->num;
362		CAPIMSG_SETCONTROL(skb->data, contr);
363	}
364
365	capi_ctr_handle_message(ctrl, appl, skb);
366}
367
368static int cmtp_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
369{
370	BT_DBG("ctrl %p data %p", ctrl, data);
371
372	return 0;
373}
374
375static void cmtp_reset_ctr(struct capi_ctr *ctrl)
376{
377	struct cmtp_session *session = ctrl->driverdata;
378
379	BT_DBG("ctrl %p", ctrl);
380
381	capi_ctr_down(ctrl);
382
383	atomic_inc(&session->terminate);
384	wake_up_process(session->task);
385}
386
387static void cmtp_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp)
388{
389	DECLARE_WAITQUEUE(wait, current);
390	struct cmtp_session *session = ctrl->driverdata;
391	struct cmtp_application *application;
392	unsigned long timeo = CMTP_INTEROP_TIMEOUT;
393	unsigned char buf[8];
394	int err = 0, nconn, want = rp->level3cnt;
395
396	BT_DBG("ctrl %p appl %d level3cnt %d datablkcnt %d datablklen %d",
397		ctrl, appl, rp->level3cnt, rp->datablkcnt, rp->datablklen);
398
399	application = cmtp_application_add(session, appl);
400	if (!application) {
401		BT_ERR("Can't allocate memory for new application");
402		return;
403	}
404
405	if (want < 0)
406		nconn = ctrl->profile.nbchannel * -want;
407	else
408		nconn = want;
409
410	if (nconn == 0)
411		nconn = ctrl->profile.nbchannel;
412
413	capimsg_setu16(buf, 0, nconn);
414	capimsg_setu16(buf, 2, rp->datablkcnt);
415	capimsg_setu16(buf, 4, rp->datablklen);
416
417	application->state = BT_CONFIG;
418	application->msgnum = cmtp_msgnum_get(session);
419
420	cmtp_send_interopmsg(session, CAPI_REQ, 0x0000, application->msgnum,
421				CAPI_FUNCTION_REGISTER, buf, 6);
422
423	add_wait_queue(&session->wait, &wait);
424	while (1) {
425		set_current_state(TASK_INTERRUPTIBLE);
426
427		if (!timeo) {
428			err = -EAGAIN;
429			break;
430		}
431
432		if (application->state == BT_CLOSED) {
433			err = -application->err;
434			break;
435		}
436
437		if (application->state == BT_CONNECTED)
438			break;
439
440		if (signal_pending(current)) {
441			err = -EINTR;
442			break;
443		}
444
445		timeo = schedule_timeout(timeo);
446	}
447	set_current_state(TASK_RUNNING);
448	remove_wait_queue(&session->wait, &wait);
449
450	if (err) {
451		cmtp_application_del(session, application);
452		return;
453	}
454}
455
456static void cmtp_release_appl(struct capi_ctr *ctrl, __u16 appl)
457{
458	struct cmtp_session *session = ctrl->driverdata;
459	struct cmtp_application *application;
460
461	BT_DBG("ctrl %p appl %d", ctrl, appl);
462
463	application = cmtp_application_get(session, CMTP_APPLID, appl);
464	if (!application) {
465		BT_ERR("Can't find application");
466		return;
467	}
468
469	application->msgnum = cmtp_msgnum_get(session);
470
471	cmtp_send_interopmsg(session, CAPI_REQ, application->mapping, application->msgnum,
472				CAPI_FUNCTION_RELEASE, NULL, 0);
473
474	wait_event_interruptible_timeout(session->wait,
475			(application->state == BT_CLOSED), CMTP_INTEROP_TIMEOUT);
476
477	cmtp_application_del(session, application);
478}
479
480static u16 cmtp_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
481{
482	struct cmtp_session *session = ctrl->driverdata;
483	struct cmtp_application *application;
484	__u16 appl;
485	__u32 contr;
486
487	BT_DBG("ctrl %p skb %p", ctrl, skb);
488
489	appl = CAPIMSG_APPID(skb->data);
490	contr = CAPIMSG_CONTROL(skb->data);
491
492	application = cmtp_application_get(session, CMTP_APPLID, appl);
493	if ((!application) || (application->state != BT_CONNECTED)) {
494		BT_ERR("Can't find application with id %d", appl);
495		return CAPI_ILLAPPNR;
496	}
497
498	CAPIMSG_SETAPPID(skb->data, application->mapping);
499
500	if ((contr & 0x7f) == session->num) {
501		contr = (contr & 0xffffff80) | 0x01;
502		CAPIMSG_SETCONTROL(skb->data, contr);
503	}
504
505	cmtp_send_capimsg(session, skb);
506
507	return CAPI_NOERROR;
508}
509
510static char *cmtp_procinfo(struct capi_ctr *ctrl)
511{
512	return "CAPI Message Transport Protocol";
513}
514
515static int cmtp_proc_show(struct seq_file *m, void *v)
516{
517	struct capi_ctr *ctrl = m->private;
518	struct cmtp_session *session = ctrl->driverdata;
519	struct cmtp_application *app;
520	struct list_head *p, *n;
521
522	seq_printf(m, "%s\n\n", cmtp_procinfo(ctrl));
523	seq_printf(m, "addr %s\n", session->name);
524	seq_printf(m, "ctrl %d\n", session->num);
525
526	list_for_each_safe(p, n, &session->applications) {
527		app = list_entry(p, struct cmtp_application, list);
528		seq_printf(m, "appl %d -> %d\n", app->appl, app->mapping);
529	}
530
531	return 0;
532}
533
534static int cmtp_proc_open(struct inode *inode, struct file *file)
535{
536	return single_open(file, cmtp_proc_show, PDE_DATA(inode));
537}
538
539static const struct file_operations cmtp_proc_fops = {
540	.owner		= THIS_MODULE,
541	.open		= cmtp_proc_open,
542	.read		= seq_read,
543	.llseek		= seq_lseek,
544	.release	= single_release,
545};
546
547int cmtp_attach_device(struct cmtp_session *session)
548{
549	unsigned char buf[4];
550	long ret;
551
552	BT_DBG("session %p", session);
553
554	capimsg_setu32(buf, 0, 0);
555
556	cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, CMTP_INITIAL_MSGNUM,
557				CAPI_FUNCTION_GET_PROFILE, buf, 4);
558
559	ret = wait_event_interruptible_timeout(session->wait,
560			session->ncontroller, CMTP_INTEROP_TIMEOUT);
561
562	BT_INFO("Found %d CAPI controller(s) on device %s", session->ncontroller, session->name);
563
564	if (!ret)
565		return -ETIMEDOUT;
566
567	if (!session->ncontroller)
568		return -ENODEV;
569
570	if (session->ncontroller > 1)
571		BT_INFO("Setting up only CAPI controller 1");
572
573	session->ctrl.owner      = THIS_MODULE;
574	session->ctrl.driverdata = session;
575	strcpy(session->ctrl.name, session->name);
576
577	session->ctrl.driver_name   = "cmtp";
578	session->ctrl.load_firmware = cmtp_load_firmware;
579	session->ctrl.reset_ctr     = cmtp_reset_ctr;
580	session->ctrl.register_appl = cmtp_register_appl;
581	session->ctrl.release_appl  = cmtp_release_appl;
582	session->ctrl.send_message  = cmtp_send_message;
583
584	session->ctrl.procinfo      = cmtp_procinfo;
585	session->ctrl.proc_fops = &cmtp_proc_fops;
586
587	if (attach_capi_ctr(&session->ctrl) < 0) {
588		BT_ERR("Can't attach new controller");
589		return -EBUSY;
590	}
591
592	session->num = session->ctrl.cnr;
593
594	BT_DBG("session %p num %d", session, session->num);
595
596	capimsg_setu32(buf, 0, 1);
597
598	cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
599				CAPI_FUNCTION_GET_MANUFACTURER, buf, 4);
600
601	cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
602				CAPI_FUNCTION_GET_VERSION, buf, 4);
603
604	cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
605				CAPI_FUNCTION_GET_SERIAL_NUMBER, buf, 4);
606
607	cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
608				CAPI_FUNCTION_GET_PROFILE, buf, 4);
609
610	return 0;
611}
612
613void cmtp_detach_device(struct cmtp_session *session)
614{
615	BT_DBG("session %p", session);
616
617	detach_capi_ctr(&session->ctrl);
618}
619