Merge branch 'for-linus' of git://neil.brown.name/md
[deliverable/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/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 }
This page took 0.181942 seconds and 5 git commands to generate.