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