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