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