Linux-2.6.12-rc2
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / net / bluetooth / cmtp / capi.c
blob1e5c030b72ad3086b7e9e6416359293000656bee
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/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>
38 #include <linux/wait.h>
39 #include <net/sock.h>
41 #include <linux/isdn/capilli.h>
42 #include <linux/isdn/capicmd.h>
43 #include <linux/isdn/capiutil.h>
45 #include "cmtp.h"
47 #ifndef CONFIG_BT_CMTP_DEBUG
48 #undef BT_DBG
49 #define BT_DBG(D...)
50 #endif
52 #define CAPI_INTEROPERABILITY 0x20
54 #define CAPI_INTEROPERABILITY_REQ CAPICMD(CAPI_INTEROPERABILITY, CAPI_REQ)
55 #define CAPI_INTEROPERABILITY_CONF CAPICMD(CAPI_INTEROPERABILITY, CAPI_CONF)
56 #define CAPI_INTEROPERABILITY_IND CAPICMD(CAPI_INTEROPERABILITY, CAPI_IND)
57 #define CAPI_INTEROPERABILITY_RESP CAPICMD(CAPI_INTEROPERABILITY, CAPI_RESP)
59 #define CAPI_INTEROPERABILITY_REQ_LEN (CAPI_MSG_BASELEN + 2)
60 #define CAPI_INTEROPERABILITY_CONF_LEN (CAPI_MSG_BASELEN + 4)
61 #define CAPI_INTEROPERABILITY_IND_LEN (CAPI_MSG_BASELEN + 2)
62 #define CAPI_INTEROPERABILITY_RESP_LEN (CAPI_MSG_BASELEN + 2)
64 #define CAPI_FUNCTION_REGISTER 0
65 #define CAPI_FUNCTION_RELEASE 1
66 #define CAPI_FUNCTION_GET_PROFILE 2
67 #define CAPI_FUNCTION_GET_MANUFACTURER 3
68 #define CAPI_FUNCTION_GET_VERSION 4
69 #define CAPI_FUNCTION_GET_SERIAL_NUMBER 5
70 #define CAPI_FUNCTION_MANUFACTURER 6
71 #define CAPI_FUNCTION_LOOPBACK 7
74 #define CMTP_MSGNUM 1
75 #define CMTP_APPLID 2
76 #define CMTP_MAPPING 3
78 static struct cmtp_application *cmtp_application_add(struct cmtp_session *session, __u16 appl)
80 struct cmtp_application *app = kmalloc(sizeof(*app), GFP_KERNEL);
82 BT_DBG("session %p application %p appl %d", session, app, appl);
84 if (!app)
85 return NULL;
87 memset(app, 0, sizeof(*app));
89 app->state = BT_OPEN;
90 app->appl = appl;
92 list_add_tail(&app->list, &session->applications);
94 return app;
97 static void cmtp_application_del(struct cmtp_session *session, struct cmtp_application *app)
99 BT_DBG("session %p application %p", session, app);
101 if (app) {
102 list_del(&app->list);
103 kfree(app);
107 static struct cmtp_application *cmtp_application_get(struct cmtp_session *session, int pattern, __u16 value)
109 struct cmtp_application *app;
110 struct list_head *p, *n;
112 list_for_each_safe(p, n, &session->applications) {
113 app = list_entry(p, struct cmtp_application, list);
114 switch (pattern) {
115 case CMTP_MSGNUM:
116 if (app->msgnum == value)
117 return app;
118 break;
119 case CMTP_APPLID:
120 if (app->appl == value)
121 return app;
122 break;
123 case CMTP_MAPPING:
124 if (app->mapping == value)
125 return app;
126 break;
130 return NULL;
133 static int cmtp_msgnum_get(struct cmtp_session *session)
135 session->msgnum++;
137 if ((session->msgnum & 0xff) > 200)
138 session->msgnum = CMTP_INITIAL_MSGNUM + 1;
140 return session->msgnum;
143 static void cmtp_send_capimsg(struct cmtp_session *session, struct sk_buff *skb)
145 struct cmtp_scb *scb = (void *) skb->cb;
147 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
149 scb->id = -1;
150 scb->data = (CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3);
152 skb_queue_tail(&session->transmit, skb);
154 cmtp_schedule(session);
157 static void cmtp_send_interopmsg(struct cmtp_session *session,
158 __u8 subcmd, __u16 appl, __u16 msgnum,
159 __u16 function, unsigned char *buf, int len)
161 struct sk_buff *skb;
162 unsigned char *s;
164 BT_DBG("session %p subcmd 0x%02x appl %d msgnum %d", session, subcmd, appl, msgnum);
166 if (!(skb = alloc_skb(CAPI_MSG_BASELEN + 6 + len, GFP_ATOMIC))) {
167 BT_ERR("Can't allocate memory for interoperability packet");
168 return;
171 s = skb_put(skb, CAPI_MSG_BASELEN + 6 + len);
173 capimsg_setu16(s, 0, CAPI_MSG_BASELEN + 6 + len);
174 capimsg_setu16(s, 2, appl);
175 capimsg_setu8 (s, 4, CAPI_INTEROPERABILITY);
176 capimsg_setu8 (s, 5, subcmd);
177 capimsg_setu16(s, 6, msgnum);
179 /* Interoperability selector (Bluetooth Device Management) */
180 capimsg_setu16(s, 8, 0x0001);
182 capimsg_setu8 (s, 10, 3 + len);
183 capimsg_setu16(s, 11, function);
184 capimsg_setu8 (s, 13, len);
186 if (len > 0)
187 memcpy(s + 14, buf, len);
189 cmtp_send_capimsg(session, skb);
192 static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *skb)
194 struct capi_ctr *ctrl = &session->ctrl;
195 struct cmtp_application *application;
196 __u16 appl, msgnum, func, info;
197 __u32 controller;
199 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
201 switch (CAPIMSG_SUBCOMMAND(skb->data)) {
202 case CAPI_CONF:
203 func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 5);
204 info = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 8);
206 switch (func) {
207 case CAPI_FUNCTION_REGISTER:
208 msgnum = CAPIMSG_MSGID(skb->data);
210 application = cmtp_application_get(session, CMTP_MSGNUM, msgnum);
211 if (application) {
212 application->state = BT_CONNECTED;
213 application->msgnum = 0;
214 application->mapping = CAPIMSG_APPID(skb->data);
215 wake_up_interruptible(&session->wait);
218 break;
220 case CAPI_FUNCTION_RELEASE:
221 appl = CAPIMSG_APPID(skb->data);
223 application = cmtp_application_get(session, CMTP_MAPPING, appl);
224 if (application) {
225 application->state = BT_CLOSED;
226 application->msgnum = 0;
227 wake_up_interruptible(&session->wait);
230 break;
232 case CAPI_FUNCTION_GET_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);
239 break;
242 if (!info && ctrl) {
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);
250 break;
252 case CAPI_FUNCTION_GET_MANUFACTURER:
253 controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 10);
255 if (!info && ctrl) {
256 strncpy(ctrl->manu,
257 skb->data + CAPI_MSG_BASELEN + 15,
258 skb->data[CAPI_MSG_BASELEN + 14]);
261 break;
263 case CAPI_FUNCTION_GET_VERSION:
264 controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12);
266 if (!info && ctrl) {
267 ctrl->version.majorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 16);
268 ctrl->version.minorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 20);
269 ctrl->version.majormanuversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 24);
270 ctrl->version.minormanuversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 28);
273 break;
275 case CAPI_FUNCTION_GET_SERIAL_NUMBER:
276 controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12);
278 if (!info && ctrl) {
279 memset(ctrl->serial, 0, CAPI_SERIAL_LEN);
280 strncpy(ctrl->serial,
281 skb->data + CAPI_MSG_BASELEN + 17,
282 skb->data[CAPI_MSG_BASELEN + 16]);
285 break;
288 break;
290 case CAPI_IND:
291 func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 3);
293 if (func == CAPI_FUNCTION_LOOPBACK) {
294 appl = CAPIMSG_APPID(skb->data);
295 msgnum = CAPIMSG_MSGID(skb->data);
296 cmtp_send_interopmsg(session, CAPI_RESP, appl, msgnum, func,
297 skb->data + CAPI_MSG_BASELEN + 6,
298 skb->data[CAPI_MSG_BASELEN + 5]);
301 break;
304 kfree_skb(skb);
307 void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb)
309 struct capi_ctr *ctrl = &session->ctrl;
310 struct cmtp_application *application;
311 __u16 cmd, appl;
312 __u32 contr;
314 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
316 if (CAPIMSG_COMMAND(skb->data) == CAPI_INTEROPERABILITY) {
317 cmtp_recv_interopmsg(session, skb);
318 return;
321 if (session->flags & (1 << CMTP_LOOPBACK)) {
322 kfree_skb(skb);
323 return;
326 cmd = CAPICMD(CAPIMSG_COMMAND(skb->data), CAPIMSG_SUBCOMMAND(skb->data));
327 appl = CAPIMSG_APPID(skb->data);
328 contr = CAPIMSG_CONTROL(skb->data);
330 application = cmtp_application_get(session, CMTP_MAPPING, appl);
331 if (application) {
332 appl = application->appl;
333 CAPIMSG_SETAPPID(skb->data, appl);
334 } else {
335 BT_ERR("Can't find application with id %d", appl);
336 kfree_skb(skb);
337 return;
340 if ((contr & 0x7f) == 0x01) {
341 contr = (contr & 0xffffff80) | session->num;
342 CAPIMSG_SETCONTROL(skb->data, contr);
345 if (!ctrl) {
346 BT_ERR("Can't find controller %d for message", session->num);
347 kfree_skb(skb);
348 return;
351 capi_ctr_handle_message(ctrl, appl, skb);
354 static int cmtp_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
356 BT_DBG("ctrl %p data %p", ctrl, data);
358 return 0;
361 static void cmtp_reset_ctr(struct capi_ctr *ctrl)
363 struct cmtp_session *session = ctrl->driverdata;
365 BT_DBG("ctrl %p", ctrl);
367 capi_ctr_reseted(ctrl);
369 atomic_inc(&session->terminate);
370 cmtp_schedule(session);
373 static void cmtp_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp)
375 DECLARE_WAITQUEUE(wait, current);
376 struct cmtp_session *session = ctrl->driverdata;
377 struct cmtp_application *application;
378 unsigned long timeo = CMTP_INTEROP_TIMEOUT;
379 unsigned char buf[8];
380 int err = 0, nconn, want = rp->level3cnt;
382 BT_DBG("ctrl %p appl %d level3cnt %d datablkcnt %d datablklen %d",
383 ctrl, appl, rp->level3cnt, rp->datablkcnt, rp->datablklen);
385 application = cmtp_application_add(session, appl);
386 if (!application) {
387 BT_ERR("Can't allocate memory for new application");
388 return;
391 if (want < 0)
392 nconn = ctrl->profile.nbchannel * -want;
393 else
394 nconn = want;
396 if (nconn == 0)
397 nconn = ctrl->profile.nbchannel;
399 capimsg_setu16(buf, 0, nconn);
400 capimsg_setu16(buf, 2, rp->datablkcnt);
401 capimsg_setu16(buf, 4, rp->datablklen);
403 application->state = BT_CONFIG;
404 application->msgnum = cmtp_msgnum_get(session);
406 cmtp_send_interopmsg(session, CAPI_REQ, 0x0000, application->msgnum,
407 CAPI_FUNCTION_REGISTER, buf, 6);
409 add_wait_queue(&session->wait, &wait);
410 while (1) {
411 set_current_state(TASK_INTERRUPTIBLE);
413 if (!timeo) {
414 err = -EAGAIN;
415 break;
418 if (application->state == BT_CLOSED) {
419 err = -application->err;
420 break;
423 if (application->state == BT_CONNECTED)
424 break;
426 if (signal_pending(current)) {
427 err = -EINTR;
428 break;
431 timeo = schedule_timeout(timeo);
433 set_current_state(TASK_RUNNING);
434 remove_wait_queue(&session->wait, &wait);
436 if (err) {
437 cmtp_application_del(session, application);
438 return;
442 static void cmtp_release_appl(struct capi_ctr *ctrl, __u16 appl)
444 struct cmtp_session *session = ctrl->driverdata;
445 struct cmtp_application *application;
447 BT_DBG("ctrl %p appl %d", ctrl, appl);
449 application = cmtp_application_get(session, CMTP_APPLID, appl);
450 if (!application) {
451 BT_ERR("Can't find application");
452 return;
455 application->msgnum = cmtp_msgnum_get(session);
457 cmtp_send_interopmsg(session, CAPI_REQ, application->mapping, application->msgnum,
458 CAPI_FUNCTION_RELEASE, NULL, 0);
460 wait_event_interruptible_timeout(session->wait,
461 (application->state == BT_CLOSED), CMTP_INTEROP_TIMEOUT);
463 cmtp_application_del(session, application);
466 static u16 cmtp_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
468 struct cmtp_session *session = ctrl->driverdata;
469 struct cmtp_application *application;
470 __u16 appl;
471 __u32 contr;
473 BT_DBG("ctrl %p skb %p", ctrl, skb);
475 appl = CAPIMSG_APPID(skb->data);
476 contr = CAPIMSG_CONTROL(skb->data);
478 application = cmtp_application_get(session, CMTP_APPLID, appl);
479 if ((!application) || (application->state != BT_CONNECTED)) {
480 BT_ERR("Can't find application with id %d", appl);
481 return CAPI_ILLAPPNR;
484 CAPIMSG_SETAPPID(skb->data, application->mapping);
486 if ((contr & 0x7f) == session->num) {
487 contr = (contr & 0xffffff80) | 0x01;
488 CAPIMSG_SETCONTROL(skb->data, contr);
491 cmtp_send_capimsg(session, skb);
493 return CAPI_NOERROR;
496 static char *cmtp_procinfo(struct capi_ctr *ctrl)
498 return "CAPI Message Transport Protocol";
501 static int cmtp_ctr_read_proc(char *page, char **start, off_t off, int count, int *eof, struct capi_ctr *ctrl)
503 struct cmtp_session *session = ctrl->driverdata;
504 struct cmtp_application *app;
505 struct list_head *p, *n;
506 int len = 0;
508 len += sprintf(page + len, "%s\n\n", cmtp_procinfo(ctrl));
509 len += sprintf(page + len, "addr %s\n", session->name);
510 len += sprintf(page + len, "ctrl %d\n", session->num);
512 list_for_each_safe(p, n, &session->applications) {
513 app = list_entry(p, struct cmtp_application, list);
514 len += sprintf(page + len, "appl %d -> %d\n", app->appl, app->mapping);
517 if (off + count >= len)
518 *eof = 1;
520 if (len < off)
521 return 0;
523 *start = page + off;
525 return ((count < len - off) ? count : len - off);
529 int cmtp_attach_device(struct cmtp_session *session)
531 unsigned char buf[4];
532 long ret;
534 BT_DBG("session %p", session);
536 capimsg_setu32(buf, 0, 0);
538 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, CMTP_INITIAL_MSGNUM,
539 CAPI_FUNCTION_GET_PROFILE, buf, 4);
541 ret = wait_event_interruptible_timeout(session->wait,
542 session->ncontroller, CMTP_INTEROP_TIMEOUT);
544 BT_INFO("Found %d CAPI controller(s) on device %s", session->ncontroller, session->name);
546 if (!ret)
547 return -ETIMEDOUT;
549 if (!session->ncontroller)
550 return -ENODEV;
552 if (session->ncontroller > 1)
553 BT_INFO("Setting up only CAPI controller 1");
555 session->ctrl.owner = THIS_MODULE;
556 session->ctrl.driverdata = session;
557 strcpy(session->ctrl.name, session->name);
559 session->ctrl.driver_name = "cmtp";
560 session->ctrl.load_firmware = cmtp_load_firmware;
561 session->ctrl.reset_ctr = cmtp_reset_ctr;
562 session->ctrl.register_appl = cmtp_register_appl;
563 session->ctrl.release_appl = cmtp_release_appl;
564 session->ctrl.send_message = cmtp_send_message;
566 session->ctrl.procinfo = cmtp_procinfo;
567 session->ctrl.ctr_read_proc = cmtp_ctr_read_proc;
569 if (attach_capi_ctr(&session->ctrl) < 0) {
570 BT_ERR("Can't attach new controller");
571 return -EBUSY;
574 session->num = session->ctrl.cnr;
576 BT_DBG("session %p num %d", session, session->num);
578 capimsg_setu32(buf, 0, 1);
580 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
581 CAPI_FUNCTION_GET_MANUFACTURER, buf, 4);
583 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
584 CAPI_FUNCTION_GET_VERSION, buf, 4);
586 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
587 CAPI_FUNCTION_GET_SERIAL_NUMBER, buf, 4);
589 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
590 CAPI_FUNCTION_GET_PROFILE, buf, 4);
592 return 0;
595 void cmtp_detach_device(struct cmtp_session *session)
597 BT_DBG("session %p", session);
599 detach_capi_ctr(&session->ctrl);