xref: /openbmc/linux/net/bluetooth/cmtp/capi.c (revision 95e9fd10)
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 #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 
73 static 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 
90 static 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 
100 static 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 
126 static 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 
136 static 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 
150 static 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 
186 static 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 
325 void 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 
374 static 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 
381 static 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 
393 static 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 
462 static 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 
486 static 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 
516 static char *cmtp_procinfo(struct capi_ctr *ctrl)
517 {
518 	return "CAPI Message Transport Protocol";
519 }
520 
521 static 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 
540 static int cmtp_proc_open(struct inode *inode, struct file *file)
541 {
542 	return single_open(file, cmtp_proc_show, PDE(inode)->data);
543 }
544 
545 static 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 
553 int 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 
619 void cmtp_detach_device(struct cmtp_session *session)
620 {
621 	BT_DBG("session %p", session);
622 
623 	detach_capi_ctr(&session->ctrl);
624 }
625