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