6fb47e00e188bb2c292f3d7e94a7689651b832f8
[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 = kmalloc(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         memset(app, 0, sizeof(*app));
86
87         app->state = BT_OPEN;
88         app->appl = appl;
89
90         list_add_tail(&app->list, &session->applications);
91
92         return app;
93 }
94
95 static void cmtp_application_del(struct cmtp_session *session, struct cmtp_application *app)
96 {
97         BT_DBG("session %p application %p", session, app);
98
99         if (app) {
100                 list_del(&app->list);
101                 kfree(app);
102         }
103 }
104
105 static struct cmtp_application *cmtp_application_get(struct cmtp_session *session, int pattern, __u16 value)
106 {
107         struct cmtp_application *app;
108         struct list_head *p, *n;
109
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;
125                 }
126         }
127
128         return NULL;
129 }
130
131 static int cmtp_msgnum_get(struct cmtp_session *session)
132 {
133         session->msgnum++;
134
135         if ((session->msgnum & 0xff) > 200)
136                 session->msgnum = CMTP_INITIAL_MSGNUM + 1;
137
138         return session->msgnum;
139 }
140
141 static void cmtp_send_capimsg(struct cmtp_session *session, struct sk_buff *skb)
142 {
143         struct cmtp_scb *scb = (void *) skb->cb;
144
145         BT_DBG("session %p skb %p len %d", session, skb, skb->len);
146
147         scb->id = -1;
148         scb->data = (CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3);
149
150         skb_queue_tail(&session->transmit, skb);
151
152         cmtp_schedule(session);
153 }
154
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)
158 {
159         struct sk_buff *skb;
160         unsigned char *s;
161
162         BT_DBG("session %p subcmd 0x%02x appl %d msgnum %d", session, subcmd, appl, msgnum);
163
164         if (!(skb = alloc_skb(CAPI_MSG_BASELEN + 6 + len, GFP_ATOMIC))) {
165                 BT_ERR("Can't allocate memory for interoperability packet");
166                 return;
167         }
168
169         s = skb_put(skb, CAPI_MSG_BASELEN + 6 + len);
170
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);
176
177         /* Interoperability selector (Bluetooth Device Management) */
178         capimsg_setu16(s, 8, 0x0001);
179
180         capimsg_setu8 (s, 10, 3 + len);
181         capimsg_setu16(s, 11, function);
182         capimsg_setu8 (s, 13, len);
183
184         if (len > 0)
185                 memcpy(s + 14, buf, len);
186
187         cmtp_send_capimsg(session, skb);
188 }
189
190 static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *skb)
191 {
192         struct capi_ctr *ctrl = &session->ctrl;
193         struct cmtp_application *application;
194         __u16 appl, msgnum, func, info;
195         __u32 controller;
196
197         BT_DBG("session %p skb %p len %d", session, skb, skb->len);
198
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);
203
204                 switch (func) {
205                 case CAPI_FUNCTION_REGISTER:
206                         msgnum = CAPIMSG_MSGID(skb->data);
207
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);
214                         }
215
216                         break;
217
218                 case CAPI_FUNCTION_RELEASE:
219                         appl = CAPIMSG_APPID(skb->data);
220
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);
226                         }
227
228                         break;
229
230                 case CAPI_FUNCTION_GET_PROFILE:
231                         controller = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 11);
232                         msgnum = CAPIMSG_MSGID(skb->data);
233
234                         if (!info && (msgnum == CMTP_INITIAL_MSGNUM)) {
235                                 session->ncontroller = controller;
236                                 wake_up_interruptible(&session->wait);
237                                 break;
238                         }
239
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);
246                         }
247
248                         break;
249
250                 case CAPI_FUNCTION_GET_MANUFACTURER:
251                         controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 10);
252
253                         if (!info && ctrl) {
254                                 strncpy(ctrl->manu,
255                                         skb->data + CAPI_MSG_BASELEN + 15,
256                                         skb->data[CAPI_MSG_BASELEN + 14]);
257                         }
258
259                         break;
260
261                 case CAPI_FUNCTION_GET_VERSION:
262                         controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12);
263
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);
269                         }
270
271                         break;
272
273                 case CAPI_FUNCTION_GET_SERIAL_NUMBER:
274                         controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12);
275
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]);
281                         }
282
283                         break;
284                 }
285
286                 break;
287
288         case CAPI_IND:
289                 func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 3);
290
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]);
297                 }
298
299                 break;
300         }
301
302         kfree_skb(skb);
303 }
304
305 void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb)
306 {
307         struct capi_ctr *ctrl = &session->ctrl;
308         struct cmtp_application *application;
309         __u16 cmd, appl;
310         __u32 contr;
311
312         BT_DBG("session %p skb %p len %d", session, skb, skb->len);
313
314         if (CAPIMSG_COMMAND(skb->data) == CAPI_INTEROPERABILITY) {
315                 cmtp_recv_interopmsg(session, skb);
316                 return;
317         }
318
319         if (session->flags & (1 << CMTP_LOOPBACK)) {
320                 kfree_skb(skb);
321                 return;
322         }
323
324         cmd = CAPICMD(CAPIMSG_COMMAND(skb->data), CAPIMSG_SUBCOMMAND(skb->data));
325         appl = CAPIMSG_APPID(skb->data);
326         contr = CAPIMSG_CONTROL(skb->data);
327
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;
336         }
337
338         if ((contr & 0x7f) == 0x01) {
339                 contr = (contr & 0xffffff80) | session->num;
340                 CAPIMSG_SETCONTROL(skb->data, contr);
341         }
342
343         if (!ctrl) {
344                 BT_ERR("Can't find controller %d for message", session->num);
345                 kfree_skb(skb);
346                 return;
347         }
348
349         capi_ctr_handle_message(ctrl, appl, skb);
350 }
351
352 static int cmtp_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
353 {
354         BT_DBG("ctrl %p data %p", ctrl, data);
355
356         return 0;
357 }
358
359 static void cmtp_reset_ctr(struct capi_ctr *ctrl)
360 {
361         struct cmtp_session *session = ctrl->driverdata;
362
363         BT_DBG("ctrl %p", ctrl);
364
365         capi_ctr_reseted(ctrl);
366
367         atomic_inc(&session->terminate);
368         cmtp_schedule(session);
369 }
370
371 static void cmtp_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp)
372 {
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;
379
380         BT_DBG("ctrl %p appl %d level3cnt %d datablkcnt %d datablklen %d",
381                 ctrl, appl, rp->level3cnt, rp->datablkcnt, rp->datablklen);
382
383         application = cmtp_application_add(session, appl);
384         if (!application) {
385                 BT_ERR("Can't allocate memory for new application");
386                 return;
387         }
388
389         if (want < 0)
390                 nconn = ctrl->profile.nbchannel * -want;
391         else
392                 nconn = want;
393
394         if (nconn == 0)
395                 nconn = ctrl->profile.nbchannel;
396
397         capimsg_setu16(buf, 0, nconn);
398         capimsg_setu16(buf, 2, rp->datablkcnt);
399         capimsg_setu16(buf, 4, rp->datablklen);
400
401         application->state = BT_CONFIG;
402         application->msgnum = cmtp_msgnum_get(session);
403
404         cmtp_send_interopmsg(session, CAPI_REQ, 0x0000, application->msgnum,
405                                 CAPI_FUNCTION_REGISTER, buf, 6);
406
407         add_wait_queue(&session->wait, &wait);
408         while (1) {
409                 set_current_state(TASK_INTERRUPTIBLE);
410
411                 if (!timeo) {
412                         err = -EAGAIN;
413                         break;
414                 }
415
416                 if (application->state == BT_CLOSED) {
417                         err = -application->err;
418                         break;
419                 }
420
421                 if (application->state == BT_CONNECTED)
422                         break;
423
424                 if (signal_pending(current)) {
425                         err = -EINTR;
426                         break;
427                 }
428
429                 timeo = schedule_timeout(timeo);
430         }
431         set_current_state(TASK_RUNNING);
432         remove_wait_queue(&session->wait, &wait);
433
434         if (err) {
435                 cmtp_application_del(session, application);
436                 return;
437         }
438 }
439
440 static void cmtp_release_appl(struct capi_ctr *ctrl, __u16 appl)
441 {
442         struct cmtp_session *session = ctrl->driverdata;
443         struct cmtp_application *application;
444
445         BT_DBG("ctrl %p appl %d", ctrl, appl);
446
447         application = cmtp_application_get(session, CMTP_APPLID, appl);
448         if (!application) {
449                 BT_ERR("Can't find application");
450                 return;
451         }
452
453         application->msgnum = cmtp_msgnum_get(session);
454
455         cmtp_send_interopmsg(session, CAPI_REQ, application->mapping, application->msgnum,
456                                 CAPI_FUNCTION_RELEASE, NULL, 0);
457
458         wait_event_interruptible_timeout(session->wait,
459                         (application->state == BT_CLOSED), CMTP_INTEROP_TIMEOUT);
460
461         cmtp_application_del(session, application);
462 }
463
464 static u16 cmtp_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
465 {
466         struct cmtp_session *session = ctrl->driverdata;
467         struct cmtp_application *application;
468         __u16 appl;
469         __u32 contr;
470
471         BT_DBG("ctrl %p skb %p", ctrl, skb);
472
473         appl = CAPIMSG_APPID(skb->data);
474         contr = CAPIMSG_CONTROL(skb->data);
475
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;
480         }
481
482         CAPIMSG_SETAPPID(skb->data, application->mapping);
483
484         if ((contr & 0x7f) == session->num) {
485                 contr = (contr & 0xffffff80) | 0x01;
486                 CAPIMSG_SETCONTROL(skb->data, contr);
487         }
488
489         cmtp_send_capimsg(session, skb);
490
491         return CAPI_NOERROR;
492 }
493
494 static char *cmtp_procinfo(struct capi_ctr *ctrl)
495 {
496         return "CAPI Message Transport Protocol";
497 }
498
499 static int cmtp_ctr_read_proc(char *page, char **start, off_t off, int count, int *eof, struct capi_ctr *ctrl)
500 {
501         struct cmtp_session *session = ctrl->driverdata;
502         struct cmtp_application *app;
503         struct list_head *p, *n;
504         int len = 0;
505
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);
509
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);
513         }
514
515         if (off + count >= len)
516                 *eof = 1;
517
518         if (len < off)
519                 return 0;
520
521         *start = page + off;
522
523         return ((count < len - off) ? count : len - off);
524 }
525
526
527 int cmtp_attach_device(struct cmtp_session *session)
528 {
529         unsigned char buf[4];
530         long ret;
531
532         BT_DBG("session %p", session);
533
534         capimsg_setu32(buf, 0, 0);
535
536         cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, CMTP_INITIAL_MSGNUM,
537                                 CAPI_FUNCTION_GET_PROFILE, buf, 4);
538
539         ret = wait_event_interruptible_timeout(session->wait,
540                         session->ncontroller, CMTP_INTEROP_TIMEOUT);
541         
542         BT_INFO("Found %d CAPI controller(s) on device %s", session->ncontroller, session->name);
543
544         if (!ret)
545                 return -ETIMEDOUT;
546
547         if (!session->ncontroller)
548                 return -ENODEV;
549
550         if (session->ncontroller > 1)
551                 BT_INFO("Setting up only CAPI controller 1");
552
553         session->ctrl.owner      = THIS_MODULE;
554         session->ctrl.driverdata = session;
555         strcpy(session->ctrl.name, session->name);
556
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;
563
564         session->ctrl.procinfo      = cmtp_procinfo;
565         session->ctrl.ctr_read_proc = cmtp_ctr_read_proc;
566
567         if (attach_capi_ctr(&session->ctrl) < 0) {
568                 BT_ERR("Can't attach new controller");
569                 return -EBUSY;
570         }
571
572         session->num = session->ctrl.cnr;
573
574         BT_DBG("session %p num %d", session, session->num);
575
576         capimsg_setu32(buf, 0, 1);
577
578         cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
579                                 CAPI_FUNCTION_GET_MANUFACTURER, buf, 4);
580
581         cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
582                                 CAPI_FUNCTION_GET_VERSION, buf, 4);
583
584         cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
585                                 CAPI_FUNCTION_GET_SERIAL_NUMBER, buf, 4);
586
587         cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
588                                 CAPI_FUNCTION_GET_PROFILE, buf, 4);
589
590         return 0;
591 }
592
593 void cmtp_detach_device(struct cmtp_session *session)
594 {
595         BT_DBG("session %p", session);
596
597         detach_capi_ctr(&session->ctrl);
598 }