u3g.c revision 1.20.2.1 1 /* $NetBSD: u3g.c,v 1.20.2.1 2011/11/10 14:31:47 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.1 2011/11/10 14:31:47 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_K3765 },
189 { USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_MOBILE },
190 /* OEM: Merlin */
191 { USB_VENDOR_MERLIN, USB_PRODUCT_MERLIN_V620 },
192 /* OEM: Novatel */
193 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_ES620 },
194 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_MC950D },
195 #if 0
196 /* These are matched in u3ginit_match() */
197 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_MC950D_DRIVER },
198 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_U760_DRIVER },
199 #endif
200 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_MERLINU740 },
201 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_MERLINV620 },
202 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_S720 },
203 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_U720 },
204 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_U727 },
205 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_U740_2 },
206 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_U760 },
207 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_U870 },
208 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_V740 },
209 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_X950D },
210 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_XU870 },
211 /* OEM: Option N.V. */
212 { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_QUADPLUSUMTS },
213 { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_HSDPA },
214 { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_GTMAXHSUPA },
215 /* OEM: Qualcomm, Inc. */
216 { USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_CDMA_MSM },
217 { USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_ZTE_MF626 },
218
219 /* OEM: Sierra Wireless: */
220 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC595U },
221 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC597E },
222 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC875U },
223 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880 },
224 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880E },
225 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880U },
226 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881 },
227 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881E },
228 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881U },
229 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD580 },
230 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD595 },
231 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD875 },
232 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_C597 },
233 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_EM5625 },
234 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720 },
235 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720_2 },
236 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5725 },
237 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755 },
238 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755_2 },
239 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755_3 },
240 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8765 },
241 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8775_2 },
242 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8780 },
243 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8781 },
244 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MINI5725 },
245 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_USB305 },
246
247 /* Toshiba */
248 { USB_VENDOR_TOSHIBA, USB_PRODUCT_TOSHIBA_HSDPA_MODEM_EU870DT1 },
249
250 /* 4G Systems */
251 { USB_VENDOR_4GSYSTEMS, USB_PRODUCT_4GSYSTEMS_XSSTICK_P14 },
252 };
253
254 static int
255 send_bulkmsg(usbd_device_handle dev, void *cmd, size_t cmdlen)
256 {
257 usbd_interface_handle iface;
258 usb_interface_descriptor_t *id;
259 usb_endpoint_descriptor_t *ed;
260 usbd_pipe_handle pipe;
261 usbd_xfer_handle xfer;
262 int err, i;
263
264 /* Move the device into the configured state. */
265 err = usbd_set_config_index(dev, 0, 0);
266 if (err) {
267 aprint_error("u3g: failed to set configuration index\n");
268 return UMATCH_NONE;
269 }
270
271 err = usbd_device2interface_handle(dev, 0, &iface);
272 if (err != 0) {
273 aprint_error("u3ginit: failed to get interface\n");
274 return UMATCH_NONE;
275 }
276
277 id = usbd_get_interface_descriptor(iface);
278 ed = NULL;
279 for (i = 0 ; i < id->bNumEndpoints ; i++) {
280 ed = usbd_interface2endpoint_descriptor(iface, i);
281 if (ed == NULL)
282 continue;
283 if (UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_OUT)
284 continue;
285 if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK)
286 break;
287 }
288
289 if (i == id->bNumEndpoints)
290 return UMATCH_NONE;
291
292 err = usbd_open_pipe(iface, ed->bEndpointAddress,
293 USBD_EXCLUSIVE_USE, &pipe);
294 if (err != 0) {
295 aprint_error("u3ginit: failed to open bulk transfer pipe %d\n",
296 ed->bEndpointAddress);
297 return UMATCH_NONE;
298 }
299
300 xfer = usbd_alloc_xfer(dev);
301 if (xfer != NULL) {
302 usbd_setup_xfer(xfer, pipe, NULL, cmd, cmdlen,
303 USBD_SYNCHRONOUS, USBD_DEFAULT_TIMEOUT, NULL);
304
305 err = usbd_transfer(xfer);
306
307 #if 0 /* XXXpooka: at least my huawei "fails" this always, but still detaches */
308 if (err)
309 aprint_error("u3ginit: transfer failed\n");
310 #else
311 err = 0;
312 #endif
313 usbd_free_xfer(xfer);
314 } else {
315 aprint_error("u3ginit: failed to allocate xfer\n");
316 err = USBD_NOMEM;
317 }
318
319 usbd_abort_pipe(pipe);
320 usbd_close_pipe(pipe);
321
322 return (err == USBD_NORMAL_COMPLETION ? UMATCH_HIGHEST : UMATCH_NONE);
323 }
324
325 static int
326 u3g_novatel_reinit(usbd_device_handle dev)
327 {
328 unsigned char cmd[31];
329
330 memset(cmd, 0, sizeof(cmd));
331 /* Byte 0..3: Command Block Wrapper (CBW) signature */
332 cmd[0] = 0x55;
333 cmd[1] = 0x53;
334 cmd[2] = 0x42;
335 cmd[3] = 0x43;
336 /* 4..7: CBW Tag, has to unique, but only a single transfer used. */
337 cmd[4] = 0x01;
338 /* 8..11: CBW Transfer Length, no data here */
339 /* 12: CBW Flag: output, so 0 */
340 /* 13: CBW Lun: 0 */
341 /* 14: CBW Length */
342 cmd[14] = 0x06;
343 /* Rest is the SCSI payload */
344 /* 0: SCSI START/STOP opcode */
345 cmd[15] = 0x1b;
346 /* 1..3 unused */
347 /* 4 Load/Eject command */
348 cmd[19] = 0x02;
349 /* 5: unused */
350
351 return send_bulkmsg(dev, cmd, sizeof(cmd));
352 }
353
354 static int
355 u3g_huawei_reinit(usbd_device_handle dev)
356 {
357 /*
358 * The Huawei device presents itself as a umass device with Windows
359 * drivers on it. After installation of the driver, it reinits into a
360 * 3G serial device.
361 */
362 usb_device_request_t req;
363 usb_config_descriptor_t *cdesc;
364
365 /* Get the config descriptor */
366 cdesc = usbd_get_config_descriptor(dev);
367 if (cdesc == NULL) {
368 usb_device_descriptor_t dd;
369
370 if (usbd_get_device_desc(dev, &dd) != 0)
371 return (UMATCH_NONE);
372
373 if (dd.bNumConfigurations != 1)
374 return (UMATCH_NONE);
375
376 if (usbd_set_config_index(dev, 0, 1) != 0)
377 return (UMATCH_NONE);
378
379 cdesc = usbd_get_config_descriptor(dev);
380
381 if (cdesc == NULL)
382 return (UMATCH_NONE);
383 }
384
385 /*
386 * One iface means umass mode, more than 1 (4 usually) means 3G mode.
387 *
388 * XXX: We should check the first interface's device class just to be
389 * sure. If it's a mass storage device, then we can be fairly certain
390 * it needs a mode-switch.
391 */
392 if (cdesc->bNumInterface > 1)
393 return (UMATCH_NONE);
394
395 req.bmRequestType = UT_WRITE_DEVICE;
396 req.bRequest = UR_SET_FEATURE;
397 USETW(req.wValue, UF_DEVICE_REMOTE_WAKEUP);
398 USETW(req.wIndex, UHF_PORT_SUSPEND);
399 USETW(req.wLength, 0);
400
401 (void) usbd_do_request(dev, &req, 0);
402
403 return (UMATCH_HIGHEST); /* Prevent umass from attaching */
404 }
405
406 static int
407 u3g_huawei_k3765_reinit(usbd_device_handle dev)
408 {
409 unsigned char cmd[31];
410
411 /* magic string adapted from some webpage */
412 memset(cmd, 0, sizeof(cmd));
413 cmd[0] = 0x55;
414 cmd[1] = 0x53;
415 cmd[2] = 0x42;
416 cmd[3] = 0x43;
417 cmd[15]= 0x11;
418 cmd[16]= 0x06;
419
420 return send_bulkmsg(dev, cmd, sizeof(cmd));
421 }
422
423 static int
424 u3g_sierra_reinit(usbd_device_handle dev)
425 {
426 /* Some Sierra devices presents themselves as a umass device with
427 * Windows drivers on it. After installation of the driver, it
428 * reinits into a * 3G serial device.
429 */
430 usb_device_request_t req;
431
432 req.bmRequestType = UT_VENDOR;
433 req.bRequest = UR_SET_INTERFACE;
434 USETW(req.wValue, UF_DEVICE_REMOTE_WAKEUP);
435 USETW(req.wIndex, UHF_PORT_CONNECTION);
436 USETW(req.wLength, 0);
437
438 (void) usbd_do_request(dev, &req, 0);
439
440 return (UMATCH_HIGHEST); /* Match to prevent umass from attaching */
441 }
442
443 static int
444 u3g_4gsystems_reinit(usbd_device_handle dev)
445 {
446 /* magic string adapted from usb_modeswitch database */
447 static unsigned char cmd[31] = {
448 0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x78, 0x80, 0x00,
449 0x00, 0x00, 0x80, 0x00, 0x06, 0x06, 0xf5, 0x04, 0x02, 0x52,
450 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
451 0x00
452 };
453
454 return send_bulkmsg(dev, cmd, sizeof(cmd));
455 }
456
457 /*
458 * First personality:
459 *
460 * Claim the entire device if a mode-switch is required.
461 */
462
463 static int
464 u3ginit_match(device_t parent, cfdata_t match, void *aux)
465 {
466 struct usb_attach_arg *uaa = aux;
467
468 /*
469 * Huawei changes product when it is configured as a modem.
470 */
471 switch (uaa->vendor) {
472 case USB_VENDOR_HUAWEI:
473 if (uaa->product == USB_PRODUCT_HUAWEI_K3765)
474 return UMATCH_NONE;
475
476 switch (uaa->product) {
477 case USB_PRODUCT_HUAWEI_E1750INIT:
478 case USB_PRODUCT_HUAWEI_K3765INIT:
479 return u3g_huawei_k3765_reinit(uaa->device);
480 break;
481 default:
482 return u3g_huawei_reinit(uaa->device);
483 break;
484 }
485 break;
486
487 case USB_VENDOR_NOVATEL2:
488 switch (uaa->product){
489 case USB_PRODUCT_NOVATEL2_MC950D_DRIVER:
490 case USB_PRODUCT_NOVATEL2_U760_DRIVER:
491 return u3g_novatel_reinit(uaa->device);
492 break;
493 default:
494 break;
495 }
496 break;
497
498 case USB_VENDOR_SIERRA:
499 if (uaa->product == USB_PRODUCT_SIERRA_INSTALLER)
500 return u3g_sierra_reinit(uaa->device);
501 break;
502
503 case USB_VENDOR_QUALCOMMINC:
504 if (uaa->product == USB_PRODUCT_QUALCOMMINC_ZTE_STOR)
505 return u3g_novatel_reinit(uaa->device);
506 break;
507
508 case USB_VENDOR_4GSYSTEMS:
509 if (uaa->product == USB_PRODUCT_4GSYSTEMS_XSSTICK_P14_INSTALLER)
510 return u3g_4gsystems_reinit(uaa->device);
511 break;
512
513 default:
514 break;
515 }
516
517 return UMATCH_NONE;
518 }
519
520 static void
521 u3ginit_attach(device_t parent, device_t self, void *aux)
522 {
523 struct usb_attach_arg *uaa = aux;
524
525 aprint_naive("\n");
526 aprint_normal(": Switching to 3G mode\n");
527
528 if (uaa->vendor == USB_VENDOR_NOVATEL2) {
529 switch (uaa->product) {
530 case USB_PRODUCT_NOVATEL2_MC950D_DRIVER:
531 case USB_PRODUCT_NOVATEL2_U760_DRIVER:
532 /* About to disappear... */
533 return;
534 break;
535 default:
536 break;
537 }
538 }
539
540 /* Move the device into the configured state. */
541 (void) usbd_set_config_index(uaa->device, 0, 1);
542 }
543
544 static int
545 u3ginit_detach(device_t self, int flags)
546 {
547
548 return (0);
549 }
550
551
552 /*
553 * Second personality:
554 *
555 * Claim only those interfaces required for 3G modem operation.
556 */
557
558 static int
559 u3g_match(device_t parent, cfdata_t match, void *aux)
560 {
561 struct usbif_attach_arg *uaa = aux;
562 usbd_interface_handle iface;
563 usb_interface_descriptor_t *id;
564 usbd_status error;
565
566 if (!usb_lookup(u3g_devs, uaa->vendor, uaa->product))
567 return (UMATCH_NONE);
568
569 error = usbd_device2interface_handle(uaa->device, uaa->ifaceno, &iface);
570 if (error) {
571 printf("u3g_match: failed to get interface, err=%s\n",
572 usbd_errstr(error));
573 return (UMATCH_NONE);
574 }
575
576 id = usbd_get_interface_descriptor(iface);
577 if (id == NULL) {
578 printf("u3g_match: failed to get interface descriptor\n");
579 return (UMATCH_NONE);
580 }
581
582 /*
583 * 3G modems generally report vendor-specific class
584 *
585 * XXX: this may be too generalised.
586 */
587 return ((id->bInterfaceClass == UICLASS_VENDOR) ?
588 UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
589 }
590
591 static void
592 u3g_attach(device_t parent, device_t self, void *aux)
593 {
594 struct u3g_softc *sc = device_private(self);
595 struct usbif_attach_arg *uaa = aux;
596 usbd_device_handle dev = uaa->device;
597 usbd_interface_handle iface;
598 usb_interface_descriptor_t *id;
599 usb_endpoint_descriptor_t *ed;
600 struct ucom_attach_args uca;
601 usbd_status error;
602 int n, intr_address, intr_size;
603
604 aprint_naive("\n");
605 aprint_normal("\n");
606
607 sc->sc_dev = self;
608 sc->sc_dying = false;
609 sc->sc_udev = dev;
610
611 error = usbd_device2interface_handle(dev, uaa->ifaceno, &iface);
612 if (error) {
613 aprint_error_dev(self, "failed to get interface, err=%s\n",
614 usbd_errstr(error));
615 return;
616 }
617
618 id = usbd_get_interface_descriptor(iface);
619
620 uca.info = "3G Modem";
621 uca.ibufsize = U3G_BUFF_SIZE;
622 uca.obufsize = U3G_BUFF_SIZE;
623 uca.ibufsizepad = U3G_BUFF_SIZE;
624 uca.portno = uaa->ifaceno;
625 uca.opkthdrlen = 0;
626 uca.device = dev;
627 uca.iface = iface;
628 uca.methods = &u3g_methods;
629 uca.arg = sc;
630 uca.bulkin = uca.bulkout = -1;
631
632 sc->sc_outpins = 0;
633 sc->sc_msr = UMSR_DSR | UMSR_CTS | UMSR_DCD;
634 sc->sc_ifaceno = uaa->ifaceno;
635 sc->sc_open = false;
636 sc->sc_purging = false;
637
638 intr_address = -1;
639 intr_size = 0;
640
641 for (n = 0; n < id->bNumEndpoints; n++) {
642 ed = usbd_interface2endpoint_descriptor(iface, n);
643 if (ed == NULL) {
644 aprint_error_dev(self, "no endpoint descriptor "
645 "for %d (interface: %d)\n", n, sc->sc_ifaceno);
646 sc->sc_dying = true;
647 return;
648 }
649
650 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
651 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
652 intr_address = ed->bEndpointAddress;
653 intr_size = UGETW(ed->wMaxPacketSize);
654 } else
655 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
656 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
657 uca.bulkin = ed->bEndpointAddress;
658 } else
659 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
660 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
661 uca.bulkout = ed->bEndpointAddress;
662 }
663 }
664
665 if (uca.bulkin == -1) {
666 aprint_error_dev(self, "Missing bulk in for interface %d\n",
667 sc->sc_ifaceno);
668 sc->sc_dying = true;
669 return;
670 }
671
672 if (uca.bulkout == -1) {
673 aprint_error_dev(self, "Missing bulk out for interface %d\n",
674 sc->sc_ifaceno);
675 sc->sc_dying = true;
676 return;
677 }
678
679 sc->sc_ucom = config_found_sm_loc(self, "ucombus",
680 NULL, &uca, ucomprint, ucomsubmatch);
681
682 /*
683 * If the interface has an interrupt pipe, open it immediately so
684 * that we can track input pin state changes regardless of whether
685 * the tty(4) device is open or not.
686 */
687 if (intr_address != -1) {
688 sc->sc_intr_buff = malloc(intr_size, M_USBDEV, M_WAITOK);
689 error = usbd_open_pipe_intr(iface, intr_address,
690 USBD_SHORT_XFER_OK, &sc->sc_intr_pipe, sc, sc->sc_intr_buff,
691 intr_size, u3g_intr, 100);
692 if (error) {
693 aprint_error_dev(self, "cannot open interrupt pipe "
694 "(addr %d)\n", intr_address);
695 return;
696 }
697 } else {
698 sc->sc_intr_pipe = NULL;
699 sc->sc_intr_buff = NULL;
700 }
701
702 if (!pmf_device_register(self, NULL, NULL))
703 aprint_error_dev(self, "couldn't establish power handler\n");
704 }
705
706 static int
707 u3g_detach(device_t self, int flags)
708 {
709 struct u3g_softc *sc = device_private(self);
710 int rv;
711
712 if (sc->sc_dying)
713 return 0;
714
715 pmf_device_deregister(self);
716
717 if (sc->sc_ucom != NULL) {
718 rv = config_detach(sc->sc_ucom, flags);
719 if (rv != 0) {
720 aprint_verbose_dev(self, "Can't deallocate "
721 "port (%d)", rv);
722 }
723 }
724
725 if (sc->sc_intr_pipe != NULL) {
726 (void) usbd_abort_pipe(sc->sc_intr_pipe);
727 (void) usbd_close_pipe(sc->sc_intr_pipe);
728 sc->sc_intr_pipe = NULL;
729 }
730 if (sc->sc_intr_buff != NULL) {
731 free(sc->sc_intr_buff, M_USBDEV);
732 sc->sc_intr_buff = NULL;
733 }
734
735 return (0);
736 }
737
738 static void
739 u3g_childdet(device_t self, device_t child)
740 {
741 struct u3g_softc *sc = device_private(self);
742
743 if (sc->sc_ucom == child)
744 sc->sc_ucom = NULL;
745 }
746
747 static int
748 u3g_activate(device_t self, enum devact act)
749 {
750 struct u3g_softc *sc = device_private(self);
751 int rv;
752
753 switch (act) {
754 case DVACT_DEACTIVATE:
755 if (sc->sc_ucom != NULL && config_deactivate(sc->sc_ucom))
756 rv = -1;
757 else
758 rv = 0;
759 break;
760
761 default:
762 rv = 0;
763 break;
764 }
765
766 return (rv);
767 }
768
769 static void
770 u3g_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
771 {
772 struct u3g_softc *sc = (struct u3g_softc *)priv;
773 u_char *buf;
774
775 if (sc->sc_dying)
776 return;
777
778 if (status != USBD_NORMAL_COMPLETION) {
779 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
780 return;
781 usbd_clear_endpoint_stall_async(sc->sc_intr_pipe);
782 return;
783 }
784
785 buf = sc->sc_intr_buff;
786 if (buf[0] == 0xa1 && buf[1] == 0x20) {
787 u_char msr;
788
789 msr = sc->sc_msr & ~(UMSR_DCD | UMSR_DSR | UMSR_RI);
790
791 if (buf[8] & U3G_INPIN_DCD)
792 msr |= UMSR_DCD;
793
794 if (buf[8] & U3G_INPIN_DSR)
795 msr |= UMSR_DSR;
796
797 if (buf[8] & U3G_INPIN_RI)
798 msr |= UMSR_RI;
799
800 if (msr != sc->sc_msr) {
801 sc->sc_msr = msr;
802 if (sc->sc_open)
803 ucom_status_change(device_private(sc->sc_ucom));
804 }
805 }
806 }
807
808 /*ARGSUSED*/
809 static void
810 u3g_get_status(void *arg, int portno, u_char *lsr, u_char *msr)
811 {
812 struct u3g_softc *sc = arg;
813
814 if (lsr != NULL)
815 *lsr = 0; /* LSR isn't supported */
816 if (msr != NULL)
817 *msr = sc->sc_msr;
818 }
819
820 /*ARGSUSED*/
821 static void
822 u3g_set(void *arg, int portno, int reg, int onoff)
823 {
824 struct u3g_softc *sc = arg;
825 usb_device_request_t req;
826 uint16_t mask, new_state;
827 usbd_status err;
828
829 if (sc->sc_dying)
830 return;
831
832 switch (reg) {
833 case UCOM_SET_DTR:
834 mask = U3G_OUTPIN_DTR;
835 break;
836 case UCOM_SET_RTS:
837 mask = U3G_OUTPIN_RTS;
838 break;
839 default:
840 return;
841 }
842
843 new_state = sc->sc_outpins & ~mask;
844 if (onoff)
845 new_state |= mask;
846
847 if (new_state == sc->sc_outpins)
848 return;
849
850 sc->sc_outpins = new_state;
851
852 req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
853 req.bRequest = U3G_SET_PIN;
854 USETW(req.wValue, new_state);
855 USETW(req.wIndex, sc->sc_ifaceno);
856 USETW(req.wLength, 0);
857
858 err = usbd_do_request(sc->sc_udev, &req, 0);
859 if (err == USBD_STALLED)
860 usbd_clear_endpoint_stall(sc->sc_udev->default_pipe);
861 }
862
863 /*ARGSUSED*/
864 static int
865 u3g_open(void *arg, int portno)
866 {
867 struct u3g_softc *sc = arg;
868 usb_device_request_t req;
869 usb_endpoint_descriptor_t *ed;
870 usb_interface_descriptor_t *id;
871 usbd_interface_handle ih;
872 usbd_status err;
873 int i;
874
875 if (sc->sc_dying)
876 return (0);
877
878 err = usbd_device2interface_handle(sc->sc_udev, portno, &ih);
879 if (err)
880 return (EIO);
881
882 id = usbd_get_interface_descriptor(ih);
883
884 for (i = 0; i < id->bNumEndpoints; i++) {
885 ed = usbd_interface2endpoint_descriptor(ih, i);
886 if (ed == NULL)
887 return (EIO);
888
889 if (UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
890 /* Issue ENDPOINT_HALT request */
891 req.bmRequestType = UT_WRITE_ENDPOINT;
892 req.bRequest = UR_CLEAR_FEATURE;
893 USETW(req.wValue, UF_ENDPOINT_HALT);
894 USETW(req.wIndex, ed->bEndpointAddress);
895 USETW(req.wLength, 0);
896 err = usbd_do_request(sc->sc_udev, &req, 0);
897 if (err)
898 return (EIO);
899 }
900 }
901
902 sc->sc_open = true;
903 sc->sc_purging = true;
904 getmicrotime(&sc->sc_purge_start);
905
906 return (0);
907 }
908
909 /*ARGSUSED*/
910 static void
911 u3g_close(void *arg, int portno)
912 {
913 struct u3g_softc *sc = arg;
914
915 sc->sc_open = false;
916 }
917
918 /*ARGSUSED*/
919 static void
920 u3g_read(void *arg, int portno, u_char **cpp, uint32_t *ccp)
921 {
922 struct u3g_softc *sc = arg;
923 struct timeval curr_tv, diff_tv;
924
925 /*
926 * If we're not purging input data following first open, do nothing.
927 */
928 if (sc->sc_purging == false)
929 return;
930
931 /*
932 * Otherwise check if the purge timeout has expired
933 */
934 getmicrotime(&curr_tv);
935 timersub(&curr_tv, &sc->sc_purge_start, &diff_tv);
936
937 if (diff_tv.tv_sec >= U3G_PURGE_SECS) {
938 /* Timeout expired. */
939 sc->sc_purging = false;
940 } else {
941 /* Still purging. Adjust the caller's byte count. */
942 *ccp = 0;
943 }
944 }
945
946 /*ARGSUSED*/
947 static void
948 u3g_write(void *arg, int portno, u_char *to, u_char *from, u_int32_t *count)
949 {
950 struct u3g_softc *sc = arg;
951
952 /*
953 * Stop purging as soon as the first data is written to the device.
954 */
955 sc->sc_purging = false;
956 memcpy(to, from, *count);
957 }
958