Remove obsolete #include <linux/config.h>
[linux-2.6/verdex.git] / net / bluetooth / cmtp / capi.c
blob6fb47e00e188bb2c292f3d7e94a7689651b832f8
1 /*
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>
37 #include <net/sock.h>
39 #include <linux/isdn/capilli.h>
40 #include <linux/isdn/capicmd.h>
41 #include <linux/isdn/capiutil.h>
43 #include "cmtp.h"
45 #ifndef CONFIG_BT_CMTP_DEBUG
46 #undef BT_DBG
47 #define BT_DBG(D...)
48 #endif
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
72 #define CMTP_MSGNUM 1
73 #define CMTP_APPLID 2
74 #define CMTP_MAPPING 3
76 static struct cmtp_application *cmtp_application_add(struct cmtp_session *session, __u16 appl)
78 struct cmtp_application *app = kmalloc(sizeof(*app), GFP_KERNEL);
80 BT_DBG("session %p application %p appl %d", session, app, appl);
82 if (!app)
83 return NULL;
85 memset(app, 0, sizeof(*app));
87 app->state = BT_OPEN;
88 app->appl = appl;
90 list_add_tail(&app->list, &session->applications);
92 return app;
95 static void cmtp_application_del(struct cmtp_session *session, struct cmtp_application *app)
97 BT_DBG("session %p application %p", session, app);
99 if (app) {
100 list_del(&app->list);
101 kfree(app);
105 static struct cmtp_application *cmtp_application_get(struct cmtp_session *session, int pattern, __u16 value)
107 struct cmtp_application *app;
108 struct list_head *p, *n;
110 list_for_each_safe(p, n, &session->applications) {
111 app = list_entry(p, struct cmtp_application, list);
112 switch (pattern) {
113 case CMTP_MSGNUM:
114 if (app->msgnum == value)
115 return app;
116 break;
117 case CMTP_APPLID:
118 if (app->appl == value)
119 return app;
120 break;
121 case CMTP_MAPPING:
122 if (app->mapping == value)
123 return app;
124 break;
128 return NULL;
131 static int cmtp_msgnum_get(struct cmtp_session *session)
133 session->msgnum++;
135 if ((session->msgnum & 0xff) > 200)
136 session->msgnum = CMTP_INITIAL_MSGNUM + 1;
138 return session->msgnum;
141 static void cmtp_send_capimsg(struct cmtp_session *session, struct sk_buff *skb)
143 struct cmtp_scb *scb = (void *) skb->cb;
145 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
147 scb->id = -1;
148 scb->data = (CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3);
150 skb_queue_tail(&session->transmit, skb);
152 cmtp_schedule(session);
155 static void cmtp_send_interopmsg(struct cmtp_session *session,
156 __u8 subcmd, __u16 appl, __u16 msgnum,
157 __u16 function, unsigned char *buf, int len)
159 struct sk_buff *skb;
160 unsigned char *s;
162 BT_DBG("session %p subcmd 0x%02x appl %d msgnum %d", session, subcmd, appl, msgnum);
164 if (!(skb = alloc_skb(CAPI_MSG_BASELEN + 6 + len, GFP_ATOMIC))) {
165 BT_ERR("Can't allocate memory for interoperability packet");
166 return;
169 s = skb_put(skb, CAPI_MSG_BASELEN + 6 + len);
171 capimsg_setu16(s, 0, CAPI_MSG_BASELEN + 6 + len);
172 capimsg_setu16(s, 2, appl);
173 capimsg_setu8 (s, 4, CAPI_INTEROPERABILITY);
174 capimsg_setu8 (s, 5, subcmd);
175 capimsg_setu16(s, 6, msgnum);
177 /* Interoperability selector (Bluetooth Device Management) */
178 capimsg_setu16(s, 8, 0x0001);
180 capimsg_setu8 (s, 10, 3 + len);
181 capimsg_setu16(s, 11, function);
182 capimsg_setu8 (s, 13, len);
184 if (len > 0)
185 memcpy(s + 14, buf, len);
187 cmtp_send_capimsg(session, skb);
190 static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *skb)
192 struct capi_ctr *ctrl = &session->ctrl;
193 struct cmtp_application *application;
194 __u16 appl, msgnum, func, info;
195 __u32 controller;
197 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
199 switch (CAPIMSG_SUBCOMMAND(skb->data)) {
200 case CAPI_CONF:
201 func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 5);
202 info = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 8);
204 switch (func) {
205 case CAPI_FUNCTION_REGISTER:
206 msgnum = CAPIMSG_MSGID(skb->data);
208 application = cmtp_application_get(session, CMTP_MSGNUM, msgnum);
209 if (application) {
210 application->state = BT_CONNECTED;
211 application->msgnum = 0;
212 application->mapping = CAPIMSG_APPID(skb->data);
213 wake_up_interruptible(&session->wait);
216 break;
218 case CAPI_FUNCTION_RELEASE:
219 appl = CAPIMSG_APPID(skb->data);
221 application = cmtp_application_get(session, CMTP_MAPPING, appl);
222 if (application) {
223 application->state = BT_CLOSED;
224 application->msgnum = 0;
225 wake_up_interruptible(&session->wait);
228 break;
230 case CAPI_FUNCTION_GET_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);
237 break;
240 if (!info && ctrl) {
241 memcpy(&ctrl->profile,
242 skb->data + CAPI_MSG_BASELEN + 11,
243 sizeof(capi_profile));
244 session->state = BT_CONNECTED;
245 capi_ctr_ready(ctrl);
248 break;
250 case CAPI_FUNCTION_GET_MANUFACTURER:
251 controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 10);
253 if (!info && ctrl) {
254 strncpy(ctrl->manu,
255 skb->data + CAPI_MSG_BASELEN + 15,
256 skb->data[CAPI_MSG_BASELEN + 14]);
259 break;
261 case CAPI_FUNCTION_GET_VERSION:
262 controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12);
264 if (!info && ctrl) {
265 ctrl->version.majorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 16);
266 ctrl->version.minorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 20);
267 ctrl->version.majormanuversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 24);
268 ctrl->version.minormanuversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 28);
271 break;
273 case CAPI_FUNCTION_GET_SERIAL_NUMBER:
274 controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12);
276 if (!info && ctrl) {
277 memset(ctrl->serial, 0, CAPI_SERIAL_LEN);
278 strncpy(ctrl->serial,
279 skb->data + CAPI_MSG_BASELEN + 17,
280 skb->data[CAPI_MSG_BASELEN + 16]);
283 break;
286 break;
288 case CAPI_IND:
289 func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 3);
291 if (func == CAPI_FUNCTION_LOOPBACK) {
292 appl = CAPIMSG_APPID(skb->data);
293 msgnum = CAPIMSG_MSGID(skb->data);
294 cmtp_send_interopmsg(session, CAPI_RESP, appl, msgnum, func,
295 skb->data + CAPI_MSG_BASELEN + 6,
296 skb->data[CAPI_MSG_BASELEN + 5]);
299 break;
302 kfree_skb(skb);
305 void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb)
307 struct capi_ctr *ctrl = &session->ctrl;
308 struct cmtp_application *application;
309 __u16 cmd, appl;
310 __u32 contr;
312 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
314 if (CAPIMSG_COMMAND(skb->data) == CAPI_INTEROPERABILITY) {
315 cmtp_recv_interopmsg(session, skb);
316 return;
319 if (session->flags & (1 << CMTP_LOOPBACK)) {
320 kfree_skb(skb);
321 return;
324 cmd = CAPICMD(CAPIMSG_COMMAND(skb->data), CAPIMSG_SUBCOMMAND(skb->data));
325 appl = CAPIMSG_APPID(skb->data);
326 contr = CAPIMSG_CONTROL(skb->data);
328 application = cmtp_application_get(session, CMTP_MAPPING, appl);
329 if (application) {
330 appl = application->appl;
331 CAPIMSG_SETAPPID(skb->data, appl);
332 } else {
333 BT_ERR("Can't find application with id %d", appl);
334 kfree_skb(skb);
335 return;
338 if ((contr & 0x7f) == 0x01) {
339 contr = (contr & 0xffffff80) | session->num;
340 CAPIMSG_SETCONTROL(skb->data, contr);
343 if (!ctrl) {
344 BT_ERR("Can't find controller %d for message", session->num);
345 kfree_skb(skb);
346 return;
349 capi_ctr_handle_message(ctrl, appl, skb);
352 static int cmtp_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
354 BT_DBG("ctrl %p data %p", ctrl, data);
356 return 0;
359 static void cmtp_reset_ctr(struct capi_ctr *ctrl)
361 struct cmtp_session *session = ctrl->driverdata;
363 BT_DBG("ctrl %p", ctrl);
365 capi_ctr_reseted(ctrl);
367 atomic_inc(&session->terminate);
368 cmtp_schedule(session);
371 static void cmtp_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp)
373 DECLARE_WAITQUEUE(wait, current);
374 struct cmtp_session *session = ctrl->driverdata;
375 struct cmtp_application *application;
376 unsigned long timeo = CMTP_INTEROP_TIMEOUT;
377 unsigned char buf[8];
378 int err = 0, nconn, want = rp->level3cnt;
380 BT_DBG("ctrl %p appl %d level3cnt %d datablkcnt %d datablklen %d",
381 ctrl, appl, rp->level3cnt, rp->datablkcnt, rp->datablklen);
383 application = cmtp_application_add(session, appl);
384 if (!application) {
385 BT_ERR("Can't allocate memory for new application");
386 return;
389 if (want < 0)
390 nconn = ctrl->profile.nbchannel * -want;
391 else
392 nconn = want;
394 if (nconn == 0)
395 nconn = ctrl->profile.nbchannel;
397 capimsg_setu16(buf, 0, nconn);
398 capimsg_setu16(buf, 2, rp->datablkcnt);
399 capimsg_setu16(buf, 4, rp->datablklen);
401 application->state = BT_CONFIG;
402 application->msgnum = cmtp_msgnum_get(session);
404 cmtp_send_interopmsg(session, CAPI_REQ, 0x0000, application->msgnum,
405 CAPI_FUNCTION_REGISTER, buf, 6);
407 add_wait_queue(&session->wait, &wait);
408 while (1) {
409 set_current_state(TASK_INTERRUPTIBLE);
411 if (!timeo) {
412 err = -EAGAIN;
413 break;
416 if (application->state == BT_CLOSED) {
417 err = -application->err;
418 break;
421 if (application->state == BT_CONNECTED)
422 break;
424 if (signal_pending(current)) {
425 err = -EINTR;
426 break;
429 timeo = schedule_timeout(timeo);
431 set_current_state(TASK_RUNNING);
432 remove_wait_queue(&session->wait, &wait);
434 if (err) {
435 cmtp_application_del(session, application);
436 return;
440 static void cmtp_release_appl(struct capi_ctr *ctrl, __u16 appl)
442 struct cmtp_session *session = ctrl->driverdata;
443 struct cmtp_application *application;
445 BT_DBG("ctrl %p appl %d", ctrl, appl);
447 application = cmtp_application_get(session, CMTP_APPLID, appl);
448 if (!application) {
449 BT_ERR("Can't find application");
450 return;
453 application->msgnum = cmtp_msgnum_get(session);
455 cmtp_send_interopmsg(session, CAPI_REQ, application->mapping, application->msgnum,
456 CAPI_FUNCTION_RELEASE, NULL, 0);
458 wait_event_interruptible_timeout(session->wait,
459 (application->state == BT_CLOSED), CMTP_INTEROP_TIMEOUT);
461 cmtp_application_del(session, application);
464 static u16 cmtp_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
466 struct cmtp_session *session = ctrl->driverdata;
467 struct cmtp_application *application;
468 __u16 appl;
469 __u32 contr;
471 BT_DBG("ctrl %p skb %p", ctrl, skb);
473 appl = CAPIMSG_APPID(skb->data);
474 contr = CAPIMSG_CONTROL(skb->data);
476 application = cmtp_application_get(session, CMTP_APPLID, appl);
477 if ((!application) || (application->state != BT_CONNECTED)) {
478 BT_ERR("Can't find application with id %d", appl);
479 return CAPI_ILLAPPNR;
482 CAPIMSG_SETAPPID(skb->data, application->mapping);
484 if ((contr & 0x7f) == session->num) {
485 contr = (contr & 0xffffff80) | 0x01;
486 CAPIMSG_SETCONTROL(skb->data, contr);
489 cmtp_send_capimsg(session, skb);
491 return CAPI_NOERROR;
494 static char *cmtp_procinfo(struct capi_ctr *ctrl)
496 return "CAPI Message Transport Protocol";
499 static int cmtp_ctr_read_proc(char *page, char **start, off_t off, int count, int *eof, struct capi_ctr *ctrl)
501 struct cmtp_session *session = ctrl->driverdata;
502 struct cmtp_application *app;
503 struct list_head *p, *n;
504 int len = 0;
506 len += sprintf(page + len, "%s\n\n", cmtp_procinfo(ctrl));
507 len += sprintf(page + len, "addr %s\n", session->name);
508 len += sprintf(page + len, "ctrl %d\n", session->num);
510 list_for_each_safe(p, n, &session->applications) {
511 app = list_entry(p, struct cmtp_application, list);
512 len += sprintf(page + len, "appl %d -> %d\n", app->appl, app->mapping);
515 if (off + count >= len)
516 *eof = 1;
518 if (len < off)
519 return 0;
521 *start = page + off;
523 return ((count < len - off) ? count : len - off);
527 int cmtp_attach_device(struct cmtp_session *session)
529 unsigned char buf[4];
530 long ret;
532 BT_DBG("session %p", session);
534 capimsg_setu32(buf, 0, 0);
536 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, CMTP_INITIAL_MSGNUM,
537 CAPI_FUNCTION_GET_PROFILE, buf, 4);
539 ret = wait_event_interruptible_timeout(session->wait,
540 session->ncontroller, CMTP_INTEROP_TIMEOUT);
542 BT_INFO("Found %d CAPI controller(s) on device %s", session->ncontroller, session->name);
544 if (!ret)
545 return -ETIMEDOUT;
547 if (!session->ncontroller)
548 return -ENODEV;
550 if (session->ncontroller > 1)
551 BT_INFO("Setting up only CAPI controller 1");
553 session->ctrl.owner = THIS_MODULE;
554 session->ctrl.driverdata = session;
555 strcpy(session->ctrl.name, session->name);
557 session->ctrl.driver_name = "cmtp";
558 session->ctrl.load_firmware = cmtp_load_firmware;
559 session->ctrl.reset_ctr = cmtp_reset_ctr;
560 session->ctrl.register_appl = cmtp_register_appl;
561 session->ctrl.release_appl = cmtp_release_appl;
562 session->ctrl.send_message = cmtp_send_message;
564 session->ctrl.procinfo = cmtp_procinfo;
565 session->ctrl.ctr_read_proc = cmtp_ctr_read_proc;
567 if (attach_capi_ctr(&session->ctrl) < 0) {
568 BT_ERR("Can't attach new controller");
569 return -EBUSY;
572 session->num = session->ctrl.cnr;
574 BT_DBG("session %p num %d", session, session->num);
576 capimsg_setu32(buf, 0, 1);
578 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
579 CAPI_FUNCTION_GET_MANUFACTURER, buf, 4);
581 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
582 CAPI_FUNCTION_GET_VERSION, buf, 4);
584 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
585 CAPI_FUNCTION_GET_SERIAL_NUMBER, buf, 4);
587 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
588 CAPI_FUNCTION_GET_PROFILE, buf, 4);
590 return 0;
593 void cmtp_detach_device(struct cmtp_session *session)
595 BT_DBG("session %p", session);
597 detach_capi_ctr(&session->ctrl);