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