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/module.h>
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>
39 #include <linux/isdn/capilli.h>
40 #include <linux/isdn/capicmd.h>
41 #include <linux/isdn/capiutil.h>
45 #ifndef CONFIG_BT_CMTP_DEBUG
50 #define CAPI_INTEROPERABILITY 0x20
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)
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)
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
74 #define CMTP_MAPPING 3
76 static struct cmtp_application *cmtp_application_add(struct cmtp_session *session, __u16 appl)
78 struct cmtp_application *app = kzalloc(sizeof(*app), GFP_KERNEL);
80 BT_DBG("session %p application %p appl %d", session, app, appl);
88 list_add_tail(&app->list, &session->applications);
93 static void cmtp_application_del(struct cmtp_session *session, struct cmtp_application *app)
95 BT_DBG("session %p application %p", session, app);
103 static struct cmtp_application *cmtp_application_get(struct cmtp_session *session, int pattern, __u16 value)
105 struct cmtp_application *app;
106 struct list_head *p, *n;
108 list_for_each_safe(p, n, &session->applications) {
109 app = list_entry(p, struct cmtp_application, list);
112 if (app->msgnum == value)
116 if (app->appl == value)
120 if (app->mapping == value)
129 static int cmtp_msgnum_get(struct cmtp_session *session)
133 if ((session->msgnum & 0xff) > 200)
134 session->msgnum = CMTP_INITIAL_MSGNUM + 1;
136 return session->msgnum;
139 static void cmtp_send_capimsg(struct cmtp_session *session, struct sk_buff *skb)
141 struct cmtp_scb *scb = (void *) skb->cb;
143 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
146 scb->data = (CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3);
148 skb_queue_tail(&session->transmit, skb);
150 cmtp_schedule(session);
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)
160 BT_DBG("session %p subcmd 0x%02x appl %d msgnum %d", session, subcmd, appl, msgnum);
162 if (!(skb = alloc_skb(CAPI_MSG_BASELEN + 6 + len, GFP_ATOMIC))) {
163 BT_ERR("Can't allocate memory for interoperability packet");
167 s = skb_put(skb, CAPI_MSG_BASELEN + 6 + len);
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);
175 /* Interoperability selector (Bluetooth Device Management) */
176 capimsg_setu16(s, 8, 0x0001);
178 capimsg_setu8 (s, 10, 3 + len);
179 capimsg_setu16(s, 11, function);
180 capimsg_setu8 (s, 13, len);
183 memcpy(s + 14, buf, len);
185 cmtp_send_capimsg(session, skb);
188 static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *skb)
190 struct capi_ctr *ctrl = &session->ctrl;
191 struct cmtp_application *application;
192 __u16 appl, msgnum, func, info;
195 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
197 switch (CAPIMSG_SUBCOMMAND(skb->data)) {
199 if (skb->len < CAPI_MSG_BASELEN + 10)
202 func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 5);
203 info = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 8);
206 case CAPI_FUNCTION_REGISTER:
207 msgnum = CAPIMSG_MSGID(skb->data);
209 application = cmtp_application_get(session, CMTP_MSGNUM, msgnum);
211 application->state = BT_CONNECTED;
212 application->msgnum = 0;
213 application->mapping = CAPIMSG_APPID(skb->data);
214 wake_up_interruptible(&session->wait);
219 case CAPI_FUNCTION_RELEASE:
220 appl = CAPIMSG_APPID(skb->data);
222 application = cmtp_application_get(session, CMTP_MAPPING, appl);
224 application->state = BT_CLOSED;
225 application->msgnum = 0;
226 wake_up_interruptible(&session->wait);
231 case CAPI_FUNCTION_GET_PROFILE:
232 if (skb->len < CAPI_MSG_BASELEN + 11 + sizeof(capi_profile))
235 controller = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 11);
236 msgnum = CAPIMSG_MSGID(skb->data);
238 if (!info && (msgnum == CMTP_INITIAL_MSGNUM)) {
239 session->ncontroller = controller;
240 wake_up_interruptible(&session->wait);
245 memcpy(&ctrl->profile,
246 skb->data + CAPI_MSG_BASELEN + 11,
247 sizeof(capi_profile));
248 session->state = BT_CONNECTED;
249 capi_ctr_ready(ctrl);
254 case CAPI_FUNCTION_GET_MANUFACTURER:
255 if (skb->len < CAPI_MSG_BASELEN + 15)
258 controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 10);
261 int len = min_t(uint, CAPI_MANUFACTURER_LEN,
262 skb->data[CAPI_MSG_BASELEN + 14]);
264 memset(ctrl->manu, 0, CAPI_MANUFACTURER_LEN);
266 skb->data + CAPI_MSG_BASELEN + 15, len);
271 case CAPI_FUNCTION_GET_VERSION:
272 if (skb->len < CAPI_MSG_BASELEN + 32)
275 controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12);
278 ctrl->version.majorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 16);
279 ctrl->version.minorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 20);
280 ctrl->version.majormanuversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 24);
281 ctrl->version.minormanuversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 28);
286 case CAPI_FUNCTION_GET_SERIAL_NUMBER:
287 if (skb->len < CAPI_MSG_BASELEN + 17)
290 controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12);
293 int len = min_t(uint, CAPI_SERIAL_LEN,
294 skb->data[CAPI_MSG_BASELEN + 16]);
296 memset(ctrl->serial, 0, CAPI_SERIAL_LEN);
297 strncpy(ctrl->serial,
298 skb->data + CAPI_MSG_BASELEN + 17, len);
307 if (skb->len < CAPI_MSG_BASELEN + 6)
310 func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 3);
312 if (func == CAPI_FUNCTION_LOOPBACK) {
313 int len = min_t(uint, skb->len - CAPI_MSG_BASELEN - 6,
314 skb->data[CAPI_MSG_BASELEN + 5]);
315 appl = CAPIMSG_APPID(skb->data);
316 msgnum = CAPIMSG_MSGID(skb->data);
317 cmtp_send_interopmsg(session, CAPI_RESP, appl, msgnum, func,
318 skb->data + CAPI_MSG_BASELEN + 6, len);
327 void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb)
329 struct capi_ctr *ctrl = &session->ctrl;
330 struct cmtp_application *application;
334 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
336 if (skb->len < CAPI_MSG_BASELEN)
339 if (CAPIMSG_COMMAND(skb->data) == CAPI_INTEROPERABILITY) {
340 cmtp_recv_interopmsg(session, skb);
344 if (session->flags & (1 << CMTP_LOOPBACK)) {
349 cmd = CAPICMD(CAPIMSG_COMMAND(skb->data), CAPIMSG_SUBCOMMAND(skb->data));
350 appl = CAPIMSG_APPID(skb->data);
351 contr = CAPIMSG_CONTROL(skb->data);
353 application = cmtp_application_get(session, CMTP_MAPPING, appl);
355 appl = application->appl;
356 CAPIMSG_SETAPPID(skb->data, appl);
358 BT_ERR("Can't find application with id %d", appl);
363 if ((contr & 0x7f) == 0x01) {
364 contr = (contr & 0xffffff80) | session->num;
365 CAPIMSG_SETCONTROL(skb->data, contr);
369 BT_ERR("Can't find controller %d for message", session->num);
374 capi_ctr_handle_message(ctrl, appl, skb);
377 static int cmtp_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
379 BT_DBG("ctrl %p data %p", ctrl, data);
384 static void cmtp_reset_ctr(struct capi_ctr *ctrl)
386 struct cmtp_session *session = ctrl->driverdata;
388 BT_DBG("ctrl %p", ctrl);
390 capi_ctr_reseted(ctrl);
392 atomic_inc(&session->terminate);
393 cmtp_schedule(session);
396 static void cmtp_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp)
398 DECLARE_WAITQUEUE(wait, current);
399 struct cmtp_session *session = ctrl->driverdata;
400 struct cmtp_application *application;
401 unsigned long timeo = CMTP_INTEROP_TIMEOUT;
402 unsigned char buf[8];
403 int err = 0, nconn, want = rp->level3cnt;
405 BT_DBG("ctrl %p appl %d level3cnt %d datablkcnt %d datablklen %d",
406 ctrl, appl, rp->level3cnt, rp->datablkcnt, rp->datablklen);
408 application = cmtp_application_add(session, appl);
410 BT_ERR("Can't allocate memory for new application");
415 nconn = ctrl->profile.nbchannel * -want;
420 nconn = ctrl->profile.nbchannel;
422 capimsg_setu16(buf, 0, nconn);
423 capimsg_setu16(buf, 2, rp->datablkcnt);
424 capimsg_setu16(buf, 4, rp->datablklen);
426 application->state = BT_CONFIG;
427 application->msgnum = cmtp_msgnum_get(session);
429 cmtp_send_interopmsg(session, CAPI_REQ, 0x0000, application->msgnum,
430 CAPI_FUNCTION_REGISTER, buf, 6);
432 add_wait_queue(&session->wait, &wait);
434 set_current_state(TASK_INTERRUPTIBLE);
441 if (application->state == BT_CLOSED) {
442 err = -application->err;
446 if (application->state == BT_CONNECTED)
449 if (signal_pending(current)) {
454 timeo = schedule_timeout(timeo);
456 set_current_state(TASK_RUNNING);
457 remove_wait_queue(&session->wait, &wait);
460 cmtp_application_del(session, application);
465 static void cmtp_release_appl(struct capi_ctr *ctrl, __u16 appl)
467 struct cmtp_session *session = ctrl->driverdata;
468 struct cmtp_application *application;
470 BT_DBG("ctrl %p appl %d", ctrl, appl);
472 application = cmtp_application_get(session, CMTP_APPLID, appl);
474 BT_ERR("Can't find application");
478 application->msgnum = cmtp_msgnum_get(session);
480 cmtp_send_interopmsg(session, CAPI_REQ, application->mapping, application->msgnum,
481 CAPI_FUNCTION_RELEASE, NULL, 0);
483 wait_event_interruptible_timeout(session->wait,
484 (application->state == BT_CLOSED), CMTP_INTEROP_TIMEOUT);
486 cmtp_application_del(session, application);
489 static u16 cmtp_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
491 struct cmtp_session *session = ctrl->driverdata;
492 struct cmtp_application *application;
496 BT_DBG("ctrl %p skb %p", ctrl, skb);
498 appl = CAPIMSG_APPID(skb->data);
499 contr = CAPIMSG_CONTROL(skb->data);
501 application = cmtp_application_get(session, CMTP_APPLID, appl);
502 if ((!application) || (application->state != BT_CONNECTED)) {
503 BT_ERR("Can't find application with id %d", appl);
504 return CAPI_ILLAPPNR;
507 CAPIMSG_SETAPPID(skb->data, application->mapping);
509 if ((contr & 0x7f) == session->num) {
510 contr = (contr & 0xffffff80) | 0x01;
511 CAPIMSG_SETCONTROL(skb->data, contr);
514 cmtp_send_capimsg(session, skb);
519 static char *cmtp_procinfo(struct capi_ctr *ctrl)
521 return "CAPI Message Transport Protocol";
524 static int cmtp_ctr_read_proc(char *page, char **start, off_t off, int count, int *eof, struct capi_ctr *ctrl)
526 struct cmtp_session *session = ctrl->driverdata;
527 struct cmtp_application *app;
528 struct list_head *p, *n;
531 len += sprintf(page + len, "%s\n\n", cmtp_procinfo(ctrl));
532 len += sprintf(page + len, "addr %s\n", session->name);
533 len += sprintf(page + len, "ctrl %d\n", session->num);
535 list_for_each_safe(p, n, &session->applications) {
536 app = list_entry(p, struct cmtp_application, list);
537 len += sprintf(page + len, "appl %d -> %d\n", app->appl, app->mapping);
540 if (off + count >= len)
548 return ((count < len - off) ? count : len - off);
552 int cmtp_attach_device(struct cmtp_session *session)
554 unsigned char buf[4];
557 BT_DBG("session %p", session);
559 capimsg_setu32(buf, 0, 0);
561 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, CMTP_INITIAL_MSGNUM,
562 CAPI_FUNCTION_GET_PROFILE, buf, 4);
564 ret = wait_event_interruptible_timeout(session->wait,
565 session->ncontroller, CMTP_INTEROP_TIMEOUT);
567 BT_INFO("Found %d CAPI controller(s) on device %s", session->ncontroller, session->name);
572 if (!session->ncontroller)
575 if (session->ncontroller > 1)
576 BT_INFO("Setting up only CAPI controller 1");
578 session->ctrl.owner = THIS_MODULE;
579 session->ctrl.driverdata = session;
580 strcpy(session->ctrl.name, session->name);
582 session->ctrl.driver_name = "cmtp";
583 session->ctrl.load_firmware = cmtp_load_firmware;
584 session->ctrl.reset_ctr = cmtp_reset_ctr;
585 session->ctrl.register_appl = cmtp_register_appl;
586 session->ctrl.release_appl = cmtp_release_appl;
587 session->ctrl.send_message = cmtp_send_message;
589 session->ctrl.procinfo = cmtp_procinfo;
590 session->ctrl.ctr_read_proc = cmtp_ctr_read_proc;
592 if (attach_capi_ctr(&session->ctrl) < 0) {
593 BT_ERR("Can't attach new controller");
597 session->num = session->ctrl.cnr;
599 BT_DBG("session %p num %d", session, session->num);
601 capimsg_setu32(buf, 0, 1);
603 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
604 CAPI_FUNCTION_GET_MANUFACTURER, buf, 4);
606 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
607 CAPI_FUNCTION_GET_VERSION, buf, 4);
609 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
610 CAPI_FUNCTION_GET_SERIAL_NUMBER, buf, 4);
612 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
613 CAPI_FUNCTION_GET_PROFILE, buf, 4);
618 void cmtp_detach_device(struct cmtp_session *session)
620 BT_DBG("session %p", session);
622 detach_capi_ctr(&session->ctrl);