vserver 2.0 rc7
[linux-2.6.git] / net / bluetooth / cmtp / capi.c
1 /* 
2    CMTP implementation for Linux Bluetooth stack (BlueZ).
3    Copyright (C) 2002-2003 Marcel Holtmann <marcel@holtmann.org>
4
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;
8
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.
17
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.
21 */
22
23 #include <linux/config.h>
24 #include <linux/module.h>
25
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 <net/sock.h>
39
40 #include <linux/isdn/capilli.h>
41 #include <linux/isdn/capicmd.h>
42 #include <linux/isdn/capiutil.h>
43
44 #include "cmtp.h"
45
46 #ifndef CONFIG_BT_CMTP_DEBUG
47 #undef  BT_DBG
48 #define BT_DBG(D...)
49 #endif
50
51 #define CAPI_INTEROPERABILITY           0x20
52
53 #define CAPI_INTEROPERABILITY_REQ       CAPICMD(CAPI_INTEROPERABILITY, CAPI_REQ)
54 #define CAPI_INTEROPERABILITY_CONF      CAPICMD(CAPI_INTEROPERABILITY, CAPI_CONF)
55 #define CAPI_INTEROPERABILITY_IND       CAPICMD(CAPI_INTEROPERABILITY, CAPI_IND)
56 #define CAPI_INTEROPERABILITY_RESP      CAPICMD(CAPI_INTEROPERABILITY, CAPI_RESP)
57
58 #define CAPI_INTEROPERABILITY_REQ_LEN   (CAPI_MSG_BASELEN + 2)
59 #define CAPI_INTEROPERABILITY_CONF_LEN  (CAPI_MSG_BASELEN + 4)
60 #define CAPI_INTEROPERABILITY_IND_LEN   (CAPI_MSG_BASELEN + 2)
61 #define CAPI_INTEROPERABILITY_RESP_LEN  (CAPI_MSG_BASELEN + 2)
62
63 #define CAPI_FUNCTION_REGISTER          0
64 #define CAPI_FUNCTION_RELEASE           1
65 #define CAPI_FUNCTION_GET_PROFILE       2
66 #define CAPI_FUNCTION_GET_MANUFACTURER  3
67 #define CAPI_FUNCTION_GET_VERSION       4
68 #define CAPI_FUNCTION_GET_SERIAL_NUMBER 5
69 #define CAPI_FUNCTION_MANUFACTURER      6
70 #define CAPI_FUNCTION_LOOPBACK          7
71
72
73 #define CMTP_MSGNUM     1
74 #define CMTP_APPLID     2
75 #define CMTP_MAPPING    3
76
77 static struct cmtp_application *cmtp_application_add(struct cmtp_session *session, __u16 appl)
78 {
79         struct cmtp_application *app = kmalloc(sizeof(*app), GFP_KERNEL);
80
81         BT_DBG("session %p application %p appl %d", session, app, appl);
82
83         if (!app)
84                 return NULL;
85
86         memset(app, 0, sizeof(*app));
87
88         app->state = BT_OPEN;
89         app->appl = appl;
90
91         list_add_tail(&app->list, &session->applications);
92
93         return app;
94 }
95
96 static void cmtp_application_del(struct cmtp_session *session, struct cmtp_application *app)
97 {
98         BT_DBG("session %p application %p", session, app);
99
100         if (app) {
101                 list_del(&app->list);
102                 kfree(app);
103         }
104 }
105
106 static struct cmtp_application *cmtp_application_get(struct cmtp_session *session, int pattern, __u16 value)
107 {
108         struct cmtp_application *app;
109         struct list_head *p, *n;
110
111         list_for_each_safe(p, n, &session->applications) {
112                 app = list_entry(p, struct cmtp_application, list);
113                 switch (pattern) {
114                 case CMTP_MSGNUM:
115                         if (app->msgnum == value)
116                                 return app;
117                         break;
118                 case CMTP_APPLID:
119                         if (app->appl == value)
120                                 return app;
121                         break;
122                 case CMTP_MAPPING:
123                         if (app->mapping == value)
124                                 return app;
125                         break;
126                 }
127         }
128
129         return NULL;
130 }
131
132 static int cmtp_msgnum_get(struct cmtp_session *session)
133 {
134         session->msgnum++;
135
136         if ((session->msgnum & 0xff) > 200)
137                 session->msgnum = CMTP_INITIAL_MSGNUM + 1;
138
139         return session->msgnum;
140 }
141
142 static void cmtp_send_capimsg(struct cmtp_session *session, struct sk_buff *skb)
143 {
144         struct cmtp_scb *scb = (void *) skb->cb;
145
146         BT_DBG("session %p skb %p len %d", session, skb, skb->len);
147
148         scb->id = -1;
149         scb->data = (CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3);
150
151         skb_queue_tail(&session->transmit, skb);
152
153         cmtp_schedule(session);
154 }
155
156 static void cmtp_send_interopmsg(struct cmtp_session *session,
157                                         __u8 subcmd, __u16 appl, __u16 msgnum,
158                                         __u16 function, unsigned char *buf, int len)
159 {
160         struct sk_buff *skb;
161         unsigned char *s;
162
163         BT_DBG("session %p subcmd 0x%02x appl %d msgnum %d", session, subcmd, appl, msgnum);
164
165         if (!(skb = alloc_skb(CAPI_MSG_BASELEN + 6 + len, GFP_ATOMIC))) {
166                 BT_ERR("Can't allocate memory for interoperability packet");
167                 return;
168         }
169
170         s = skb_put(skb, CAPI_MSG_BASELEN + 6 + len);
171
172         capimsg_setu16(s, 0, CAPI_MSG_BASELEN + 6 + len);
173         capimsg_setu16(s, 2, appl);
174         capimsg_setu8 (s, 4, CAPI_INTEROPERABILITY);
175         capimsg_setu8 (s, 5, subcmd);
176         capimsg_setu16(s, 6, msgnum);
177
178         /* Interoperability selector (Bluetooth Device Management) */
179         capimsg_setu16(s, 8, 0x0001);
180
181         capimsg_setu8 (s, 10, 3 + len);
182         capimsg_setu16(s, 11, function);
183         capimsg_setu8 (s, 13, len);
184
185         if (len > 0)
186                 memcpy(s + 14, buf, len);
187
188         cmtp_send_capimsg(session, skb);
189 }
190
191 static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *skb)
192 {
193         struct capi_ctr *ctrl = &session->ctrl;
194         struct cmtp_application *application;
195         __u16 appl, msgnum, func, info;
196         __u32 controller;
197
198         BT_DBG("session %p skb %p len %d", session, skb, skb->len);
199
200         switch (CAPIMSG_SUBCOMMAND(skb->data)) {
201         case CAPI_CONF:
202                 func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 5);
203                 info = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 8);
204
205                 switch (func) {
206                 case CAPI_FUNCTION_REGISTER:
207                         msgnum = CAPIMSG_MSGID(skb->data);
208
209                         application = cmtp_application_get(session, CMTP_MSGNUM, msgnum);
210                         if (application) {
211                                 application->state = BT_CONNECTED;
212                                 application->msgnum = 0;
213                                 application->mapping = CAPIMSG_APPID(skb->data);
214                                 wake_up_interruptible(&session->wait);
215                         }
216
217                         break;
218
219                 case CAPI_FUNCTION_RELEASE:
220                         appl = CAPIMSG_APPID(skb->data);
221
222                         application = cmtp_application_get(session, CMTP_MAPPING, appl);
223                         if (application) {
224                                 application->state = BT_CLOSED;
225                                 application->msgnum = 0;
226                                 wake_up_interruptible(&session->wait);
227                         }
228
229                         break;
230
231                 case CAPI_FUNCTION_GET_PROFILE:
232                         controller = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 11);
233                         msgnum = CAPIMSG_MSGID(skb->data);
234
235                         if (!info && (msgnum == CMTP_INITIAL_MSGNUM)) {
236                                 session->ncontroller = controller;
237                                 wake_up_interruptible(&session->wait);
238                                 break;
239                         }
240
241                         if (!info && ctrl) {
242                                 memcpy(&ctrl->profile,
243                                         skb->data + CAPI_MSG_BASELEN + 11,
244                                         sizeof(capi_profile));
245                                 session->state = BT_CONNECTED;
246                                 capi_ctr_ready(ctrl);
247                         }
248
249                         break;
250
251                 case CAPI_FUNCTION_GET_MANUFACTURER:
252                         controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 10);
253
254                         if (!info && ctrl) {
255                                 strncpy(ctrl->manu,
256                                         skb->data + CAPI_MSG_BASELEN + 15,
257                                         skb->data[CAPI_MSG_BASELEN + 14]);
258                         }
259
260                         break;
261
262                 case CAPI_FUNCTION_GET_VERSION:
263                         controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12);
264
265                         if (!info && ctrl) {
266                                 ctrl->version.majorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 16);
267                                 ctrl->version.minorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 20);
268                                 ctrl->version.majormanuversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 24);
269                                 ctrl->version.minormanuversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 28);
270                         }
271
272                         break;
273
274                 case CAPI_FUNCTION_GET_SERIAL_NUMBER:
275                         controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12);
276
277                         if (!info && ctrl) {
278                                 memset(ctrl->serial, 0, CAPI_SERIAL_LEN);
279                                 strncpy(ctrl->serial,
280                                         skb->data + CAPI_MSG_BASELEN + 17,
281                                         skb->data[CAPI_MSG_BASELEN + 16]);
282                         }
283
284                         break;
285                 }
286
287                 break;
288
289         case CAPI_IND:
290                 func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 3);
291
292                 if (func == CAPI_FUNCTION_LOOPBACK) {
293                         appl = CAPIMSG_APPID(skb->data);
294                         msgnum = CAPIMSG_MSGID(skb->data);
295                         cmtp_send_interopmsg(session, CAPI_RESP, appl, msgnum, func,
296                                                 skb->data + CAPI_MSG_BASELEN + 6,
297                                                 skb->data[CAPI_MSG_BASELEN + 5]);
298                 }
299
300                 break;
301         }
302
303         kfree_skb(skb);
304 }
305
306 void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb)
307 {
308         struct capi_ctr *ctrl = &session->ctrl;
309         struct cmtp_application *application;
310         __u16 cmd, appl;
311         __u32 contr;
312
313         BT_DBG("session %p skb %p len %d", session, skb, skb->len);
314
315         if (CAPIMSG_COMMAND(skb->data) == CAPI_INTEROPERABILITY) {
316                 cmtp_recv_interopmsg(session, skb);
317                 return;
318         }
319
320         if (session->flags & (1 << CMTP_LOOPBACK)) {
321                 kfree_skb(skb);
322                 return;
323         }
324
325         cmd = CAPICMD(CAPIMSG_COMMAND(skb->data), CAPIMSG_SUBCOMMAND(skb->data));
326         appl = CAPIMSG_APPID(skb->data);
327         contr = CAPIMSG_CONTROL(skb->data);
328
329         application = cmtp_application_get(session, CMTP_MAPPING, appl);
330         if (application) {
331                 appl = application->appl;
332                 CAPIMSG_SETAPPID(skb->data, appl);
333         } else {
334                 BT_ERR("Can't find application with id %d", appl);
335                 kfree_skb(skb);
336                 return;
337         }
338
339         if ((contr & 0x7f) == 0x01) {
340                 contr = (contr & 0xffffff80) | session->num;
341                 CAPIMSG_SETCONTROL(skb->data, contr);
342         }
343
344         if (!ctrl) {
345                 BT_ERR("Can't find controller %d for message", session->num);
346                 kfree_skb(skb);
347                 return;
348         }
349
350         capi_ctr_handle_message(ctrl, appl, skb);
351 }
352
353 static int cmtp_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
354 {
355         BT_DBG("ctrl %p data %p", ctrl, data);
356
357         return 0;
358 }
359
360 static void cmtp_reset_ctr(struct capi_ctr *ctrl)
361 {
362         struct cmtp_session *session = ctrl->driverdata;
363
364         BT_DBG("ctrl %p", ctrl);
365
366         capi_ctr_reseted(ctrl);
367
368         atomic_inc(&session->terminate);
369         cmtp_schedule(session);
370 }
371
372 static void cmtp_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp)
373 {
374         DECLARE_WAITQUEUE(wait, current);
375         struct cmtp_session *session = ctrl->driverdata;
376         struct cmtp_application *application;
377         unsigned long timeo = CMTP_INTEROP_TIMEOUT;
378         unsigned char buf[8];
379         int err = 0, nconn, want = rp->level3cnt;
380
381         BT_DBG("ctrl %p appl %d level3cnt %d datablkcnt %d datablklen %d",
382                 ctrl, appl, rp->level3cnt, rp->datablkcnt, rp->datablklen);
383
384         application = cmtp_application_add(session, appl);
385         if (!application) {
386                 BT_ERR("Can't allocate memory for new application");
387                 return;
388         }
389
390         if (want < 0)
391                 nconn = ctrl->profile.nbchannel * -want;
392         else
393                 nconn = want;
394
395         if (nconn == 0)
396                 nconn = ctrl->profile.nbchannel;
397
398         capimsg_setu16(buf, 0, nconn);
399         capimsg_setu16(buf, 2, rp->datablkcnt);
400         capimsg_setu16(buf, 4, rp->datablklen);
401
402         application->state = BT_CONFIG;
403         application->msgnum = cmtp_msgnum_get(session);
404
405         cmtp_send_interopmsg(session, CAPI_REQ, 0x0000, application->msgnum,
406                                 CAPI_FUNCTION_REGISTER, buf, 6);
407
408         add_wait_queue(&session->wait, &wait);
409         while (1) {
410                 set_current_state(TASK_INTERRUPTIBLE);
411
412                 if (!timeo) {
413                         err = -EAGAIN;
414                         break;
415                 }
416
417                 if (application->state == BT_CLOSED) {
418                         err = -application->err;
419                         break;
420                 }
421
422                 if (application->state == BT_CONNECTED)
423                         break;
424
425                 if (signal_pending(current)) {
426                         err = -EINTR;
427                         break;
428                 }
429
430                 timeo = schedule_timeout(timeo);
431         }
432         set_current_state(TASK_RUNNING);
433         remove_wait_queue(&session->wait, &wait);
434
435         if (err) {
436                 cmtp_application_del(session, application);
437                 return;
438         }
439 }
440
441 static void cmtp_release_appl(struct capi_ctr *ctrl, __u16 appl)
442 {
443         struct cmtp_session *session = ctrl->driverdata;
444         struct cmtp_application *application;
445
446         BT_DBG("ctrl %p appl %d", ctrl, appl);
447
448         application = cmtp_application_get(session, CMTP_APPLID, appl);
449         if (!application) {
450                 BT_ERR("Can't find application");
451                 return;
452         }
453
454         application->msgnum = cmtp_msgnum_get(session);
455
456         cmtp_send_interopmsg(session, CAPI_REQ, application->mapping, application->msgnum,
457                                 CAPI_FUNCTION_RELEASE, NULL, 0);
458
459         wait_event_interruptible_timeout(session->wait,
460                         (application->state == BT_CLOSED), CMTP_INTEROP_TIMEOUT);
461
462         cmtp_application_del(session, application);
463 }
464
465 static u16 cmtp_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
466 {
467         struct cmtp_session *session = ctrl->driverdata;
468         struct cmtp_application *application;
469         __u16 appl;
470         __u32 contr;
471
472         BT_DBG("ctrl %p skb %p", ctrl, skb);
473
474         appl = CAPIMSG_APPID(skb->data);
475         contr = CAPIMSG_CONTROL(skb->data);
476
477         application = cmtp_application_get(session, CMTP_APPLID, appl);
478         if ((!application) || (application->state != BT_CONNECTED)) {
479                 BT_ERR("Can't find application with id %d", appl);
480                 return CAPI_ILLAPPNR;
481         }
482
483         CAPIMSG_SETAPPID(skb->data, application->mapping);
484
485         if ((contr & 0x7f) == session->num) {
486                 contr = (contr & 0xffffff80) | 0x01;
487                 CAPIMSG_SETCONTROL(skb->data, contr);
488         }
489
490         cmtp_send_capimsg(session, skb);
491
492         return CAPI_NOERROR;
493 }
494
495 static char *cmtp_procinfo(struct capi_ctr *ctrl)
496 {
497         return "CAPI Message Transport Protocol";
498 }
499
500 static int cmtp_ctr_read_proc(char *page, char **start, off_t off, int count, int *eof, struct capi_ctr *ctrl)
501 {
502         struct cmtp_session *session = ctrl->driverdata;
503         struct cmtp_application *app;
504         struct list_head *p, *n;
505         int len = 0;
506
507         len += sprintf(page + len, "%s\n\n", cmtp_procinfo(ctrl));
508         len += sprintf(page + len, "addr %s\n", session->name);
509         len += sprintf(page + len, "ctrl %d\n", session->num);
510
511         list_for_each_safe(p, n, &session->applications) {
512                 app = list_entry(p, struct cmtp_application, list);
513                 len += sprintf(page + len, "appl %d -> %d\n", app->appl, app->mapping);
514         }
515
516         if (off + count >= len)
517                 *eof = 1;
518
519         if (len < off)
520                 return 0;
521
522         *start = page + off;
523
524         return ((count < len - off) ? count : len - off);
525 }
526
527
528 int cmtp_attach_device(struct cmtp_session *session)
529 {
530         unsigned char buf[4];
531         long ret;
532
533         BT_DBG("session %p", session);
534
535         capimsg_setu32(buf, 0, 0);
536
537         cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, CMTP_INITIAL_MSGNUM,
538                                 CAPI_FUNCTION_GET_PROFILE, buf, 4);
539
540         ret = wait_event_interruptible_timeout(session->wait,
541                         session->ncontroller, CMTP_INTEROP_TIMEOUT);
542         
543         BT_INFO("Found %d CAPI controller(s) on device %s", session->ncontroller, session->name);
544
545         if (!ret)
546                 return -ETIMEDOUT;
547
548         if (!session->ncontroller)
549                 return -ENODEV;
550
551         if (session->ncontroller > 1)
552                 BT_INFO("Setting up only CAPI controller 1");
553
554         session->ctrl.owner      = THIS_MODULE;
555         session->ctrl.driverdata = session;
556         strcpy(session->ctrl.name, session->name);
557
558         session->ctrl.driver_name   = "cmtp";
559         session->ctrl.load_firmware = cmtp_load_firmware;
560         session->ctrl.reset_ctr     = cmtp_reset_ctr;
561         session->ctrl.register_appl = cmtp_register_appl;
562         session->ctrl.release_appl  = cmtp_release_appl;
563         session->ctrl.send_message  = cmtp_send_message;
564
565         session->ctrl.procinfo      = cmtp_procinfo;
566         session->ctrl.ctr_read_proc = cmtp_ctr_read_proc;
567
568         if (attach_capi_ctr(&session->ctrl) < 0) {
569                 BT_ERR("Can't attach new controller");
570                 return -EBUSY;
571         }
572
573         session->num = session->ctrl.cnr;
574
575         BT_DBG("session %p num %d", session, session->num);
576
577         capimsg_setu32(buf, 0, 1);
578
579         cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
580                                 CAPI_FUNCTION_GET_MANUFACTURER, buf, 4);
581
582         cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
583                                 CAPI_FUNCTION_GET_VERSION, buf, 4);
584
585         cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
586                                 CAPI_FUNCTION_GET_SERIAL_NUMBER, buf, 4);
587
588         cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
589                                 CAPI_FUNCTION_GET_PROFILE, buf, 4);
590
591         return 0;
592 }
593
594 void cmtp_detach_device(struct cmtp_session *session)
595 {
596         BT_DBG("session %p", session);
597
598         detach_capi_ctr(&session->ctrl);
599 }