xref: /linux/net/bluetooth/cmtp/capi.c (revision 6e8331ac6973435b1e7604c30f2ad394035b46e1)
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 
76 static 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 
93 static 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 
103 static 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 
129 static 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 
139 static 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 
153 static 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 
188 static 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 
303 void 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 
350 static 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 
357 static 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 
369 static 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 
438 static 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 
462 static 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 
492 static char *cmtp_procinfo(struct capi_ctr *ctrl)
493 {
494 	return "CAPI Message Transport Protocol";
495 }
496 
497 static 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 
525 int 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 
591 void cmtp_detach_device(struct cmtp_session *session)
592 {
593 	BT_DBG("session %p", session);
594 
595 	detach_capi_ctr(&session->ctrl);
596 }
597