u3g.c revision 1.20.2.3 1 /* $NetBSD: u3g.c,v 1.20.2.3 2012/10/30 17:22:07 yamt Exp $ */
2
3 /*-
4 * Copyright (c) 2009 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
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 *
18 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 /*
32 * Copyright (c) 2008 AnyWi Technologies
33 * Author: Andrea Guzzo <aguzzo (at) anywi.com>
34 * * based on uark.c 1.1 2006/08/14 08:30:22 jsg *
35 * * parts from ubsa.c 183348 2008-09-25 12:00:56Z phk *
36 *
37 * Permission to use, copy, modify, and distribute this software for any
38 * purpose with or without fee is hereby granted, provided that the above
39 * copyright notice and this permission notice appear in all copies.
40 *
41 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
42 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
43 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
44 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
45 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
46 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
47 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
48 *
49 * $FreeBSD$
50 */
51
52 #include <sys/cdefs.h>
53 __KERNEL_RCSID(0, "$NetBSD: u3g.c,v 1.20.2.3 2012/10/30 17:22:07 yamt Exp $");
54
55 #include <sys/param.h>
56 #include <sys/systm.h>
57 #include <sys/kernel.h>
58 #include <sys/malloc.h>
59 #include <sys/bus.h>
60 #include <sys/conf.h>
61 #include <sys/tty.h>
62
63 #include <dev/usb/usb.h>
64 #include <dev/usb/usbdi.h>
65 #include <dev/usb/usbdivar.h>
66 #include <dev/usb/usbdi_util.h>
67
68 #include <dev/usb/ucomvar.h>
69
70 #include "usbdevs.h"
71
72 /*
73 * We read/write data from/to the device in 4KB chunks to maximise
74 * performance.
75 */
76 #define U3G_BUFF_SIZE 4096
77
78 /*
79 * Some 3G devices (the Huawei E160/E220 springs to mind here) buffer up
80 * data internally even when the USB pipes are closed. So on first open,
81 * we can receive a large chunk of stale data.
82 *
83 * This causes a real problem because the default TTYDEF_LFLAG (applied
84 * on first open) has the ECHO flag set, resulting in all the stale data
85 * being echoed straight back to the device by the tty(4) layer. Some
86 * devices (again, the Huawei E160/E220 for example) react to this spew
87 * by going catatonic.
88 *
89 * All this happens before the application gets a chance to disable ECHO.
90 *
91 * We work around this by ignoring all data received from the device for
92 * a period of two seconds, or until the application starts sending data -
93 * whichever comes first.
94 */
95 #define U3G_PURGE_SECS 2
96
97 /*
98 * Define bits for the virtual modem control pins.
99 * The input pin states are reported via the interrupt pipe on some devices.
100 */
101 #define U3G_OUTPIN_DTR (1u << 0)
102 #define U3G_OUTPIN_RTS (1u << 1)
103 #define U3G_INPIN_DCD (1u << 0)
104 #define U3G_INPIN_DSR (1u << 1)
105 #define U3G_INPIN_RI (1u << 3)
106
107 /*
108 * USB request to set the output pin status
109 */
110 #define U3G_SET_PIN 0x22
111
112 struct u3g_softc {
113 device_t sc_dev;
114 usbd_device_handle sc_udev;
115 bool sc_dying; /* We're going away */
116
117 device_t sc_ucom; /* Child ucom(4) handle */
118 int sc_ifaceno; /* Device interface number */
119
120 bool sc_open; /* Device is in use */
121 bool sc_purging; /* Purging stale data */
122 struct timeval sc_purge_start; /* Control duration of purge */
123
124 u_char sc_msr; /* Emulated 'msr' */
125 uint16_t sc_outpins; /* Output pin state */
126
127 usbd_pipe_handle sc_intr_pipe; /* Interrupt pipe */
128 u_char *sc_intr_buff; /* Interrupt buffer */
129 };
130
131 /*
132 * The device driver has two personalities. The first uses the 'usbdevif'
133 * interface attribute so that a match will claim the entire USB device
134 * for itself. This is used for when a device needs to be mode-switched
135 * and ensures any other interfaces present cannot be claimed by other
136 * drivers while the mode-switch is in progress.
137 *
138 * The second personality uses the 'usbifif' interface attribute so that
139 * it can claim the 3G modem interfaces for itself, leaving others (such
140 * as the mass storage interfaces on some devices) for other drivers.
141 */
142 static int u3ginit_match(device_t, cfdata_t, void *);
143 static void u3ginit_attach(device_t, device_t, void *);
144 static int u3ginit_detach(device_t, int);
145
146 CFATTACH_DECL2_NEW(u3ginit, 0, u3ginit_match,
147 u3ginit_attach, u3ginit_detach, NULL, NULL, NULL);
148
149
150 static int u3g_match(device_t, cfdata_t, void *);
151 static void u3g_attach(device_t, device_t, void *);
152 static int u3g_detach(device_t, int);
153 static int u3g_activate(device_t, enum devact);
154 static void u3g_childdet(device_t, device_t);
155
156 CFATTACH_DECL2_NEW(u3g, sizeof(struct u3g_softc), u3g_match,
157 u3g_attach, u3g_detach, u3g_activate, NULL, u3g_childdet);
158
159
160 static void u3g_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
161 static void u3g_get_status(void *, int, u_char *, u_char *);
162 static void u3g_set(void *, int, int, int);
163 static int u3g_open(void *, int);
164 static void u3g_close(void *, int);
165 static void u3g_read(void *, int, u_char **, uint32_t *);
166 static void u3g_write(void *, int, u_char *, u_char *, u_int32_t *);
167
168 struct ucom_methods u3g_methods = {
169 u3g_get_status,
170 u3g_set,
171 NULL,
172 NULL,
173 u3g_open,
174 u3g_close,
175 u3g_read,
176 u3g_write,
177 };
178
179 /*
180 * Allegedly supported devices
181 */
182 static const struct usb_devno u3g_devs[] = {
183 { USB_VENDOR_DELL, USB_PRODUCT_DELL_W5500 },
184 /* OEM: Huawei */
185 { USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1750 },
186 { USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1820 },
187 { USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E220 },
188 { USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_EM770W },
189 { USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_K3765 },
190 { USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_MOBILE },
191 /* OEM: Merlin */
192 { USB_VENDOR_MERLIN, USB_PRODUCT_MERLIN_V620 },
193 /* OEM: Novatel */
194 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_ES620 },
195 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_EU8X0D },
196 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_MC950D },
197 #if 0
198 /* These are matched in u3ginit_match() */
199 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_MC950D_DRIVER },
200 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_U760_DRIVER },
201 #endif
202 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_MERLINU740 },
203 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_MERLINV620 },
204 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_S720 },
205 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_U720 },
206 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_U727 },
207 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_U740_2 },
208 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_U760 },
209 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_U870 },
210 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_V740 },
211 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_X950D },
212 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_XU870 },
213 /* OEM: Option N.V. */
214 { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_QUADPLUSUMTS },
215 { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_HSDPA },
216 { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_GTMAXHSUPA },
217 /* OEM: Qualcomm, Inc. */
218 { USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_CDMA_MSM },
219 { USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_ZTE_MF626 },
220 { USB_VENDOR_QUALCOMM, USB_PRODUCT_QUALCOMM_NTT_DOCOMO_L02C_MODEM },
221
222 /* OEM: Sierra Wireless: */
223 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC595U },
224 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC597E },
225 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC875U },
226 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880 },
227 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880E },
228 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880U },
229 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881 },
230 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881E },
231 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881U },
232 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD580 },
233 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD595 },
234 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD875 },
235 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_C597 },
236 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_EM5625 },
237 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720 },
238 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720_2 },
239 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5725 },
240 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755 },
241 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755_2 },
242 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755_3 },
243 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8765 },
244 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8775_2 },
245 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8780 },
246 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8781 },
247 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MINI5725 },
248 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_USB305 },
249
250 /* Toshiba */
251 { USB_VENDOR_TOSHIBA, USB_PRODUCT_TOSHIBA_HSDPA_MODEM_EU870DT1 },
252
253 /* 4G Systems */
254 { USB_VENDOR_4GSYSTEMS, USB_PRODUCT_4GSYSTEMS_XSSTICK_P14 },
255 };
256
257 static int
258 send_bulkmsg(usbd_device_handle dev, void *cmd, size_t cmdlen)
259 {
260 usbd_interface_handle iface;
261 usb_interface_descriptor_t *id;
262 usb_endpoint_descriptor_t *ed;
263 usbd_pipe_handle pipe;
264 usbd_xfer_handle xfer;
265 int err, i;
266
267 /* Move the device into the configured state. */
268 err = usbd_set_config_index(dev, 0, 0);
269 if (err) {
270 aprint_error("u3g: failed to set configuration index\n");
271 return UMATCH_NONE;
272 }
273
274 err = usbd_device2interface_handle(dev, 0, &iface);
275 if (err != 0) {
276 aprint_error("u3ginit: failed to get interface\n");
277 return UMATCH_NONE;
278 }
279
280 id = usbd_get_interface_descriptor(iface);
281 ed = NULL;
282 for (i = 0 ; i < id->bNumEndpoints ; i++) {
283 ed = usbd_interface2endpoint_descriptor(iface, i);
284 if (ed == NULL)
285 continue;
286 if (UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_OUT)
287 continue;
288 if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK)
289 break;
290 }
291
292 if (i == id->bNumEndpoints)
293 return UMATCH_NONE;
294
295 err = usbd_open_pipe(iface, ed->bEndpointAddress,
296 USBD_EXCLUSIVE_USE, &pipe);
297 if (err != 0) {
298 aprint_error("u3ginit: failed to open bulk transfer pipe %d\n",
299 ed->bEndpointAddress);
300 return UMATCH_NONE;
301 }
302
303 xfer = usbd_alloc_xfer(dev);
304 if (xfer != NULL) {
305 usbd_setup_xfer(xfer, pipe, NULL, cmd, cmdlen,
306 USBD_SYNCHRONOUS, USBD_DEFAULT_TIMEOUT, NULL);
307
308 err = usbd_transfer(xfer);
309
310 #if 0 /* XXXpooka: at least my huawei "fails" this always, but still detaches */
311 if (err)
312 aprint_error("u3ginit: transfer failed\n");
313 #else
314 err = 0;
315 #endif
316 usbd_free_xfer(xfer);
317 } else {
318 aprint_error("u3ginit: failed to allocate xfer\n");
319 err = USBD_NOMEM;
320 }
321
322 usbd_abort_pipe(pipe);
323 usbd_close_pipe(pipe);
324
325 return (err == USBD_NORMAL_COMPLETION ? UMATCH_HIGHEST : UMATCH_NONE);
326 }
327
328 static int
329 u3g_novatel_reinit(usbd_device_handle dev)
330 {
331 unsigned char cmd[31];
332
333 memset(cmd, 0, sizeof(cmd));
334 /* Byte 0..3: Command Block Wrapper (CBW) signature */
335 cmd[0] = 0x55;
336 cmd[1] = 0x53;
337 cmd[2] = 0x42;
338 cmd[3] = 0x43;
339 /* 4..7: CBW Tag, has to unique, but only a single transfer used. */
340 cmd[4] = 0x01;
341 /* 8..11: CBW Transfer Length, no data here */
342 /* 12: CBW Flag: output, so 0 */
343 /* 13: CBW Lun: 0 */
344 /* 14: CBW Length */
345 cmd[14] = 0x06;
346 /* Rest is the SCSI payload */
347 /* 0: SCSI START/STOP opcode */
348 cmd[15] = 0x1b;
349 /* 1..3 unused */
350 /* 4 Load/Eject command */
351 cmd[19] = 0x02;
352 /* 5: unused */
353
354 return send_bulkmsg(dev, cmd, sizeof(cmd));
355 }
356
357 static int
358 u3g_huawei_reinit(usbd_device_handle dev)
359 {
360 /*
361 * The Huawei device presents itself as a umass device with Windows
362 * drivers on it. After installation of the driver, it reinits into a
363 * 3G serial device.
364 */
365 usb_device_request_t req;
366 usb_config_descriptor_t *cdesc;
367
368 /* Get the config descriptor */
369 cdesc = usbd_get_config_descriptor(dev);
370 if (cdesc == NULL) {
371 usb_device_descriptor_t dd;
372
373 if (usbd_get_device_desc(dev, &dd) != 0)
374 return (UMATCH_NONE);
375
376 if (dd.bNumConfigurations != 1)
377 return (UMATCH_NONE);
378
379 if (usbd_set_config_index(dev, 0, 1) != 0)
380 return (UMATCH_NONE);
381
382 cdesc = usbd_get_config_descriptor(dev);
383
384 if (cdesc == NULL)
385 return (UMATCH_NONE);
386 }
387
388 /*
389 * One iface means umass mode, more than 1 (4 usually) means 3G mode.
390 *
391 * XXX: We should check the first interface's device class just to be
392 * sure. If it's a mass storage device, then we can be fairly certain
393 * it needs a mode-switch.
394 */
395 if (cdesc->bNumInterface > 1)
396 return (UMATCH_NONE);
397
398 req.bmRequestType = UT_WRITE_DEVICE;
399 req.bRequest = UR_SET_FEATURE;
400 USETW(req.wValue, UF_DEVICE_REMOTE_WAKEUP);
401 USETW(req.wIndex, UHF_PORT_SUSPEND);
402 USETW(req.wLength, 0);
403
404 (void) usbd_do_request(dev, &req, 0);
405
406 return (UMATCH_HIGHEST); /* Prevent umass from attaching */
407 }
408
409 static int
410 u3g_huawei_k3765_reinit(usbd_device_handle dev)
411 {
412 unsigned char cmd[31];
413
414 /* magic string adapted from some webpage */
415 memset(cmd, 0, sizeof(cmd));
416 cmd[0] = 0x55;
417 cmd[1] = 0x53;
418 cmd[2] = 0x42;
419 cmd[3] = 0x43;
420 cmd[15]= 0x11;
421 cmd[16]= 0x06;
422
423 return send_bulkmsg(dev, cmd, sizeof(cmd));
424 }
425
426 static int
427 u3g_sierra_reinit(usbd_device_handle dev)
428 {
429 /* Some Sierra devices presents themselves as a umass device with
430 * Windows drivers on it. After installation of the driver, it
431 * reinits into a * 3G serial device.
432 */
433 usb_device_request_t req;
434
435 req.bmRequestType = UT_VENDOR;
436 req.bRequest = UR_SET_INTERFACE;
437 USETW(req.wValue, UF_DEVICE_REMOTE_WAKEUP);
438 USETW(req.wIndex, UHF_PORT_CONNECTION);
439 USETW(req.wLength, 0);
440
441 (void) usbd_do_request(dev, &req, 0);
442
443 return (UMATCH_HIGHEST); /* Match to prevent umass from attaching */
444 }
445
446 static int
447 u3g_4gsystems_reinit(usbd_device_handle dev)
448 {
449 /* magic string adapted from usb_modeswitch database */
450 static unsigned char cmd[31] = {
451 0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x78, 0x80, 0x00,
452 0x00, 0x00, 0x80, 0x00, 0x06, 0x06, 0xf5, 0x04, 0x02, 0x52,
453 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
454 0x00
455 };
456
457 return send_bulkmsg(dev, cmd, sizeof(cmd));
458 }
459
460 /*
461 * First personality:
462 *
463 * Claim the entire device if a mode-switch is required.
464 */
465
466 static int
467 u3ginit_match(device_t parent, cfdata_t match, void *aux)
468 {
469 struct usb_attach_arg *uaa = aux;
470
471 /*
472 * Huawei changes product when it is configured as a modem.
473 */
474 switch (uaa->vendor) {
475 case USB_VENDOR_HUAWEI:
476 if (uaa->product == USB_PRODUCT_HUAWEI_K3765)
477 return UMATCH_NONE;
478
479 switch (uaa->product) {
480 case USB_PRODUCT_HUAWEI_E1750INIT:
481 case USB_PRODUCT_HUAWEI_K3765INIT:
482 return u3g_huawei_k3765_reinit(uaa->device);
483 break;
484 default:
485 return u3g_huawei_reinit(uaa->device);
486 break;
487 }
488 break;
489
490 case USB_VENDOR_NOVATEL2:
491 switch (uaa->product){
492 case USB_PRODUCT_NOVATEL2_MC950D_DRIVER:
493 case USB_PRODUCT_NOVATEL2_U760_DRIVER:
494 return u3g_novatel_reinit(uaa->device);
495 break;
496 default:
497 break;
498 }
499 break;
500
501 case USB_VENDOR_SIERRA:
502 if (uaa->product == USB_PRODUCT_SIERRA_INSTALLER)
503 return u3g_sierra_reinit(uaa->device);
504 break;
505
506 case USB_VENDOR_QUALCOMMINC:
507 if (uaa->product == USB_PRODUCT_QUALCOMMINC_ZTE_STOR)
508 return u3g_novatel_reinit(uaa->device);
509 break;
510
511 case USB_VENDOR_QUALCOMM:
512 if (uaa->product == USB_PRODUCT_QUALCOMM_NTT_DOCOMO_L02C_STORAGE)
513 return u3g_novatel_reinit(uaa->device);
514 break;
515
516 case USB_VENDOR_4GSYSTEMS:
517 if (uaa->product == USB_PRODUCT_4GSYSTEMS_XSSTICK_P14_INSTALLER)
518 return u3g_4gsystems_reinit(uaa->device);
519 break;
520
521 default:
522 break;
523 }
524
525 return UMATCH_NONE;
526 }
527
528 static void
529 u3ginit_attach(device_t parent, device_t self, void *aux)
530 {
531 struct usb_attach_arg *uaa = aux;
532
533 aprint_naive("\n");
534 aprint_normal(": Switching to 3G mode\n");
535
536 if (uaa->vendor == USB_VENDOR_NOVATEL2) {
537 switch (uaa->product) {
538 case USB_PRODUCT_NOVATEL2_MC950D_DRIVER:
539 case USB_PRODUCT_NOVATEL2_U760_DRIVER:
540 /* About to disappear... */
541 return;
542 break;
543 default:
544 break;
545 }
546 }
547
548 /* Move the device into the configured state. */
549 (void) usbd_set_config_index(uaa->device, 0, 1);
550 }
551
552 static int
553 u3ginit_detach(device_t self, int flags)
554 {
555
556 return (0);
557 }
558
559
560 /*
561 * Second personality:
562 *
563 * Claim only those interfaces required for 3G modem operation.
564 */
565
566 static int
567 u3g_match(device_t parent, cfdata_t match, void *aux)
568 {
569 struct usbif_attach_arg *uaa = aux;
570 usbd_interface_handle iface;
571 usb_interface_descriptor_t *id;
572 usbd_status error;
573
574 if (!usb_lookup(u3g_devs, uaa->vendor, uaa->product))
575 return (UMATCH_NONE);
576
577 error = usbd_device2interface_handle(uaa->device, uaa->ifaceno, &iface);
578 if (error) {
579 printf("u3g_match: failed to get interface, err=%s\n",
580 usbd_errstr(error));
581 return (UMATCH_NONE);
582 }
583
584 id = usbd_get_interface_descriptor(iface);
585 if (id == NULL) {
586 printf("u3g_match: failed to get interface descriptor\n");
587 return (UMATCH_NONE);
588 }
589
590 /*
591 * 3G modems generally report vendor-specific class
592 *
593 * XXX: this may be too generalised.
594 */
595 return ((id->bInterfaceClass == UICLASS_VENDOR) ?
596 UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
597 }
598
599 static void
600 u3g_attach(device_t parent, device_t self, void *aux)
601 {
602 struct u3g_softc *sc = device_private(self);
603 struct usbif_attach_arg *uaa = aux;
604 usbd_device_handle dev = uaa->device;
605 usbd_interface_handle iface;
606 usb_interface_descriptor_t *id;
607 usb_endpoint_descriptor_t *ed;
608 struct ucom_attach_args uca;
609 usbd_status error;
610 int n, intr_address, intr_size;
611
612 aprint_naive("\n");
613 aprint_normal("\n");
614
615 sc->sc_dev = self;
616 sc->sc_dying = false;
617 sc->sc_udev = dev;
618
619 error = usbd_device2interface_handle(dev, uaa->ifaceno, &iface);
620 if (error) {
621 aprint_error_dev(self, "failed to get interface, err=%s\n",
622 usbd_errstr(error));
623 return;
624 }
625
626 id = usbd_get_interface_descriptor(iface);
627
628 uca.info = "3G Modem";
629 uca.ibufsize = U3G_BUFF_SIZE;
630 uca.obufsize = U3G_BUFF_SIZE;
631 uca.ibufsizepad = U3G_BUFF_SIZE;
632 uca.portno = uaa->ifaceno;
633 uca.opkthdrlen = 0;
634 uca.device = dev;
635 uca.iface = iface;
636 uca.methods = &u3g_methods;
637 uca.arg = sc;
638 uca.bulkin = uca.bulkout = -1;
639
640 sc->sc_outpins = 0;
641 sc->sc_msr = UMSR_DSR | UMSR_CTS | UMSR_DCD;
642 sc->sc_ifaceno = uaa->ifaceno;
643 sc->sc_open = false;
644 sc->sc_purging = false;
645
646 intr_address = -1;
647 intr_size = 0;
648
649 for (n = 0; n < id->bNumEndpoints; n++) {
650 ed = usbd_interface2endpoint_descriptor(iface, n);
651 if (ed == NULL) {
652 aprint_error_dev(self, "no endpoint descriptor "
653 "for %d (interface: %d)\n", n, sc->sc_ifaceno);
654 sc->sc_dying = true;
655 return;
656 }
657
658 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
659 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
660 intr_address = ed->bEndpointAddress;
661 intr_size = UGETW(ed->wMaxPacketSize);
662 } else
663 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
664 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
665 uca.bulkin = ed->bEndpointAddress;
666 } else
667 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
668 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
669 uca.bulkout = ed->bEndpointAddress;
670 }
671 }
672
673 if (uca.bulkin == -1) {
674 aprint_error_dev(self, "Missing bulk in for interface %d\n",
675 sc->sc_ifaceno);
676 sc->sc_dying = true;
677 return;
678 }
679
680 if (uca.bulkout == -1) {
681 aprint_error_dev(self, "Missing bulk out for interface %d\n",
682 sc->sc_ifaceno);
683 sc->sc_dying = true;
684 return;
685 }
686
687 sc->sc_ucom = config_found_sm_loc(self, "ucombus",
688 NULL, &uca, ucomprint, ucomsubmatch);
689
690 /*
691 * If the interface has an interrupt pipe, open it immediately so
692 * that we can track input pin state changes regardless of whether
693 * the tty(4) device is open or not.
694 */
695 if (intr_address != -1) {
696 sc->sc_intr_buff = malloc(intr_size, M_USBDEV, M_WAITOK);
697 error = usbd_open_pipe_intr(iface, intr_address,
698 USBD_SHORT_XFER_OK, &sc->sc_intr_pipe, sc, sc->sc_intr_buff,
699 intr_size, u3g_intr, 100);
700 if (error) {
701 aprint_error_dev(self, "cannot open interrupt pipe "
702 "(addr %d)\n", intr_address);
703 return;
704 }
705 } else {
706 sc->sc_intr_pipe = NULL;
707 sc->sc_intr_buff = NULL;
708 }
709
710 if (!pmf_device_register(self, NULL, NULL))
711 aprint_error_dev(self, "couldn't establish power handler\n");
712 }
713
714 static int
715 u3g_detach(device_t self, int flags)
716 {
717 struct u3g_softc *sc = device_private(self);
718 int rv;
719
720 if (sc->sc_dying)
721 return 0;
722
723 pmf_device_deregister(self);
724
725 if (sc->sc_ucom != NULL) {
726 rv = config_detach(sc->sc_ucom, flags);
727 if (rv != 0) {
728 aprint_verbose_dev(self, "Can't deallocate "
729 "port (%d)", rv);
730 }
731 }
732
733 if (sc->sc_intr_pipe != NULL) {
734 (void) usbd_abort_pipe(sc->sc_intr_pipe);
735 (void) usbd_close_pipe(sc->sc_intr_pipe);
736 sc->sc_intr_pipe = NULL;
737 }
738 if (sc->sc_intr_buff != NULL) {
739 free(sc->sc_intr_buff, M_USBDEV);
740 sc->sc_intr_buff = NULL;
741 }
742
743 return (0);
744 }
745
746 static void
747 u3g_childdet(device_t self, device_t child)
748 {
749 struct u3g_softc *sc = device_private(self);
750
751 if (sc->sc_ucom == child)
752 sc->sc_ucom = NULL;
753 }
754
755 static int
756 u3g_activate(device_t self, enum devact act)
757 {
758 struct u3g_softc *sc = device_private(self);
759 int rv;
760
761 switch (act) {
762 case DVACT_DEACTIVATE:
763 if (sc->sc_ucom != NULL && config_deactivate(sc->sc_ucom))
764 rv = -1;
765 else
766 rv = 0;
767 break;
768
769 default:
770 rv = 0;
771 break;
772 }
773
774 return (rv);
775 }
776
777 static void
778 u3g_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
779 {
780 struct u3g_softc *sc = (struct u3g_softc *)priv;
781 u_char *buf;
782
783 if (sc->sc_dying)
784 return;
785
786 if (status != USBD_NORMAL_COMPLETION) {
787 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
788 return;
789 usbd_clear_endpoint_stall_async(sc->sc_intr_pipe);
790 return;
791 }
792
793 buf = sc->sc_intr_buff;
794 if (buf[0] == 0xa1 && buf[1] == 0x20) {
795 u_char msr;
796
797 msr = sc->sc_msr & ~(UMSR_DCD | UMSR_DSR | UMSR_RI);
798
799 if (buf[8] & U3G_INPIN_DCD)
800 msr |= UMSR_DCD;
801
802 if (buf[8] & U3G_INPIN_DSR)
803 msr |= UMSR_DSR;
804
805 if (buf[8] & U3G_INPIN_RI)
806 msr |= UMSR_RI;
807
808 if (msr != sc->sc_msr) {
809 sc->sc_msr = msr;
810 if (sc->sc_open)
811 ucom_status_change(device_private(sc->sc_ucom));
812 }
813 }
814 }
815
816 /*ARGSUSED*/
817 static void
818 u3g_get_status(void *arg, int portno, u_char *lsr, u_char *msr)
819 {
820 struct u3g_softc *sc = arg;
821
822 if (lsr != NULL)
823 *lsr = 0; /* LSR isn't supported */
824 if (msr != NULL)
825 *msr = sc->sc_msr;
826 }
827
828 /*ARGSUSED*/
829 static void
830 u3g_set(void *arg, int portno, int reg, int onoff)
831 {
832 struct u3g_softc *sc = arg;
833 usb_device_request_t req;
834 uint16_t mask, new_state;
835 usbd_status err;
836
837 if (sc->sc_dying)
838 return;
839
840 switch (reg) {
841 case UCOM_SET_DTR:
842 mask = U3G_OUTPIN_DTR;
843 break;
844 case UCOM_SET_RTS:
845 mask = U3G_OUTPIN_RTS;
846 break;
847 default:
848 return;
849 }
850
851 new_state = sc->sc_outpins & ~mask;
852 if (onoff)
853 new_state |= mask;
854
855 if (new_state == sc->sc_outpins)
856 return;
857
858 sc->sc_outpins = new_state;
859
860 req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
861 req.bRequest = U3G_SET_PIN;
862 USETW(req.wValue, new_state);
863 USETW(req.wIndex, sc->sc_ifaceno);
864 USETW(req.wLength, 0);
865
866 err = usbd_do_request(sc->sc_udev, &req, 0);
867 if (err == USBD_STALLED)
868 usbd_clear_endpoint_stall(sc->sc_udev->default_pipe);
869 }
870
871 /*ARGSUSED*/
872 static int
873 u3g_open(void *arg, int portno)
874 {
875 struct u3g_softc *sc = arg;
876 usb_device_request_t req;
877 usb_endpoint_descriptor_t *ed;
878 usb_interface_descriptor_t *id;
879 usbd_interface_handle ih;
880 usbd_status err;
881 int i;
882
883 if (sc->sc_dying)
884 return (0);
885
886 err = usbd_device2interface_handle(sc->sc_udev, portno, &ih);
887 if (err)
888 return (EIO);
889
890 id = usbd_get_interface_descriptor(ih);
891
892 for (i = 0; i < id->bNumEndpoints; i++) {
893 ed = usbd_interface2endpoint_descriptor(ih, i);
894 if (ed == NULL)
895 return (EIO);
896
897 if (UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
898 /* Issue ENDPOINT_HALT request */
899 req.bmRequestType = UT_WRITE_ENDPOINT;
900 req.bRequest = UR_CLEAR_FEATURE;
901 USETW(req.wValue, UF_ENDPOINT_HALT);
902 USETW(req.wIndex, ed->bEndpointAddress);
903 USETW(req.wLength, 0);
904 err = usbd_do_request(sc->sc_udev, &req, 0);
905 if (err)
906 return (EIO);
907 }
908 }
909
910 sc->sc_open = true;
911 sc->sc_purging = true;
912 getmicrotime(&sc->sc_purge_start);
913
914 return (0);
915 }
916
917 /*ARGSUSED*/
918 static void
919 u3g_close(void *arg, int portno)
920 {
921 struct u3g_softc *sc = arg;
922
923 sc->sc_open = false;
924 }
925
926 /*ARGSUSED*/
927 static void
928 u3g_read(void *arg, int portno, u_char **cpp, uint32_t *ccp)
929 {
930 struct u3g_softc *sc = arg;
931 struct timeval curr_tv, diff_tv;
932
933 /*
934 * If we're not purging input data following first open, do nothing.
935 */
936 if (sc->sc_purging == false)
937 return;
938
939 /*
940 * Otherwise check if the purge timeout has expired
941 */
942 getmicrotime(&curr_tv);
943 timersub(&curr_tv, &sc->sc_purge_start, &diff_tv);
944
945 if (diff_tv.tv_sec >= U3G_PURGE_SECS) {
946 /* Timeout expired. */
947 sc->sc_purging = false;
948 } else {
949 /* Still purging. Adjust the caller's byte count. */
950 *ccp = 0;
951 }
952 }
953
954 /*ARGSUSED*/
955 static void
956 u3g_write(void *arg, int portno, u_char *to, u_char *from, u_int32_t *count)
957 {
958 struct u3g_softc *sc = arg;
959
960 /*
961 * Stop purging as soon as the first data is written to the device.
962 */
963 sc->sc_purging = false;
964 memcpy(to, from, *count);
965 }
966