1 /* $NetBSD: bthub.c,v 1.14 2008/06/12 21:47:11 cegger Exp $ */
4 * Copyright (c) 2006 Itronix Inc.
7 * Written by Iain Hibbert for 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/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: bthub.c,v 1.14 2008/06/12 21:47:11 cegger Exp $");
37 #include <sys/param.h>
39 #include <sys/device.h>
40 #include <sys/fcntl.h>
41 #include <sys/kernel.h>
42 #include <sys/queue.h>
43 #include <sys/malloc.h>
46 #include <sys/systm.h>
48 #include <prop/proplib.h>
50 #include <netbt/bluetooth.h>
52 #include <dev/bluetooth/btdev.h>
56 /*****************************************************************************
58 * Bluetooth Device Hub
61 /* autoconf(9) glue */
62 static int bthub_match(device_t
, cfdata_t
, void *);
63 static void bthub_attach(device_t
, device_t
, void *);
64 static int bthub_detach(device_t
, int);
66 CFATTACH_DECL_NEW(bthub
, 0,
67 bthub_match
, bthub_attach
, bthub_detach
, NULL
);
70 dev_type_ioctl(bthubioctl
);
72 const struct cdevsw bthub_cdevsw
= {
73 nullopen
, nullclose
, noread
, nowrite
, bthubioctl
,
74 nostop
, notty
, nopoll
, nommap
, nokqfilter
, D_OTHER
,
78 static int bthub_print(void *, const char *);
79 static int bthub_pioctl(dev_t
, unsigned long, prop_dictionary_t
, int, struct lwp
*);
81 /*****************************************************************************
83 * bthub autoconf(9) routines
85 * A Hub is attached to each Bluetooth Controller as it is enabled
89 bthub_match(device_t self
, cfdata_t cfdata
, void *arg
)
96 bthub_attach(device_t parent
, device_t self
, void *aux
)
99 prop_dictionary_t dict
;
102 dict
= device_properties(self
);
103 obj
= prop_data_create_data(addr
, sizeof(*addr
));
104 prop_dictionary_set(dict
, BTDEVladdr
, obj
);
105 prop_object_release(obj
);
107 aprint_verbose(" %s %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
109 addr
->b
[5], addr
->b
[4], addr
->b
[3],
110 addr
->b
[2], addr
->b
[1], addr
->b
[0]);
116 bthub_detach(device_t self
, int flags
)
119 return config_detach_children(self
, flags
);
122 /*****************************************************************************
124 * bthub access functions to control device
128 bthubioctl(dev_t devno
, unsigned long cmd
, void *data
, int flag
, struct lwp
*l
)
130 prop_dictionary_t dict
;
136 /* load dictionary */
137 err
= prop_dictionary_copyin_ioctl(data
, cmd
, &dict
);
139 err
= bthub_pioctl(devno
, cmd
, dict
, flag
, l
);
140 prop_object_release(dict
);
153 bthub_pioctl(dev_t devno
, unsigned long cmd
, prop_dictionary_t dict
,
154 int flag
, struct lwp
*l
)
156 prop_data_t laddr
, raddr
;
157 prop_string_t service
;
158 prop_dictionary_t prop
;
164 /* validate local address */
165 laddr
= prop_dictionary_get(dict
, BTDEVladdr
);
166 if (prop_data_size(laddr
) != sizeof(bdaddr_t
))
169 /* locate the relevant bthub */
170 for (unit
= 0 ; ; unit
++) {
171 if (unit
== bthub_cd
.cd_ndevs
)
174 self
= device_lookup(&bthub_cd
, unit
);
178 prop
= device_properties(self
);
179 obj
= prop_dictionary_get(prop
, BTDEVladdr
);
180 if (prop_data_equals(laddr
, obj
))
184 /* validate remote address */
185 raddr
= prop_dictionary_get(dict
, BTDEVraddr
);
186 if (prop_data_size(raddr
) != sizeof(bdaddr_t
)
187 || bdaddr_any(prop_data_data_nocopy(raddr
)))
190 /* validate service name */
191 service
= prop_dictionary_get(dict
, BTDEVservice
);
192 if (prop_object_type(service
) != PROP_TYPE_STRING
)
195 /* locate matching child device, if any */
196 deviter_init(&di
, 0);
197 while ((dev
= deviter_next(&di
)) != NULL
) {
198 if (device_parent(dev
) != self
)
201 prop
= device_properties(dev
);
203 obj
= prop_dictionary_get(prop
, BTDEVraddr
);
204 if (!prop_object_equals(raddr
, obj
))
207 obj
= prop_dictionary_get(prop
, BTDEVservice
);
208 if (!prop_object_equals(service
, obj
))
213 deviter_release(&di
);
216 case BTDEV_ATTACH
: /* attach BTDEV */
220 dev
= config_found(self
, dict
, bthub_print
);
224 prop
= device_properties(dev
);
225 prop_dictionary_set(prop
, BTDEVladdr
, laddr
);
226 prop_dictionary_set(prop
, BTDEVraddr
, raddr
);
227 prop_dictionary_set(prop
, BTDEVservice
, service
);
230 case BTDEV_DETACH
: /* detach BTDEV */
234 config_detach(dev
, DETACH_FORCE
);
242 bthub_print(void *aux
, const char *pnp
)
244 prop_dictionary_t dict
= aux
;
246 const bdaddr_t
*raddr
;
249 obj
= prop_dictionary_get(dict
, BTDEVtype
);
250 aprint_normal("%s: %s '%s',", pnp
, BTDEVtype
,
251 prop_string_cstring_nocopy(obj
));
254 obj
= prop_dictionary_get(dict
, BTDEVraddr
);
255 raddr
= prop_data_data_nocopy(obj
);
257 aprint_verbose(" %s %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
259 raddr
->b
[5], raddr
->b
[4], raddr
->b
[3],
260 raddr
->b
[2], raddr
->b
[1], raddr
->b
[0]);