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/export.h>
24 #include <linux/proc_fs.h>
25 #include <linux/seq_file.h>
26 #include <linux/types.h>
27 #include <linux/errno.h>
28 #include <linux/kernel.h>
29 #include <linux/sched.h>
30 #include <linux/slab.h>
31 #include <linux/poll.h>
32 #include <linux/fcntl.h>
33 #include <linux/skbuff.h>
34 #include <linux/socket.h>
35 #include <linux/ioctl.h>
36 #include <linux/file.h>
37 #include <linux/wait.h>
38 #include <linux/kthread.h>
41 #include <linux/isdn/capilli.h>
42 #include <linux/isdn/capicmd.h>
43 #include <linux/isdn/capiutil.h>
47 #define CAPI_INTEROPERABILITY 0x20
49 #define CAPI_INTEROPERABILITY_REQ CAPICMD(CAPI_INTEROPERABILITY, CAPI_REQ)
50 #define CAPI_INTEROPERABILITY_CONF CAPICMD(CAPI_INTEROPERABILITY, CAPI_CONF)
51 #define CAPI_INTEROPERABILITY_IND CAPICMD(CAPI_INTEROPERABILITY, CAPI_IND)
52 #define CAPI_INTEROPERABILITY_RESP CAPICMD(CAPI_INTEROPERABILITY, CAPI_RESP)
54 #define CAPI_INTEROPERABILITY_REQ_LEN (CAPI_MSG_BASELEN + 2)
55 #define CAPI_INTEROPERABILITY_CONF_LEN (CAPI_MSG_BASELEN + 4)
56 #define CAPI_INTEROPERABILITY_IND_LEN (CAPI_MSG_BASELEN + 2)
57 #define CAPI_INTEROPERABILITY_RESP_LEN (CAPI_MSG_BASELEN + 2)
59 #define CAPI_FUNCTION_REGISTER 0
60 #define CAPI_FUNCTION_RELEASE 1
61 #define CAPI_FUNCTION_GET_PROFILE 2
62 #define CAPI_FUNCTION_GET_MANUFACTURER 3
63 #define CAPI_FUNCTION_GET_VERSION 4
64 #define CAPI_FUNCTION_GET_SERIAL_NUMBER 5
65 #define CAPI_FUNCTION_MANUFACTURER 6
66 #define CAPI_FUNCTION_LOOPBACK 7
71 #define CMTP_MAPPING 3
73 static struct cmtp_application *cmtp_application_add(struct cmtp_session *session, __u16 appl)
75 struct cmtp_application *app = kzalloc(sizeof(*app), GFP_KERNEL);
77 BT_DBG("session %p application %p appl %d", session, app, appl);
85 list_add_tail(&app->list, &session->applications);
90 static void cmtp_application_del(struct cmtp_session *session, struct cmtp_application *app)
92 BT_DBG("session %p application %p", session, app);
100 static struct cmtp_application *cmtp_application_get(struct cmtp_session *session, int pattern, __u16 value)
102 struct cmtp_application *app;
105 list_for_each(p, &session->applications) {
106 app = list_entry(p, struct cmtp_application, list);
109 if (app->msgnum == value)
113 if (app->appl == value)
117 if (app->mapping == value)
126 static int cmtp_msgnum_get(struct cmtp_session *session)
130 if ((session->msgnum & 0xff) > 200)
131 session->msgnum = CMTP_INITIAL_MSGNUM + 1;
133 return session->msgnum;
136 static void cmtp_send_capimsg(struct cmtp_session *session, struct sk_buff *skb)
138 struct cmtp_scb *scb = (void *) skb->cb;
140 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
143 scb->data = (CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3);
145 skb_queue_tail(&session->transmit, skb);
147 wake_up_interruptible(sk_sleep(session->sock->sk));
150 static void cmtp_send_interopmsg(struct cmtp_session *session,
151 __u8 subcmd, __u16 appl, __u16 msgnum,
152 __u16 function, unsigned char *buf, int len)
157 BT_DBG("session %p subcmd 0x%02x appl %d msgnum %d", session, subcmd, appl, msgnum);
159 skb = alloc_skb(CAPI_MSG_BASELEN + 6 + len, GFP_ATOMIC);
161 BT_ERR("Can't allocate memory for interoperability packet");
165 s = skb_put(skb, CAPI_MSG_BASELEN + 6 + len);
167 capimsg_setu16(s, 0, CAPI_MSG_BASELEN + 6 + len);
168 capimsg_setu16(s, 2, appl);
169 capimsg_setu8 (s, 4, CAPI_INTEROPERABILITY);
170 capimsg_setu8 (s, 5, subcmd);
171 capimsg_setu16(s, 6, msgnum);
173 /* Interoperability selector (Bluetooth Device Management) */
174 capimsg_setu16(s, 8, 0x0001);
176 capimsg_setu8 (s, 10, 3 + len);
177 capimsg_setu16(s, 11, function);
178 capimsg_setu8 (s, 13, len);
181 memcpy(s + 14, buf, len);
183 cmtp_send_capimsg(session, skb);
186 static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *skb)
188 struct capi_ctr *ctrl = &session->ctrl;
189 struct cmtp_application *application;
190 __u16 appl, msgnum, func, info;
193 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
195 switch (CAPIMSG_SUBCOMMAND(skb->data)) {
197 if (skb->len < CAPI_MSG_BASELEN + 10)
200 func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 5);
201 info = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 8);
204 case CAPI_FUNCTION_REGISTER:
205 msgnum = CAPIMSG_MSGID(skb->data);
207 application = cmtp_application_get(session, CMTP_MSGNUM, msgnum);
209 application->state = BT_CONNECTED;
210 application->msgnum = 0;
211 application->mapping = CAPIMSG_APPID(skb->data);
212 wake_up_interruptible(&session->wait);
217 case CAPI_FUNCTION_RELEASE:
218 appl = CAPIMSG_APPID(skb->data);
220 application = cmtp_application_get(session, CMTP_MAPPING, appl);
222 application->state = BT_CLOSED;
223 application->msgnum = 0;
224 wake_up_interruptible(&session->wait);
229 case CAPI_FUNCTION_GET_PROFILE:
230 if (skb->len < CAPI_MSG_BASELEN + 11 + sizeof(capi_profile))
233 controller = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 11);
234 msgnum = CAPIMSG_MSGID(skb->data);
236 if (!info && (msgnum == CMTP_INITIAL_MSGNUM)) {
237 session->ncontroller = controller;
238 wake_up_interruptible(&session->wait);
243 memcpy(&ctrl->profile,
244 skb->data + CAPI_MSG_BASELEN + 11,
245 sizeof(capi_profile));
246 session->state = BT_CONNECTED;
247 capi_ctr_ready(ctrl);
252 case CAPI_FUNCTION_GET_MANUFACTURER:
253 if (skb->len < CAPI_MSG_BASELEN + 15)
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)
272 ctrl->version.majorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 16);
273 ctrl->version.minorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 20);
274 ctrl->version.majormanuversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 24);
275 ctrl->version.minormanuversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 28);
280 case CAPI_FUNCTION_GET_SERIAL_NUMBER:
281 if (skb->len < CAPI_MSG_BASELEN + 17)
285 int len = min_t(uint, CAPI_SERIAL_LEN,
286 skb->data[CAPI_MSG_BASELEN + 16]);
288 memset(ctrl->serial, 0, CAPI_SERIAL_LEN);
289 strncpy(ctrl->serial,
290 skb->data + CAPI_MSG_BASELEN + 17, len);
299 if (skb->len < CAPI_MSG_BASELEN + 6)
302 func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 3);
304 if (func == CAPI_FUNCTION_LOOPBACK) {
305 int len = min_t(uint, skb->len - CAPI_MSG_BASELEN - 6,
306 skb->data[CAPI_MSG_BASELEN + 5]);
307 appl = CAPIMSG_APPID(skb->data);
308 msgnum = CAPIMSG_MSGID(skb->data);
309 cmtp_send_interopmsg(session, CAPI_RESP, appl, msgnum, func,
310 skb->data + CAPI_MSG_BASELEN + 6, len);
319 void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb)
321 struct capi_ctr *ctrl = &session->ctrl;
322 struct cmtp_application *application;
326 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
328 if (skb->len < CAPI_MSG_BASELEN)
331 if (CAPIMSG_COMMAND(skb->data) == CAPI_INTEROPERABILITY) {
332 cmtp_recv_interopmsg(session, skb);
336 if (session->flags & BIT(CMTP_LOOPBACK)) {
341 appl = CAPIMSG_APPID(skb->data);
342 contr = CAPIMSG_CONTROL(skb->data);
344 application = cmtp_application_get(session, CMTP_MAPPING, appl);
346 appl = application->appl;
347 CAPIMSG_SETAPPID(skb->data, appl);
349 BT_ERR("Can't find application with id %d", appl);
354 if ((contr & 0x7f) == 0x01) {
355 contr = (contr & 0xffffff80) | session->num;
356 CAPIMSG_SETCONTROL(skb->data, contr);
359 capi_ctr_handle_message(ctrl, appl, skb);
362 static int cmtp_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
364 BT_DBG("ctrl %p data %p", ctrl, data);
369 static void cmtp_reset_ctr(struct capi_ctr *ctrl)
371 struct cmtp_session *session = ctrl->driverdata;
373 BT_DBG("ctrl %p", ctrl);
377 atomic_inc(&session->terminate);
378 wake_up_process(session->task);
381 static void cmtp_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp)
383 DECLARE_WAITQUEUE(wait, current);
384 struct cmtp_session *session = ctrl->driverdata;
385 struct cmtp_application *application;
386 unsigned long timeo = CMTP_INTEROP_TIMEOUT;
387 unsigned char buf[8];
388 int err = 0, nconn, want = rp->level3cnt;
390 BT_DBG("ctrl %p appl %d level3cnt %d datablkcnt %d datablklen %d",
391 ctrl, appl, rp->level3cnt, rp->datablkcnt, rp->datablklen);
393 application = cmtp_application_add(session, appl);
395 BT_ERR("Can't allocate memory for new application");
400 nconn = ctrl->profile.nbchannel * -want;
405 nconn = ctrl->profile.nbchannel;
407 capimsg_setu16(buf, 0, nconn);
408 capimsg_setu16(buf, 2, rp->datablkcnt);
409 capimsg_setu16(buf, 4, rp->datablklen);
411 application->state = BT_CONFIG;
412 application->msgnum = cmtp_msgnum_get(session);
414 cmtp_send_interopmsg(session, CAPI_REQ, 0x0000, application->msgnum,
415 CAPI_FUNCTION_REGISTER, buf, 6);
417 add_wait_queue(&session->wait, &wait);
419 set_current_state(TASK_INTERRUPTIBLE);
426 if (application->state == BT_CLOSED) {
427 err = -application->err;
431 if (application->state == BT_CONNECTED)
434 if (signal_pending(current)) {
439 timeo = schedule_timeout(timeo);
441 set_current_state(TASK_RUNNING);
442 remove_wait_queue(&session->wait, &wait);
445 cmtp_application_del(session, application);
450 static void cmtp_release_appl(struct capi_ctr *ctrl, __u16 appl)
452 struct cmtp_session *session = ctrl->driverdata;
453 struct cmtp_application *application;
455 BT_DBG("ctrl %p appl %d", ctrl, appl);
457 application = cmtp_application_get(session, CMTP_APPLID, appl);
459 BT_ERR("Can't find application");
463 application->msgnum = cmtp_msgnum_get(session);
465 cmtp_send_interopmsg(session, CAPI_REQ, application->mapping, application->msgnum,
466 CAPI_FUNCTION_RELEASE, NULL, 0);
468 wait_event_interruptible_timeout(session->wait,
469 (application->state == BT_CLOSED), CMTP_INTEROP_TIMEOUT);
471 cmtp_application_del(session, application);
474 static u16 cmtp_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
476 struct cmtp_session *session = ctrl->driverdata;
477 struct cmtp_application *application;
481 BT_DBG("ctrl %p skb %p", ctrl, skb);
483 appl = CAPIMSG_APPID(skb->data);
484 contr = CAPIMSG_CONTROL(skb->data);
486 application = cmtp_application_get(session, CMTP_APPLID, appl);
487 if ((!application) || (application->state != BT_CONNECTED)) {
488 BT_ERR("Can't find application with id %d", appl);
489 return CAPI_ILLAPPNR;
492 CAPIMSG_SETAPPID(skb->data, application->mapping);
494 if ((contr & 0x7f) == session->num) {
495 contr = (contr & 0xffffff80) | 0x01;
496 CAPIMSG_SETCONTROL(skb->data, contr);
499 cmtp_send_capimsg(session, skb);
504 static char *cmtp_procinfo(struct capi_ctr *ctrl)
506 return "CAPI Message Transport Protocol";
509 static int cmtp_proc_show(struct seq_file *m, void *v)
511 struct capi_ctr *ctrl = m->private;
512 struct cmtp_session *session = ctrl->driverdata;
513 struct cmtp_application *app;
516 seq_printf(m, "%s\n\n", cmtp_procinfo(ctrl));
517 seq_printf(m, "addr %s\n", session->name);
518 seq_printf(m, "ctrl %d\n", session->num);
520 list_for_each(p, &session->applications) {
521 app = list_entry(p, struct cmtp_application, list);
522 seq_printf(m, "appl %d -> %d\n", app->appl, app->mapping);
528 static int cmtp_proc_open(struct inode *inode, struct file *file)
530 return single_open(file, cmtp_proc_show, PDE_DATA(inode));
533 static const struct file_operations cmtp_proc_fops = {
534 .owner = THIS_MODULE,
535 .open = cmtp_proc_open,
538 .release = single_release,
541 int cmtp_attach_device(struct cmtp_session *session)
543 unsigned char buf[4];
546 BT_DBG("session %p", session);
548 capimsg_setu32(buf, 0, 0);
550 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, CMTP_INITIAL_MSGNUM,
551 CAPI_FUNCTION_GET_PROFILE, buf, 4);
553 ret = wait_event_interruptible_timeout(session->wait,
554 session->ncontroller, CMTP_INTEROP_TIMEOUT);
556 BT_INFO("Found %d CAPI controller(s) on device %s", session->ncontroller, session->name);
561 if (!session->ncontroller)
564 if (session->ncontroller > 1)
565 BT_INFO("Setting up only CAPI controller 1");
567 session->ctrl.owner = THIS_MODULE;
568 session->ctrl.driverdata = session;
569 strcpy(session->ctrl.name, session->name);
571 session->ctrl.driver_name = "cmtp";
572 session->ctrl.load_firmware = cmtp_load_firmware;
573 session->ctrl.reset_ctr = cmtp_reset_ctr;
574 session->ctrl.register_appl = cmtp_register_appl;
575 session->ctrl.release_appl = cmtp_release_appl;
576 session->ctrl.send_message = cmtp_send_message;
578 session->ctrl.procinfo = cmtp_procinfo;
579 session->ctrl.proc_fops = &cmtp_proc_fops;
581 if (attach_capi_ctr(&session->ctrl) < 0) {
582 BT_ERR("Can't attach new controller");
586 session->num = session->ctrl.cnr;
588 BT_DBG("session %p num %d", session, session->num);
590 capimsg_setu32(buf, 0, 1);
592 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
593 CAPI_FUNCTION_GET_MANUFACTURER, buf, 4);
595 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
596 CAPI_FUNCTION_GET_VERSION, buf, 4);
598 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
599 CAPI_FUNCTION_GET_SERIAL_NUMBER, buf, 4);
601 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
602 CAPI_FUNCTION_GET_PROFILE, buf, 4);
607 void cmtp_detach_device(struct cmtp_session *session)
609 BT_DBG("session %p", session);
611 detach_capi_ctr(&session->ctrl);