This commit was generated by cvs2svn to compensate for changes in r517,
[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                 return CAPI_ILLAPPNR;
497         }
498
499         CAPIMSG_SETAPPID(skb->data, application->mapping);
500
501         if ((contr & 0x7f) == session->num) {
502                 contr = (contr & 0xffffff80) | 0x01;
503                 CAPIMSG_SETCONTROL(skb->data, contr);
504         }
505
506         cmtp_send_capimsg(session, skb);
507
508         return CAPI_NOERROR;
509 }
510
511 static char *cmtp_procinfo(struct capi_ctr *ctrl)
512 {
513         return "CAPI Message Transport Protocol";
514 }
515
516 static int cmtp_ctr_read_proc(char *page, char **start, off_t off, int count, int *eof, struct capi_ctr *ctrl)
517 {
518         struct cmtp_session *session = ctrl->driverdata;
519         struct cmtp_application *app;
520         struct list_head *p, *n;
521         int len = 0;
522
523         len += sprintf(page + len, "%s\n\n", cmtp_procinfo(ctrl));
524         len += sprintf(page + len, "addr %s\n", session->name);
525         len += sprintf(page + len, "ctrl %d\n", session->num);
526
527         list_for_each_safe(p, n, &session->applications) {
528                 app = list_entry(p, struct cmtp_application, list);
529                 len += sprintf(page + len, "appl %d -> %d\n", app->appl, app->mapping);
530         }
531
532         if (off + count >= len)
533                 *eof = 1;
534
535         if (len < off)
536                 return 0;
537
538         *start = page + off;
539
540         return ((count < len - off) ? count : len - off);
541 }
542
543
544 int cmtp_attach_device(struct cmtp_session *session)
545 {
546         DECLARE_WAITQUEUE(wait, current);
547         unsigned long timeo = CMTP_INTEROP_TIMEOUT;
548         unsigned char buf[4];
549
550         BT_DBG("session %p", session);
551
552         capimsg_setu32(buf, 0, 0);
553
554         cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, CMTP_INITIAL_MSGNUM,
555                                 CAPI_FUNCTION_GET_PROFILE, buf, 4);
556
557         add_wait_queue(&session->wait, &wait);
558         while (timeo) {
559                 set_current_state(TASK_INTERRUPTIBLE);
560
561                 if (session->ncontroller)
562                         break;
563
564                 if (signal_pending(current))
565                         break;
566
567                 timeo = schedule_timeout(timeo);
568         }
569         set_current_state(TASK_RUNNING);
570         remove_wait_queue(&session->wait, &wait);
571
572         BT_INFO("Found %d CAPI controller(s) on device %s", session->ncontroller, session->name);
573
574         if (!timeo)
575                 return -ETIMEDOUT;
576
577         if (!session->ncontroller)
578                 return -ENODEV;
579
580
581         if (session->ncontroller > 1)
582                 BT_INFO("Setting up only CAPI controller 1");
583
584         session->ctrl.owner      = THIS_MODULE;
585         session->ctrl.driverdata = session;
586         strcpy(session->ctrl.name, session->name);
587
588         session->ctrl.driver_name   = "cmtp";
589         session->ctrl.load_firmware = cmtp_load_firmware;
590         session->ctrl.reset_ctr     = cmtp_reset_ctr;
591         session->ctrl.register_appl = cmtp_register_appl;
592         session->ctrl.release_appl  = cmtp_release_appl;
593         session->ctrl.send_message  = cmtp_send_message;
594
595         session->ctrl.procinfo      = cmtp_procinfo;
596         session->ctrl.ctr_read_proc = cmtp_ctr_read_proc;
597
598         if (attach_capi_ctr(&session->ctrl) < 0) {
599                 BT_ERR("Can't attach new controller");
600                 return -EBUSY;
601         }
602
603         session->num = session->ctrl.cnr;
604
605         BT_DBG("session %p num %d", session, session->num);
606
607         capimsg_setu32(buf, 0, 1);
608
609         cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
610                                 CAPI_FUNCTION_GET_MANUFACTURER, buf, 4);
611
612         cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
613                                 CAPI_FUNCTION_GET_VERSION, buf, 4);
614
615         cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
616                                 CAPI_FUNCTION_GET_SERIAL_NUMBER, buf, 4);
617
618         cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
619                                 CAPI_FUNCTION_GET_PROFILE, buf, 4);
620
621         return 0;
622 }
623
624 void cmtp_detach_device(struct cmtp_session *session)
625 {
626         BT_DBG("session %p", session);
627
628         detach_capi_ctr(&session->ctrl);
629 }