1 /* $OpenBSD: hci_ioctl.c,v 1.1 2007/06/01 02:46:11 uwe Exp $ */
2 /* $NetBSD: hci_ioctl.c,v 1.5 2007/01/04 19:07:03 elad Exp $ */
3 /* $DragonFly: src/sys/netbt/hci_ioctl.c,v 1.1 2007/12/30 20:02:56 hasso 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>
41 #include <sys/systm.h>
42 #include <sys/thread2.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 TAILQ_FOREACH(unit
, &hci_unit_list
, hci_next
) {
65 kprintf("UNIT %s: flags 0x%4.4x, "
66 "num_cmd=%d, num_acl=%d, num_sco=%d\n",
67 unit
->hci_devname
, 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 kprintf("+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 kprintf("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 kprintf("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 kprintf("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 kprintf("+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 kprintf("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 kprintf("+DLC channel=%d\n", dlc
->rd_laddr
.bt_channel
);
135 hci_ioctl(unsigned long cmd
, void *data
, struct proc
*p
)
137 struct btreq
*btr
= data
;
138 struct thread
*td
= curthread
;
139 struct hci_unit
*unit
;
142 DPRINTFN(1, "cmd %#lx\n", cmd
);
145 #ifdef BLUETOOTH_DEBUG
151 * Get unit info based on address rather than name
154 unit
= hci_unit_lookup(&btr
->btr_bdaddr
);
161 * The remaining ioctl's all use the same btreq structure and
162 * index on the name of the device, so we look that up first.
165 /* empty name means give the first unit */
166 if (btr
->btr_name
[0] == '\0') {
171 /* else fall through and look it up */
179 TAILQ_FOREACH(unit
, &hci_unit_list
, hci_next
) {
180 if (strncmp(unit
->hci_devname
, btr
->btr_name
,
181 HCI_DEVNAME_SIZE
) == 0)
190 default: /* not one of mine */
195 case SIOCNBTINFO
: /* get next info */
197 unit
= TAILQ_NEXT(unit
, hci_next
);
199 unit
= TAILQ_FIRST(&hci_unit_list
);
206 /* and fall through to */
207 case SIOCGBTINFO
: /* get unit info */
208 case SIOCGBTINFOA
: /* get info by address */
209 memset(btr
, 0, sizeof(struct btreq
));
210 strlcpy(btr
->btr_name
, unit
->hci_devname
, HCI_DEVNAME_SIZE
);
211 bdaddr_copy(&btr
->btr_bdaddr
, &unit
->hci_bdaddr
);
213 btr
->btr_flags
= unit
->hci_flags
;
215 btr
->btr_num_cmd
= unit
->hci_num_cmd_pkts
;
216 btr
->btr_num_acl
= unit
->hci_num_acl_pkts
;
217 btr
->btr_num_sco
= unit
->hci_num_sco_pkts
;
218 btr
->btr_acl_mtu
= unit
->hci_max_acl_size
;
219 btr
->btr_sco_mtu
= unit
->hci_max_sco_size
;
221 btr
->btr_packet_type
= unit
->hci_packet_type
;
222 btr
->btr_link_policy
= unit
->hci_link_policy
;
225 case SIOCSBTFLAGS
: /* set unit flags (privileged) */
230 if ((unit
->hci_flags
& BTF_UP
)
231 && (btr
->btr_flags
& BTF_UP
) == 0) {
233 unit
->hci_flags
&= ~BTF_UP
;
237 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
);
247 unit
->hci_flags
|= BTF_UP
;
251 btr
->btr_flags
= unit
->hci_flags
;
254 case SIOCSBTPOLICY
: /* set unit link policy (privileged) */
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) */
269 unit
->hci_packet_type
= btr
->btr_packet_type
;
270 unit
->hci_packet_type
&= unit
->hci_acl_mask
;
271 btr
->btr_packet_type
= unit
->hci_packet_type
;
274 case SIOCGBTSTATS
: /* get unit statistics */
276 memcpy(&btr
->btr_stats
, &unit
->hci_stats
,
277 sizeof(struct bt_stats
));
281 case SIOCZBTSTATS
: /* get & reset unit statistics */
287 memcpy(&btr
->btr_stats
, &unit
->hci_stats
,
288 sizeof(struct bt_stats
));
289 memset(&unit
->hci_stats
, 0, sizeof(struct bt_stats
));
294 case SIOCSBTSCOMTU
: /* set sco_mtu value for unit */
296 * This is a temporary ioctl and may not be supported
297 * in the future. The need is that if SCO packets are
298 * sent to USB bluetooth controllers that are not an
299 * integer number of frame sizes, the USB bus locks up.
305 unit
->hci_max_sco_size
= btr
->btr_sco_mtu
;