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