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