2 CMTP implementation for Linux Bluetooth stack (BlueZ).
3 Copyright (C) 2002-2003 Marcel Holtmann <marcel@holtmann.org>
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;
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.
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.
23 #include <linux/config.h>
24 #include <linux/module.h>
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>
40 #include <linux/capi.h>
42 #include "../drivers/isdn/avmb1/capilli.h"
43 #include "../drivers/isdn/avmb1/capicmd.h"
44 #include "../drivers/isdn/avmb1/capiutil.h"
48 #ifndef CONFIG_BLUEZ_CMTP_DEBUG
53 #define REVISION "1.0"
55 #define CAPI_INTEROPERABILITY 0x20
57 #define CAPI_INTEROPERABILITY_REQ CAPICMD(CAPI_INTEROPERABILITY, CAPI_REQ)
58 #define CAPI_INTEROPERABILITY_CONF CAPICMD(CAPI_INTEROPERABILITY, CAPI_CONF)
59 #define CAPI_INTEROPERABILITY_IND CAPICMD(CAPI_INTEROPERABILITY, CAPI_IND)
60 #define CAPI_INTEROPERABILITY_RESP CAPICMD(CAPI_INTEROPERABILITY, CAPI_RESP)
62 #define CAPI_INTEROPERABILITY_REQ_LEN (CAPI_MSG_BASELEN + 2)
63 #define CAPI_INTEROPERABILITY_CONF_LEN (CAPI_MSG_BASELEN + 4)
64 #define CAPI_INTEROPERABILITY_IND_LEN (CAPI_MSG_BASELEN + 2)
65 #define CAPI_INTEROPERABILITY_RESP_LEN (CAPI_MSG_BASELEN + 2)
67 #define CAPI_FUNCTION_REGISTER 0
68 #define CAPI_FUNCTION_RELEASE 1
69 #define CAPI_FUNCTION_GET_PROFILE 2
70 #define CAPI_FUNCTION_GET_MANUFACTURER 3
71 #define CAPI_FUNCTION_GET_VERSION 4
72 #define CAPI_FUNCTION_GET_SERIAL_NUMBER 5
73 #define CAPI_FUNCTION_MANUFACTURER 6
74 #define CAPI_FUNCTION_LOOPBACK 7
76 static struct capi_driver_interface *di;
81 #define CMTP_MAPPING 3
83 static struct cmtp_application *cmtp_application_add(struct cmtp_session *session, __u16 appl)
85 struct cmtp_application *app = kmalloc(sizeof(*app), GFP_KERNEL);
87 BT_DBG("session %p application %p appl %d", session, app, appl);
92 memset(app, 0, sizeof(*app));
97 list_add_tail(&app->list, &session->applications);
102 static void cmtp_application_del(struct cmtp_session *session, struct cmtp_application *app)
104 BT_DBG("session %p application %p", session, app);
107 list_del(&app->list);
112 static struct cmtp_application *cmtp_application_get(struct cmtp_session *session, int pattern, __u16 value)
114 struct cmtp_application *app;
115 struct list_head *p, *n;
117 list_for_each_safe(p, n, &session->applications) {
118 app = list_entry(p, struct cmtp_application, list);
121 if (app->msgnum == value)
125 if (app->appl == value)
129 if (app->mapping == value)
138 static int cmtp_msgnum_get(struct cmtp_session *session)
142 if ((session->msgnum & 0xff) > 200)
143 session->msgnum = CMTP_INITIAL_MSGNUM + 1;
145 return session->msgnum;
149 static void cmtp_send_interopmsg(struct cmtp_session *session,
150 __u8 subcmd, __u16 appl, __u16 msgnum,
151 __u16 function, unsigned char *buf, int len)
156 BT_DBG("session %p subcmd 0x%02x appl %d msgnum %d", session, subcmd, appl, msgnum);
158 if (!(skb = alloc_skb(CAPI_MSG_BASELEN + 6 + len, GFP_ATOMIC))) {
159 BT_ERR("Can't allocate memory for interoperability packet");
163 s = skb_put(skb, CAPI_MSG_BASELEN + 6 + len);
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);
171 /* Interoperability selector (Bluetooth Device Management) */
172 capimsg_setu16(s, 8, 0x0001);
174 capimsg_setu8 (s, 10, 3 + len);
175 capimsg_setu16(s, 11, function);
176 capimsg_setu8 (s, 13, len);
179 memcpy(s + 14, buf, len);
181 cmtp_send_capimsg(session, skb);
184 static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *skb)
186 struct capi_ctr *ctrl = session->ctrl;
187 struct cmtp_application *application;
188 __u16 appl, msgnum, func, info;
191 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
193 switch (CAPIMSG_SUBCOMMAND(skb->data)) {
195 if (skb->len < CAPI_MSG_BASELEN + 10)
198 func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 5);
199 info = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 8);
202 case CAPI_FUNCTION_REGISTER:
203 msgnum = CAPIMSG_MSGID(skb->data);
205 application = cmtp_application_get(session, CMTP_MSGNUM, msgnum);
207 application->state = BT_CONNECTED;
208 application->msgnum = 0;
209 application->mapping = CAPIMSG_APPID(skb->data);
210 wake_up_interruptible(&session->wait);
215 case CAPI_FUNCTION_RELEASE:
216 appl = CAPIMSG_APPID(skb->data);
218 application = cmtp_application_get(session, CMTP_MAPPING, appl);
220 application->state = BT_CLOSED;
221 application->msgnum = 0;
222 wake_up_interruptible(&session->wait);
227 case CAPI_FUNCTION_GET_PROFILE:
228 if (skb->len < CAPI_MSG_BASELEN + 11 + sizeof(capi_profile))
231 controller = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 11);
232 msgnum = CAPIMSG_MSGID(skb->data);
234 if (!info && (msgnum == CMTP_INITIAL_MSGNUM)) {
235 session->ncontroller = controller;
236 wake_up_interruptible(&session->wait);
241 memcpy(&ctrl->profile,
242 skb->data + CAPI_MSG_BASELEN + 11,
243 sizeof(capi_profile));
244 session->state = BT_CONNECTED;
250 case CAPI_FUNCTION_GET_MANUFACTURER:
251 if (skb->len < CAPI_MSG_BASELEN + 15)
254 controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 10);
257 int len = min_t(uint, CAPI_MANUFACTURER_LEN,
258 skb->data[CAPI_MSG_BASELEN + 14]);
260 memset(ctrl->manu, 0, CAPI_MANUFACTURER_LEN);
262 skb->data + CAPI_MSG_BASELEN + 15, len);
267 case CAPI_FUNCTION_GET_VERSION:
268 if (skb->len < CAPI_MSG_BASELEN + 32)
271 controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12);
274 ctrl->version.majorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 16);
275 ctrl->version.minorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 20);
276 ctrl->version.majormanuversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 24);
277 ctrl->version.minormanuversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 28);
282 case CAPI_FUNCTION_GET_SERIAL_NUMBER:
283 if (skb->len < CAPI_MSG_BASELEN + 17)
286 controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12);
289 int len = min_t(uint, CAPI_SERIAL_LEN,
290 skb->data[CAPI_MSG_BASELEN + 16]);
292 memset(ctrl->serial, 0, CAPI_SERIAL_LEN);
293 strncpy(ctrl->serial,
294 skb->data + CAPI_MSG_BASELEN + 17, len);
303 if (skb->len < CAPI_MSG_BASELEN + 6)
306 func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 3);
308 if (func == CAPI_FUNCTION_LOOPBACK) {
309 int len = min_t(uint, skb->len - CAPI_MSG_BASELEN - 6,
310 skb->data[CAPI_MSG_BASELEN + 5]);
311 appl = CAPIMSG_APPID(skb->data);
312 msgnum = CAPIMSG_MSGID(skb->data);
313 cmtp_send_interopmsg(session, CAPI_RESP, appl, msgnum, func,
314 skb->data + CAPI_MSG_BASELEN + 6, len);
323 void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb)
325 struct capi_ctr *ctrl = session->ctrl;
326 struct cmtp_application *application;
327 __u16 cmd, appl, info;
330 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
332 if (skb->len < CAPI_MSG_BASELEN)
335 if (CAPIMSG_COMMAND(skb->data) == CAPI_INTEROPERABILITY) {
336 cmtp_recv_interopmsg(session, skb);
340 if (session->flags & (1 << CMTP_LOOPBACK)) {
345 cmd = CAPICMD(CAPIMSG_COMMAND(skb->data), CAPIMSG_SUBCOMMAND(skb->data));
346 appl = CAPIMSG_APPID(skb->data);
347 contr = CAPIMSG_CONTROL(skb->data);
349 application = cmtp_application_get(session, CMTP_MAPPING, appl);
351 appl = application->appl;
352 CAPIMSG_SETAPPID(skb->data, appl);
354 BT_ERR("Can't find application with id %d", appl);
359 if ((contr & 0x7f) == 0x01) {
360 contr = (contr & 0xffffff80) | session->num;
361 CAPIMSG_SETCONTROL(skb->data, contr);
365 BT_ERR("Can't find controller %d for message", session->num);
371 case CAPI_CONNECT_B3_CONF:
372 ncci = CAPIMSG_NCCI(skb->data);
373 info = CAPIMSG_U16(skb->data, 12);
375 BT_DBG("CONNECT_B3_CONF ncci 0x%02x info 0x%02x", ncci, info);
378 ctrl->new_ncci(ctrl, appl, ncci, 8);
380 ctrl->handle_capimsg(ctrl, appl, skb);
383 case CAPI_CONNECT_B3_IND:
384 ncci = CAPIMSG_NCCI(skb->data);
386 BT_DBG("CONNECT_B3_IND ncci 0x%02x", ncci);
388 ctrl->new_ncci(ctrl, appl, ncci, 8);
389 ctrl->handle_capimsg(ctrl, appl, skb);
392 case CAPI_DISCONNECT_B3_IND:
393 ncci = CAPIMSG_NCCI(skb->data);
395 BT_DBG("DISCONNECT_B3_IND ncci 0x%02x", ncci);
397 if (ncci == 0xffffffff)
398 BT_ERR("DISCONNECT_B3_IND with ncci 0xffffffff");
400 ctrl->handle_capimsg(ctrl, appl, skb);
401 ctrl->free_ncci(ctrl, appl, ncci);
405 ctrl->handle_capimsg(ctrl, appl, skb);
410 void cmtp_send_capimsg(struct cmtp_session *session, struct sk_buff *skb)
412 struct cmtp_scb *scb = (void *) skb->cb;
414 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
417 scb->data = (CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3);
419 skb_queue_tail(&session->transmit, skb);
421 cmtp_schedule(session);
425 static int cmtp_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
427 BT_DBG("ctrl %p data %p", ctrl, data);
432 static void cmtp_reset_ctr(struct capi_ctr *ctrl)
434 BT_DBG("ctrl %p", ctrl);
439 static void cmtp_remove_ctr(struct capi_ctr *ctrl)
441 struct cmtp_session *session = ctrl->driverdata;
443 BT_DBG("ctrl %p", ctrl);
445 ctrl->suspend_output(ctrl);
447 atomic_inc(&session->terminate);
448 cmtp_schedule(session);
451 static void cmtp_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp)
453 DECLARE_WAITQUEUE(wait, current);
454 struct cmtp_session *session = ctrl->driverdata;
455 struct cmtp_application *application;
456 unsigned long timeo = CMTP_INTEROP_TIMEOUT;
457 unsigned char buf[8];
458 int err = 0, nconn, want = rp->level3cnt;
460 BT_DBG("ctrl %p appl %d level3cnt %d datablkcnt %d datablklen %d",
461 ctrl, appl, rp->level3cnt, rp->datablkcnt, rp->datablklen);
463 application = cmtp_application_add(session, appl);
465 BT_ERR("Can't allocate memory for new application");
466 ctrl->appl_released(ctrl, appl);
471 nconn = ctrl->profile.nbchannel * -want;
476 nconn = ctrl->profile.nbchannel;
478 capimsg_setu16(buf, 0, nconn);
479 capimsg_setu16(buf, 2, rp->datablkcnt);
480 capimsg_setu16(buf, 4, rp->datablklen);
482 application->state = BT_CONFIG;
483 application->msgnum = cmtp_msgnum_get(session);
485 cmtp_send_interopmsg(session, CAPI_REQ, 0x0000, application->msgnum,
486 CAPI_FUNCTION_REGISTER, buf, 6);
488 add_wait_queue(&session->wait, &wait);
490 set_current_state(TASK_INTERRUPTIBLE);
497 if (application->state == BT_CLOSED) {
498 err = -application->err;
502 if (application->state == BT_CONNECTED)
505 if (signal_pending(current)) {
510 timeo = schedule_timeout(timeo);
512 set_current_state(TASK_RUNNING);
513 remove_wait_queue(&session->wait, &wait);
516 ctrl->appl_released(ctrl, appl);
517 cmtp_application_del(session, application);
521 ctrl->appl_registered(ctrl, appl);
524 static void cmtp_release_appl(struct capi_ctr *ctrl, __u16 appl)
526 DECLARE_WAITQUEUE(wait, current);
527 struct cmtp_session *session = ctrl->driverdata;
528 struct cmtp_application *application;
529 unsigned long timeo = CMTP_INTEROP_TIMEOUT;
531 BT_DBG("ctrl %p appl %d", ctrl, appl);
533 application = cmtp_application_get(session, CMTP_APPLID, appl);
535 BT_ERR("Can't find application");
539 application->msgnum = cmtp_msgnum_get(session);
541 cmtp_send_interopmsg(session, CAPI_REQ, application->mapping, application->msgnum,
542 CAPI_FUNCTION_RELEASE, NULL, 0);
544 add_wait_queue(&session->wait, &wait);
546 set_current_state(TASK_INTERRUPTIBLE);
548 if (application->state == BT_CLOSED)
551 if (signal_pending(current))
554 timeo = schedule_timeout(timeo);
556 set_current_state(TASK_RUNNING);
557 remove_wait_queue(&session->wait, &wait);
559 cmtp_application_del(session, application);
560 ctrl->appl_released(ctrl, appl);
563 static void cmtp_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
565 struct cmtp_session *session = ctrl->driverdata;
566 struct cmtp_application *application;
570 BT_DBG("ctrl %p skb %p", ctrl, skb);
572 appl = CAPIMSG_APPID(skb->data);
573 contr = CAPIMSG_CONTROL(skb->data);
575 application = cmtp_application_get(session, CMTP_APPLID, appl);
576 if ((!application) || (application->state != BT_CONNECTED)) {
577 BT_ERR("Can't find application with id %d", appl);
582 CAPIMSG_SETAPPID(skb->data, application->mapping);
584 if ((contr & 0x7f) == session->num) {
585 contr = (contr & 0xffffff80) | 0x01;
586 CAPIMSG_SETCONTROL(skb->data, contr);
589 cmtp_send_capimsg(session, skb);
592 static char *cmtp_procinfo(struct capi_ctr *ctrl)
594 return "CAPI Message Transport Protocol";
597 static int cmtp_ctr_read_proc(char *page, char **start, off_t off, int count, int *eof, struct capi_ctr *ctrl)
599 struct cmtp_session *session = ctrl->driverdata;
600 struct cmtp_application *app;
601 struct list_head *p, *n;
604 len += sprintf(page + len, "%s (Revision %s)\n\n", cmtp_procinfo(ctrl), REVISION);
605 len += sprintf(page + len, "addr %s\n", session->name);
606 len += sprintf(page + len, "ctrl %d\n", session->num);
608 list_for_each_safe(p, n, &session->applications) {
609 app = list_entry(p, struct cmtp_application, list);
610 len += sprintf(page + len, "appl %d -> %d\n", app->appl, app->mapping);
613 if (off + count >= len)
621 return ((count < len - off) ? count : len - off);
624 static struct capi_driver cmtp_driver = {
627 load_firmware: cmtp_load_firmware,
628 reset_ctr: cmtp_reset_ctr,
629 remove_ctr: cmtp_remove_ctr,
630 register_appl: cmtp_register_appl,
631 release_appl: cmtp_release_appl,
632 send_message: cmtp_send_message,
633 procinfo: cmtp_procinfo,
634 ctr_read_proc: cmtp_ctr_read_proc,
641 int cmtp_attach_device(struct cmtp_session *session)
643 DECLARE_WAITQUEUE(wait, current);
644 unsigned long timeo = CMTP_INTEROP_TIMEOUT;
645 unsigned char buf[4];
647 BT_DBG("session %p", session);
649 capimsg_setu32(buf, 0, 0);
651 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, CMTP_INITIAL_MSGNUM,
652 CAPI_FUNCTION_GET_PROFILE, buf, 4);
654 add_wait_queue(&session->wait, &wait);
656 set_current_state(TASK_INTERRUPTIBLE);
658 if (session->ncontroller)
661 if (signal_pending(current))
664 timeo = schedule_timeout(timeo);
666 set_current_state(TASK_RUNNING);
667 remove_wait_queue(&session->wait, &wait);
669 BT_INFO("Found %d CAPI controller(s) on device %s", session->ncontroller, session->name);
674 if (!session->ncontroller)
678 if (session->ncontroller > 1)
679 BT_INFO("Setting up only CAPI controller 1");
681 if (!(session->ctrl = di->attach_ctr(&cmtp_driver, session->name, session))) {
682 BT_ERR("Can't attach new controller");
686 session->num = session->ctrl->cnr;
688 BT_DBG("session %p ctrl %p num %d", session, session->ctrl, session->num);
690 capimsg_setu32(buf, 0, 1);
692 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
693 CAPI_FUNCTION_GET_MANUFACTURER, buf, 4);
695 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
696 CAPI_FUNCTION_GET_VERSION, buf, 4);
698 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
699 CAPI_FUNCTION_GET_SERIAL_NUMBER, buf, 4);
701 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
702 CAPI_FUNCTION_GET_PROFILE, buf, 4);
707 void cmtp_detach_device(struct cmtp_session *session)
709 struct capi_ctr *ctrl = session->ctrl;
711 BT_DBG("session %p ctrl %p", session, ctrl);
718 di->detach_ctr(ctrl);
721 int cmtp_init_capi(void)
723 if (!(di = attach_capi_driver(&cmtp_driver))) {
724 BT_ERR("Can't attach CAPI driver");
731 void cmtp_cleanup_capi(void)
733 detach_capi_driver(&cmtp_driver);