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