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