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 #define CAPI_INTEROPERABILITY 0x20
47 #define CAPI_INTEROPERABILITY_REQ CAPICMD(CAPI_INTEROPERABILITY, CAPI_REQ)
48 #define CAPI_INTEROPERABILITY_CONF CAPICMD(CAPI_INTEROPERABILITY, CAPI_CONF)
49 #define CAPI_INTEROPERABILITY_IND CAPICMD(CAPI_INTEROPERABILITY, CAPI_IND)
50 #define CAPI_INTEROPERABILITY_RESP CAPICMD(CAPI_INTEROPERABILITY, CAPI_RESP)
52 #define CAPI_INTEROPERABILITY_REQ_LEN (CAPI_MSG_BASELEN + 2)
53 #define CAPI_INTEROPERABILITY_CONF_LEN (CAPI_MSG_BASELEN + 4)
54 #define CAPI_INTEROPERABILITY_IND_LEN (CAPI_MSG_BASELEN + 2)
55 #define CAPI_INTEROPERABILITY_RESP_LEN (CAPI_MSG_BASELEN + 2)
57 #define CAPI_FUNCTION_REGISTER 0
58 #define CAPI_FUNCTION_RELEASE 1
59 #define CAPI_FUNCTION_GET_PROFILE 2
60 #define CAPI_FUNCTION_GET_MANUFACTURER 3
61 #define CAPI_FUNCTION_GET_VERSION 4
62 #define CAPI_FUNCTION_GET_SERIAL_NUMBER 5
63 #define CAPI_FUNCTION_MANUFACTURER 6
64 #define CAPI_FUNCTION_LOOPBACK 7
69 #define CMTP_MAPPING 3
71 static struct cmtp_application *cmtp_application_add(struct cmtp_session *session, __u16 appl)
73 struct cmtp_application *app = kzalloc(sizeof(*app), GFP_KERNEL);
75 BT_DBG("session %p application %p appl %d", session, app, appl);
83 list_add_tail(&app->list, &session->applications);
88 static void cmtp_application_del(struct cmtp_session *session, struct cmtp_application *app)
90 BT_DBG("session %p application %p", session, app);
98 static struct cmtp_application *cmtp_application_get(struct cmtp_session *session, int pattern, __u16 value)
100 struct cmtp_application *app;
101 struct list_head *p, *n;
103 list_for_each_safe(p, n, &session->applications) {
104 app = list_entry(p, struct cmtp_application, list);
107 if (app->msgnum == value)
111 if (app->appl == value)
115 if (app->mapping == value)
124 static int cmtp_msgnum_get(struct cmtp_session *session)
128 if ((session->msgnum & 0xff) > 200)
129 session->msgnum = CMTP_INITIAL_MSGNUM + 1;
131 return session->msgnum;
134 static void cmtp_send_capimsg(struct cmtp_session *session, struct sk_buff *skb)
136 struct cmtp_scb *scb = (void *) skb->cb;
138 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
141 scb->data = (CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3);
143 skb_queue_tail(&session->transmit, skb);
145 cmtp_schedule(session);
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)
155 BT_DBG("session %p subcmd 0x%02x appl %d msgnum %d", session, subcmd, appl, msgnum);
157 if (!(skb = alloc_skb(CAPI_MSG_BASELEN + 6 + len, GFP_ATOMIC))) {
158 BT_ERR("Can't allocate memory for interoperability packet");
162 s = skb_put(skb, CAPI_MSG_BASELEN + 6 + len);
164 capimsg_setu16(s, 0, CAPI_MSG_BASELEN + 6 + len);
165 capimsg_setu16(s, 2, appl);
166 capimsg_setu8 (s, 4, CAPI_INTEROPERABILITY);
167 capimsg_setu8 (s, 5, subcmd);
168 capimsg_setu16(s, 6, msgnum);
170 /* Interoperability selector (Bluetooth Device Management) */
171 capimsg_setu16(s, 8, 0x0001);
173 capimsg_setu8 (s, 10, 3 + len);
174 capimsg_setu16(s, 11, function);
175 capimsg_setu8 (s, 13, len);
178 memcpy(s + 14, buf, len);
180 cmtp_send_capimsg(session, skb);
183 static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *skb)
185 struct capi_ctr *ctrl = &session->ctrl;
186 struct cmtp_application *application;
187 __u16 appl, msgnum, func, info;
190 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
192 switch (CAPIMSG_SUBCOMMAND(skb->data)) {
194 if (skb->len < CAPI_MSG_BASELEN + 10)
197 func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 5);
198 info = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 8);
201 case CAPI_FUNCTION_REGISTER:
202 msgnum = CAPIMSG_MSGID(skb->data);
204 application = cmtp_application_get(session, CMTP_MSGNUM, msgnum);
206 application->state = BT_CONNECTED;
207 application->msgnum = 0;
208 application->mapping = CAPIMSG_APPID(skb->data);
209 wake_up_interruptible(&session->wait);
214 case CAPI_FUNCTION_RELEASE:
215 appl = CAPIMSG_APPID(skb->data);
217 application = cmtp_application_get(session, CMTP_MAPPING, appl);
219 application->state = BT_CLOSED;
220 application->msgnum = 0;
221 wake_up_interruptible(&session->wait);
226 case CAPI_FUNCTION_GET_PROFILE:
227 if (skb->len < CAPI_MSG_BASELEN + 11 + sizeof(capi_profile))
230 controller = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 11);
231 msgnum = CAPIMSG_MSGID(skb->data);
233 if (!info && (msgnum == CMTP_INITIAL_MSGNUM)) {
234 session->ncontroller = controller;
235 wake_up_interruptible(&session->wait);
240 memcpy(&ctrl->profile,
241 skb->data + CAPI_MSG_BASELEN + 11,
242 sizeof(capi_profile));
243 session->state = BT_CONNECTED;
244 capi_ctr_ready(ctrl);
249 case CAPI_FUNCTION_GET_MANUFACTURER:
250 if (skb->len < CAPI_MSG_BASELEN + 15)
253 controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 10);
256 int len = min_t(uint, CAPI_MANUFACTURER_LEN,
257 skb->data[CAPI_MSG_BASELEN + 14]);
259 memset(ctrl->manu, 0, CAPI_MANUFACTURER_LEN);
261 skb->data + CAPI_MSG_BASELEN + 15, len);
266 case CAPI_FUNCTION_GET_VERSION:
267 if (skb->len < CAPI_MSG_BASELEN + 32)
270 controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12);
273 ctrl->version.majorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 16);
274 ctrl->version.minorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 20);
275 ctrl->version.majormanuversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 24);
276 ctrl->version.minormanuversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 28);
281 case CAPI_FUNCTION_GET_SERIAL_NUMBER:
282 if (skb->len < CAPI_MSG_BASELEN + 17)
285 controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12);
288 int len = min_t(uint, CAPI_SERIAL_LEN,
289 skb->data[CAPI_MSG_BASELEN + 16]);
291 memset(ctrl->serial, 0, CAPI_SERIAL_LEN);
292 strncpy(ctrl->serial,
293 skb->data + CAPI_MSG_BASELEN + 17, len);
302 if (skb->len < CAPI_MSG_BASELEN + 6)
305 func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 3);
307 if (func == CAPI_FUNCTION_LOOPBACK) {
308 int len = min_t(uint, skb->len - CAPI_MSG_BASELEN - 6,
309 skb->data[CAPI_MSG_BASELEN + 5]);
310 appl = CAPIMSG_APPID(skb->data);
311 msgnum = CAPIMSG_MSGID(skb->data);
312 cmtp_send_interopmsg(session, CAPI_RESP, appl, msgnum, func,
313 skb->data + CAPI_MSG_BASELEN + 6, len);
322 void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb)
324 struct capi_ctr *ctrl = &session->ctrl;
325 struct cmtp_application *application;
329 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
331 if (skb->len < CAPI_MSG_BASELEN)
334 if (CAPIMSG_COMMAND(skb->data) == CAPI_INTEROPERABILITY) {
335 cmtp_recv_interopmsg(session, skb);
339 if (session->flags & (1 << CMTP_LOOPBACK)) {
344 cmd = CAPICMD(CAPIMSG_COMMAND(skb->data), CAPIMSG_SUBCOMMAND(skb->data));
345 appl = CAPIMSG_APPID(skb->data);
346 contr = CAPIMSG_CONTROL(skb->data);
348 application = cmtp_application_get(session, CMTP_MAPPING, appl);
350 appl = application->appl;
351 CAPIMSG_SETAPPID(skb->data, appl);
353 BT_ERR("Can't find application with id %d", appl);
358 if ((contr & 0x7f) == 0x01) {
359 contr = (contr & 0xffffff80) | session->num;
360 CAPIMSG_SETCONTROL(skb->data, contr);
364 BT_ERR("Can't find controller %d for message", session->num);
369 capi_ctr_handle_message(ctrl, appl, skb);
372 static int cmtp_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
374 BT_DBG("ctrl %p data %p", ctrl, data);
379 static void cmtp_reset_ctr(struct capi_ctr *ctrl)
381 struct cmtp_session *session = ctrl->driverdata;
383 BT_DBG("ctrl %p", ctrl);
387 atomic_inc(&session->terminate);
388 cmtp_schedule(session);
391 static void cmtp_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp)
393 DECLARE_WAITQUEUE(wait, current);
394 struct cmtp_session *session = ctrl->driverdata;
395 struct cmtp_application *application;
396 unsigned long timeo = CMTP_INTEROP_TIMEOUT;
397 unsigned char buf[8];
398 int err = 0, nconn, want = rp->level3cnt;
400 BT_DBG("ctrl %p appl %d level3cnt %d datablkcnt %d datablklen %d",
401 ctrl, appl, rp->level3cnt, rp->datablkcnt, rp->datablklen);
403 application = cmtp_application_add(session, appl);
405 BT_ERR("Can't allocate memory for new application");
410 nconn = ctrl->profile.nbchannel * -want;
415 nconn = ctrl->profile.nbchannel;
417 capimsg_setu16(buf, 0, nconn);
418 capimsg_setu16(buf, 2, rp->datablkcnt);
419 capimsg_setu16(buf, 4, rp->datablklen);
421 application->state = BT_CONFIG;
422 application->msgnum = cmtp_msgnum_get(session);
424 cmtp_send_interopmsg(session, CAPI_REQ, 0x0000, application->msgnum,
425 CAPI_FUNCTION_REGISTER, buf, 6);
427 add_wait_queue(&session->wait, &wait);
429 set_current_state(TASK_INTERRUPTIBLE);
436 if (application->state == BT_CLOSED) {
437 err = -application->err;
441 if (application->state == BT_CONNECTED)
444 if (signal_pending(current)) {
449 timeo = schedule_timeout(timeo);
451 set_current_state(TASK_RUNNING);
452 remove_wait_queue(&session->wait, &wait);
455 cmtp_application_del(session, application);
460 static void cmtp_release_appl(struct capi_ctr *ctrl, __u16 appl)
462 struct cmtp_session *session = ctrl->driverdata;
463 struct cmtp_application *application;
465 BT_DBG("ctrl %p appl %d", ctrl, appl);
467 application = cmtp_application_get(session, CMTP_APPLID, appl);
469 BT_ERR("Can't find application");
473 application->msgnum = cmtp_msgnum_get(session);
475 cmtp_send_interopmsg(session, CAPI_REQ, application->mapping, application->msgnum,
476 CAPI_FUNCTION_RELEASE, NULL, 0);
478 wait_event_interruptible_timeout(session->wait,
479 (application->state == BT_CLOSED), CMTP_INTEROP_TIMEOUT);
481 cmtp_application_del(session, application);
484 static u16 cmtp_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
486 struct cmtp_session *session = ctrl->driverdata;
487 struct cmtp_application *application;
491 BT_DBG("ctrl %p skb %p", ctrl, skb);
493 appl = CAPIMSG_APPID(skb->data);
494 contr = CAPIMSG_CONTROL(skb->data);
496 application = cmtp_application_get(session, CMTP_APPLID, appl);
497 if ((!application) || (application->state != BT_CONNECTED)) {
498 BT_ERR("Can't find application with id %d", appl);
499 return CAPI_ILLAPPNR;
502 CAPIMSG_SETAPPID(skb->data, application->mapping);
504 if ((contr & 0x7f) == session->num) {
505 contr = (contr & 0xffffff80) | 0x01;
506 CAPIMSG_SETCONTROL(skb->data, contr);
509 cmtp_send_capimsg(session, skb);
514 static char *cmtp_procinfo(struct capi_ctr *ctrl)
516 return "CAPI Message Transport Protocol";
519 static int cmtp_ctr_read_proc(char *page, char **start, off_t off, int count, int *eof, struct capi_ctr *ctrl)
521 struct cmtp_session *session = ctrl->driverdata;
522 struct cmtp_application *app;
523 struct list_head *p, *n;
526 len += sprintf(page + len, "%s\n\n", cmtp_procinfo(ctrl));
527 len += sprintf(page + len, "addr %s\n", session->name);
528 len += sprintf(page + len, "ctrl %d\n", session->num);
530 list_for_each_safe(p, n, &session->applications) {
531 app = list_entry(p, struct cmtp_application, list);
532 len += sprintf(page + len, "appl %d -> %d\n", app->appl, app->mapping);
535 if (off + count >= len)
543 return ((count < len - off) ? count : len - off);
547 int cmtp_attach_device(struct cmtp_session *session)
549 unsigned char buf[4];
552 BT_DBG("session %p", session);
554 capimsg_setu32(buf, 0, 0);
556 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, CMTP_INITIAL_MSGNUM,
557 CAPI_FUNCTION_GET_PROFILE, buf, 4);
559 ret = wait_event_interruptible_timeout(session->wait,
560 session->ncontroller, CMTP_INTEROP_TIMEOUT);
562 BT_INFO("Found %d CAPI controller(s) on device %s", session->ncontroller, session->name);
567 if (!session->ncontroller)
570 if (session->ncontroller > 1)
571 BT_INFO("Setting up only CAPI controller 1");
573 session->ctrl.owner = THIS_MODULE;
574 session->ctrl.driverdata = session;
575 strcpy(session->ctrl.name, session->name);
577 session->ctrl.driver_name = "cmtp";
578 session->ctrl.load_firmware = cmtp_load_firmware;
579 session->ctrl.reset_ctr = cmtp_reset_ctr;
580 session->ctrl.register_appl = cmtp_register_appl;
581 session->ctrl.release_appl = cmtp_release_appl;
582 session->ctrl.send_message = cmtp_send_message;
584 session->ctrl.procinfo = cmtp_procinfo;
585 session->ctrl.ctr_read_proc = cmtp_ctr_read_proc;
587 if (attach_capi_ctr(&session->ctrl) < 0) {
588 BT_ERR("Can't attach new controller");
592 session->num = session->ctrl.cnr;
594 BT_DBG("session %p num %d", session, session->num);
596 capimsg_setu32(buf, 0, 1);
598 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
599 CAPI_FUNCTION_GET_MANUFACTURER, buf, 4);
601 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
602 CAPI_FUNCTION_GET_VERSION, buf, 4);
604 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
605 CAPI_FUNCTION_GET_SERIAL_NUMBER, buf, 4);
607 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
608 CAPI_FUNCTION_GET_PROFILE, buf, 4);
613 void cmtp_detach_device(struct cmtp_session *session)
615 BT_DBG("session %p", session);
617 detach_capi_ctr(&session->ctrl);