xref: /openbmc/linux/net/bluetooth/cmtp/capi.c (revision 22246614)
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 		if (skb->len < CAPI_MSG_BASELEN + 10)
200 			break;
201 
202 		func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 5);
203 		info = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 8);
204 
205 		switch (func) {
206 		case CAPI_FUNCTION_REGISTER:
207 			msgnum = CAPIMSG_MSGID(skb->data);
208 
209 			application = cmtp_application_get(session, CMTP_MSGNUM, msgnum);
210 			if (application) {
211 				application->state = BT_CONNECTED;
212 				application->msgnum = 0;
213 				application->mapping = CAPIMSG_APPID(skb->data);
214 				wake_up_interruptible(&session->wait);
215 			}
216 
217 			break;
218 
219 		case CAPI_FUNCTION_RELEASE:
220 			appl = CAPIMSG_APPID(skb->data);
221 
222 			application = cmtp_application_get(session, CMTP_MAPPING, appl);
223 			if (application) {
224 				application->state = BT_CLOSED;
225 				application->msgnum = 0;
226 				wake_up_interruptible(&session->wait);
227 			}
228 
229 			break;
230 
231 		case CAPI_FUNCTION_GET_PROFILE:
232 			if (skb->len < CAPI_MSG_BASELEN + 11 + sizeof(capi_profile))
233 				break;
234 
235 			controller = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 11);
236 			msgnum = CAPIMSG_MSGID(skb->data);
237 
238 			if (!info && (msgnum == CMTP_INITIAL_MSGNUM)) {
239 				session->ncontroller = controller;
240 				wake_up_interruptible(&session->wait);
241 				break;
242 			}
243 
244 			if (!info && ctrl) {
245 				memcpy(&ctrl->profile,
246 					skb->data + CAPI_MSG_BASELEN + 11,
247 					sizeof(capi_profile));
248 				session->state = BT_CONNECTED;
249 				capi_ctr_ready(ctrl);
250 			}
251 
252 			break;
253 
254 		case CAPI_FUNCTION_GET_MANUFACTURER:
255 			if (skb->len < CAPI_MSG_BASELEN + 15)
256 				break;
257 
258 			controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 10);
259 
260 			if (!info && ctrl) {
261 				int len = min_t(uint, CAPI_MANUFACTURER_LEN,
262 						skb->data[CAPI_MSG_BASELEN + 14]);
263 
264 				memset(ctrl->manu, 0, CAPI_MANUFACTURER_LEN);
265 				strncpy(ctrl->manu,
266 					skb->data + CAPI_MSG_BASELEN + 15, len);
267 			}
268 
269 			break;
270 
271 		case CAPI_FUNCTION_GET_VERSION:
272 			if (skb->len < CAPI_MSG_BASELEN + 32)
273 				break;
274 
275 			controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12);
276 
277 			if (!info && ctrl) {
278 				ctrl->version.majorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 16);
279 				ctrl->version.minorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 20);
280 				ctrl->version.majormanuversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 24);
281 				ctrl->version.minormanuversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 28);
282 			}
283 
284 			break;
285 
286 		case CAPI_FUNCTION_GET_SERIAL_NUMBER:
287 			if (skb->len < CAPI_MSG_BASELEN + 17)
288 				break;
289 
290 			controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12);
291 
292 			if (!info && ctrl) {
293 				int len = min_t(uint, CAPI_SERIAL_LEN,
294 						skb->data[CAPI_MSG_BASELEN + 16]);
295 
296 				memset(ctrl->serial, 0, CAPI_SERIAL_LEN);
297 				strncpy(ctrl->serial,
298 					skb->data + CAPI_MSG_BASELEN + 17, len);
299 			}
300 
301 			break;
302 		}
303 
304 		break;
305 
306 	case CAPI_IND:
307 		if (skb->len < CAPI_MSG_BASELEN + 6)
308 			break;
309 
310 		func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 3);
311 
312 		if (func == CAPI_FUNCTION_LOOPBACK) {
313 			int len = min_t(uint, skb->len - CAPI_MSG_BASELEN - 6,
314 						skb->data[CAPI_MSG_BASELEN + 5]);
315 			appl = CAPIMSG_APPID(skb->data);
316 			msgnum = CAPIMSG_MSGID(skb->data);
317 			cmtp_send_interopmsg(session, CAPI_RESP, appl, msgnum, func,
318 						skb->data + CAPI_MSG_BASELEN + 6, len);
319 		}
320 
321 		break;
322 	}
323 
324 	kfree_skb(skb);
325 }
326 
327 void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb)
328 {
329 	struct capi_ctr *ctrl = &session->ctrl;
330 	struct cmtp_application *application;
331 	__u16 cmd, appl;
332 	__u32 contr;
333 
334 	BT_DBG("session %p skb %p len %d", session, skb, skb->len);
335 
336 	if (skb->len < CAPI_MSG_BASELEN)
337 		return;
338 
339 	if (CAPIMSG_COMMAND(skb->data) == CAPI_INTEROPERABILITY) {
340 		cmtp_recv_interopmsg(session, skb);
341 		return;
342 	}
343 
344 	if (session->flags & (1 << CMTP_LOOPBACK)) {
345 		kfree_skb(skb);
346 		return;
347 	}
348 
349 	cmd = CAPICMD(CAPIMSG_COMMAND(skb->data), CAPIMSG_SUBCOMMAND(skb->data));
350 	appl = CAPIMSG_APPID(skb->data);
351 	contr = CAPIMSG_CONTROL(skb->data);
352 
353 	application = cmtp_application_get(session, CMTP_MAPPING, appl);
354 	if (application) {
355 		appl = application->appl;
356 		CAPIMSG_SETAPPID(skb->data, appl);
357 	} else {
358 		BT_ERR("Can't find application with id %d", appl);
359 		kfree_skb(skb);
360 		return;
361 	}
362 
363 	if ((contr & 0x7f) == 0x01) {
364 		contr = (contr & 0xffffff80) | session->num;
365 		CAPIMSG_SETCONTROL(skb->data, contr);
366 	}
367 
368 	if (!ctrl) {
369 		BT_ERR("Can't find controller %d for message", session->num);
370 		kfree_skb(skb);
371 		return;
372 	}
373 
374 	capi_ctr_handle_message(ctrl, appl, skb);
375 }
376 
377 static int cmtp_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
378 {
379 	BT_DBG("ctrl %p data %p", ctrl, data);
380 
381 	return 0;
382 }
383 
384 static void cmtp_reset_ctr(struct capi_ctr *ctrl)
385 {
386 	struct cmtp_session *session = ctrl->driverdata;
387 
388 	BT_DBG("ctrl %p", ctrl);
389 
390 	capi_ctr_reseted(ctrl);
391 
392 	atomic_inc(&session->terminate);
393 	cmtp_schedule(session);
394 }
395 
396 static void cmtp_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp)
397 {
398 	DECLARE_WAITQUEUE(wait, current);
399 	struct cmtp_session *session = ctrl->driverdata;
400 	struct cmtp_application *application;
401 	unsigned long timeo = CMTP_INTEROP_TIMEOUT;
402 	unsigned char buf[8];
403 	int err = 0, nconn, want = rp->level3cnt;
404 
405 	BT_DBG("ctrl %p appl %d level3cnt %d datablkcnt %d datablklen %d",
406 		ctrl, appl, rp->level3cnt, rp->datablkcnt, rp->datablklen);
407 
408 	application = cmtp_application_add(session, appl);
409 	if (!application) {
410 		BT_ERR("Can't allocate memory for new application");
411 		return;
412 	}
413 
414 	if (want < 0)
415 		nconn = ctrl->profile.nbchannel * -want;
416 	else
417 		nconn = want;
418 
419 	if (nconn == 0)
420 		nconn = ctrl->profile.nbchannel;
421 
422 	capimsg_setu16(buf, 0, nconn);
423 	capimsg_setu16(buf, 2, rp->datablkcnt);
424 	capimsg_setu16(buf, 4, rp->datablklen);
425 
426 	application->state = BT_CONFIG;
427 	application->msgnum = cmtp_msgnum_get(session);
428 
429 	cmtp_send_interopmsg(session, CAPI_REQ, 0x0000, application->msgnum,
430 				CAPI_FUNCTION_REGISTER, buf, 6);
431 
432 	add_wait_queue(&session->wait, &wait);
433 	while (1) {
434 		set_current_state(TASK_INTERRUPTIBLE);
435 
436 		if (!timeo) {
437 			err = -EAGAIN;
438 			break;
439 		}
440 
441 		if (application->state == BT_CLOSED) {
442 			err = -application->err;
443 			break;
444 		}
445 
446 		if (application->state == BT_CONNECTED)
447 			break;
448 
449 		if (signal_pending(current)) {
450 			err = -EINTR;
451 			break;
452 		}
453 
454 		timeo = schedule_timeout(timeo);
455 	}
456 	set_current_state(TASK_RUNNING);
457 	remove_wait_queue(&session->wait, &wait);
458 
459 	if (err) {
460 		cmtp_application_del(session, application);
461 		return;
462 	}
463 }
464 
465 static void cmtp_release_appl(struct capi_ctr *ctrl, __u16 appl)
466 {
467 	struct cmtp_session *session = ctrl->driverdata;
468 	struct cmtp_application *application;
469 
470 	BT_DBG("ctrl %p appl %d", ctrl, appl);
471 
472 	application = cmtp_application_get(session, CMTP_APPLID, appl);
473 	if (!application) {
474 		BT_ERR("Can't find application");
475 		return;
476 	}
477 
478 	application->msgnum = cmtp_msgnum_get(session);
479 
480 	cmtp_send_interopmsg(session, CAPI_REQ, application->mapping, application->msgnum,
481 				CAPI_FUNCTION_RELEASE, NULL, 0);
482 
483 	wait_event_interruptible_timeout(session->wait,
484 			(application->state == BT_CLOSED), CMTP_INTEROP_TIMEOUT);
485 
486 	cmtp_application_del(session, application);
487 }
488 
489 static u16 cmtp_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
490 {
491 	struct cmtp_session *session = ctrl->driverdata;
492 	struct cmtp_application *application;
493 	__u16 appl;
494 	__u32 contr;
495 
496 	BT_DBG("ctrl %p skb %p", ctrl, skb);
497 
498 	appl = CAPIMSG_APPID(skb->data);
499 	contr = CAPIMSG_CONTROL(skb->data);
500 
501 	application = cmtp_application_get(session, CMTP_APPLID, appl);
502 	if ((!application) || (application->state != BT_CONNECTED)) {
503 		BT_ERR("Can't find application with id %d", appl);
504 		return CAPI_ILLAPPNR;
505 	}
506 
507 	CAPIMSG_SETAPPID(skb->data, application->mapping);
508 
509 	if ((contr & 0x7f) == session->num) {
510 		contr = (contr & 0xffffff80) | 0x01;
511 		CAPIMSG_SETCONTROL(skb->data, contr);
512 	}
513 
514 	cmtp_send_capimsg(session, skb);
515 
516 	return CAPI_NOERROR;
517 }
518 
519 static char *cmtp_procinfo(struct capi_ctr *ctrl)
520 {
521 	return "CAPI Message Transport Protocol";
522 }
523 
524 static int cmtp_ctr_read_proc(char *page, char **start, off_t off, int count, int *eof, struct capi_ctr *ctrl)
525 {
526 	struct cmtp_session *session = ctrl->driverdata;
527 	struct cmtp_application *app;
528 	struct list_head *p, *n;
529 	int len = 0;
530 
531 	len += sprintf(page + len, "%s\n\n", cmtp_procinfo(ctrl));
532 	len += sprintf(page + len, "addr %s\n", session->name);
533 	len += sprintf(page + len, "ctrl %d\n", session->num);
534 
535 	list_for_each_safe(p, n, &session->applications) {
536 		app = list_entry(p, struct cmtp_application, list);
537 		len += sprintf(page + len, "appl %d -> %d\n", app->appl, app->mapping);
538 	}
539 
540 	if (off + count >= len)
541 		*eof = 1;
542 
543 	if (len < off)
544 		return 0;
545 
546 	*start = page + off;
547 
548 	return ((count < len - off) ? count : len - off);
549 }
550 
551 
552 int cmtp_attach_device(struct cmtp_session *session)
553 {
554 	unsigned char buf[4];
555 	long ret;
556 
557 	BT_DBG("session %p", session);
558 
559 	capimsg_setu32(buf, 0, 0);
560 
561 	cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, CMTP_INITIAL_MSGNUM,
562 				CAPI_FUNCTION_GET_PROFILE, buf, 4);
563 
564 	ret = wait_event_interruptible_timeout(session->wait,
565 			session->ncontroller, CMTP_INTEROP_TIMEOUT);
566 
567 	BT_INFO("Found %d CAPI controller(s) on device %s", session->ncontroller, session->name);
568 
569 	if (!ret)
570 		return -ETIMEDOUT;
571 
572 	if (!session->ncontroller)
573 		return -ENODEV;
574 
575 	if (session->ncontroller > 1)
576 		BT_INFO("Setting up only CAPI controller 1");
577 
578 	session->ctrl.owner      = THIS_MODULE;
579 	session->ctrl.driverdata = session;
580 	strcpy(session->ctrl.name, session->name);
581 
582 	session->ctrl.driver_name   = "cmtp";
583 	session->ctrl.load_firmware = cmtp_load_firmware;
584 	session->ctrl.reset_ctr     = cmtp_reset_ctr;
585 	session->ctrl.register_appl = cmtp_register_appl;
586 	session->ctrl.release_appl  = cmtp_release_appl;
587 	session->ctrl.send_message  = cmtp_send_message;
588 
589 	session->ctrl.procinfo      = cmtp_procinfo;
590 	session->ctrl.ctr_read_proc = cmtp_ctr_read_proc;
591 
592 	if (attach_capi_ctr(&session->ctrl) < 0) {
593 		BT_ERR("Can't attach new controller");
594 		return -EBUSY;
595 	}
596 
597 	session->num = session->ctrl.cnr;
598 
599 	BT_DBG("session %p num %d", session, session->num);
600 
601 	capimsg_setu32(buf, 0, 1);
602 
603 	cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
604 				CAPI_FUNCTION_GET_MANUFACTURER, buf, 4);
605 
606 	cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
607 				CAPI_FUNCTION_GET_VERSION, buf, 4);
608 
609 	cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
610 				CAPI_FUNCTION_GET_SERIAL_NUMBER, buf, 4);
611 
612 	cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
613 				CAPI_FUNCTION_GET_PROFILE, buf, 4);
614 
615 	return 0;
616 }
617 
618 void cmtp_detach_device(struct cmtp_session *session)
619 {
620 	BT_DBG("session %p", session);
621 
622 	detach_capi_ctr(&session->ctrl);
623 }
624