xref: /openbmc/linux/net/bluetooth/cmtp/capi.c (revision 3932b9ca)
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 
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 	capi_ctr_handle_message(ctrl, appl, skb);
366 }
367 
368 static int cmtp_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
369 {
370 	BT_DBG("ctrl %p data %p", ctrl, data);
371 
372 	return 0;
373 }
374 
375 static void cmtp_reset_ctr(struct capi_ctr *ctrl)
376 {
377 	struct cmtp_session *session = ctrl->driverdata;
378 
379 	BT_DBG("ctrl %p", ctrl);
380 
381 	capi_ctr_down(ctrl);
382 
383 	atomic_inc(&session->terminate);
384 	wake_up_process(session->task);
385 }
386 
387 static void cmtp_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp)
388 {
389 	DECLARE_WAITQUEUE(wait, current);
390 	struct cmtp_session *session = ctrl->driverdata;
391 	struct cmtp_application *application;
392 	unsigned long timeo = CMTP_INTEROP_TIMEOUT;
393 	unsigned char buf[8];
394 	int err = 0, nconn, want = rp->level3cnt;
395 
396 	BT_DBG("ctrl %p appl %d level3cnt %d datablkcnt %d datablklen %d",
397 		ctrl, appl, rp->level3cnt, rp->datablkcnt, rp->datablklen);
398 
399 	application = cmtp_application_add(session, appl);
400 	if (!application) {
401 		BT_ERR("Can't allocate memory for new application");
402 		return;
403 	}
404 
405 	if (want < 0)
406 		nconn = ctrl->profile.nbchannel * -want;
407 	else
408 		nconn = want;
409 
410 	if (nconn == 0)
411 		nconn = ctrl->profile.nbchannel;
412 
413 	capimsg_setu16(buf, 0, nconn);
414 	capimsg_setu16(buf, 2, rp->datablkcnt);
415 	capimsg_setu16(buf, 4, rp->datablklen);
416 
417 	application->state = BT_CONFIG;
418 	application->msgnum = cmtp_msgnum_get(session);
419 
420 	cmtp_send_interopmsg(session, CAPI_REQ, 0x0000, application->msgnum,
421 				CAPI_FUNCTION_REGISTER, buf, 6);
422 
423 	add_wait_queue(&session->wait, &wait);
424 	while (1) {
425 		set_current_state(TASK_INTERRUPTIBLE);
426 
427 		if (!timeo) {
428 			err = -EAGAIN;
429 			break;
430 		}
431 
432 		if (application->state == BT_CLOSED) {
433 			err = -application->err;
434 			break;
435 		}
436 
437 		if (application->state == BT_CONNECTED)
438 			break;
439 
440 		if (signal_pending(current)) {
441 			err = -EINTR;
442 			break;
443 		}
444 
445 		timeo = schedule_timeout(timeo);
446 	}
447 	set_current_state(TASK_RUNNING);
448 	remove_wait_queue(&session->wait, &wait);
449 
450 	if (err) {
451 		cmtp_application_del(session, application);
452 		return;
453 	}
454 }
455 
456 static void cmtp_release_appl(struct capi_ctr *ctrl, __u16 appl)
457 {
458 	struct cmtp_session *session = ctrl->driverdata;
459 	struct cmtp_application *application;
460 
461 	BT_DBG("ctrl %p appl %d", ctrl, appl);
462 
463 	application = cmtp_application_get(session, CMTP_APPLID, appl);
464 	if (!application) {
465 		BT_ERR("Can't find application");
466 		return;
467 	}
468 
469 	application->msgnum = cmtp_msgnum_get(session);
470 
471 	cmtp_send_interopmsg(session, CAPI_REQ, application->mapping, application->msgnum,
472 				CAPI_FUNCTION_RELEASE, NULL, 0);
473 
474 	wait_event_interruptible_timeout(session->wait,
475 			(application->state == BT_CLOSED), CMTP_INTEROP_TIMEOUT);
476 
477 	cmtp_application_del(session, application);
478 }
479 
480 static u16 cmtp_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
481 {
482 	struct cmtp_session *session = ctrl->driverdata;
483 	struct cmtp_application *application;
484 	__u16 appl;
485 	__u32 contr;
486 
487 	BT_DBG("ctrl %p skb %p", ctrl, skb);
488 
489 	appl = CAPIMSG_APPID(skb->data);
490 	contr = CAPIMSG_CONTROL(skb->data);
491 
492 	application = cmtp_application_get(session, CMTP_APPLID, appl);
493 	if ((!application) || (application->state != BT_CONNECTED)) {
494 		BT_ERR("Can't find application with id %d", appl);
495 		return CAPI_ILLAPPNR;
496 	}
497 
498 	CAPIMSG_SETAPPID(skb->data, application->mapping);
499 
500 	if ((contr & 0x7f) == session->num) {
501 		contr = (contr & 0xffffff80) | 0x01;
502 		CAPIMSG_SETCONTROL(skb->data, contr);
503 	}
504 
505 	cmtp_send_capimsg(session, skb);
506 
507 	return CAPI_NOERROR;
508 }
509 
510 static char *cmtp_procinfo(struct capi_ctr *ctrl)
511 {
512 	return "CAPI Message Transport Protocol";
513 }
514 
515 static int cmtp_proc_show(struct seq_file *m, void *v)
516 {
517 	struct capi_ctr *ctrl = m->private;
518 	struct cmtp_session *session = ctrl->driverdata;
519 	struct cmtp_application *app;
520 	struct list_head *p, *n;
521 
522 	seq_printf(m, "%s\n\n", cmtp_procinfo(ctrl));
523 	seq_printf(m, "addr %s\n", session->name);
524 	seq_printf(m, "ctrl %d\n", session->num);
525 
526 	list_for_each_safe(p, n, &session->applications) {
527 		app = list_entry(p, struct cmtp_application, list);
528 		seq_printf(m, "appl %d -> %d\n", app->appl, app->mapping);
529 	}
530 
531 	return 0;
532 }
533 
534 static int cmtp_proc_open(struct inode *inode, struct file *file)
535 {
536 	return single_open(file, cmtp_proc_show, PDE_DATA(inode));
537 }
538 
539 static const struct file_operations cmtp_proc_fops = {
540 	.owner		= THIS_MODULE,
541 	.open		= cmtp_proc_open,
542 	.read		= seq_read,
543 	.llseek		= seq_lseek,
544 	.release	= single_release,
545 };
546 
547 int cmtp_attach_device(struct cmtp_session *session)
548 {
549 	unsigned char buf[4];
550 	long ret;
551 
552 	BT_DBG("session %p", session);
553 
554 	capimsg_setu32(buf, 0, 0);
555 
556 	cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, CMTP_INITIAL_MSGNUM,
557 				CAPI_FUNCTION_GET_PROFILE, buf, 4);
558 
559 	ret = wait_event_interruptible_timeout(session->wait,
560 			session->ncontroller, CMTP_INTEROP_TIMEOUT);
561 
562 	BT_INFO("Found %d CAPI controller(s) on device %s", session->ncontroller, session->name);
563 
564 	if (!ret)
565 		return -ETIMEDOUT;
566 
567 	if (!session->ncontroller)
568 		return -ENODEV;
569 
570 	if (session->ncontroller > 1)
571 		BT_INFO("Setting up only CAPI controller 1");
572 
573 	session->ctrl.owner      = THIS_MODULE;
574 	session->ctrl.driverdata = session;
575 	strcpy(session->ctrl.name, session->name);
576 
577 	session->ctrl.driver_name   = "cmtp";
578 	session->ctrl.load_firmware = cmtp_load_firmware;
579 	session->ctrl.reset_ctr     = cmtp_reset_ctr;
580 	session->ctrl.register_appl = cmtp_register_appl;
581 	session->ctrl.release_appl  = cmtp_release_appl;
582 	session->ctrl.send_message  = cmtp_send_message;
583 
584 	session->ctrl.procinfo      = cmtp_procinfo;
585 	session->ctrl.proc_fops = &cmtp_proc_fops;
586 
587 	if (attach_capi_ctr(&session->ctrl) < 0) {
588 		BT_ERR("Can't attach new controller");
589 		return -EBUSY;
590 	}
591 
592 	session->num = session->ctrl.cnr;
593 
594 	BT_DBG("session %p num %d", session, session->num);
595 
596 	capimsg_setu32(buf, 0, 1);
597 
598 	cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
599 				CAPI_FUNCTION_GET_MANUFACTURER, buf, 4);
600 
601 	cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
602 				CAPI_FUNCTION_GET_VERSION, buf, 4);
603 
604 	cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
605 				CAPI_FUNCTION_GET_SERIAL_NUMBER, buf, 4);
606 
607 	cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
608 				CAPI_FUNCTION_GET_PROFILE, buf, 4);
609 
610 	return 0;
611 }
612 
613 void cmtp_detach_device(struct cmtp_session *session)
614 {
615 	BT_DBG("session %p", session);
616 
617 	detach_capi_ctr(&session->ctrl);
618 }
619