nrelease Makefile adjustments: Packages, newaliases, check target, etc
[dragonfly.git] / sys / netbt / hci_ioctl.c
blob0c7554131e0b3cd35bd16d00cd7ac67021071e1b
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 $ */
5 /*-
6 * Copyright (c) 2005 Iain Hibbert.
7 * Copyright (c) 2006 Itronix Inc.
8 * All rights reserved.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
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>
39 #include <sys/mbuf.h>
40 #include <sys/proc.h>
41 #include <sys/priv.h>
42 #include <sys/systm.h>
43 #include <sys/thread2.h>
44 #include <sys/bus.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]
55 static void
56 hci_dump(void)
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;
64 kprintf("HCI:\n");
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",
76 link->hl_handle,
77 (link->hl_type == HCI_LINK_ACL ? "ACL":"SCO"),
78 BDADDR(link->hl_bdaddr),
79 link->hl_state, link->hl_refcnt);
83 kprintf("L2CAP:\n");
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) {
102 chan = rs->rs_l2cap;
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) {
122 chan = rs->rs_l2cap;
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);
132 #undef BDADDR
133 #endif
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;
141 int err = 0;
143 DPRINTFN(1, "cmd %#lx\n", cmd);
145 switch(cmd) {
146 #ifdef BLUETOOTH_DEBUG
147 case SIOCBTDUMP:
148 hci_dump();
149 return 0;
150 #endif
152 * Get unit info based on address rather than name
154 case SIOCGBTINFOA:
155 unit = hci_unit_lookup(&btr->btr_bdaddr);
156 if (unit == NULL)
157 return ENXIO;
159 break;
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.
165 case SIOCNBTINFO:
166 /* empty name means give the first unit */
167 if (btr->btr_name[0] == '\0') {
168 unit = NULL;
169 break;
172 /* else fall through and look it up */
173 case SIOCGBTINFO:
174 case SIOCSBTFLAGS:
175 case SIOCSBTPOLICY:
176 case SIOCSBTPTYPE:
177 case SIOCGBTSTATS:
178 case SIOCZBTSTATS:
179 case SIOCSBTSCOMTU:
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)
183 break;
186 if (unit == NULL)
187 return ENXIO;
189 break;
191 default: /* not one of mine */
192 return EPASSTHROUGH;
195 switch(cmd) {
196 case SIOCNBTINFO: /* get next info */
197 if (unit)
198 unit = TAILQ_NEXT(unit, hci_next);
199 else
200 unit = TAILQ_FIRST(&hci_unit_list);
202 if (unit == NULL) {
203 err = ENXIO;
204 break;
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),
212 HCI_DEVNAME_SIZE);
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;
225 break;
227 case SIOCSBTFLAGS: /* set unit flags (privileged) */
228 err = priv_check(td, PRIV_ROOT);
229 if (err)
230 break;
232 if ((unit->hci_flags & BTF_UP)
233 && (btr->btr_flags & BTF_UP) == 0) {
234 hci_disable(unit);
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);
243 if (err)
244 break;
246 unit->hci_flags |= BTF_UP;
249 btr->btr_flags = unit->hci_flags;
250 break;
252 case SIOCSBTPOLICY: /* set unit link policy (privileged) */
253 err = priv_check(td, PRIV_ROOT);
254 if (err)
255 break;
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;
260 break;
262 case SIOCSBTPTYPE: /* set unit packet types (privileged) */
263 err = priv_check(td, PRIV_ROOT);
264 if (err)
265 break;
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;
270 break;
272 case SIOCGBTSTATS: /* get unit statistics */
273 (*unit->hci_if->get_stats)(unit->hci_dev, &btr->btr_stats, 0);
274 break;
276 case SIOCZBTSTATS: /* get & reset unit statistics */
277 err = priv_check(td, PRIV_ROOT);
278 if (err)
279 break;
281 (*unit->hci_if->get_stats)(unit->hci_dev, &btr->btr_stats, 1);
282 break;
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);
292 if (err)
293 break;
295 unit->hci_max_sco_size = btr->btr_sco_mtu;
296 break;
298 default:
299 err = EFAULT;
300 break;
303 return err;