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