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