2 CMTP implementation for Linux Bluetooth stack (BlueZ).
3 Copyright (C) 2002-2003 Marcel Holtmann <marcel@holtmann.org>
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;
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.
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.
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/signal.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>
41 #include <linux/isdn/capilli.h>
42 #include <linux/isdn/capicmd.h>
43 #include <linux/isdn/capiutil.h>
47 #define CAPI_INTEROPERABILITY 0x20
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)
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)
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
71 #define CMTP_MAPPING 3
73 static struct cmtp_application
*cmtp_application_add(struct cmtp_session
*session
, __u16 appl
)
75 struct cmtp_application
*app
= kzalloc(sizeof(*app
), GFP_KERNEL
);
77 BT_DBG("session %p application %p appl %d", session
, app
, appl
);
85 list_add_tail(&app
->list
, &session
->applications
);
90 static void cmtp_application_del(struct cmtp_session
*session
, struct cmtp_application
*app
)
92 BT_DBG("session %p application %p", session
, app
);
100 static struct cmtp_application
*cmtp_application_get(struct cmtp_session
*session
, int pattern
, __u16 value
)
102 struct cmtp_application
*app
;
104 list_for_each_entry(app
, &session
->applications
, list
) {
107 if (app
->msgnum
== value
)
111 if (app
->appl
== value
)
115 if (app
->mapping
== value
)
124 static int cmtp_msgnum_get(struct cmtp_session
*session
)
128 if ((session
->msgnum
& 0xff) > 200)
129 session
->msgnum
= CMTP_INITIAL_MSGNUM
+ 1;
131 return session
->msgnum
;
134 static void cmtp_send_capimsg(struct cmtp_session
*session
, struct sk_buff
*skb
)
136 struct cmtp_scb
*scb
= (void *) skb
->cb
;
138 BT_DBG("session %p skb %p len %d", session
, skb
, skb
->len
);
141 scb
->data
= (CAPIMSG_COMMAND(skb
->data
) == CAPI_DATA_B3
);
143 skb_queue_tail(&session
->transmit
, skb
);
145 wake_up_interruptible(sk_sleep(session
->sock
->sk
));
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
)
155 BT_DBG("session %p subcmd 0x%02x appl %d msgnum %d", session
, subcmd
, appl
, msgnum
);
157 skb
= alloc_skb(CAPI_MSG_BASELEN
+ 6 + len
, GFP_ATOMIC
);
159 BT_ERR("Can't allocate memory for interoperability packet");
163 s
= skb_put(skb
, CAPI_MSG_BASELEN
+ 6 + len
);
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
);
171 /* Interoperability selector (Bluetooth Device Management) */
172 capimsg_setu16(s
, 8, 0x0001);
174 capimsg_setu8 (s
, 10, 3 + len
);
175 capimsg_setu16(s
, 11, function
);
176 capimsg_setu8 (s
, 13, len
);
179 memcpy(s
+ 14, buf
, len
);
181 cmtp_send_capimsg(session
, skb
);
184 static void cmtp_recv_interopmsg(struct cmtp_session
*session
, struct sk_buff
*skb
)
186 struct capi_ctr
*ctrl
= &session
->ctrl
;
187 struct cmtp_application
*application
;
188 __u16 appl
, msgnum
, func
, info
;
191 BT_DBG("session %p skb %p len %d", session
, skb
, skb
->len
);
193 switch (CAPIMSG_SUBCOMMAND(skb
->data
)) {
195 if (skb
->len
< CAPI_MSG_BASELEN
+ 10)
198 func
= CAPIMSG_U16(skb
->data
, CAPI_MSG_BASELEN
+ 5);
199 info
= CAPIMSG_U16(skb
->data
, CAPI_MSG_BASELEN
+ 8);
202 case CAPI_FUNCTION_REGISTER
:
203 msgnum
= CAPIMSG_MSGID(skb
->data
);
205 application
= cmtp_application_get(session
, CMTP_MSGNUM
, msgnum
);
207 application
->state
= BT_CONNECTED
;
208 application
->msgnum
= 0;
209 application
->mapping
= CAPIMSG_APPID(skb
->data
);
210 wake_up_interruptible(&session
->wait
);
215 case CAPI_FUNCTION_RELEASE
:
216 appl
= CAPIMSG_APPID(skb
->data
);
218 application
= cmtp_application_get(session
, CMTP_MAPPING
, appl
);
220 application
->state
= BT_CLOSED
;
221 application
->msgnum
= 0;
222 wake_up_interruptible(&session
->wait
);
227 case CAPI_FUNCTION_GET_PROFILE
:
228 if (skb
->len
< CAPI_MSG_BASELEN
+ 11 + sizeof(capi_profile
))
231 controller
= CAPIMSG_U16(skb
->data
, CAPI_MSG_BASELEN
+ 11);
232 msgnum
= CAPIMSG_MSGID(skb
->data
);
234 if (!info
&& (msgnum
== CMTP_INITIAL_MSGNUM
)) {
235 session
->ncontroller
= controller
;
236 wake_up_interruptible(&session
->wait
);
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
);
250 case CAPI_FUNCTION_GET_MANUFACTURER
:
251 if (skb
->len
< CAPI_MSG_BASELEN
+ 15)
255 int len
= min_t(uint
, CAPI_MANUFACTURER_LEN
,
256 skb
->data
[CAPI_MSG_BASELEN
+ 14]);
258 memset(ctrl
->manu
, 0, CAPI_MANUFACTURER_LEN
);
260 skb
->data
+ CAPI_MSG_BASELEN
+ 15, len
);
265 case CAPI_FUNCTION_GET_VERSION
:
266 if (skb
->len
< CAPI_MSG_BASELEN
+ 32)
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);
278 case CAPI_FUNCTION_GET_SERIAL_NUMBER
:
279 if (skb
->len
< CAPI_MSG_BASELEN
+ 17)
283 int len
= min_t(uint
, CAPI_SERIAL_LEN
,
284 skb
->data
[CAPI_MSG_BASELEN
+ 16]);
286 memset(ctrl
->serial
, 0, CAPI_SERIAL_LEN
);
287 strncpy(ctrl
->serial
,
288 skb
->data
+ CAPI_MSG_BASELEN
+ 17, len
);
297 if (skb
->len
< CAPI_MSG_BASELEN
+ 6)
300 func
= CAPIMSG_U16(skb
->data
, CAPI_MSG_BASELEN
+ 3);
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
);
317 void cmtp_recv_capimsg(struct cmtp_session
*session
, struct sk_buff
*skb
)
319 struct capi_ctr
*ctrl
= &session
->ctrl
;
320 struct cmtp_application
*application
;
324 BT_DBG("session %p skb %p len %d", session
, skb
, skb
->len
);
326 if (skb
->len
< CAPI_MSG_BASELEN
)
329 if (CAPIMSG_COMMAND(skb
->data
) == CAPI_INTEROPERABILITY
) {
330 cmtp_recv_interopmsg(session
, skb
);
334 if (session
->flags
& BIT(CMTP_LOOPBACK
)) {
339 appl
= CAPIMSG_APPID(skb
->data
);
340 contr
= CAPIMSG_CONTROL(skb
->data
);
342 application
= cmtp_application_get(session
, CMTP_MAPPING
, appl
);
344 appl
= application
->appl
;
345 CAPIMSG_SETAPPID(skb
->data
, appl
);
347 BT_ERR("Can't find application with id %d", appl
);
352 if ((contr
& 0x7f) == 0x01) {
353 contr
= (contr
& 0xffffff80) | session
->num
;
354 CAPIMSG_SETCONTROL(skb
->data
, contr
);
357 capi_ctr_handle_message(ctrl
, appl
, skb
);
360 static int cmtp_load_firmware(struct capi_ctr
*ctrl
, capiloaddata
*data
)
362 BT_DBG("ctrl %p data %p", ctrl
, data
);
367 static void cmtp_reset_ctr(struct capi_ctr
*ctrl
)
369 struct cmtp_session
*session
= ctrl
->driverdata
;
371 BT_DBG("ctrl %p", ctrl
);
375 atomic_inc(&session
->terminate
);
376 wake_up_process(session
->task
);
379 static void cmtp_register_appl(struct capi_ctr
*ctrl
, __u16 appl
, capi_register_params
*rp
)
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
;
388 BT_DBG("ctrl %p appl %d level3cnt %d datablkcnt %d datablklen %d",
389 ctrl
, appl
, rp
->level3cnt
, rp
->datablkcnt
, rp
->datablklen
);
391 application
= cmtp_application_add(session
, appl
);
393 BT_ERR("Can't allocate memory for new application");
398 nconn
= ctrl
->profile
.nbchannel
* -want
;
403 nconn
= ctrl
->profile
.nbchannel
;
405 capimsg_setu16(buf
, 0, nconn
);
406 capimsg_setu16(buf
, 2, rp
->datablkcnt
);
407 capimsg_setu16(buf
, 4, rp
->datablklen
);
409 application
->state
= BT_CONFIG
;
410 application
->msgnum
= cmtp_msgnum_get(session
);
412 cmtp_send_interopmsg(session
, CAPI_REQ
, 0x0000, application
->msgnum
,
413 CAPI_FUNCTION_REGISTER
, buf
, 6);
415 add_wait_queue(&session
->wait
, &wait
);
417 set_current_state(TASK_INTERRUPTIBLE
);
424 if (application
->state
== BT_CLOSED
) {
425 err
= -application
->err
;
429 if (application
->state
== BT_CONNECTED
)
432 if (signal_pending(current
)) {
437 timeo
= schedule_timeout(timeo
);
439 set_current_state(TASK_RUNNING
);
440 remove_wait_queue(&session
->wait
, &wait
);
443 cmtp_application_del(session
, application
);
448 static void cmtp_release_appl(struct capi_ctr
*ctrl
, __u16 appl
)
450 struct cmtp_session
*session
= ctrl
->driverdata
;
451 struct cmtp_application
*application
;
453 BT_DBG("ctrl %p appl %d", ctrl
, appl
);
455 application
= cmtp_application_get(session
, CMTP_APPLID
, appl
);
457 BT_ERR("Can't find application");
461 application
->msgnum
= cmtp_msgnum_get(session
);
463 cmtp_send_interopmsg(session
, CAPI_REQ
, application
->mapping
, application
->msgnum
,
464 CAPI_FUNCTION_RELEASE
, NULL
, 0);
466 wait_event_interruptible_timeout(session
->wait
,
467 (application
->state
== BT_CLOSED
), CMTP_INTEROP_TIMEOUT
);
469 cmtp_application_del(session
, application
);
472 static u16
cmtp_send_message(struct capi_ctr
*ctrl
, struct sk_buff
*skb
)
474 struct cmtp_session
*session
= ctrl
->driverdata
;
475 struct cmtp_application
*application
;
479 BT_DBG("ctrl %p skb %p", ctrl
, skb
);
481 appl
= CAPIMSG_APPID(skb
->data
);
482 contr
= CAPIMSG_CONTROL(skb
->data
);
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
;
490 CAPIMSG_SETAPPID(skb
->data
, application
->mapping
);
492 if ((contr
& 0x7f) == session
->num
) {
493 contr
= (contr
& 0xffffff80) | 0x01;
494 CAPIMSG_SETCONTROL(skb
->data
, contr
);
497 cmtp_send_capimsg(session
, skb
);
502 static char *cmtp_procinfo(struct capi_ctr
*ctrl
)
504 return "CAPI Message Transport Protocol";
507 static int cmtp_proc_show(struct seq_file
*m
, void *v
)
509 struct capi_ctr
*ctrl
= m
->private;
510 struct cmtp_session
*session
= ctrl
->driverdata
;
511 struct cmtp_application
*app
;
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
);
517 list_for_each_entry(app
, &session
->applications
, list
) {
518 seq_printf(m
, "appl %d -> %d\n", app
->appl
, app
->mapping
);
524 int cmtp_attach_device(struct cmtp_session
*session
)
526 unsigned char buf
[4];
529 BT_DBG("session %p", session
);
531 capimsg_setu32(buf
, 0, 0);
533 cmtp_send_interopmsg(session
, CAPI_REQ
, 0xffff, CMTP_INITIAL_MSGNUM
,
534 CAPI_FUNCTION_GET_PROFILE
, buf
, 4);
536 ret
= wait_event_interruptible_timeout(session
->wait
,
537 session
->ncontroller
, CMTP_INTEROP_TIMEOUT
);
539 BT_INFO("Found %d CAPI controller(s) on device %s", session
->ncontroller
, session
->name
);
544 if (!session
->ncontroller
)
547 if (session
->ncontroller
> 1)
548 BT_INFO("Setting up only CAPI controller 1");
550 session
->ctrl
.owner
= THIS_MODULE
;
551 session
->ctrl
.driverdata
= session
;
552 strcpy(session
->ctrl
.name
, session
->name
);
554 session
->ctrl
.driver_name
= "cmtp";
555 session
->ctrl
.load_firmware
= cmtp_load_firmware
;
556 session
->ctrl
.reset_ctr
= cmtp_reset_ctr
;
557 session
->ctrl
.register_appl
= cmtp_register_appl
;
558 session
->ctrl
.release_appl
= cmtp_release_appl
;
559 session
->ctrl
.send_message
= cmtp_send_message
;
561 session
->ctrl
.procinfo
= cmtp_procinfo
;
562 session
->ctrl
.proc_show
= cmtp_proc_show
;
564 if (attach_capi_ctr(&session
->ctrl
) < 0) {
565 BT_ERR("Can't attach new controller");
569 session
->num
= session
->ctrl
.cnr
;
571 BT_DBG("session %p num %d", session
, session
->num
);
573 capimsg_setu32(buf
, 0, 1);
575 cmtp_send_interopmsg(session
, CAPI_REQ
, 0xffff, cmtp_msgnum_get(session
),
576 CAPI_FUNCTION_GET_MANUFACTURER
, buf
, 4);
578 cmtp_send_interopmsg(session
, CAPI_REQ
, 0xffff, cmtp_msgnum_get(session
),
579 CAPI_FUNCTION_GET_VERSION
, buf
, 4);
581 cmtp_send_interopmsg(session
, CAPI_REQ
, 0xffff, cmtp_msgnum_get(session
),
582 CAPI_FUNCTION_GET_SERIAL_NUMBER
, buf
, 4);
584 cmtp_send_interopmsg(session
, CAPI_REQ
, 0xffff, cmtp_msgnum_get(session
),
585 CAPI_FUNCTION_GET_PROFILE
, buf
, 4);
590 void cmtp_detach_device(struct cmtp_session
*session
)
592 BT_DBG("session %p", session
);
594 detach_capi_ctr(&session
->ctrl
);