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			if (!info && ctrl) {
257				int len = min_t(uint, CAPI_MANUFACTURER_LEN,
258						skb->data[CAPI_MSG_BASELEN + 14]);
259
260				memset(ctrl->manu, 0, CAPI_MANUFACTURER_LEN);
261				strncpy(ctrl->manu,
262					skb->data + CAPI_MSG_BASELEN + 15, len);
263			}
264
265			break;
266
267		case CAPI_FUNCTION_GET_VERSION:
268			if (skb->len < CAPI_MSG_BASELEN + 32)
269				break;
270
271			if (!info && ctrl) {
272				ctrl->version.majorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 16);
273				ctrl->version.minorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 20);
274				ctrl->version.majormanuversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 24);
275				ctrl->version.minormanuversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 28);
276			}
277
278			break;
279
280		case CAPI_FUNCTION_GET_SERIAL_NUMBER:
281			if (skb->len < CAPI_MSG_BASELEN + 17)
282				break;
283
284			if (!info && ctrl) {
285				int len = min_t(uint, CAPI_SERIAL_LEN,
286						skb->data[CAPI_MSG_BASELEN + 16]);
287
288				memset(ctrl->serial, 0, CAPI_SERIAL_LEN);
289				strncpy(ctrl->serial,
290					skb->data + CAPI_MSG_BASELEN + 17, len);
291			}
292
293			break;
294		}
295
296		break;
297
298	case CAPI_IND:
299		if (skb->len < CAPI_MSG_BASELEN + 6)
300			break;
301
302		func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 3);
303
304		if (func == CAPI_FUNCTION_LOOPBACK) {
305			int len = min_t(uint, skb->len - CAPI_MSG_BASELEN - 6,
306						skb->data[CAPI_MSG_BASELEN + 5]);
307			appl = CAPIMSG_APPID(skb->data);
308			msgnum = CAPIMSG_MSGID(skb->data);
309			cmtp_send_interopmsg(session, CAPI_RESP, appl, msgnum, func,
310						skb->data + CAPI_MSG_BASELEN + 6, len);
311		}
312
313		break;
314	}
315
316	kfree_skb(skb);
317}
318
319void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb)
320{
321	struct capi_ctr *ctrl = &session->ctrl;
322	struct cmtp_application *application;
323	__u16 appl;
324	__u32 contr;
325
326	BT_DBG("session %p skb %p len %d", session, skb, skb->len);
327
328	if (skb->len < CAPI_MSG_BASELEN)
329		return;
330
331	if (CAPIMSG_COMMAND(skb->data) == CAPI_INTEROPERABILITY) {
332		cmtp_recv_interopmsg(session, skb);
333		return;
334	}
335
336	if (session->flags & BIT(CMTP_LOOPBACK)) {
337		kfree_skb(skb);
338		return;
339	}
340
341	appl = CAPIMSG_APPID(skb->data);
342	contr = CAPIMSG_CONTROL(skb->data);
343
344	application = cmtp_application_get(session, CMTP_MAPPING, appl);
345	if (application) {
346		appl = application->appl;
347		CAPIMSG_SETAPPID(skb->data, appl);
348	} else {
349		BT_ERR("Can't find application with id %d", appl);
350		kfree_skb(skb);
351		return;
352	}
353
354	if ((contr & 0x7f) == 0x01) {
355		contr = (contr & 0xffffff80) | session->num;
356		CAPIMSG_SETCONTROL(skb->data, contr);
357	}
358
359	capi_ctr_handle_message(ctrl, appl, skb);
360}
361
362static int cmtp_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
363{
364	BT_DBG("ctrl %p data %p", ctrl, data);
365
366	return 0;
367}
368
369static void cmtp_reset_ctr(struct capi_ctr *ctrl)
370{
371	struct cmtp_session *session = ctrl->driverdata;
372
373	BT_DBG("ctrl %p", ctrl);
374
375	capi_ctr_down(ctrl);
376
377	atomic_inc(&session->terminate);
378	wake_up_process(session->task);
379}
380
381static void cmtp_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp)
382{
383	DECLARE_WAITQUEUE(wait, current);
384	struct cmtp_session *session = ctrl->driverdata;
385	struct cmtp_application *application;
386	unsigned long timeo = CMTP_INTEROP_TIMEOUT;
387	unsigned char buf[8];
388	int err = 0, nconn, want = rp->level3cnt;
389
390	BT_DBG("ctrl %p appl %d level3cnt %d datablkcnt %d datablklen %d",
391		ctrl, appl, rp->level3cnt, rp->datablkcnt, rp->datablklen);
392
393	application = cmtp_application_add(session, appl);
394	if (!application) {
395		BT_ERR("Can't allocate memory for new application");
396		return;
397	}
398
399	if (want < 0)
400		nconn = ctrl->profile.nbchannel * -want;
401	else
402		nconn = want;
403
404	if (nconn == 0)
405		nconn = ctrl->profile.nbchannel;
406
407	capimsg_setu16(buf, 0, nconn);
408	capimsg_setu16(buf, 2, rp->datablkcnt);
409	capimsg_setu16(buf, 4, rp->datablklen);
410
411	application->state = BT_CONFIG;
412	application->msgnum = cmtp_msgnum_get(session);
413
414	cmtp_send_interopmsg(session, CAPI_REQ, 0x0000, application->msgnum,
415				CAPI_FUNCTION_REGISTER, buf, 6);
416
417	add_wait_queue(&session->wait, &wait);
418	while (1) {
419		set_current_state(TASK_INTERRUPTIBLE);
420
421		if (!timeo) {
422			err = -EAGAIN;
423			break;
424		}
425
426		if (application->state == BT_CLOSED) {
427			err = -application->err;
428			break;
429		}
430
431		if (application->state == BT_CONNECTED)
432			break;
433
434		if (signal_pending(current)) {
435			err = -EINTR;
436			break;
437		}
438
439		timeo = schedule_timeout(timeo);
440	}
441	set_current_state(TASK_RUNNING);
442	remove_wait_queue(&session->wait, &wait);
443
444	if (err) {
445		cmtp_application_del(session, application);
446		return;
447	}
448}
449
450static void cmtp_release_appl(struct capi_ctr *ctrl, __u16 appl)
451{
452	struct cmtp_session *session = ctrl->driverdata;
453	struct cmtp_application *application;
454
455	BT_DBG("ctrl %p appl %d", ctrl, appl);
456
457	application = cmtp_application_get(session, CMTP_APPLID, appl);
458	if (!application) {
459		BT_ERR("Can't find application");
460		return;
461	}
462
463	application->msgnum = cmtp_msgnum_get(session);
464
465	cmtp_send_interopmsg(session, CAPI_REQ, application->mapping, application->msgnum,
466				CAPI_FUNCTION_RELEASE, NULL, 0);
467
468	wait_event_interruptible_timeout(session->wait,
469			(application->state == BT_CLOSED), CMTP_INTEROP_TIMEOUT);
470
471	cmtp_application_del(session, application);
472}
473
474static u16 cmtp_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
475{
476	struct cmtp_session *session = ctrl->driverdata;
477	struct cmtp_application *application;
478	__u16 appl;
479	__u32 contr;
480
481	BT_DBG("ctrl %p skb %p", ctrl, skb);
482
483	appl = CAPIMSG_APPID(skb->data);
484	contr = CAPIMSG_CONTROL(skb->data);
485
486	application = cmtp_application_get(session, CMTP_APPLID, appl);
487	if ((!application) || (application->state != BT_CONNECTED)) {
488		BT_ERR("Can't find application with id %d", appl);
489		return CAPI_ILLAPPNR;
490	}
491
492	CAPIMSG_SETAPPID(skb->data, application->mapping);
493
494	if ((contr & 0x7f) == session->num) {
495		contr = (contr & 0xffffff80) | 0x01;
496		CAPIMSG_SETCONTROL(skb->data, contr);
497	}
498
499	cmtp_send_capimsg(session, skb);
500
501	return CAPI_NOERROR;
502}
503
504static char *cmtp_procinfo(struct capi_ctr *ctrl)
505{
506	return "CAPI Message Transport Protocol";
507}
508
509static int cmtp_proc_show(struct seq_file *m, void *v)
510{
511	struct capi_ctr *ctrl = m->private;
512	struct cmtp_session *session = ctrl->driverdata;
513	struct cmtp_application *app;
514	struct list_head *p, *n;
515
516	seq_printf(m, "%s\n\n", cmtp_procinfo(ctrl));
517	seq_printf(m, "addr %s\n", session->name);
518	seq_printf(m, "ctrl %d\n", session->num);
519
520	list_for_each_safe(p, n, &session->applications) {
521		app = list_entry(p, struct cmtp_application, list);
522		seq_printf(m, "appl %d -> %d\n", app->appl, app->mapping);
523	}
524
525	return 0;
526}
527
528static int cmtp_proc_open(struct inode *inode, struct file *file)
529{
530	return single_open(file, cmtp_proc_show, PDE_DATA(inode));
531}
532
533static const struct file_operations cmtp_proc_fops = {
534	.owner		= THIS_MODULE,
535	.open		= cmtp_proc_open,
536	.read		= seq_read,
537	.llseek		= seq_lseek,
538	.release	= single_release,
539};
540
541int cmtp_attach_device(struct cmtp_session *session)
542{
543	unsigned char buf[4];
544	long ret;
545
546	BT_DBG("session %p", session);
547
548	capimsg_setu32(buf, 0, 0);
549
550	cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, CMTP_INITIAL_MSGNUM,
551				CAPI_FUNCTION_GET_PROFILE, buf, 4);
552
553	ret = wait_event_interruptible_timeout(session->wait,
554			session->ncontroller, CMTP_INTEROP_TIMEOUT);
555
556	BT_INFO("Found %d CAPI controller(s) on device %s", session->ncontroller, session->name);
557
558	if (!ret)
559		return -ETIMEDOUT;
560
561	if (!session->ncontroller)
562		return -ENODEV;
563
564	if (session->ncontroller > 1)
565		BT_INFO("Setting up only CAPI controller 1");
566
567	session->ctrl.owner      = THIS_MODULE;
568	session->ctrl.driverdata = session;
569	strcpy(session->ctrl.name, session->name);
570
571	session->ctrl.driver_name   = "cmtp";
572	session->ctrl.load_firmware = cmtp_load_firmware;
573	session->ctrl.reset_ctr     = cmtp_reset_ctr;
574	session->ctrl.register_appl = cmtp_register_appl;
575	session->ctrl.release_appl  = cmtp_release_appl;
576	session->ctrl.send_message  = cmtp_send_message;
577
578	session->ctrl.procinfo      = cmtp_procinfo;
579	session->ctrl.proc_fops = &cmtp_proc_fops;
580
581	if (attach_capi_ctr(&session->ctrl) < 0) {
582		BT_ERR("Can't attach new controller");
583		return -EBUSY;
584	}
585
586	session->num = session->ctrl.cnr;
587
588	BT_DBG("session %p num %d", session, session->num);
589
590	capimsg_setu32(buf, 0, 1);
591
592	cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
593				CAPI_FUNCTION_GET_MANUFACTURER, buf, 4);
594
595	cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
596				CAPI_FUNCTION_GET_VERSION, buf, 4);
597
598	cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
599				CAPI_FUNCTION_GET_SERIAL_NUMBER, buf, 4);
600
601	cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
602				CAPI_FUNCTION_GET_PROFILE, buf, 4);
603
604	return 0;
605}
606
607void cmtp_detach_device(struct cmtp_session *session)
608{
609	BT_DBG("session %p", session);
610
611	detach_capi_ctr(&session->ctrl);
612}
613