1 /* $NetBSD: hci_ioctl.c,v 1.8 2009/05/03 17:21:12 elad Exp $ */
4 * Copyright (c) 2005 Iain Hibbert.
5 * Copyright (c) 2006 Itronix Inc.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of Itronix Inc. may not be used to endorse
17 * or promote products derived from this software without specific
18 * prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
24 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27 * ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: hci_ioctl.c,v 1.8 2009/05/03 17:21:12 elad Exp $");
36 #include <sys/param.h>
37 #include <sys/domain.h>
38 #include <sys/ioctl.h>
39 #include <sys/kauth.h>
40 #include <sys/kernel.h>
43 #include <sys/systm.h>
45 #include <netbt/bluetooth.h>
46 #include <netbt/hci.h>
47 #include <netbt/l2cap.h>
48 #include <netbt/rfcomm.h>
50 #ifdef BLUETOOTH_DEBUG
51 #define BDADDR(bd) (bd).b[5], (bd).b[4], (bd).b[3], \
52 (bd).b[2], (bd).b[1], (bd).b[0]
57 struct hci_unit
*unit
;
58 struct hci_link
*link
;
59 struct l2cap_channel
*chan
;
60 struct rfcomm_session
*rs
;
61 struct rfcomm_dlc
*dlc
;
64 SIMPLEQ_FOREACH(unit
, &hci_unit_list
, hci_next
) {
65 uprintf("UNIT %s: flags 0x%4.4x, "
66 "num_cmd=%d, num_acl=%d, num_sco=%d\n",
67 device_xname(unit
->hci_dev
), unit
->hci_flags
,
68 unit
->hci_num_cmd_pkts
,
69 unit
->hci_num_acl_pkts
,
70 unit
->hci_num_sco_pkts
);
71 TAILQ_FOREACH(link
, &unit
->hci_links
, hl_next
) {
72 uprintf("+HANDLE #%d: %s "
73 "raddr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
74 "state %d, refcnt %d\n",
76 (link
->hl_type
== HCI_LINK_ACL
? "ACL":"SCO"),
77 BDADDR(link
->hl_bdaddr
),
78 link
->hl_state
, link
->hl_refcnt
);
83 LIST_FOREACH(chan
, &l2cap_active_list
, lc_ncid
) {
84 uprintf("CID #%d state %d, psm=0x%4.4x, "
85 "laddr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
86 "raddr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
87 chan
->lc_lcid
, chan
->lc_state
, chan
->lc_raddr
.bt_psm
,
88 BDADDR(chan
->lc_laddr
.bt_bdaddr
),
89 BDADDR(chan
->lc_raddr
.bt_bdaddr
));
92 LIST_FOREACH(chan
, &l2cap_listen_list
, lc_ncid
) {
93 uprintf("LISTEN psm=0x%4.4x, "
94 "laddr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
95 chan
->lc_laddr
.bt_psm
,
96 BDADDR(chan
->lc_laddr
.bt_bdaddr
));
100 LIST_FOREACH(rs
, &rfcomm_session_active
, rs_next
) {
102 uprintf("SESSION: state=%d, flags=0x%4.4x, psm 0x%4.4x "
103 "laddr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
104 "raddr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
105 rs
->rs_state
, rs
->rs_flags
, chan
->lc_raddr
.bt_psm
,
106 BDADDR(chan
->lc_laddr
.bt_bdaddr
),
107 BDADDR(chan
->lc_raddr
.bt_bdaddr
));
108 LIST_FOREACH(dlc
, &rs
->rs_dlcs
, rd_next
) {
109 uprintf("+DLC channel=%d, dlci=%d, "
110 "state=%d, flags=0x%4.4x, rxcred=%d, rxsize=%ld, "
111 "txcred=%d, pending=%d, txqlen=%d\n",
112 dlc
->rd_raddr
.bt_channel
, dlc
->rd_dlci
,
113 dlc
->rd_state
, dlc
->rd_flags
,
114 dlc
->rd_rxcred
, (unsigned long)dlc
->rd_rxsize
,
115 dlc
->rd_txcred
, dlc
->rd_pending
,
116 (dlc
->rd_txbuf
? dlc
->rd_txbuf
->m_pkthdr
.len
: 0));
120 LIST_FOREACH(rs
, &rfcomm_session_listen
, rs_next
) {
122 uprintf("LISTEN: psm 0x%4.4x, "
123 "laddr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
124 chan
->lc_laddr
.bt_psm
,
125 BDADDR(chan
->lc_laddr
.bt_bdaddr
));
126 LIST_FOREACH(dlc
, &rs
->rs_dlcs
, rd_next
)
127 uprintf("+DLC channel=%d\n", dlc
->rd_laddr
.bt_channel
);
135 hci_ioctl(unsigned long cmd
, void *data
, struct lwp
*l
)
137 struct btreq
*btr
= data
;
138 struct hci_unit
*unit
;
141 DPRINTFN(1, "cmd %#lx\n", cmd
);
144 #ifdef BLUETOOTH_DEBUG
150 * Get unit info based on address rather than name
153 unit
= hci_unit_lookup(&btr
->btr_bdaddr
);
160 * The remaining ioctl's all use the same btreq structure and
161 * index on the name of the device, so we look that up first.
164 /* empty name means give the first unit */
165 if (btr
->btr_name
[0] == '\0') {
170 /* else fall through and look it up */
178 SIMPLEQ_FOREACH(unit
, &hci_unit_list
, hci_next
) {
179 if (strncmp(device_xname(unit
->hci_dev
),
180 btr
->btr_name
, HCI_DEVNAME_SIZE
) == 0)
189 default: /* not one of mine */
194 case SIOCNBTINFO
: /* get next info */
196 unit
= SIMPLEQ_NEXT(unit
, hci_next
);
198 unit
= SIMPLEQ_FIRST(&hci_unit_list
);
205 /* and fall through to */
206 case SIOCGBTINFO
: /* get unit info */
207 case SIOCGBTINFOA
: /* get info by address */
208 memset(btr
, 0, sizeof(struct btreq
));
209 strlcpy(btr
->btr_name
, device_xname(unit
->hci_dev
), HCI_DEVNAME_SIZE
);
210 bdaddr_copy(&btr
->btr_bdaddr
, &unit
->hci_bdaddr
);
212 btr
->btr_flags
= unit
->hci_flags
;
214 btr
->btr_num_cmd
= unit
->hci_num_cmd_pkts
;
215 btr
->btr_num_acl
= unit
->hci_num_acl_pkts
;
216 btr
->btr_num_sco
= unit
->hci_num_sco_pkts
;
217 btr
->btr_acl_mtu
= unit
->hci_max_acl_size
;
218 btr
->btr_sco_mtu
= unit
->hci_max_sco_size
;
220 btr
->btr_packet_type
= unit
->hci_packet_type
;
221 btr
->btr_link_policy
= unit
->hci_link_policy
;
224 case SIOCSBTFLAGS
: /* set unit flags (privileged) */
225 err
= kauth_authorize_device(l
->l_cred
,
226 KAUTH_DEVICE_BLUETOOTH_SETPRIV
, unit
, KAUTH_ARG(cmd
),
231 if ((unit
->hci_flags
& BTF_UP
)
232 && (btr
->btr_flags
& BTF_UP
) == 0) {
234 unit
->hci_flags
&= ~BTF_UP
;
237 unit
->hci_flags
&= ~BTF_MASTER
;
238 unit
->hci_flags
|= (btr
->btr_flags
& (BTF_INIT
| BTF_MASTER
));
240 if ((unit
->hci_flags
& BTF_UP
) == 0
241 && (btr
->btr_flags
& BTF_UP
)) {
242 err
= hci_enable(unit
);
246 unit
->hci_flags
|= BTF_UP
;
249 btr
->btr_flags
= unit
->hci_flags
;
252 case SIOCSBTPOLICY
: /* set unit link policy (privileged) */
253 err
= kauth_authorize_device(l
->l_cred
,
254 KAUTH_DEVICE_BLUETOOTH_SETPRIV
, unit
, KAUTH_ARG(cmd
),
259 unit
->hci_link_policy
= btr
->btr_link_policy
;
260 unit
->hci_link_policy
&= unit
->hci_lmp_mask
;
261 btr
->btr_link_policy
= unit
->hci_link_policy
;
264 case SIOCSBTPTYPE
: /* set unit packet types (privileged) */
265 err
= kauth_authorize_device(l
->l_cred
,
266 KAUTH_DEVICE_BLUETOOTH_SETPRIV
, unit
, KAUTH_ARG(cmd
),
271 unit
->hci_packet_type
= btr
->btr_packet_type
;
272 unit
->hci_packet_type
&= unit
->hci_acl_mask
;
273 btr
->btr_packet_type
= unit
->hci_packet_type
;
276 case SIOCGBTSTATS
: /* get unit statistics */
277 (*unit
->hci_if
->get_stats
)(unit
->hci_dev
, &btr
->btr_stats
, 0);
280 case SIOCZBTSTATS
: /* get & reset unit statistics */
281 err
= kauth_authorize_device(l
->l_cred
,
282 KAUTH_DEVICE_BLUETOOTH_SETPRIV
, unit
, KAUTH_ARG(cmd
),
287 (*unit
->hci_if
->get_stats
)(unit
->hci_dev
, &btr
->btr_stats
, 1);
290 case SIOCSBTSCOMTU
: /* set sco_mtu value for unit */
292 * This is a temporary ioctl and may not be supported
293 * in the future. The need is that if SCO packets are
294 * sent to USB bluetooth controllers that are not an
295 * integer number of frame sizes, the USB bus locks up.
297 err
= kauth_authorize_device(l
->l_cred
,
298 KAUTH_DEVICE_BLUETOOTH_SETPRIV
, unit
, KAUTH_ARG(cmd
),
303 unit
->hci_max_sco_size
= btr
->btr_sco_mtu
;