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