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	if (!ctrl) {
366		BT_ERR("Can't find controller %d for message", session->num);
367		kfree_skb(skb);
368		return;
369	}
370
371	capi_ctr_handle_message(ctrl, appl, skb);
372}
373
374static int cmtp_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
375{
376	BT_DBG("ctrl %p data %p", ctrl, data);
377
378	return 0;
379}
380
381static void cmtp_reset_ctr(struct capi_ctr *ctrl)
382{
383	struct cmtp_session *session = ctrl->driverdata;
384
385	BT_DBG("ctrl %p", ctrl);
386
387	capi_ctr_down(ctrl);
388
389	atomic_inc(&session->terminate);
390	wake_up_process(session->task);
391}
392
393static void cmtp_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp)
394{
395	DECLARE_WAITQUEUE(wait, current);
396	struct cmtp_session *session = ctrl->driverdata;
397	struct cmtp_application *application;
398	unsigned long timeo = CMTP_INTEROP_TIMEOUT;
399	unsigned char buf[8];
400	int err = 0, nconn, want = rp->level3cnt;
401
402	BT_DBG("ctrl %p appl %d level3cnt %d datablkcnt %d datablklen %d",
403		ctrl, appl, rp->level3cnt, rp->datablkcnt, rp->datablklen);
404
405	application = cmtp_application_add(session, appl);
406	if (!application) {
407		BT_ERR("Can't allocate memory for new application");
408		return;
409	}
410
411	if (want < 0)
412		nconn = ctrl->profile.nbchannel * -want;
413	else
414		nconn = want;
415
416	if (nconn == 0)
417		nconn = ctrl->profile.nbchannel;
418
419	capimsg_setu16(buf, 0, nconn);
420	capimsg_setu16(buf, 2, rp->datablkcnt);
421	capimsg_setu16(buf, 4, rp->datablklen);
422
423	application->state = BT_CONFIG;
424	application->msgnum = cmtp_msgnum_get(session);
425
426	cmtp_send_interopmsg(session, CAPI_REQ, 0x0000, application->msgnum,
427				CAPI_FUNCTION_REGISTER, buf, 6);
428
429	add_wait_queue(&session->wait, &wait);
430	while (1) {
431		set_current_state(TASK_INTERRUPTIBLE);
432
433		if (!timeo) {
434			err = -EAGAIN;
435			break;
436		}
437
438		if (application->state == BT_CLOSED) {
439			err = -application->err;
440			break;
441		}
442
443		if (application->state == BT_CONNECTED)
444			break;
445
446		if (signal_pending(current)) {
447			err = -EINTR;
448			break;
449		}
450
451		timeo = schedule_timeout(timeo);
452	}
453	set_current_state(TASK_RUNNING);
454	remove_wait_queue(&session->wait, &wait);
455
456	if (err) {
457		cmtp_application_del(session, application);
458		return;
459	}
460}
461
462static void cmtp_release_appl(struct capi_ctr *ctrl, __u16 appl)
463{
464	struct cmtp_session *session = ctrl->driverdata;
465	struct cmtp_application *application;
466
467	BT_DBG("ctrl %p appl %d", ctrl, appl);
468
469	application = cmtp_application_get(session, CMTP_APPLID, appl);
470	if (!application) {
471		BT_ERR("Can't find application");
472		return;
473	}
474
475	application->msgnum = cmtp_msgnum_get(session);
476
477	cmtp_send_interopmsg(session, CAPI_REQ, application->mapping, application->msgnum,
478				CAPI_FUNCTION_RELEASE, NULL, 0);
479
480	wait_event_interruptible_timeout(session->wait,
481			(application->state == BT_CLOSED), CMTP_INTEROP_TIMEOUT);
482
483	cmtp_application_del(session, application);
484}
485
486static u16 cmtp_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
487{
488	struct cmtp_session *session = ctrl->driverdata;
489	struct cmtp_application *application;
490	__u16 appl;
491	__u32 contr;
492
493	BT_DBG("ctrl %p skb %p", ctrl, skb);
494
495	appl = CAPIMSG_APPID(skb->data);
496	contr = CAPIMSG_CONTROL(skb->data);
497
498	application = cmtp_application_get(session, CMTP_APPLID, appl);
499	if ((!application) || (application->state != BT_CONNECTED)) {
500		BT_ERR("Can't find application with id %d", appl);
501		return CAPI_ILLAPPNR;
502	}
503
504	CAPIMSG_SETAPPID(skb->data, application->mapping);
505
506	if ((contr & 0x7f) == session->num) {
507		contr = (contr & 0xffffff80) | 0x01;
508		CAPIMSG_SETCONTROL(skb->data, contr);
509	}
510
511	cmtp_send_capimsg(session, skb);
512
513	return CAPI_NOERROR;
514}
515
516static char *cmtp_procinfo(struct capi_ctr *ctrl)
517{
518	return "CAPI Message Transport Protocol";
519}
520
521static int cmtp_proc_show(struct seq_file *m, void *v)
522{
523	struct capi_ctr *ctrl = m->private;
524	struct cmtp_session *session = ctrl->driverdata;
525	struct cmtp_application *app;
526	struct list_head *p, *n;
527
528	seq_printf(m, "%s\n\n", cmtp_procinfo(ctrl));
529	seq_printf(m, "addr %s\n", session->name);
530	seq_printf(m, "ctrl %d\n", session->num);
531
532	list_for_each_safe(p, n, &session->applications) {
533		app = list_entry(p, struct cmtp_application, list);
534		seq_printf(m, "appl %d -> %d\n", app->appl, app->mapping);
535	}
536
537	return 0;
538}
539
540static int cmtp_proc_open(struct inode *inode, struct file *file)
541{
542	return single_open(file, cmtp_proc_show, PDE_DATA(inode));
543}
544
545static const struct file_operations cmtp_proc_fops = {
546	.owner		= THIS_MODULE,
547	.open		= cmtp_proc_open,
548	.read		= seq_read,
549	.llseek		= seq_lseek,
550	.release	= single_release,
551};
552
553int cmtp_attach_device(struct cmtp_session *session)
554{
555	unsigned char buf[4];
556	long ret;
557
558	BT_DBG("session %p", session);
559
560	capimsg_setu32(buf, 0, 0);
561
562	cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, CMTP_INITIAL_MSGNUM,
563				CAPI_FUNCTION_GET_PROFILE, buf, 4);
564
565	ret = wait_event_interruptible_timeout(session->wait,
566			session->ncontroller, CMTP_INTEROP_TIMEOUT);
567
568	BT_INFO("Found %d CAPI controller(s) on device %s", session->ncontroller, session->name);
569
570	if (!ret)
571		return -ETIMEDOUT;
572
573	if (!session->ncontroller)
574		return -ENODEV;
575
576	if (session->ncontroller > 1)
577		BT_INFO("Setting up only CAPI controller 1");
578
579	session->ctrl.owner      = THIS_MODULE;
580	session->ctrl.driverdata = session;
581	strcpy(session->ctrl.name, session->name);
582
583	session->ctrl.driver_name   = "cmtp";
584	session->ctrl.load_firmware = cmtp_load_firmware;
585	session->ctrl.reset_ctr     = cmtp_reset_ctr;
586	session->ctrl.register_appl = cmtp_register_appl;
587	session->ctrl.release_appl  = cmtp_release_appl;
588	session->ctrl.send_message  = cmtp_send_message;
589
590	session->ctrl.procinfo      = cmtp_procinfo;
591	session->ctrl.proc_fops = &cmtp_proc_fops;
592
593	if (attach_capi_ctr(&session->ctrl) < 0) {
594		BT_ERR("Can't attach new controller");
595		return -EBUSY;
596	}
597
598	session->num = session->ctrl.cnr;
599
600	BT_DBG("session %p num %d", session, session->num);
601
602	capimsg_setu32(buf, 0, 1);
603
604	cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
605				CAPI_FUNCTION_GET_MANUFACTURER, buf, 4);
606
607	cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
608				CAPI_FUNCTION_GET_VERSION, buf, 4);
609
610	cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
611				CAPI_FUNCTION_GET_SERIAL_NUMBER, buf, 4);
612
613	cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
614				CAPI_FUNCTION_GET_PROFILE, buf, 4);
615
616	return 0;
617}
618
619void cmtp_detach_device(struct cmtp_session *session)
620{
621	BT_DBG("session %p", session);
622
623	detach_capi_ctr(&session->ctrl);
624}
625