u3g.c revision 1.3 1 1.1 joerg /*
2 1.1 joerg * Copyright (c) 2008 AnyWi Technologies
3 1.1 joerg * Author: Andrea Guzzo <aguzzo (at) anywi.com>
4 1.1 joerg * * based on uark.c 1.1 2006/08/14 08:30:22 jsg *
5 1.1 joerg * * parts from ubsa.c 183348 2008-09-25 12:00:56Z phk *
6 1.1 joerg *
7 1.1 joerg * Permission to use, copy, modify, and distribute this software for any
8 1.1 joerg * purpose with or without fee is hereby granted, provided that the above
9 1.1 joerg * copyright notice and this permission notice appear in all copies.
10 1.1 joerg *
11 1.1 joerg * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 1.1 joerg * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 1.1 joerg * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 1.1 joerg * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 1.1 joerg * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 1.1 joerg * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 1.1 joerg * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 1.1 joerg *
19 1.1 joerg * $FreeBSD$
20 1.1 joerg */
21 1.1 joerg
22 1.1 joerg #include <sys/param.h>
23 1.1 joerg #include <sys/systm.h>
24 1.1 joerg #include <sys/kernel.h>
25 1.1 joerg #include <sys/malloc.h>
26 1.1 joerg #include <sys/module.h>
27 1.1 joerg #include <sys/bus.h>
28 1.1 joerg #include <sys/ioccom.h>
29 1.1 joerg #include <sys/fcntl.h>
30 1.1 joerg #include <sys/conf.h>
31 1.1 joerg #include <sys/tty.h>
32 1.1 joerg #include <sys/file.h>
33 1.1 joerg #include <sys/selinfo.h>
34 1.1 joerg
35 1.1 joerg #include <dev/usb/usb.h>
36 1.1 joerg #include <dev/usb/usbdi.h>
37 1.1 joerg #include <dev/usb/usbdivar.h>
38 1.1 joerg #include <dev/usb/usbdi_util.h>
39 1.1 joerg
40 1.1 joerg #include <dev/usb/ucomvar.h>
41 1.1 joerg
42 1.1 joerg #include "usbdevs.h"
43 1.1 joerg
44 1.1 joerg #define U3GBUFSZ 1024
45 1.1 joerg #define U3G_MAXPORTS 4
46 1.1 joerg
47 1.1 joerg struct u3g_softc {
48 1.1 joerg device_t sc_ucom[U3G_MAXPORTS];;
49 1.1 joerg device_t sc_dev;
50 1.1 joerg usbd_device_handle sc_udev;
51 1.1 joerg u_char sc_msr;
52 1.1 joerg u_char sc_lsr;
53 1.1 joerg u_char numports;
54 1.1 joerg
55 1.1 joerg usbd_interface_handle sc_intr_iface; /* interrupt interface */
56 1.1 joerg #ifdef U3G_DEBUG
57 1.1 joerg int sc_intr_number; /* interrupt number */
58 1.1 joerg usbd_pipe_handle sc_intr_pipe; /* interrupt pipe */
59 1.1 joerg u_char *sc_intr_buf; /* interrupt buffer */
60 1.1 joerg #endif
61 1.1 joerg int sc_isize;
62 1.2 joerg bool sc_pseudodev;
63 1.1 joerg };
64 1.1 joerg
65 1.1 joerg struct ucom_methods u3g_methods = {
66 1.1 joerg NULL,
67 1.1 joerg NULL,
68 1.1 joerg NULL,
69 1.1 joerg NULL,
70 1.1 joerg NULL,
71 1.1 joerg NULL,
72 1.1 joerg NULL,
73 1.1 joerg NULL,
74 1.1 joerg };
75 1.1 joerg
76 1.1 joerg static const struct usb_devno u3g_devs[] = {
77 1.1 joerg /* OEM: Option N.V. */
78 1.1 joerg { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_QUADPLUSUMTS },
79 1.1 joerg { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_HSDPA },
80 1.3 joerg { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_GTMAXHSUPA },
81 1.3 joerg /* OEM: Qualcomm, Inc. */
82 1.3 joerg { USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_CDMA_MSM },
83 1.1 joerg /* OEM: Huawei */
84 1.1 joerg { USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_MOBILE },
85 1.1 joerg { USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E220 },
86 1.1 joerg /* OEM: Novatel */
87 1.3 joerg { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_MERLINV620 },
88 1.3 joerg { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_ES620 },
89 1.1 joerg { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_MC950D },
90 1.3 joerg { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_U720 },
91 1.3 joerg { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_U727 },
92 1.3 joerg { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_MERLINU740 },
93 1.3 joerg { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_U740_2 },
94 1.3 joerg { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_U870 },
95 1.3 joerg { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_MERLINV620 },
96 1.3 joerg { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_S720 },
97 1.3 joerg { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_V740 },
98 1.3 joerg { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_X950D },
99 1.3 joerg { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_XU870 },
100 1.3 joerg { USB_VENDOR_DELL, USB_PRODUCT_DELL_W5500 },
101 1.3 joerg #if 0
102 1.3 joerg { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_MC950D_DRIVER },
103 1.3 joerg #endif
104 1.3 joerg /* OEM: Merlin */
105 1.3 joerg { USB_VENDOR_MERLIN, USB_PRODUCT_MERLIN_V620 },
106 1.1 joerg
107 1.3 joerg /* OEM: Sierra Wireless: */
108 1.3 joerg { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD580 },
109 1.3 joerg { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD595 },
110 1.3 joerg { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC595U },
111 1.3 joerg { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC597E },
112 1.3 joerg { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_C597 },
113 1.3 joerg { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880 },
114 1.3 joerg { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880E },
115 1.3 joerg { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880U },
116 1.3 joerg { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881 },
117 1.3 joerg { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881E },
118 1.3 joerg { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881U },
119 1.3 joerg { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_EM5625 },
120 1.3 joerg { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720 },
121 1.3 joerg { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720_2 },
122 1.3 joerg { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5725 },
123 1.3 joerg { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MINI5725 },
124 1.3 joerg { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD875 },
125 1.3 joerg { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755 },
126 1.3 joerg { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755_2 },
127 1.3 joerg { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755_3 },
128 1.3 joerg { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8765 },
129 1.3 joerg { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC875U },
130 1.3 joerg { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8775_2 },
131 1.3 joerg { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8780 },
132 1.3 joerg { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8781 },
133 1.1 joerg { 0, 0 }
134 1.1 joerg };
135 1.1 joerg
136 1.1 joerg #ifdef U3G_DEBUG
137 1.1 joerg static void
138 1.1 joerg u3g_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
139 1.1 joerg {
140 1.1 joerg struct u3g_softc *sc = (struct u3g_softc *)priv;
141 1.1 joerg aprint_normal_dev(sc->sc_dev, "INTERRUPT CALLBACK\n");
142 1.1 joerg }
143 1.1 joerg #endif
144 1.1 joerg
145 1.1 joerg static int
146 1.2 joerg u3g_novatel_reinit(struct usb_attach_arg *uaa)
147 1.2 joerg {
148 1.2 joerg unsigned char cmd[31];
149 1.2 joerg usbd_interface_handle iface;
150 1.2 joerg usb_interface_descriptor_t *id;
151 1.2 joerg usb_endpoint_descriptor_t *ed;
152 1.2 joerg usbd_pipe_handle pipe;
153 1.2 joerg usbd_xfer_handle xfer;
154 1.2 joerg int err, i;
155 1.2 joerg
156 1.2 joerg memset(cmd, 0, sizeof(cmd));
157 1.2 joerg /* Byte 0..3: Command Block Wrapper (CBW) signature */
158 1.2 joerg cmd[0] = 0x55;
159 1.2 joerg cmd[1] = 0x53;
160 1.2 joerg cmd[2] = 0x42;
161 1.2 joerg cmd[3] = 0x43;
162 1.2 joerg /* 4..7: CBW Tag, has to unique, but only a single transfer used. */
163 1.2 joerg cmd[4] = 0x01;
164 1.2 joerg /* 8..11: CBW Transfer Length, no data here */
165 1.2 joerg /* 12: CBW Flag: output, so 0 */
166 1.2 joerg /* 13: CBW Lun: 0 */
167 1.2 joerg /* 14: CBW Length */
168 1.2 joerg cmd[14] = 0x06;
169 1.2 joerg /* Rest is the SCSI payload */
170 1.2 joerg /* 0: SCSI START/STOP opcode */
171 1.2 joerg cmd[15] = 0x1b;
172 1.2 joerg /* 1..3 unused */
173 1.2 joerg /* 4 Load/Eject command */
174 1.2 joerg cmd[19] = 0x02;
175 1.2 joerg /* 5: unused */
176 1.2 joerg
177 1.2 joerg
178 1.2 joerg /* Move the device into the configured state. */
179 1.2 joerg err = usbd_set_config_index(uaa->device, 0, 0);
180 1.2 joerg if (err) {
181 1.2 joerg aprint_error("u3g: failed to set configuration index\n");
182 1.2 joerg return UMATCH_NONE;
183 1.2 joerg }
184 1.2 joerg
185 1.2 joerg err = usbd_device2interface_handle(uaa->device, 0, &iface);
186 1.2 joerg if (err != 0) {
187 1.2 joerg aprint_error("u3g: failed to get interface\n");
188 1.2 joerg return UMATCH_NONE;
189 1.2 joerg }
190 1.2 joerg
191 1.2 joerg id = usbd_get_interface_descriptor(iface);
192 1.2 joerg ed = NULL;
193 1.2 joerg for (i = 0 ; i < id->bNumEndpoints ; i++) {
194 1.2 joerg ed = usbd_interface2endpoint_descriptor(iface, i);
195 1.2 joerg if (ed == NULL)
196 1.2 joerg continue;
197 1.2 joerg if (UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_OUT)
198 1.2 joerg continue;
199 1.2 joerg if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK)
200 1.2 joerg break;
201 1.2 joerg }
202 1.2 joerg
203 1.2 joerg if (i == id->bNumEndpoints)
204 1.2 joerg return UMATCH_NONE;
205 1.2 joerg
206 1.2 joerg err = usbd_open_pipe(iface, ed->bEndpointAddress, USBD_EXCLUSIVE_USE,
207 1.2 joerg &pipe);
208 1.2 joerg if (err != 0) {
209 1.2 joerg aprint_error("u3g: failed to open bulk transfer pipe %d\n",
210 1.2 joerg ed->bEndpointAddress);
211 1.2 joerg return UMATCH_NONE;
212 1.2 joerg }
213 1.2 joerg
214 1.2 joerg xfer = usbd_alloc_xfer(uaa->device);
215 1.2 joerg if (xfer != NULL) {
216 1.2 joerg usbd_setup_xfer(xfer, pipe, NULL, cmd, sizeof(cmd),
217 1.2 joerg USBD_SYNCHRONOUS, USBD_DEFAULT_TIMEOUT, NULL);
218 1.2 joerg
219 1.2 joerg err = usbd_transfer(xfer);
220 1.2 joerg if (err)
221 1.2 joerg aprint_error("u3g: transfer failed\n");
222 1.2 joerg usbd_free_xfer(xfer);
223 1.2 joerg } else {
224 1.2 joerg aprint_error("u3g: failed to allocate xfer\n");
225 1.2 joerg err = USBD_NOMEM;
226 1.2 joerg }
227 1.2 joerg
228 1.2 joerg usbd_abort_pipe(pipe);
229 1.2 joerg usbd_close_pipe(pipe);
230 1.2 joerg
231 1.2 joerg return (err == USBD_NORMAL_COMPLETION ? UMATCH_HIGHEST : UMATCH_NONE);
232 1.2 joerg }
233 1.2 joerg
234 1.2 joerg static int
235 1.1 joerg u3g_huawei_reinit(usbd_device_handle dev)
236 1.1 joerg {
237 1.1 joerg /* The Huawei device presents itself as a umass device with Windows
238 1.1 joerg * drivers on it. After installation of the driver, it reinits into a
239 1.1 joerg * 3G serial device.
240 1.1 joerg */
241 1.1 joerg usb_device_request_t req;
242 1.1 joerg usb_config_descriptor_t *cdesc;
243 1.1 joerg
244 1.1 joerg /* Get the config descriptor */
245 1.1 joerg cdesc = usbd_get_config_descriptor(dev);
246 1.1 joerg if (cdesc == NULL)
247 1.1 joerg return (UMATCH_NONE);
248 1.1 joerg
249 1.1 joerg /* One iface means umass mode, more than 1 (4 usually) means 3G mode */
250 1.1 joerg if (cdesc->bNumInterface > 1)
251 1.1 joerg return (UMATCH_VENDOR_PRODUCT);
252 1.1 joerg
253 1.1 joerg req.bmRequestType = UT_WRITE_DEVICE;
254 1.1 joerg req.bRequest = UR_SET_FEATURE;
255 1.1 joerg USETW(req.wValue, UF_DEVICE_REMOTE_WAKEUP);
256 1.1 joerg USETW(req.wIndex, UHF_PORT_SUSPEND);
257 1.1 joerg USETW(req.wLength, 0);
258 1.1 joerg
259 1.1 joerg (void) usbd_do_request(dev, &req, 0);
260 1.1 joerg
261 1.2 joerg
262 1.2 joerg return (UMATCH_HIGHEST); /* Match to prevent umass from attaching */
263 1.1 joerg }
264 1.1 joerg
265 1.1 joerg static int
266 1.1 joerg u3g_match(device_t parent, cfdata_t match, void *aux)
267 1.1 joerg {
268 1.1 joerg struct usb_attach_arg *uaa = aux;
269 1.1 joerg
270 1.1 joerg if (uaa->vendor == USB_VENDOR_HUAWEI)
271 1.1 joerg return u3g_huawei_reinit(uaa->device);
272 1.1 joerg
273 1.2 joerg if (uaa->vendor == USB_VENDOR_NOVATEL2 &&
274 1.2 joerg uaa->product == USB_PRODUCT_NOVATEL2_MC950D_DRIVER)
275 1.2 joerg return u3g_novatel_reinit(uaa);
276 1.2 joerg
277 1.1 joerg if (usb_lookup(u3g_devs, uaa->vendor, uaa->product))
278 1.1 joerg return UMATCH_VENDOR_PRODUCT;
279 1.1 joerg
280 1.1 joerg return UMATCH_NONE;
281 1.1 joerg }
282 1.1 joerg
283 1.1 joerg static void
284 1.1 joerg u3g_attach(device_t parent, device_t self, void *aux)
285 1.1 joerg {
286 1.1 joerg struct u3g_softc *sc = device_private(self);
287 1.1 joerg struct usb_attach_arg *uaa = aux;
288 1.1 joerg usbd_device_handle dev = uaa->device;
289 1.1 joerg usbd_interface_handle iface;
290 1.1 joerg usb_interface_descriptor_t *id;
291 1.1 joerg usb_endpoint_descriptor_t *ed;
292 1.1 joerg usbd_status error;
293 1.1 joerg int i, n;
294 1.1 joerg usb_config_descriptor_t *cdesc;
295 1.1 joerg
296 1.1 joerg aprint_naive("\n");
297 1.1 joerg aprint_normal("\n");
298 1.1 joerg
299 1.2 joerg if (uaa->vendor == USB_VENDOR_NOVATEL2 &&
300 1.2 joerg uaa->product == USB_PRODUCT_NOVATEL2_MC950D_DRIVER) {
301 1.2 joerg /* About to disappear... */
302 1.2 joerg sc->sc_pseudodev = true;
303 1.2 joerg return;
304 1.2 joerg }
305 1.2 joerg
306 1.1 joerg sc->sc_dev = self;
307 1.1 joerg #ifdef U3G_DEBUG
308 1.1 joerg sc->sc_intr_number = -1;
309 1.1 joerg sc->sc_intr_pipe = NULL;
310 1.1 joerg #endif
311 1.1 joerg /* Move the device into the configured state. */
312 1.1 joerg error = usbd_set_config_index(dev, 0, 1);
313 1.1 joerg if (error) {
314 1.1 joerg aprint_error_dev(self, "failed to set configuration: %s\n",
315 1.1 joerg usbd_errstr(error));
316 1.1 joerg return;
317 1.1 joerg }
318 1.1 joerg
319 1.1 joerg /* get the config descriptor */
320 1.1 joerg cdesc = usbd_get_config_descriptor(dev);
321 1.1 joerg
322 1.1 joerg if (cdesc == NULL) {
323 1.1 joerg aprint_error_dev(self, "failed to get configuration descriptor\n");
324 1.1 joerg return;
325 1.1 joerg }
326 1.1 joerg
327 1.2 joerg if (uaa->vendor == USB_VENDOR_HUAWEI && cdesc->bNumInterface > 1) {
328 1.2 joerg /* About to disappear... */
329 1.2 joerg sc->sc_pseudodev = true;
330 1.2 joerg return;
331 1.2 joerg }
332 1.2 joerg
333 1.1 joerg sc->sc_udev = dev;
334 1.1 joerg sc->numports = (cdesc->bNumInterface <= U3G_MAXPORTS)?cdesc->bNumInterface:U3G_MAXPORTS;
335 1.1 joerg for ( i = 0; i < sc->numports; i++ ) {
336 1.1 joerg struct ucom_attach_args uca;
337 1.1 joerg
338 1.1 joerg error = usbd_device2interface_handle(dev, i, &iface);
339 1.1 joerg if (error) {
340 1.1 joerg aprint_error_dev(self,
341 1.1 joerg "failed to get interface, err=%s\n",
342 1.1 joerg usbd_errstr(error));
343 1.1 joerg return;
344 1.1 joerg }
345 1.1 joerg id = usbd_get_interface_descriptor(iface);
346 1.1 joerg
347 1.1 joerg uca.info = "Generic 3G Serial Device";
348 1.1 joerg uca.ibufsize = U3GBUFSZ;
349 1.1 joerg uca.obufsize = U3GBUFSZ;
350 1.1 joerg uca.ibufsizepad = U3GBUFSZ;
351 1.1 joerg uca.portno = i;
352 1.1 joerg uca.opkthdrlen = 0;
353 1.1 joerg uca.device = dev;
354 1.1 joerg uca.iface = iface;
355 1.1 joerg uca.methods = &u3g_methods;
356 1.1 joerg uca.arg = sc;
357 1.1 joerg
358 1.1 joerg uca.bulkin = uca.bulkout = -1;
359 1.1 joerg for (n = 0; n < id->bNumEndpoints; n++) {
360 1.1 joerg ed = usbd_interface2endpoint_descriptor(iface, n);
361 1.1 joerg if (ed == NULL) {
362 1.1 joerg aprint_error_dev(self,
363 1.1 joerg "could not read endpoint descriptor\n");
364 1.1 joerg return;
365 1.1 joerg }
366 1.1 joerg if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
367 1.1 joerg UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
368 1.1 joerg uca.bulkin = ed->bEndpointAddress;
369 1.1 joerg else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
370 1.1 joerg UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
371 1.1 joerg uca.bulkout = ed->bEndpointAddress;
372 1.1 joerg }
373 1.1 joerg if (uca.bulkin == -1 || uca.bulkout == -1) {
374 1.1 joerg aprint_error_dev(self, "missing endpoint\n");
375 1.1 joerg return;
376 1.1 joerg }
377 1.1 joerg
378 1.1 joerg sc->sc_ucom[i] = config_found_sm_loc(self, "ucombus", NULL, &uca,
379 1.1 joerg ucomprint, ucomsubmatch);
380 1.1 joerg }
381 1.1 joerg
382 1.1 joerg #ifdef U3G_DEBUG
383 1.1 joerg if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) {
384 1.1 joerg sc->sc_intr_buf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK);
385 1.1 joerg error = usbd_open_pipe_intr(sc->sc_intr_iface,
386 1.1 joerg sc->sc_intr_number,
387 1.1 joerg USBD_SHORT_XFER_OK,
388 1.1 joerg &sc->sc_intr_pipe,
389 1.1 joerg sc,
390 1.1 joerg sc->sc_intr_buf,
391 1.1 joerg sc->sc_isize,
392 1.1 joerg u3g_intr,
393 1.1 joerg 100);
394 1.1 joerg if (error) {
395 1.1 joerg aprint_error_dev(self,
396 1.1 joerg "cannot open interrupt pipe (addr %d)\n",
397 1.1 joerg sc->sc_intr_number);
398 1.1 joerg return;
399 1.1 joerg }
400 1.1 joerg }
401 1.1 joerg #endif
402 1.1 joerg
403 1.1 joerg
404 1.1 joerg if (!pmf_device_register(self, NULL, NULL))
405 1.1 joerg aprint_error_dev(self, "couldn't establish power handler\n");
406 1.1 joerg }
407 1.1 joerg
408 1.1 joerg static int
409 1.1 joerg u3g_detach(device_t self, int flags)
410 1.1 joerg {
411 1.1 joerg struct u3g_softc *sc = device_private(self);
412 1.1 joerg int rv = 0;
413 1.1 joerg int i;
414 1.1 joerg
415 1.2 joerg if (sc->sc_pseudodev)
416 1.2 joerg return 0;
417 1.2 joerg
418 1.1 joerg pmf_device_deregister(self);
419 1.1 joerg
420 1.1 joerg for (i = 0; i < sc->numports; i++) {
421 1.1 joerg if(sc->sc_ucom[i]) {
422 1.1 joerg rv = config_detach(sc->sc_ucom[i], flags);
423 1.1 joerg if(rv != 0) {
424 1.1 joerg aprint_verbose_dev(self, "Can't deallocat port %d", i);
425 1.1 joerg return rv;
426 1.1 joerg }
427 1.1 joerg }
428 1.1 joerg }
429 1.1 joerg
430 1.1 joerg #ifdef U3G_DEBUG
431 1.1 joerg if (sc->sc_intr_pipe != NULL) {
432 1.1 joerg int err = usbd_abort_pipe(sc->sc_intr_pipe);
433 1.1 joerg if (err)
434 1.1 joerg aprint_error_dev(self,
435 1.1 joerg "abort interrupt pipe failed: %s\n",
436 1.1 joerg usbd_errstr(err));
437 1.1 joerg err = usbd_close_pipe(sc->sc_intr_pipe);
438 1.1 joerg if (err)
439 1.1 joerg aprint_error_dev(self,
440 1.1 joerg "close interrupt pipe failed: %s\n",
441 1.1 joerg usbd_errstr(err));
442 1.1 joerg free(sc->sc_intr_buf, M_USBDEV);
443 1.1 joerg sc->sc_intr_pipe = NULL;
444 1.1 joerg }
445 1.1 joerg #endif
446 1.1 joerg
447 1.1 joerg return 0;
448 1.1 joerg }
449 1.1 joerg
450 1.1 joerg static void
451 1.1 joerg u3g_childdet(device_t self, device_t child)
452 1.1 joerg {
453 1.1 joerg struct u3g_softc *sc = device_private(self);
454 1.1 joerg int i;
455 1.1 joerg
456 1.1 joerg for (i = 0; i < sc->numports; i++) {
457 1.1 joerg if (sc->sc_ucom[i] == child)
458 1.1 joerg sc->sc_ucom[i] = NULL;
459 1.1 joerg }
460 1.1 joerg }
461 1.1 joerg
462 1.1 joerg static int
463 1.1 joerg u3g_activate(device_t self, enum devact act)
464 1.1 joerg {
465 1.1 joerg struct u3g_softc *sc = device_private(self);
466 1.1 joerg int i, rv = 0;
467 1.1 joerg
468 1.1 joerg switch (act) {
469 1.1 joerg case DVACT_ACTIVATE:
470 1.1 joerg return (EOPNOTSUPP);
471 1.1 joerg break;
472 1.1 joerg
473 1.1 joerg case DVACT_DEACTIVATE:
474 1.1 joerg for (i = 0; i < sc->numports; i++) {
475 1.1 joerg if (sc->sc_ucom[i] && config_deactivate(sc->sc_ucom[i]))
476 1.1 joerg rv = -1;
477 1.1 joerg }
478 1.1 joerg break;
479 1.1 joerg }
480 1.1 joerg return (rv);
481 1.1 joerg }
482 1.1 joerg
483 1.1 joerg CFATTACH_DECL2_NEW(u3g, sizeof(struct u3g_softc), u3g_match,
484 1.1 joerg u3g_attach, u3g_detach, u3g_activate, NULL, u3g_childdet);
485