xref: /linux/net/bluetooth/cmtp/capi.c (revision 9410645520e9b820069761f3450ef6661418e279)
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/signal.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 
cmtp_application_add(struct cmtp_session * session,__u16 appl)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 %u", 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 
cmtp_application_del(struct cmtp_session * session,struct cmtp_application * app)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 
cmtp_application_get(struct cmtp_session * session,int pattern,__u16 value)100 static struct cmtp_application *cmtp_application_get(struct cmtp_session *session, int pattern, __u16 value)
101 {
102 	struct cmtp_application *app;
103 
104 	list_for_each_entry(app, &session->applications, list) {
105 		switch (pattern) {
106 		case CMTP_MSGNUM:
107 			if (app->msgnum == value)
108 				return app;
109 			break;
110 		case CMTP_APPLID:
111 			if (app->appl == value)
112 				return app;
113 			break;
114 		case CMTP_MAPPING:
115 			if (app->mapping == value)
116 				return app;
117 			break;
118 		}
119 	}
120 
121 	return NULL;
122 }
123 
cmtp_msgnum_get(struct cmtp_session * session)124 static int cmtp_msgnum_get(struct cmtp_session *session)
125 {
126 	session->msgnum++;
127 
128 	if ((session->msgnum & 0xff) > 200)
129 		session->msgnum = CMTP_INITIAL_MSGNUM + 1;
130 
131 	return session->msgnum;
132 }
133 
cmtp_send_capimsg(struct cmtp_session * session,struct sk_buff * skb)134 static void cmtp_send_capimsg(struct cmtp_session *session, struct sk_buff *skb)
135 {
136 	struct cmtp_scb *scb = (void *) skb->cb;
137 
138 	BT_DBG("session %p skb %p len %u", session, skb, skb->len);
139 
140 	scb->id = -1;
141 	scb->data = (CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3);
142 
143 	skb_queue_tail(&session->transmit, skb);
144 
145 	wake_up_interruptible(sk_sleep(session->sock->sk));
146 }
147 
cmtp_send_interopmsg(struct cmtp_session * session,__u8 subcmd,__u16 appl,__u16 msgnum,__u16 function,unsigned char * buf,int len)148 static void cmtp_send_interopmsg(struct cmtp_session *session,
149 					__u8 subcmd, __u16 appl, __u16 msgnum,
150 					__u16 function, unsigned char *buf, int len)
151 {
152 	struct sk_buff *skb;
153 	unsigned char *s;
154 
155 	BT_DBG("session %p subcmd 0x%02x appl %u msgnum %u", session, subcmd, appl, msgnum);
156 
157 	skb = alloc_skb(CAPI_MSG_BASELEN + 6 + len, GFP_ATOMIC);
158 	if (!skb) {
159 		BT_ERR("Can't allocate memory for interoperability packet");
160 		return;
161 	}
162 
163 	s = skb_put(skb, CAPI_MSG_BASELEN + 6 + len);
164 
165 	capimsg_setu16(s, 0, CAPI_MSG_BASELEN + 6 + len);
166 	capimsg_setu16(s, 2, appl);
167 	capimsg_setu8 (s, 4, CAPI_INTEROPERABILITY);
168 	capimsg_setu8 (s, 5, subcmd);
169 	capimsg_setu16(s, 6, msgnum);
170 
171 	/* Interoperability selector (Bluetooth Device Management) */
172 	capimsg_setu16(s, 8, 0x0001);
173 
174 	capimsg_setu8 (s, 10, 3 + len);
175 	capimsg_setu16(s, 11, function);
176 	capimsg_setu8 (s, 13, len);
177 
178 	if (len > 0)
179 		memcpy(s + 14, buf, len);
180 
181 	cmtp_send_capimsg(session, skb);
182 }
183 
cmtp_recv_interopmsg(struct cmtp_session * session,struct sk_buff * skb)184 static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *skb)
185 {
186 	struct capi_ctr *ctrl = &session->ctrl;
187 	struct cmtp_application *application;
188 	__u16 appl, msgnum, func, info;
189 	__u32 controller;
190 
191 	BT_DBG("session %p skb %p len %u", session, skb, skb->len);
192 
193 	switch (CAPIMSG_SUBCOMMAND(skb->data)) {
194 	case CAPI_CONF:
195 		if (skb->len < CAPI_MSG_BASELEN + 10)
196 			break;
197 
198 		func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 5);
199 		info = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 8);
200 
201 		switch (func) {
202 		case CAPI_FUNCTION_REGISTER:
203 			msgnum = CAPIMSG_MSGID(skb->data);
204 
205 			application = cmtp_application_get(session, CMTP_MSGNUM, msgnum);
206 			if (application) {
207 				application->state = BT_CONNECTED;
208 				application->msgnum = 0;
209 				application->mapping = CAPIMSG_APPID(skb->data);
210 				wake_up_interruptible(&session->wait);
211 			}
212 
213 			break;
214 
215 		case CAPI_FUNCTION_RELEASE:
216 			appl = CAPIMSG_APPID(skb->data);
217 
218 			application = cmtp_application_get(session, CMTP_MAPPING, appl);
219 			if (application) {
220 				application->state = BT_CLOSED;
221 				application->msgnum = 0;
222 				wake_up_interruptible(&session->wait);
223 			}
224 
225 			break;
226 
227 		case CAPI_FUNCTION_GET_PROFILE:
228 			if (skb->len < CAPI_MSG_BASELEN + 11 + sizeof(capi_profile))
229 				break;
230 
231 			controller = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 11);
232 			msgnum = CAPIMSG_MSGID(skb->data);
233 
234 			if (!info && (msgnum == CMTP_INITIAL_MSGNUM)) {
235 				session->ncontroller = controller;
236 				wake_up_interruptible(&session->wait);
237 				break;
238 			}
239 
240 			if (!info && ctrl) {
241 				memcpy(&ctrl->profile,
242 					skb->data + CAPI_MSG_BASELEN + 11,
243 					sizeof(capi_profile));
244 				session->state = BT_CONNECTED;
245 				capi_ctr_ready(ctrl);
246 			}
247 
248 			break;
249 
250 		case CAPI_FUNCTION_GET_MANUFACTURER:
251 			if (!info && ctrl && skb->len > CAPI_MSG_BASELEN + 14)
252 				strscpy_pad(ctrl->manu,
253 					    skb->data + CAPI_MSG_BASELEN + 15,
254 					    skb->data[CAPI_MSG_BASELEN + 14]);
255 			break;
256 
257 		case CAPI_FUNCTION_GET_VERSION:
258 			if (skb->len < CAPI_MSG_BASELEN + 32)
259 				break;
260 
261 			if (!info && ctrl) {
262 				ctrl->version.majorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 16);
263 				ctrl->version.minorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 20);
264 				ctrl->version.majormanuversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 24);
265 				ctrl->version.minormanuversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 28);
266 			}
267 
268 			break;
269 
270 		case CAPI_FUNCTION_GET_SERIAL_NUMBER:
271 			if (!info && ctrl && skb->len > CAPI_MSG_BASELEN + 16)
272 				strscpy_pad(ctrl->serial,
273 					    skb->data + CAPI_MSG_BASELEN + 17,
274 					    skb->data[CAPI_MSG_BASELEN + 16]);
275 			break;
276 		}
277 
278 		break;
279 
280 	case CAPI_IND:
281 		if (skb->len < CAPI_MSG_BASELEN + 6)
282 			break;
283 
284 		func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 3);
285 
286 		if (func == CAPI_FUNCTION_LOOPBACK) {
287 			int len = min_t(uint, skb->len - CAPI_MSG_BASELEN - 6,
288 						skb->data[CAPI_MSG_BASELEN + 5]);
289 			appl = CAPIMSG_APPID(skb->data);
290 			msgnum = CAPIMSG_MSGID(skb->data);
291 			cmtp_send_interopmsg(session, CAPI_RESP, appl, msgnum, func,
292 						skb->data + CAPI_MSG_BASELEN + 6, len);
293 		}
294 
295 		break;
296 	}
297 
298 	kfree_skb(skb);
299 }
300 
cmtp_recv_capimsg(struct cmtp_session * session,struct sk_buff * skb)301 void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb)
302 {
303 	struct capi_ctr *ctrl = &session->ctrl;
304 	struct cmtp_application *application;
305 	__u16 appl;
306 	__u32 contr;
307 
308 	BT_DBG("session %p skb %p len %u", session, skb, skb->len);
309 
310 	if (skb->len < CAPI_MSG_BASELEN)
311 		return;
312 
313 	if (CAPIMSG_COMMAND(skb->data) == CAPI_INTEROPERABILITY) {
314 		cmtp_recv_interopmsg(session, skb);
315 		return;
316 	}
317 
318 	if (session->flags & BIT(CMTP_LOOPBACK)) {
319 		kfree_skb(skb);
320 		return;
321 	}
322 
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 %u", 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 	capi_ctr_handle_message(ctrl, appl, skb);
342 }
343 
cmtp_load_firmware(struct capi_ctr * ctrl,capiloaddata * data)344 static int cmtp_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
345 {
346 	BT_DBG("ctrl %p data %p", ctrl, data);
347 
348 	return 0;
349 }
350 
cmtp_reset_ctr(struct capi_ctr * ctrl)351 static void cmtp_reset_ctr(struct capi_ctr *ctrl)
352 {
353 	struct cmtp_session *session = ctrl->driverdata;
354 
355 	BT_DBG("ctrl %p", ctrl);
356 
357 	capi_ctr_down(ctrl);
358 
359 	atomic_inc(&session->terminate);
360 	wake_up_process(session->task);
361 }
362 
cmtp_register_appl(struct capi_ctr * ctrl,__u16 appl,capi_register_params * rp)363 static void cmtp_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp)
364 {
365 	DECLARE_WAITQUEUE(wait, current);
366 	struct cmtp_session *session = ctrl->driverdata;
367 	struct cmtp_application *application;
368 	unsigned long timeo = CMTP_INTEROP_TIMEOUT;
369 	unsigned char buf[8];
370 	int err = 0, nconn, want = rp->level3cnt;
371 
372 	BT_DBG("ctrl %p appl %u level3cnt %u datablkcnt %u datablklen %u",
373 	       ctrl, appl, rp->level3cnt, rp->datablkcnt, rp->datablklen);
374 
375 	application = cmtp_application_add(session, appl);
376 	if (!application) {
377 		BT_ERR("Can't allocate memory for new application");
378 		return;
379 	}
380 
381 	if (want < 0)
382 		nconn = ctrl->profile.nbchannel * -want;
383 	else
384 		nconn = want;
385 
386 	if (nconn == 0)
387 		nconn = ctrl->profile.nbchannel;
388 
389 	capimsg_setu16(buf, 0, nconn);
390 	capimsg_setu16(buf, 2, rp->datablkcnt);
391 	capimsg_setu16(buf, 4, rp->datablklen);
392 
393 	application->state = BT_CONFIG;
394 	application->msgnum = cmtp_msgnum_get(session);
395 
396 	cmtp_send_interopmsg(session, CAPI_REQ, 0x0000, application->msgnum,
397 				CAPI_FUNCTION_REGISTER, buf, 6);
398 
399 	add_wait_queue(&session->wait, &wait);
400 	while (1) {
401 		set_current_state(TASK_INTERRUPTIBLE);
402 
403 		if (!timeo) {
404 			err = -EAGAIN;
405 			break;
406 		}
407 
408 		if (application->state == BT_CLOSED) {
409 			err = -application->err;
410 			break;
411 		}
412 
413 		if (application->state == BT_CONNECTED)
414 			break;
415 
416 		if (signal_pending(current)) {
417 			err = -EINTR;
418 			break;
419 		}
420 
421 		timeo = schedule_timeout(timeo);
422 	}
423 	set_current_state(TASK_RUNNING);
424 	remove_wait_queue(&session->wait, &wait);
425 
426 	if (err) {
427 		cmtp_application_del(session, application);
428 		return;
429 	}
430 }
431 
cmtp_release_appl(struct capi_ctr * ctrl,__u16 appl)432 static void cmtp_release_appl(struct capi_ctr *ctrl, __u16 appl)
433 {
434 	struct cmtp_session *session = ctrl->driverdata;
435 	struct cmtp_application *application;
436 
437 	BT_DBG("ctrl %p appl %u", ctrl, appl);
438 
439 	application = cmtp_application_get(session, CMTP_APPLID, appl);
440 	if (!application) {
441 		BT_ERR("Can't find application");
442 		return;
443 	}
444 
445 	application->msgnum = cmtp_msgnum_get(session);
446 
447 	cmtp_send_interopmsg(session, CAPI_REQ, application->mapping, application->msgnum,
448 				CAPI_FUNCTION_RELEASE, NULL, 0);
449 
450 	wait_event_interruptible_timeout(session->wait,
451 			(application->state == BT_CLOSED), CMTP_INTEROP_TIMEOUT);
452 
453 	cmtp_application_del(session, application);
454 }
455 
cmtp_send_message(struct capi_ctr * ctrl,struct sk_buff * skb)456 static u16 cmtp_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
457 {
458 	struct cmtp_session *session = ctrl->driverdata;
459 	struct cmtp_application *application;
460 	__u16 appl;
461 	__u32 contr;
462 
463 	BT_DBG("ctrl %p skb %p", ctrl, skb);
464 
465 	appl = CAPIMSG_APPID(skb->data);
466 	contr = CAPIMSG_CONTROL(skb->data);
467 
468 	application = cmtp_application_get(session, CMTP_APPLID, appl);
469 	if ((!application) || (application->state != BT_CONNECTED)) {
470 		BT_ERR("Can't find application with id %u", appl);
471 		return CAPI_ILLAPPNR;
472 	}
473 
474 	CAPIMSG_SETAPPID(skb->data, application->mapping);
475 
476 	if ((contr & 0x7f) == session->num) {
477 		contr = (contr & 0xffffff80) | 0x01;
478 		CAPIMSG_SETCONTROL(skb->data, contr);
479 	}
480 
481 	cmtp_send_capimsg(session, skb);
482 
483 	return CAPI_NOERROR;
484 }
485 
cmtp_procinfo(struct capi_ctr * ctrl)486 static char *cmtp_procinfo(struct capi_ctr *ctrl)
487 {
488 	return "CAPI Message Transport Protocol";
489 }
490 
cmtp_proc_show(struct seq_file * m,void * v)491 static int cmtp_proc_show(struct seq_file *m, void *v)
492 {
493 	struct capi_ctr *ctrl = m->private;
494 	struct cmtp_session *session = ctrl->driverdata;
495 	struct cmtp_application *app;
496 
497 	seq_printf(m, "%s\n\n", cmtp_procinfo(ctrl));
498 	seq_printf(m, "addr %s\n", session->name);
499 	seq_printf(m, "ctrl %d\n", session->num);
500 
501 	list_for_each_entry(app, &session->applications, list) {
502 		seq_printf(m, "appl %u -> %u\n", app->appl, app->mapping);
503 	}
504 
505 	return 0;
506 }
507 
cmtp_attach_device(struct cmtp_session * session)508 int cmtp_attach_device(struct cmtp_session *session)
509 {
510 	unsigned char buf[4];
511 	long ret;
512 
513 	BT_DBG("session %p", session);
514 
515 	capimsg_setu32(buf, 0, 0);
516 
517 	cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, CMTP_INITIAL_MSGNUM,
518 				CAPI_FUNCTION_GET_PROFILE, buf, 4);
519 
520 	ret = wait_event_interruptible_timeout(session->wait,
521 			session->ncontroller, CMTP_INTEROP_TIMEOUT);
522 
523 	BT_INFO("Found %d CAPI controller(s) on device %s", session->ncontroller, session->name);
524 
525 	if (!ret)
526 		return -ETIMEDOUT;
527 
528 	if (!session->ncontroller)
529 		return -ENODEV;
530 
531 	if (session->ncontroller > 1)
532 		BT_INFO("Setting up only CAPI controller 1");
533 
534 	session->ctrl.owner      = THIS_MODULE;
535 	session->ctrl.driverdata = session;
536 	strcpy(session->ctrl.name, session->name);
537 
538 	session->ctrl.driver_name   = "cmtp";
539 	session->ctrl.load_firmware = cmtp_load_firmware;
540 	session->ctrl.reset_ctr     = cmtp_reset_ctr;
541 	session->ctrl.register_appl = cmtp_register_appl;
542 	session->ctrl.release_appl  = cmtp_release_appl;
543 	session->ctrl.send_message  = cmtp_send_message;
544 
545 	session->ctrl.procinfo      = cmtp_procinfo;
546 	session->ctrl.proc_show     = cmtp_proc_show;
547 
548 	if (attach_capi_ctr(&session->ctrl) < 0) {
549 		BT_ERR("Can't attach new controller");
550 		return -EBUSY;
551 	}
552 
553 	session->num = session->ctrl.cnr;
554 
555 	BT_DBG("session %p num %d", session, session->num);
556 
557 	capimsg_setu32(buf, 0, 1);
558 
559 	cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
560 				CAPI_FUNCTION_GET_MANUFACTURER, buf, 4);
561 
562 	cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
563 				CAPI_FUNCTION_GET_VERSION, buf, 4);
564 
565 	cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
566 				CAPI_FUNCTION_GET_SERIAL_NUMBER, buf, 4);
567 
568 	cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
569 				CAPI_FUNCTION_GET_PROFILE, buf, 4);
570 
571 	return 0;
572 }
573 
cmtp_detach_device(struct cmtp_session * session)574 void cmtp_detach_device(struct cmtp_session *session)
575 {
576 	BT_DBG("session %p", session);
577 
578 	detach_capi_ctr(&session->ctrl);
579 }
580