ubt.c revision 1.1 1 /* $NetBSD: ubt.c,v 1.1 2002/08/22 10:15:58 augustss Exp $ */
2
3 /*
4 * Copyright (c) 2002 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Lennart Augustsson (lennart (at) augustsson.net).
9 *
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. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: ubt.c,v 1.1 2002/08/22 10:15:58 augustss Exp $");
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
45 #include <sys/device.h>
46 #include <sys/lock.h>
47 #include <sys/ioctl.h>
48 #include <sys/conf.h>
49 #include <sys/file.h>
50 #include <sys/poll.h>
51 #include <sys/select.h>
52 #include <sys/proc.h>
53
54 #include <dev/usb/usb.h>
55 #include <dev/usb/usbdi.h>
56 #include <dev/usb/usbdi_util.h>
57 #include <dev/usb/usbdevs.h>
58
59 #ifdef UBT_DEBUG
60 #define DPRINTF(x) if (ubtdebug) logprintf x
61 #define DPRINTFN(n,x) if (ubtdebug>(n)) logprintf x
62 int ubtdebug = 0;
63 #else
64 #define DPRINTF(x)
65 #define DPRINTFN(n,x)
66 #endif
67
68 /*
69 * Protocol related definitions
70 */
71
72 struct ubt_softc {
73 USBBASEDEVICE sc_dev;
74 usbd_device_handle sc_udev;
75 usbd_interface_handle sc_ctliface;
76
77 int sc_rd_addr;
78 usbd_pipe_handle sc_rd_pipe;
79
80 int sc_wr_addr;
81 usbd_pipe_handle sc_wr_pipe;
82
83 struct device *sc_child;
84 int sc_refcnt;
85 char sc_dying;
86 };
87
88 USB_DECLARE_DRIVER(ubt);
89
90 USB_MATCH(ubt)
91 {
92 USB_MATCH_START(ubt, uaa);
93 usb_interface_descriptor_t *id;
94
95 DPRINTFN(50,("ubt_match\n"));
96
97 if (uaa->iface == NULL)
98 return (UMATCH_NONE);
99
100 id = usbd_get_interface_descriptor(uaa->iface);
101 if (id != NULL &&
102 id->bInterfaceClass == UICLASS_WIRELESS &&
103 id->bInterfaceSubClass == UISUBCLASS_RF &&
104 id->bInterfaceProtocol == UIPROTO_BLUETOOTH)
105 return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO);
106 return (UMATCH_NONE);
107 }
108
109 USB_ATTACH(ubt)
110 {
111 USB_ATTACH_START(ubt, sc, uaa);
112 usbd_device_handle dev = uaa->device;
113 usbd_interface_handle iface = uaa->iface;
114 char devinfo[1024];
115 usb_endpoint_descriptor_t *ed;
116 u_int8_t epcount;
117 int i;
118
119 DPRINTFN(10,("ubt_attach: sc=%p\n", sc));
120
121 usbd_devinfo(dev, 0, devinfo);
122 USB_ATTACH_SETUP;
123 printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
124
125 sc->sc_udev = dev;
126 sc->sc_ctliface = iface;
127
128 epcount = 0;
129 (void)usbd_endpoint_count(iface, &epcount);
130
131 sc->sc_rd_addr = -1;
132 sc->sc_wr_addr = -1;
133 for (i = 0; i < epcount; i++) {
134 ed = usbd_interface2endpoint_descriptor(iface, i);
135 if (ed == NULL) {
136 printf("%s: couldn't get ep %d\n",
137 USBDEVNAME(sc->sc_dev), i);
138 USB_ATTACH_ERROR_RETURN;
139 }
140 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
141 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
142 sc->sc_rd_addr = ed->bEndpointAddress;
143 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
144 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
145 sc->sc_wr_addr = ed->bEndpointAddress;
146 }
147 }
148 #if 0
149 if (sc->sc_rd_addr == -1 || sc->sc_wr_addr == -1) {
150 printf("%s: missing endpoint\n", USBDEVNAME(sc->sc_dev));
151 USB_ATTACH_ERROR_RETURN;
152 }
153 #endif
154
155 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
156 USBDEV(sc->sc_dev));
157
158 #if 0
159 sc->sc_child = config_found(self, &ia, ir_print);
160 #endif
161
162 USB_ATTACH_SUCCESS_RETURN;
163 }
164
165 USB_DETACH(ubt)
166 {
167 USB_DETACH_START(ubt, sc);
168 int s;
169 int rv = 0;
170
171 DPRINTF(("ubt_detach: sc=%p flags=%d\n", sc, flags));
172
173 sc->sc_dying = 1;
174 /* Abort all pipes. Causes processes waiting for transfer to wake. */
175 if (sc->sc_rd_pipe != NULL) {
176 usbd_abort_pipe(sc->sc_rd_pipe);
177 usbd_close_pipe(sc->sc_rd_pipe);
178 sc->sc_rd_pipe = NULL;
179 }
180 if (sc->sc_wr_pipe != NULL) {
181 usbd_abort_pipe(sc->sc_wr_pipe);
182 usbd_close_pipe(sc->sc_wr_pipe);
183 sc->sc_wr_pipe = NULL;
184 }
185 #if 0
186 wakeup(&sc->sc_rd_count);
187 #endif
188
189 s = splusb();
190 if (--sc->sc_refcnt >= 0) {
191 /* Wait for processes to go away. */
192 usb_detach_wait(USBDEV(sc->sc_dev));
193 }
194 splx(s);
195
196 if (sc->sc_child != NULL) {
197 rv = config_detach(sc->sc_child, flags);
198 sc->sc_child = NULL;
199 }
200
201 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
202 USBDEV(sc->sc_dev));
203
204 return (rv);
205 }
206
207 int
208 ubt_activate(device_ptr_t self, enum devact act)
209 {
210 struct ubt_softc *sc = (struct ubt_softc *)self;
211 int error = 0;
212
213 switch (act) {
214 case DVACT_ACTIVATE:
215 return (EOPNOTSUPP);
216 break;
217
218 case DVACT_DEACTIVATE:
219 sc->sc_dying = 1;
220 if (sc->sc_child != NULL)
221 error = config_deactivate(sc->sc_child);
222 break;
223 }
224 return (error);
225 }
226