1 /* $DragonFly: src/sys/netbt/hci_ioctl.c,v 1.2 2008/03/18 13:41:42 hasso Exp $ */
2 /* $OpenBSD: src/sys/netbt/hci_ioctl.c,v 1.2 2008/02/24 21:34:48 uwe Exp $ */
3 /* $NetBSD: hci_ioctl.c,v 1.7 2007/11/28 20:16:12 plunky Exp $ */
6 * Copyright (c) 2005 Iain Hibbert.
7 * Copyright (c) 2006 Itronix Inc.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. The name of Itronix Inc. may not be used to endorse
19 * or promote products derived from this software without specific
20 * prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
26 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 * ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
35 #include <sys/param.h>
36 #include <sys/domain.h>
37 #include <sys/ioccom.h>
38 #include <sys/kernel.h>
42 #include <sys/systm.h>
43 #include <sys/thread2.h>
46 #include <netbt/bluetooth.h>
47 #include <netbt/hci.h>
48 #include <netbt/l2cap.h>
49 #include <netbt/rfcomm.h>
51 #ifdef BLUETOOTH_DEBUG
52 #define BDADDR(bd) (bd).b[5], (bd).b[4], (bd).b[3], \
53 (bd).b[2], (bd).b[1], (bd).b[0]
58 struct hci_unit
*unit
;
59 struct hci_link
*link
;
60 struct l2cap_channel
*chan
;
61 struct rfcomm_session
*rs
;
62 struct rfcomm_dlc
*dlc
;
65 TAILQ_FOREACH(unit
, &hci_unit_list
, hci_next
) {
66 kprintf("UNIT %s: flags 0x%4.4x, "
67 "num_cmd=%d, num_acl=%d, num_sco=%d\n",
68 device_get_nameunit(unit
->hci_dev
), unit
->hci_flags
,
69 unit
->hci_num_cmd_pkts
,
70 unit
->hci_num_acl_pkts
,
71 unit
->hci_num_sco_pkts
);
72 TAILQ_FOREACH(link
, &unit
->hci_links
, hl_next
) {
73 kprintf("+HANDLE #%d: %s "
74 "raddr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
75 "state %d, refcnt %d\n",
77 (link
->hl_type
== HCI_LINK_ACL
? "ACL":"SCO"),
78 BDADDR(link
->hl_bdaddr
),
79 link
->hl_state
, link
->hl_refcnt
);
84 LIST_FOREACH(chan
, &l2cap_active_list
, lc_ncid
) {
85 kprintf("CID #%d state %d, psm=0x%4.4x, "
86 "laddr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
87 "raddr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
88 chan
->lc_lcid
, chan
->lc_state
, chan
->lc_raddr
.bt_psm
,
89 BDADDR(chan
->lc_laddr
.bt_bdaddr
),
90 BDADDR(chan
->lc_raddr
.bt_bdaddr
));
93 LIST_FOREACH(chan
, &l2cap_listen_list
, lc_ncid
) {
94 kprintf("LISTEN psm=0x%4.4x, "
95 "laddr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
96 chan
->lc_laddr
.bt_psm
,
97 BDADDR(chan
->lc_laddr
.bt_bdaddr
));
100 kprintf("RFCOMM:\n");
101 LIST_FOREACH(rs
, &rfcomm_session_active
, rs_next
) {
103 kprintf("SESSION: state=%d, flags=0x%4.4x, psm 0x%4.4x "
104 "laddr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
105 "raddr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
106 rs
->rs_state
, rs
->rs_flags
, chan
->lc_raddr
.bt_psm
,
107 BDADDR(chan
->lc_laddr
.bt_bdaddr
),
108 BDADDR(chan
->lc_raddr
.bt_bdaddr
));
109 LIST_FOREACH(dlc
, &rs
->rs_dlcs
, rd_next
) {
110 kprintf("+DLC channel=%d, dlci=%d, "
111 "state=%d, flags=0x%4.4x, rxcred=%d, rxsize=%ld, "
112 "txcred=%d, pending=%d, txqlen=%d\n",
113 dlc
->rd_raddr
.bt_channel
, dlc
->rd_dlci
,
114 dlc
->rd_state
, dlc
->rd_flags
,
115 dlc
->rd_rxcred
, (unsigned long)dlc
->rd_rxsize
,
116 dlc
->rd_txcred
, dlc
->rd_pending
,
117 (dlc
->rd_txbuf
? dlc
->rd_txbuf
->m_pkthdr
.len
: 0));
121 LIST_FOREACH(rs
, &rfcomm_session_listen
, rs_next
) {
123 kprintf("LISTEN: psm 0x%4.4x, "
124 "laddr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
125 chan
->lc_laddr
.bt_psm
,
126 BDADDR(chan
->lc_laddr
.bt_bdaddr
));
127 LIST_FOREACH(dlc
, &rs
->rs_dlcs
, rd_next
)
128 kprintf("+DLC channel=%d\n", dlc
->rd_laddr
.bt_channel
);
136 hci_ioctl(unsigned long cmd
, void *data
, struct proc
*p
)
138 struct btreq
*btr
= data
;
139 struct thread
*td
= curthread
;
140 struct hci_unit
*unit
;
143 DPRINTFN(1, "cmd %#lx\n", cmd
);
146 #ifdef BLUETOOTH_DEBUG
152 * Get unit info based on address rather than name
155 unit
= hci_unit_lookup(&btr
->btr_bdaddr
);
162 * The remaining ioctl's all use the same btreq structure and
163 * index on the name of the device, so we look that up first.
166 /* empty name means give the first unit */
167 if (btr
->btr_name
[0] == '\0') {
172 /* else fall through and look it up */
180 TAILQ_FOREACH(unit
, &hci_unit_list
, hci_next
) {
181 if (strncmp(device_get_nameunit(unit
->hci_dev
),
182 btr
->btr_name
, HCI_DEVNAME_SIZE
) == 0)
191 default: /* not one of mine */
196 case SIOCNBTINFO
: /* get next info */
198 unit
= TAILQ_NEXT(unit
, hci_next
);
200 unit
= TAILQ_FIRST(&hci_unit_list
);
207 /* and fall through to */
208 case SIOCGBTINFO
: /* get unit info */
209 case SIOCGBTINFOA
: /* get info by address */
210 memset(btr
, 0, sizeof(struct btreq
));
211 strlcpy(btr
->btr_name
, device_get_nameunit(unit
->hci_dev
),
213 bdaddr_copy(&btr
->btr_bdaddr
, &unit
->hci_bdaddr
);
215 btr
->btr_flags
= unit
->hci_flags
;
217 btr
->btr_num_cmd
= unit
->hci_num_cmd_pkts
;
218 btr
->btr_num_acl
= unit
->hci_num_acl_pkts
;
219 btr
->btr_num_sco
= unit
->hci_num_sco_pkts
;
220 btr
->btr_acl_mtu
= unit
->hci_max_acl_size
;
221 btr
->btr_sco_mtu
= unit
->hci_max_sco_size
;
223 btr
->btr_packet_type
= unit
->hci_packet_type
;
224 btr
->btr_link_policy
= unit
->hci_link_policy
;
227 case SIOCSBTFLAGS
: /* set unit flags (privileged) */
228 err
= priv_check(td
, PRIV_ROOT
);
232 if ((unit
->hci_flags
& BTF_UP
)
233 && (btr
->btr_flags
& BTF_UP
) == 0) {
235 unit
->hci_flags
&= ~BTF_UP
;
238 unit
->hci_flags
|= (btr
->btr_flags
& BTF_INIT
);
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
= priv_check(td
, PRIV_ROOT
);
257 unit
->hci_link_policy
= btr
->btr_link_policy
;
258 unit
->hci_link_policy
&= unit
->hci_lmp_mask
;
259 btr
->btr_link_policy
= unit
->hci_link_policy
;
262 case SIOCSBTPTYPE
: /* set unit packet types (privileged) */
263 err
= priv_check(td
, PRIV_ROOT
);
267 unit
->hci_packet_type
= btr
->btr_packet_type
;
268 unit
->hci_packet_type
&= unit
->hci_acl_mask
;
269 btr
->btr_packet_type
= unit
->hci_packet_type
;
272 case SIOCGBTSTATS
: /* get unit statistics */
273 (*unit
->hci_if
->get_stats
)(unit
->hci_dev
, &btr
->btr_stats
, 0);
276 case SIOCZBTSTATS
: /* get & reset unit statistics */
277 err
= priv_check(td
, PRIV_ROOT
);
281 (*unit
->hci_if
->get_stats
)(unit
->hci_dev
, &btr
->btr_stats
, 1);
284 case SIOCSBTSCOMTU
: /* set sco_mtu value for unit */
286 * This is a temporary ioctl and may not be supported
287 * in the future. The need is that if SCO packets are
288 * sent to USB bluetooth controllers that are not an
289 * integer number of frame sizes, the USB bus locks up.
291 err
= priv_check(td
, PRIV_ROOT
);
295 unit
->hci_max_sco_size
= btr
->btr_sco_mtu
;