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