Merge master.kernel.org:/home/rmk/linux-2.6-serial
[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                 func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 5);
200                 info = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 8);
201
202                 switch (func) {
203                 case CAPI_FUNCTION_REGISTER:
204                         msgnum = CAPIMSG_MSGID(skb->data);
205
206                         application = cmtp_application_get(session, CMTP_MSGNUM, msgnum);
207                         if (application) {
208                                 application->state = BT_CONNECTED;
209                                 application->msgnum = 0;
210                                 application->mapping = CAPIMSG_APPID(skb->data);
211                                 wake_up_interruptible(&session->wait);
212                         }
213
214                         break;
215
216                 case CAPI_FUNCTION_RELEASE:
217                         appl = CAPIMSG_APPID(skb->data);
218
219                         application = cmtp_application_get(session, CMTP_MAPPING, appl);
220                         if (application) {
221                                 application->state = BT_CLOSED;
222                                 application->msgnum = 0;
223                                 wake_up_interruptible(&session->wait);
224                         }
225
226                         break;
227
228                 case CAPI_FUNCTION_GET_PROFILE:
229                         controller = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 11);
230                         msgnum = CAPIMSG_MSGID(skb->data);
231
232                         if (!info && (msgnum == CMTP_INITIAL_MSGNUM)) {
233                                 session->ncontroller = controller;
234                                 wake_up_interruptible(&session->wait);
235                                 break;
236                         }
237
238                         if (!info && ctrl) {
239                                 memcpy(&ctrl->profile,
240                                         skb->data + CAPI_MSG_BASELEN + 11,
241                                         sizeof(capi_profile));
242                                 session->state = BT_CONNECTED;
243                                 capi_ctr_ready(ctrl);
244                         }
245
246                         break;
247
248                 case CAPI_FUNCTION_GET_MANUFACTURER:
249                         controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 10);
250
251                         if (!info && ctrl) {
252                                 strncpy(ctrl->manu,
253                                         skb->data + CAPI_MSG_BASELEN + 15,
254                                         skb->data[CAPI_MSG_BASELEN + 14]);
255                         }
256
257                         break;
258
259                 case CAPI_FUNCTION_GET_VERSION:
260                         controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12);
261
262                         if (!info && ctrl) {
263                                 ctrl->version.majorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 16);
264                                 ctrl->version.minorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 20);
265                                 ctrl->version.majormanuversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 24);
266                                 ctrl->version.minormanuversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 28);
267                         }
268
269                         break;
270
271                 case CAPI_FUNCTION_GET_SERIAL_NUMBER:
272                         controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12);
273
274                         if (!info && ctrl) {
275                                 memset(ctrl->serial, 0, CAPI_SERIAL_LEN);
276                                 strncpy(ctrl->serial,
277                                         skb->data + CAPI_MSG_BASELEN + 17,
278                                         skb->data[CAPI_MSG_BASELEN + 16]);
279                         }
280
281                         break;
282                 }
283
284                 break;
285
286         case CAPI_IND:
287                 func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 3);
288
289                 if (func == CAPI_FUNCTION_LOOPBACK) {
290                         appl = CAPIMSG_APPID(skb->data);
291                         msgnum = CAPIMSG_MSGID(skb->data);
292                         cmtp_send_interopmsg(session, CAPI_RESP, appl, msgnum, func,
293                                                 skb->data + CAPI_MSG_BASELEN + 6,
294                                                 skb->data[CAPI_MSG_BASELEN + 5]);
295                 }
296
297                 break;
298         }
299
300         kfree_skb(skb);
301 }
302
303 void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb)
304 {
305         struct capi_ctr *ctrl = &session->ctrl;
306         struct cmtp_application *application;
307         __u16 cmd, appl;
308         __u32 contr;
309
310         BT_DBG("session %p skb %p len %d", session, skb, skb->len);
311
312         if (CAPIMSG_COMMAND(skb->data) == CAPI_INTEROPERABILITY) {
313                 cmtp_recv_interopmsg(session, skb);
314                 return;
315         }
316
317         if (session->flags & (1 << CMTP_LOOPBACK)) {
318                 kfree_skb(skb);
319                 return;
320         }
321
322         cmd = CAPICMD(CAPIMSG_COMMAND(skb->data), CAPIMSG_SUBCOMMAND(skb->data));
323         appl = CAPIMSG_APPID(skb->data);
324         contr = CAPIMSG_CONTROL(skb->data);
325
326         application = cmtp_application_get(session, CMTP_MAPPING, appl);
327         if (application) {
328                 appl = application->appl;
329                 CAPIMSG_SETAPPID(skb->data, appl);
330         } else {
331                 BT_ERR("Can't find application with id %d", appl);
332                 kfree_skb(skb);
333                 return;
334         }
335
336         if ((contr & 0x7f) == 0x01) {
337                 contr = (contr & 0xffffff80) | session->num;
338                 CAPIMSG_SETCONTROL(skb->data, contr);
339         }
340
341         if (!ctrl) {
342                 BT_ERR("Can't find controller %d for message", session->num);
343                 kfree_skb(skb);
344                 return;
345         }
346
347         capi_ctr_handle_message(ctrl, appl, skb);
348 }
349
350 static int cmtp_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
351 {
352         BT_DBG("ctrl %p data %p", ctrl, data);
353
354         return 0;
355 }
356
357 static void cmtp_reset_ctr(struct capi_ctr *ctrl)
358 {
359         struct cmtp_session *session = ctrl->driverdata;
360
361         BT_DBG("ctrl %p", ctrl);
362
363         capi_ctr_reseted(ctrl);
364
365         atomic_inc(&session->terminate);
366         cmtp_schedule(session);
367 }
368
369 static void cmtp_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp)
370 {
371         DECLARE_WAITQUEUE(wait, current);
372         struct cmtp_session *session = ctrl->driverdata;
373         struct cmtp_application *application;
374         unsigned long timeo = CMTP_INTEROP_TIMEOUT;
375         unsigned char buf[8];
376         int err = 0, nconn, want = rp->level3cnt;
377
378         BT_DBG("ctrl %p appl %d level3cnt %d datablkcnt %d datablklen %d",
379                 ctrl, appl, rp->level3cnt, rp->datablkcnt, rp->datablklen);
380
381         application = cmtp_application_add(session, appl);
382         if (!application) {
383                 BT_ERR("Can't allocate memory for new application");
384                 return;
385         }
386
387         if (want < 0)
388                 nconn = ctrl->profile.nbchannel * -want;
389         else
390                 nconn = want;
391
392         if (nconn == 0)
393                 nconn = ctrl->profile.nbchannel;
394
395         capimsg_setu16(buf, 0, nconn);
396         capimsg_setu16(buf, 2, rp->datablkcnt);
397         capimsg_setu16(buf, 4, rp->datablklen);
398
399         application->state = BT_CONFIG;
400         application->msgnum = cmtp_msgnum_get(session);
401
402         cmtp_send_interopmsg(session, CAPI_REQ, 0x0000, application->msgnum,
403                                 CAPI_FUNCTION_REGISTER, buf, 6);
404
405         add_wait_queue(&session->wait, &wait);
406         while (1) {
407                 set_current_state(TASK_INTERRUPTIBLE);
408
409                 if (!timeo) {
410                         err = -EAGAIN;
411                         break;
412                 }
413
414                 if (application->state == BT_CLOSED) {
415                         err = -application->err;
416                         break;
417                 }
418
419                 if (application->state == BT_CONNECTED)
420                         break;
421
422                 if (signal_pending(current)) {
423                         err = -EINTR;
424                         break;
425                 }
426
427                 timeo = schedule_timeout(timeo);
428         }
429         set_current_state(TASK_RUNNING);
430         remove_wait_queue(&session->wait, &wait);
431
432         if (err) {
433                 cmtp_application_del(session, application);
434                 return;
435         }
436 }
437
438 static void cmtp_release_appl(struct capi_ctr *ctrl, __u16 appl)
439 {
440         struct cmtp_session *session = ctrl->driverdata;
441         struct cmtp_application *application;
442
443         BT_DBG("ctrl %p appl %d", ctrl, appl);
444
445         application = cmtp_application_get(session, CMTP_APPLID, appl);
446         if (!application) {
447                 BT_ERR("Can't find application");
448                 return;
449         }
450
451         application->msgnum = cmtp_msgnum_get(session);
452
453         cmtp_send_interopmsg(session, CAPI_REQ, application->mapping, application->msgnum,
454                                 CAPI_FUNCTION_RELEASE, NULL, 0);
455
456         wait_event_interruptible_timeout(session->wait,
457                         (application->state == BT_CLOSED), CMTP_INTEROP_TIMEOUT);
458
459         cmtp_application_del(session, application);
460 }
461
462 static u16 cmtp_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
463 {
464         struct cmtp_session *session = ctrl->driverdata;
465         struct cmtp_application *application;
466         __u16 appl;
467         __u32 contr;
468
469         BT_DBG("ctrl %p skb %p", ctrl, skb);
470
471         appl = CAPIMSG_APPID(skb->data);
472         contr = CAPIMSG_CONTROL(skb->data);
473
474         application = cmtp_application_get(session, CMTP_APPLID, appl);
475         if ((!application) || (application->state != BT_CONNECTED)) {
476                 BT_ERR("Can't find application with id %d", appl);
477                 return CAPI_ILLAPPNR;
478         }
479
480         CAPIMSG_SETAPPID(skb->data, application->mapping);
481
482         if ((contr & 0x7f) == session->num) {
483                 contr = (contr & 0xffffff80) | 0x01;
484                 CAPIMSG_SETCONTROL(skb->data, contr);
485         }
486
487         cmtp_send_capimsg(session, skb);
488
489         return CAPI_NOERROR;
490 }
491
492 static char *cmtp_procinfo(struct capi_ctr *ctrl)
493 {
494         return "CAPI Message Transport Protocol";
495 }
496
497 static int cmtp_ctr_read_proc(char *page, char **start, off_t off, int count, int *eof, struct capi_ctr *ctrl)
498 {
499         struct cmtp_session *session = ctrl->driverdata;
500         struct cmtp_application *app;
501         struct list_head *p, *n;
502         int len = 0;
503
504         len += sprintf(page + len, "%s\n\n", cmtp_procinfo(ctrl));
505         len += sprintf(page + len, "addr %s\n", session->name);
506         len += sprintf(page + len, "ctrl %d\n", session->num);
507
508         list_for_each_safe(p, n, &session->applications) {
509                 app = list_entry(p, struct cmtp_application, list);
510                 len += sprintf(page + len, "appl %d -> %d\n", app->appl, app->mapping);
511         }
512
513         if (off + count >= len)
514                 *eof = 1;
515
516         if (len < off)
517                 return 0;
518
519         *start = page + off;
520
521         return ((count < len - off) ? count : len - off);
522 }
523
524
525 int cmtp_attach_device(struct cmtp_session *session)
526 {
527         unsigned char buf[4];
528         long ret;
529
530         BT_DBG("session %p", session);
531
532         capimsg_setu32(buf, 0, 0);
533
534         cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, CMTP_INITIAL_MSGNUM,
535                                 CAPI_FUNCTION_GET_PROFILE, buf, 4);
536
537         ret = wait_event_interruptible_timeout(session->wait,
538                         session->ncontroller, CMTP_INTEROP_TIMEOUT);
539         
540         BT_INFO("Found %d CAPI controller(s) on device %s", session->ncontroller, session->name);
541
542         if (!ret)
543                 return -ETIMEDOUT;
544
545         if (!session->ncontroller)
546                 return -ENODEV;
547
548         if (session->ncontroller > 1)
549                 BT_INFO("Setting up only CAPI controller 1");
550
551         session->ctrl.owner      = THIS_MODULE;
552         session->ctrl.driverdata = session;
553         strcpy(session->ctrl.name, session->name);
554
555         session->ctrl.driver_name   = "cmtp";
556         session->ctrl.load_firmware = cmtp_load_firmware;
557         session->ctrl.reset_ctr     = cmtp_reset_ctr;
558         session->ctrl.register_appl = cmtp_register_appl;
559         session->ctrl.release_appl  = cmtp_release_appl;
560         session->ctrl.send_message  = cmtp_send_message;
561
562         session->ctrl.procinfo      = cmtp_procinfo;
563         session->ctrl.ctr_read_proc = cmtp_ctr_read_proc;
564
565         if (attach_capi_ctr(&session->ctrl) < 0) {
566                 BT_ERR("Can't attach new controller");
567                 return -EBUSY;
568         }
569
570         session->num = session->ctrl.cnr;
571
572         BT_DBG("session %p num %d", session, session->num);
573
574         capimsg_setu32(buf, 0, 1);
575
576         cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
577                                 CAPI_FUNCTION_GET_MANUFACTURER, buf, 4);
578
579         cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
580                                 CAPI_FUNCTION_GET_VERSION, buf, 4);
581
582         cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
583                                 CAPI_FUNCTION_GET_SERIAL_NUMBER, buf, 4);
584
585         cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
586                                 CAPI_FUNCTION_GET_PROFILE, buf, 4);
587
588         return 0;
589 }
590
591 void cmtp_detach_device(struct cmtp_session *session)
592 {
593         BT_DBG("session %p", session);
594
595         detach_capi_ctr(&session->ctrl);
596 }