1 /* $OpenBSD: src/sys/netbt/hci_ioctl.c,v 1.2 2008/02/24 21:34:48 uwe Exp $ */
2 /* $NetBSD: hci_ioctl.c,v 1.7 2007/11/28 20:16:12 plunky Exp $ */
5 * Copyright (c) 2005 Iain Hibbert.
6 * Copyright (c) 2006 Itronix Inc.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of Itronix Inc. may not be used to endorse
18 * or promote products derived from this software without specific
19 * prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 * ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
34 #include <sys/param.h>
35 #include <sys/domain.h>
36 #include <sys/kernel.h>
40 #include <sys/systm.h>
43 #include <netbt/bluetooth.h>
44 #include <netbt/hci.h>
45 #include <netbt/l2cap.h>
46 #include <netbt/rfcomm.h>
48 #ifdef BLUETOOTH_DEBUG
49 #define BDADDR(bd) (bd).b[5], (bd).b[4], (bd).b[3], \
50 (bd).b[2], (bd).b[1], (bd).b[0]
55 struct hci_unit
*unit
;
56 struct hci_link
*link
;
57 struct l2cap_channel
*chan
;
58 struct rfcomm_session
*rs
;
59 struct rfcomm_dlc
*dlc
;
62 TAILQ_FOREACH(unit
, &hci_unit_list
, hci_next
) {
63 kprintf("UNIT %s: flags 0x%4.4x, "
64 "num_cmd=%d, num_acl=%d, num_sco=%d\n",
65 device_get_nameunit(unit
->hci_dev
), unit
->hci_flags
,
66 unit
->hci_num_cmd_pkts
,
67 unit
->hci_num_acl_pkts
,
68 unit
->hci_num_sco_pkts
);
69 TAILQ_FOREACH(link
, &unit
->hci_links
, hl_next
) {
70 kprintf("+HANDLE #%d: %s "
71 "raddr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
72 "state %d, refcnt %d\n",
74 (link
->hl_type
== HCI_LINK_ACL
? "ACL":"SCO"),
75 BDADDR(link
->hl_bdaddr
),
76 link
->hl_state
, link
->hl_refcnt
);
81 LIST_FOREACH(chan
, &l2cap_active_list
, lc_ncid
) {
82 kprintf("CID #%d state %d, psm=0x%4.4x, "
83 "laddr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
84 "raddr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
85 chan
->lc_lcid
, chan
->lc_state
, chan
->lc_raddr
.bt_psm
,
86 BDADDR(chan
->lc_laddr
.bt_bdaddr
),
87 BDADDR(chan
->lc_raddr
.bt_bdaddr
));
90 LIST_FOREACH(chan
, &l2cap_listen_list
, lc_ncid
) {
91 kprintf("LISTEN psm=0x%4.4x, "
92 "laddr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
93 chan
->lc_laddr
.bt_psm
,
94 BDADDR(chan
->lc_laddr
.bt_bdaddr
));
98 LIST_FOREACH(rs
, &rfcomm_session_active
, rs_next
) {
100 kprintf("SESSION: state=%d, flags=0x%4.4x, psm 0x%4.4x "
101 "laddr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
102 "raddr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
103 rs
->rs_state
, rs
->rs_flags
, chan
->lc_raddr
.bt_psm
,
104 BDADDR(chan
->lc_laddr
.bt_bdaddr
),
105 BDADDR(chan
->lc_raddr
.bt_bdaddr
));
106 LIST_FOREACH(dlc
, &rs
->rs_dlcs
, rd_next
) {
107 kprintf("+DLC channel=%d, dlci=%d, "
108 "state=%d, flags=0x%4.4x, rxcred=%d, rxsize=%ld, "
109 "txcred=%d, pending=%d, txqlen=%d\n",
110 dlc
->rd_raddr
.bt_channel
, dlc
->rd_dlci
,
111 dlc
->rd_state
, dlc
->rd_flags
,
112 dlc
->rd_rxcred
, (unsigned long)dlc
->rd_rxsize
,
113 dlc
->rd_txcred
, dlc
->rd_pending
,
114 (dlc
->rd_txbuf
? dlc
->rd_txbuf
->m_pkthdr
.len
: 0));
118 LIST_FOREACH(rs
, &rfcomm_session_listen
, rs_next
) {
120 kprintf("LISTEN: psm 0x%4.4x, "
121 "laddr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
122 chan
->lc_laddr
.bt_psm
,
123 BDADDR(chan
->lc_laddr
.bt_bdaddr
));
124 LIST_FOREACH(dlc
, &rs
->rs_dlcs
, rd_next
)
125 kprintf("+DLC channel=%d\n", dlc
->rd_laddr
.bt_channel
);
133 hci_ioctl(unsigned long cmd
, void *data
, struct proc
*p
)
135 struct btreq
*btr
= data
;
136 struct hci_unit
*unit
;
139 DPRINTFN(1, "cmd %#lx\n", cmd
);
142 #ifdef BLUETOOTH_DEBUG
148 * Get unit info based on address rather than name
151 unit
= hci_unit_lookup(&btr
->btr_bdaddr
);
158 * The remaining ioctl's all use the same btreq structure and
159 * index on the name of the device, so we look that up first.
162 /* empty name means give the first unit */
163 if (btr
->btr_name
[0] == '\0') {
168 /* else fall through and look it up */
176 TAILQ_FOREACH(unit
, &hci_unit_list
, hci_next
) {
177 if (strncmp(device_get_nameunit(unit
->hci_dev
),
178 btr
->btr_name
, HCI_DEVNAME_SIZE
) == 0)
187 default: /* not one of mine */
192 case SIOCNBTINFO
: /* get next info */
194 unit
= TAILQ_NEXT(unit
, hci_next
);
196 unit
= TAILQ_FIRST(&hci_unit_list
);
203 /* and fall through to */
204 case SIOCGBTINFO
: /* get unit info */
205 case SIOCGBTINFOA
: /* get info by address */
206 memset(btr
, 0, sizeof(struct btreq
));
207 strlcpy(btr
->btr_name
, device_get_nameunit(unit
->hci_dev
),
209 bdaddr_copy(&btr
->btr_bdaddr
, &unit
->hci_bdaddr
);
211 btr
->btr_flags
= unit
->hci_flags
;
213 btr
->btr_num_cmd
= unit
->hci_num_cmd_pkts
;
214 btr
->btr_num_acl
= unit
->hci_num_acl_pkts
;
215 btr
->btr_num_sco
= unit
->hci_num_sco_pkts
;
216 btr
->btr_acl_mtu
= unit
->hci_max_acl_size
;
217 btr
->btr_sco_mtu
= unit
->hci_max_sco_size
;
219 btr
->btr_packet_type
= unit
->hci_packet_type
;
220 btr
->btr_link_policy
= unit
->hci_link_policy
;
223 case SIOCSBTFLAGS
: /* set unit flags (privileged) */
224 err
= caps_priv_check_self(SYSCAP_RESTRICTEDROOT
);
228 if ((unit
->hci_flags
& BTF_UP
)
229 && (btr
->btr_flags
& BTF_UP
) == 0) {
231 unit
->hci_flags
&= ~BTF_UP
;
234 unit
->hci_flags
|= (btr
->btr_flags
& BTF_INIT
);
236 if ((unit
->hci_flags
& BTF_UP
) == 0
237 && (btr
->btr_flags
& BTF_UP
)) {
238 err
= hci_enable(unit
);
242 unit
->hci_flags
|= BTF_UP
;
245 btr
->btr_flags
= unit
->hci_flags
;
248 case SIOCSBTPOLICY
: /* set unit link policy (privileged) */
249 err
= caps_priv_check_self(SYSCAP_RESTRICTEDROOT
);
253 unit
->hci_link_policy
= btr
->btr_link_policy
;
254 unit
->hci_link_policy
&= unit
->hci_lmp_mask
;
255 btr
->btr_link_policy
= unit
->hci_link_policy
;
258 case SIOCSBTPTYPE
: /* set unit packet types (privileged) */
259 err
= caps_priv_check_self(SYSCAP_RESTRICTEDROOT
);
263 unit
->hci_packet_type
= btr
->btr_packet_type
;
264 unit
->hci_packet_type
&= unit
->hci_acl_mask
;
265 btr
->btr_packet_type
= unit
->hci_packet_type
;
268 case SIOCGBTSTATS
: /* get unit statistics */
269 (*unit
->hci_if
->get_stats
)(unit
->hci_dev
, &btr
->btr_stats
, 0);
272 case SIOCZBTSTATS
: /* get & reset unit statistics */
273 err
= caps_priv_check_self(SYSCAP_RESTRICTEDROOT
);
277 (*unit
->hci_if
->get_stats
)(unit
->hci_dev
, &btr
->btr_stats
, 1);
280 case SIOCSBTSCOMTU
: /* set sco_mtu value for unit */
282 * This is a temporary ioctl and may not be supported
283 * in the future. The need is that if SCO packets are
284 * sent to USB bluetooth controllers that are not an
285 * integer number of frame sizes, the USB bus locks up.
287 err
= caps_priv_check_self(SYSCAP_RESTRICTEDROOT
);
291 unit
->hci_max_sco_size
= btr
->btr_sco_mtu
;