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