xref: /netbsd-src/sys/dev/usb/uhso.c (revision ba65fde2d7fefa7d39838fa5fa855e62bd606b5e)
1 /*	$NetBSD: uhso.c,v 1.11 2013/01/05 01:30:17 christos Exp $	*/
2 
3 /*-
4  * Copyright (c) 2009 Iain Hibbert
5  * Copyright (c) 2008 Fredrik Lindberg
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /*
30  *   This driver originated as the hso module for FreeBSD written by
31  * Fredrik Lindberg[1]. It has been rewritten almost completely for
32  * NetBSD, and to support more devices with information extracted from
33  * the Linux hso driver provided by Option N.V.[2]
34  *
35  *   [1] http://www.shapeshifter.se/code/hso
36  *   [2] http://www.pharscape.org/hso.htm
37  */
38 
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: uhso.c,v 1.11 2013/01/05 01:30:17 christos Exp $");
41 
42 #ifdef _KERNEL_OPT
43 #include "opt_inet.h"
44 #endif
45 
46 #include <sys/param.h>
47 #include <sys/conf.h>
48 #include <sys/fcntl.h>
49 #include <sys/kauth.h>
50 #include <sys/kernel.h>
51 #include <sys/kmem.h>
52 #include <sys/mbuf.h>
53 #include <sys/poll.h>
54 #include <sys/queue.h>
55 #include <sys/socket.h>
56 #include <sys/sysctl.h>
57 #include <sys/systm.h>
58 #include <sys/tty.h>
59 #include <sys/vnode.h>
60 #include <sys/lwp.h>
61 
62 #include <net/bpf.h>
63 #include <net/if.h>
64 #include <net/if_dl.h>
65 #include <net/if_types.h>
66 #include <net/netisr.h>
67 
68 #include <netinet/in_systm.h>
69 #include <netinet/in_var.h>
70 #include <netinet/ip.h>
71 
72 #include <dev/usb/usb.h>
73 #include <dev/usb/usbcdc.h>
74 #include <dev/usb/usbdi.h>
75 #include <dev/usb/usbdi_util.h>
76 #include <dev/usb/umassvar.h>
77 
78 #include <dev/scsipi/scsi_disk.h>
79 
80 #include "usbdevs.h"
81 
82 #undef DPRINTF
83 #ifdef UHSO_DEBUG
84 /*
85  * defined levels
86  *	0	warnings only
87  *	1	informational
88  *	5	really chatty
89  */
90 int uhso_debug = 0;
91 
92 #define DPRINTF(n, ...)	do {			\
93 	if (uhso_debug >= (n)) {		\
94 		printf("%s: ", __func__);	\
95 		printf(__VA_ARGS__);		\
96 	}					\
97 } while (/* CONSTCOND */0)
98 #else
99 #define DPRINTF(...)	((void)0)
100 #endif
101 
102 /*
103  * When first attached, the device class will be 0 and the modem
104  * will attach as UMASS until a SCSI REZERO_UNIT command is sent,
105  * in which case it will detach and reattach with device class set
106  * to UDCLASS_VENDOR (0xff) and provide the serial interfaces.
107  *
108  * If autoswitch is set (the default) this will happen automatically.
109  */
110 Static int uhso_autoswitch = 1;
111 
112 SYSCTL_SETUP(sysctl_hw_uhso_setup, "uhso sysctl setup")
113 {
114 	const struct sysctlnode *node = NULL;
115 
116 	sysctl_createv(clog, 0, NULL, NULL,
117 		CTLFLAG_PERMANENT,
118 		CTLTYPE_NODE, "hw",
119 		NULL,
120 		NULL, 0,
121 		NULL, 0,
122 		CTL_HW, CTL_EOL);
123 
124 	sysctl_createv(clog, 0, NULL, &node,
125 		CTLFLAG_PERMANENT,
126 		CTLTYPE_NODE, "uhso",
127 		NULL,
128 		NULL, 0,
129 		NULL, 0,
130 		CTL_HW, CTL_CREATE, CTL_EOL);
131 
132 	if (node == NULL)
133 		return;
134 
135 #ifdef UHSO_DEBUG
136 	sysctl_createv(clog, 0, &node, NULL,
137 		CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
138 		CTLTYPE_INT, "debug",
139 		SYSCTL_DESCR("uhso debug level (0, 1, 5)"),
140 		NULL, 0,
141 		&uhso_debug, sizeof(uhso_debug),
142 		CTL_CREATE, CTL_EOL);
143 #endif
144 
145 	sysctl_createv(clog, 0, &node, NULL,
146 		CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
147 		CTLTYPE_INT, "autoswitch",
148 		SYSCTL_DESCR("automatically switch device into modem mode"),
149 		NULL, 0,
150 		&uhso_autoswitch, sizeof(uhso_autoswitch),
151 		CTL_CREATE, CTL_EOL);
152 }
153 
154 /*
155  * The uhso modems have a number of interfaces providing a variety of
156  * IO ports using the bulk endpoints, or multiplexed on the control
157  * endpoints. We separate the ports by function and provide each with
158  * a predictable index number used to construct the device minor number.
159  *
160  * The Network port is configured as a network interface rather than
161  * a tty as it provides raw IPv4 packets.
162  */
163 
164 Static const char *uhso_port_name[] = {
165 	"Control",
166 	"Diagnostic",
167 	"Diagnostic2",
168 	"Application",
169 	"Application2",
170 	"GPS",
171 	"GPS Control",
172 	"PC Smartcard",
173 	"Modem",
174 	"MSD",			/* "Modem Sharing Device" ? */
175 	"Voice",
176 	"Network",
177 };
178 
179 #define UHSO_PORT_CONTROL	0x00
180 #define UHSO_PORT_DIAG		0x01
181 #define UHSO_PORT_DIAG2		0x02
182 #define UHSO_PORT_APP		0x03
183 #define UHSO_PORT_APP2		0x04
184 #define UHSO_PORT_GPS		0x05
185 #define UHSO_PORT_GPS_CONTROL	0x06
186 #define UHSO_PORT_PCSC		0x07
187 #define UHSO_PORT_MODEM		0x08
188 #define UHSO_PORT_MSD		0x09
189 #define UHSO_PORT_VOICE		0x0a
190 #define UHSO_PORT_NETWORK	0x0b
191 
192 #define UHSO_PORT_MAX		__arraycount(uhso_port_name)
193 
194 #define UHSO_IFACE_MUX		0x20
195 #define UHSO_IFACE_BULK		0x40
196 #define UHSO_IFACE_IFNET	0x80
197 
198 /*
199  * The interface specification can sometimes be deduced from the device
200  * type and interface number, or some modems support a vendor specific
201  * way to read config info which we can translate to the port index.
202  */
203 Static const uint8_t uhso_spec_default[] = {
204 	UHSO_IFACE_IFNET | UHSO_PORT_NETWORK | UHSO_IFACE_MUX,
205 	UHSO_IFACE_BULK | UHSO_PORT_DIAG,
206 	UHSO_IFACE_BULK | UHSO_PORT_MODEM,
207 };
208 
209 Static const uint8_t uhso_spec_icon321[] = {
210 	UHSO_IFACE_IFNET | UHSO_PORT_NETWORK | UHSO_IFACE_MUX,
211 	UHSO_IFACE_BULK | UHSO_PORT_DIAG2,
212 	UHSO_IFACE_BULK | UHSO_PORT_MODEM,
213 	UHSO_IFACE_BULK | UHSO_PORT_DIAG,
214 };
215 
216 Static const uint8_t uhso_spec_config[] = {
217 	0,
218 	UHSO_IFACE_BULK | UHSO_PORT_DIAG,
219 	UHSO_IFACE_BULK | UHSO_PORT_GPS,
220 	UHSO_IFACE_BULK | UHSO_PORT_GPS_CONTROL,
221 	UHSO_IFACE_BULK | UHSO_PORT_APP,
222 	UHSO_IFACE_BULK | UHSO_PORT_APP2,
223 	UHSO_IFACE_BULK | UHSO_PORT_CONTROL,
224 	UHSO_IFACE_IFNET | UHSO_PORT_NETWORK,
225 	UHSO_IFACE_BULK | UHSO_PORT_MODEM,
226 	UHSO_IFACE_BULK | UHSO_PORT_MSD,
227 	UHSO_IFACE_BULK | UHSO_PORT_PCSC,
228 	UHSO_IFACE_BULK | UHSO_PORT_VOICE,
229 };
230 
231 struct uhso_dev {
232 	uint16_t vendor;
233 	uint16_t product;
234 	uint16_t type;
235 };
236 
237 #define UHSOTYPE_DEFAULT	1
238 #define UHSOTYPE_ICON321	2
239 #define UHSOTYPE_CONFIG		3
240 
241 Static const struct uhso_dev uhso_devs[] = {
242     { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_MAXHSDPA,    UHSOTYPE_DEFAULT },
243     { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_GSICON72,    UHSOTYPE_DEFAULT },
244     { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_ICON225,     UHSOTYPE_DEFAULT },
245     { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_GEHSUPA,     UHSOTYPE_DEFAULT },
246     { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_GTHSUPA,     UHSOTYPE_DEFAULT },
247     { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_GSHSUPA,     UHSOTYPE_DEFAULT },
248     { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_GE40X1,      UHSOTYPE_CONFIG },
249     { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_GE40X2,      UHSOTYPE_CONFIG },
250     { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_GE40X3,      UHSOTYPE_CONFIG },
251     { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_ICON401,     UHSOTYPE_CONFIG },
252     { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_GTM382,	     UHSOTYPE_CONFIG },
253     { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_GE40X4,      UHSOTYPE_CONFIG },
254     { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_ICONEDGE,    UHSOTYPE_DEFAULT },
255     { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_MODHSXPA,    UHSOTYPE_ICON321 },
256     { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_ICON321,     UHSOTYPE_ICON321 },
257     { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_ICON322,     UHSOTYPE_ICON321 },
258     { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_ICON505,     UHSOTYPE_CONFIG },
259 };
260 
261 #define uhso_lookup(p, v)  ((const struct uhso_dev *)usb_lookup(uhso_devs, (p), (v)))
262 
263 /* IO buffer sizes */
264 #define UHSO_MUX_WSIZE		64
265 #define UHSO_MUX_RSIZE		1024
266 #define UHSO_BULK_WSIZE		8192
267 #define UHSO_BULK_RSIZE		4096
268 #define UHSO_IFNET_MTU		1500
269 
270 /*
271  * Each IO port provided by the modem can be mapped to a network
272  * interface (when hp_ifp != NULL) or a tty (when hp_tp != NULL)
273  * which may be multiplexed and sharing interrupt and control endpoints
274  * from an interface, or using the dedicated bulk endpoints.
275  */
276 
277 struct uhso_port;
278 struct uhso_softc;
279 
280 /* uhso callback functions return errno on failure */
281 typedef int (*uhso_callback)(struct uhso_port *);
282 
283 struct uhso_port {
284 	struct uhso_softc      *hp_sc;		/* master softc */
285 	struct tty	       *hp_tp;		/* tty pointer */
286 	struct ifnet	       *hp_ifp;		/* ifnet pointer */
287 	unsigned int		hp_flags;	/* see below */
288 	int			hp_swflags;	/* persistent tty flags */
289 	int			hp_status;	/* modem status */
290 
291 	/* port type specific handlers */
292 	uhso_callback		hp_abort;	/* abort any transfers */
293 	uhso_callback		hp_detach;	/* detach port completely */
294 	uhso_callback		hp_init;	/* init port (first open) */
295 	uhso_callback		hp_clean;	/* clean port (last close) */
296 	uhso_callback		hp_write;	/* write data */
297 	usbd_callback		hp_write_cb;	/* write callback */
298 	uhso_callback		hp_read;	/* read data */
299 	usbd_callback		hp_read_cb;	/* read callback */
300 	uhso_callback		hp_control;	/* set control lines */
301 
302 	usbd_interface_handle	hp_ifh;		/* interface handle */
303 	unsigned int		hp_index;	/* usb request index */
304 
305 	int			hp_iaddr;	/* interrupt endpoint */
306 	usbd_pipe_handle	hp_ipipe;	/* interrupt pipe */
307 	void		       *hp_ibuf;	/* interrupt buffer */
308 	size_t			hp_isize;	/* allocated size */
309 
310 	int			hp_raddr;	/* bulk in endpoint */
311 	usbd_pipe_handle	hp_rpipe;	/* bulk in pipe */
312 	usbd_xfer_handle	hp_rxfer;	/* input xfer */
313 	void		       *hp_rbuf;	/* input buffer */
314 	size_t			hp_rlen;	/* fill length */
315 	size_t			hp_rsize;	/* allocated size */
316 
317 	int			hp_waddr;	/* bulk out endpoint */
318 	usbd_pipe_handle	hp_wpipe;	/* bulk out pipe */
319 	usbd_xfer_handle	hp_wxfer;	/* output xfer */
320 	void		       *hp_wbuf;	/* output buffer */
321 	size_t			hp_wlen;	/* fill length */
322 	size_t			hp_wsize;	/* allocated size */
323 
324 	struct mbuf	       *hp_mbuf;	/* partial packet */
325 };
326 
327 /* hp_flags */
328 #define UHSO_PORT_MUXPIPE	__BIT(0)	/* duplicate ipipe/ibuf references */
329 #define UHSO_PORT_MUXREADY	__BIT(1)	/* input is ready */
330 #define UHSO_PORT_MUXBUSY	__BIT(2)	/* read in progress */
331 
332 struct uhso_softc {
333 	device_t		sc_dev;		/* self */
334 	usbd_device_handle	sc_udev;
335 	int			sc_refcnt;
336 	struct uhso_port       *sc_port[UHSO_PORT_MAX];
337 };
338 
339 #define UHSO_CONFIG_NO		1
340 
341 int uhso_match(device_t, cfdata_t, void *);
342 void uhso_attach(device_t, device_t, void *);
343 int uhso_detach(device_t, int);
344 
345 extern struct cfdriver uhso_cd;
346 
347 CFATTACH_DECL_NEW(uhso, sizeof(struct uhso_softc), uhso_match, uhso_attach,
348     uhso_detach, NULL);
349 
350 Static int uhso_switch_mode(usbd_device_handle);
351 Static int uhso_get_iface_spec(struct usb_attach_arg *, uint8_t, uint8_t *);
352 Static usb_endpoint_descriptor_t *uhso_get_endpoint(usbd_interface_handle, int, int);
353 
354 Static void uhso_mux_attach(struct uhso_softc *, usbd_interface_handle, int);
355 Static int  uhso_mux_abort(struct uhso_port *);
356 Static int  uhso_mux_detach(struct uhso_port *);
357 Static int  uhso_mux_init(struct uhso_port *);
358 Static int  uhso_mux_clean(struct uhso_port *);
359 Static int  uhso_mux_write(struct uhso_port *);
360 Static int  uhso_mux_read(struct uhso_port *);
361 Static int  uhso_mux_control(struct uhso_port *);
362 Static void uhso_mux_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
363 
364 Static void uhso_bulk_attach(struct uhso_softc *, usbd_interface_handle, int);
365 Static int  uhso_bulk_abort(struct uhso_port *);
366 Static int  uhso_bulk_detach(struct uhso_port *);
367 Static int  uhso_bulk_init(struct uhso_port *);
368 Static int  uhso_bulk_clean(struct uhso_port *);
369 Static int  uhso_bulk_write(struct uhso_port *);
370 Static int  uhso_bulk_read(struct uhso_port *);
371 Static int  uhso_bulk_control(struct uhso_port *);
372 Static void uhso_bulk_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
373 
374 Static void uhso_tty_attach(struct uhso_port *);
375 Static void uhso_tty_detach(struct uhso_port *);
376 Static void uhso_tty_read_cb(usbd_xfer_handle, usbd_private_handle, usbd_status);
377 Static void uhso_tty_write_cb(usbd_xfer_handle, usbd_private_handle, usbd_status);
378 
379 dev_type_open(uhso_tty_open);
380 dev_type_close(uhso_tty_close);
381 dev_type_read(uhso_tty_read);
382 dev_type_write(uhso_tty_write);
383 dev_type_ioctl(uhso_tty_ioctl);
384 dev_type_stop(uhso_tty_stop);
385 dev_type_tty(uhso_tty_tty);
386 dev_type_poll(uhso_tty_poll);
387 
388 const struct cdevsw uhso_cdevsw = {
389 	.d_open = uhso_tty_open,
390 	.d_close = uhso_tty_close,
391 	.d_read = uhso_tty_read,
392 	.d_write = uhso_tty_write,
393 	.d_ioctl = uhso_tty_ioctl,
394 	.d_stop = uhso_tty_stop,
395 	.d_tty = uhso_tty_tty,
396 	.d_poll = uhso_tty_poll,
397 	.d_mmap = nommap,
398 	.d_kqfilter = ttykqfilter,
399 	.d_flag = D_TTY,
400 };
401 
402 Static int  uhso_tty_init(struct uhso_port *);
403 Static void uhso_tty_clean(struct uhso_port *);
404 Static int  uhso_tty_do_ioctl(struct uhso_port *, u_long, void *, int, struct lwp *);
405 Static void uhso_tty_start(struct tty *);
406 Static int  uhso_tty_param(struct tty *, struct termios *);
407 Static int  uhso_tty_control(struct uhso_port *, u_long, int);
408 
409 #define UHSO_UNIT_MASK		0x0fff0
410 #define UHSO_PORT_MASK		0x0000f
411 #define UHSO_DIALOUT_MASK	0x80000
412 #define UHSO_CALLUNIT_MASK	0x40000
413 
414 #define UHSOUNIT(x)	((minor(x) & UHSO_UNIT_MASK) >> 4)
415 #define UHSOPORT(x)	(minor(x) & UHSO_PORT_MASK)
416 #define UHSODIALOUT(x)	(minor(x) & UHSO_DIALOUT_MASK)
417 #define UHSOMINOR(u, p)	((((u) << 4) & UHSO_UNIT_MASK) | ((p) & UHSO_UNIT_MASK))
418 
419 Static void uhso_ifnet_attach(struct uhso_softc *, usbd_interface_handle, int);
420 Static int  uhso_ifnet_abort(struct uhso_port *);
421 Static int  uhso_ifnet_detach(struct uhso_port *);
422 Static void uhso_ifnet_read_cb(usbd_xfer_handle, usbd_private_handle, usbd_status);
423 Static void uhso_ifnet_input(struct ifnet *, struct mbuf **, uint8_t *, size_t);
424 Static void uhso_ifnet_write_cb(usbd_xfer_handle, usbd_private_handle, usbd_status);
425 
426 Static int  uhso_ifnet_ioctl(struct ifnet *, u_long, void *);
427 Static int  uhso_ifnet_init(struct uhso_port *);
428 Static void uhso_ifnet_clean(struct uhso_port *);
429 Static void uhso_ifnet_start(struct ifnet *);
430 Static int  uhso_ifnet_output(struct ifnet *, struct mbuf *, const struct sockaddr *, struct rtentry *);
431 
432 
433 /*******************************************************************************
434  *
435  *	USB autoconfig
436  *
437  */
438 
439 int
440 uhso_match(device_t parent, cfdata_t match, void *aux)
441 {
442 	struct usb_attach_arg *uaa = aux;
443 
444 	/*
445 	 * don't claim this device if autoswitch is disabled
446 	 * and it is not in modem mode already
447 	 */
448 	if (!uhso_autoswitch && uaa->class != UDCLASS_VENDOR)
449 		return UMATCH_NONE;
450 
451 	if (uhso_lookup(uaa->vendor, uaa->product))
452 		return UMATCH_VENDOR_PRODUCT;
453 
454 	return UMATCH_NONE;
455 }
456 
457 void
458 uhso_attach(device_t parent, device_t self, void *aux)
459 {
460 	struct uhso_softc *sc = device_private(self);
461 	struct usb_attach_arg *uaa = aux;
462 	usbd_interface_handle ifh;
463 	char *devinfop;
464 	uint8_t count, i, spec;
465 	usbd_status status;
466 
467 	DPRINTF(1, ": sc = %p, self=%p", sc, self);
468 
469 	sc->sc_dev = self;
470 	sc->sc_udev = uaa->device;
471 
472 	aprint_naive("\n");
473 	aprint_normal("\n");
474 
475 	devinfop = usbd_devinfo_alloc(uaa->device, 0);
476 	aprint_normal_dev(self, "%s\n", devinfop);
477 	usbd_devinfo_free(devinfop);
478 
479 	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev);
480 
481 	status = usbd_set_config_no(sc->sc_udev, UHSO_CONFIG_NO, 1);
482 	if (status != USBD_NORMAL_COMPLETION) {
483 		aprint_error_dev(self, "failed to set configuration"
484 		    ", err=%s\n", usbd_errstr(status));
485 		return;
486 	}
487 
488 	if (uaa->class != UDCLASS_VENDOR) {
489 		aprint_verbose_dev(self, "Switching device into modem mode..\n");
490 		if (uhso_switch_mode(uaa->device) != 0)
491 			aprint_error_dev(self, "modem switch failed\n");
492 
493 		return;
494 	}
495 
496 	count = 0;
497 	(void)usbd_interface_count(sc->sc_udev, &count);
498 	DPRINTF(1, "interface count %d\n", count);
499 
500 	for (i = 0; i < count; i++) {
501 		status = usbd_device2interface_handle(sc->sc_udev, i, &ifh);
502 		if (status != USBD_NORMAL_COMPLETION) {
503 			aprint_error_dev(self,
504 			    "could not get interface %d: %s\n",
505 			    i, usbd_errstr(status));
506 
507 			return;
508 		}
509 
510 		if (!uhso_get_iface_spec(uaa, i, &spec)) {
511 			aprint_error_dev(self,
512 			    "could not get interface %d specification\n", i);
513 
514 			return;
515 		}
516 
517 		if (ISSET(spec, UHSO_IFACE_MUX))
518 			uhso_mux_attach(sc, ifh, UHSOPORT(spec));
519 
520 		if (ISSET(spec, UHSO_IFACE_BULK))
521 			uhso_bulk_attach(sc, ifh, UHSOPORT(spec));
522 
523 		if (ISSET(spec, UHSO_IFACE_IFNET))
524 			uhso_ifnet_attach(sc, ifh, UHSOPORT(spec));
525 	}
526 
527 	if (!pmf_device_register(self, NULL, NULL))
528 		aprint_error_dev(self, "couldn't establish power handler\n");
529 }
530 
531 int
532 uhso_detach(device_t self, int flags)
533 {
534 	struct uhso_softc *sc = device_private(self);
535 	struct uhso_port *hp;
536 	devmajor_t major;
537 	devminor_t minor;
538 	unsigned int i;
539 	int s;
540 
541 	pmf_device_deregister(self);
542 
543 	for (i = 0; i < UHSO_PORT_MAX; i++) {
544 		hp = sc->sc_port[i];
545 		if (hp != NULL)
546 			(*hp->hp_abort)(hp);
547 	}
548 
549 	s = splusb();
550 	if (sc->sc_refcnt-- > 0) {
551 		DPRINTF(1, "waiting for refcnt (%d)..\n", sc->sc_refcnt);
552 		usb_detach_waitold(sc->sc_dev);
553 	}
554 	splx(s);
555 
556 	/*
557 	 * XXX the tty close routine increases/decreases refcnt causing
558 	 * XXX another usb_detach_wakeupold() does it matter, should these
559 	 * XXX be before the detach_wait? or before the abort?
560 	 */
561 
562 	/* Nuke the vnodes for any open instances (calls close). */
563 	major = cdevsw_lookup_major(&uhso_cdevsw);
564 	minor = UHSOMINOR(device_unit(sc->sc_dev), 0);
565 	vdevgone(major, minor, minor + UHSO_PORT_MAX, VCHR);
566 	minor = UHSOMINOR(device_unit(sc->sc_dev), 0) | UHSO_DIALOUT_MASK;
567 	vdevgone(major, minor, minor + UHSO_PORT_MAX, VCHR);
568 	minor = UHSOMINOR(device_unit(sc->sc_dev), 0) | UHSO_CALLUNIT_MASK;
569 	vdevgone(major, minor, minor + UHSO_PORT_MAX, VCHR);
570 
571 	for (i = 0; i < UHSO_PORT_MAX; i++) {
572 		hp = sc->sc_port[i];
573 		if (hp != NULL)
574 			(*hp->hp_detach)(hp);
575 	}
576 
577 	usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev);
578 
579 	return 0;
580 }
581 
582 /*
583  * Send SCSI REZERO_UNIT command to switch device into modem mode
584  */
585 Static int
586 uhso_switch_mode(usbd_device_handle udev)
587 {
588 	umass_bbb_cbw_t	cmd;
589 	usb_endpoint_descriptor_t *ed;
590 	usbd_interface_handle ifh;
591 	usbd_pipe_handle pipe;
592 	usbd_xfer_handle xfer;
593 	usbd_status status;
594 
595 	status = usbd_device2interface_handle(udev, 0, &ifh);
596 	if (status != USBD_NORMAL_COMPLETION)
597 		return EIO;
598 
599 	ed = uhso_get_endpoint(ifh, UE_BULK, UE_DIR_OUT);
600 	if (ed == NULL)
601 		return ENODEV;
602 
603 	status = usbd_open_pipe(ifh, ed->bEndpointAddress, 0, &pipe);
604 	if (status != USBD_NORMAL_COMPLETION)
605 		return EIO;
606 
607 	xfer = usbd_alloc_xfer(udev);
608 	if (xfer == NULL)
609 		return ENOMEM;
610 
611 	USETDW(cmd.dCBWSignature, CBWSIGNATURE);
612 	USETDW(cmd.dCBWTag, 1);
613 	USETDW(cmd.dCBWDataTransferLength, 0);
614 	cmd.bCBWFlags = CBWFLAGS_OUT;
615 	cmd.bCBWLUN = 0;
616 	cmd.bCDBLength = 6;
617 
618 	memset(&cmd.CBWCDB, 0, CBWCDBLENGTH);
619 	cmd.CBWCDB[0] = SCSI_REZERO_UNIT;
620 
621 	usbd_setup_xfer(xfer, pipe, NULL, &cmd, sizeof(cmd),
622 		USBD_SYNCHRONOUS, USBD_DEFAULT_TIMEOUT, NULL);
623 
624 	status = usbd_transfer(xfer);
625 
626 	usbd_abort_pipe(pipe);
627 	usbd_close_pipe(pipe);
628 	usbd_free_xfer(xfer);
629 
630 	return (status == USBD_NORMAL_COMPLETION ? 0 : EIO);
631 }
632 
633 Static int
634 uhso_get_iface_spec(struct usb_attach_arg *uaa, uint8_t ifnum, uint8_t *spec)
635 {
636 	const struct uhso_dev *hd;
637 	uint8_t config[17];
638 	usb_device_request_t req;
639 	usbd_status status;
640 
641 	hd = uhso_lookup(uaa->vendor, uaa->product);
642 	KASSERT(hd != NULL);
643 
644 	switch (hd->type) {
645 	case UHSOTYPE_DEFAULT:
646 		if (ifnum > __arraycount(uhso_spec_default))
647 			break;
648 
649 		*spec = uhso_spec_default[ifnum];
650 		return 1;
651 
652 	case UHSOTYPE_ICON321:
653 		if (ifnum > __arraycount(uhso_spec_icon321))
654 			break;
655 
656 		*spec = uhso_spec_icon321[ifnum];
657 		return 1;
658 
659 	case UHSOTYPE_CONFIG:
660 		req.bmRequestType = UT_READ_VENDOR_DEVICE;
661 		req.bRequest = 0x86;	/* "Config Info" */
662 		USETW(req.wValue, 0);
663 		USETW(req.wIndex, 0);
664 		USETW(req.wLength, sizeof(config));
665 
666 		status = usbd_do_request(uaa->device, &req, config);
667 		if (status != USBD_NORMAL_COMPLETION)
668 			break;
669 
670 		if (ifnum > __arraycount(config)
671 		    || config[ifnum] > __arraycount(uhso_spec_config))
672 			break;
673 
674 		*spec = uhso_spec_config[config[ifnum]];
675 
676 		/*
677 		 * Apparently some modems also have a CRC bug that is
678 		 * indicated by ISSET(config[16], __BIT(0)) but we dont
679 		 * handle it at this time.
680 		 */
681 		return 1;
682 
683 	default:
684 		DPRINTF(0, "unknown interface type\n");
685 		break;
686 	}
687 
688 	return 0;
689 }
690 
691 Static usb_endpoint_descriptor_t *
692 uhso_get_endpoint(usbd_interface_handle ifh, int type, int dir)
693 {
694 	usb_endpoint_descriptor_t *ed;
695 	uint8_t count, i;
696 
697 	count = 0;
698 	(void)usbd_endpoint_count(ifh, &count);
699 
700 	for (i = 0; i < count; i++) {
701 		ed = usbd_interface2endpoint_descriptor(ifh, i);
702 		if (ed != NULL
703 		    && UE_GET_XFERTYPE(ed->bmAttributes) == type
704 		    && UE_GET_DIR(ed->bEndpointAddress) == dir)
705 			return ed;
706 	}
707 
708 	return NULL;
709 }
710 
711 
712 /******************************************************************************
713  *
714  *	Multiplexed ports signal with the interrupt endpoint to indicate
715  *  when data is available for reading, and a separate request is made on
716  *  the control endpoint to read or write on each port. The offsets in the
717  *  table below relate to bit numbers in the mux mask, identifying each port.
718  */
719 
720 Static const int uhso_mux_port[] = {
721 	UHSO_PORT_CONTROL,
722 	UHSO_PORT_APP,
723 	UHSO_PORT_PCSC,
724 	UHSO_PORT_GPS,
725 	UHSO_PORT_APP2,
726 };
727 
728 Static void
729 uhso_mux_attach(struct uhso_softc *sc, usbd_interface_handle ifh, int index)
730 {
731 	usbd_desc_iter_t iter;
732 	const usb_descriptor_t *desc;
733 	usb_endpoint_descriptor_t *ed;
734 	usbd_pipe_handle pipe;
735 	struct uhso_port *hp;
736 	uint8_t *buf;
737 	size_t size;
738 	unsigned int i, mux, flags;
739 	int addr;
740 	usbd_status status;
741 
742 	ed = uhso_get_endpoint(ifh, UE_INTERRUPT, UE_DIR_IN);
743 	if (ed == NULL) {
744 		aprint_error_dev(sc->sc_dev, "no interrupt endpoint\n");
745 		return;
746 	}
747 	addr = ed->bEndpointAddress;
748 	size = UGETW(ed->wMaxPacketSize);
749 
750 	/*
751 	 * There should be an additional "Class Specific" descriptor on
752 	 * the mux interface containing a single byte with a bitmask of
753 	 * enabled ports. We need to look through the device descriptor
754 	 * to find it and the port index is found from the uhso_mux_port
755 	 * array, above.
756 	 */
757 	usb_desc_iter_init(sc->sc_udev, &iter);
758 
759 	/* skip past the current interface descriptor */
760 	iter.cur = (const uByte *)usbd_get_interface_descriptor(ifh);
761 	desc = usb_desc_iter_next(&iter);
762 
763 	for (;;) {
764 		desc = usb_desc_iter_next(&iter);
765 		if (desc == NULL
766 		    || desc->bDescriptorType == UDESC_INTERFACE) {
767 			mux = 0;
768 			break;	/* not found */
769 		}
770 
771 		if (desc->bDescriptorType == UDESC_CS_INTERFACE
772 		    && desc->bLength == 3) {
773 			mux = ((const uint8_t *)desc)[2];
774 			break;
775 		}
776 	}
777 
778 	DPRINTF(1, "addr=%d, size=%zd, mux=0x%02x\n", addr, size, mux);
779 
780 	buf = kmem_alloc(size, KM_SLEEP);
781 	status = usbd_open_pipe_intr(ifh, addr, USBD_SHORT_XFER_OK, &pipe,
782 	    sc, buf, size, uhso_mux_intr, USBD_DEFAULT_INTERVAL);
783 
784 	if (status != USBD_NORMAL_COMPLETION) {
785 		aprint_error_dev(sc->sc_dev, "failed to open interrupt pipe: %s",
786 		    usbd_errstr(status));
787 
788 		kmem_free(buf, size);
789 		return;
790 	}
791 
792 	flags = 0;
793 	for (i = 0; i < __arraycount(uhso_mux_port); i++) {
794 		if (ISSET(mux, __BIT(i))) {
795 			if (sc->sc_port[uhso_mux_port[i]] != NULL) {
796 				aprint_error_dev(sc->sc_dev,
797 				    "mux port %d is duplicate!\n", i);
798 
799 				continue;
800 			}
801 
802 			hp = kmem_zalloc(sizeof(struct uhso_port), KM_SLEEP);
803 			sc->sc_port[uhso_mux_port[i]] = hp;
804 
805 			hp->hp_sc = sc;
806 			hp->hp_index = i;
807 			hp->hp_ipipe = pipe;
808 			hp->hp_ibuf = buf;
809 			hp->hp_isize = size;
810 			hp->hp_flags = flags;
811 			hp->hp_abort = uhso_mux_abort;
812 			hp->hp_detach = uhso_mux_detach;
813 			hp->hp_init = uhso_mux_init;
814 			hp->hp_clean = uhso_mux_clean;
815 			hp->hp_write = uhso_mux_write;
816 			hp->hp_write_cb = uhso_tty_write_cb;
817 			hp->hp_read = uhso_mux_read;
818 			hp->hp_read_cb = uhso_tty_read_cb;
819 			hp->hp_control = uhso_mux_control;
820 			hp->hp_wsize = UHSO_MUX_WSIZE;
821 			hp->hp_rsize = UHSO_MUX_RSIZE;
822 
823 			uhso_tty_attach(hp);
824 
825 			aprint_normal_dev(sc->sc_dev,
826 			    "%s (port %d) attached as mux tty\n",
827 			    uhso_port_name[uhso_mux_port[i]], uhso_mux_port[i]);
828 
829 			/*
830 			 * As the pipe handle is stored in each mux, mark
831 			 * secondary references so they don't get released
832 			 */
833 			flags = UHSO_PORT_MUXPIPE;
834 		}
835 	}
836 
837 	if (flags == 0) {
838 		/* for whatever reasons, nothing was attached */
839 		usbd_abort_pipe(pipe);
840 		usbd_close_pipe(pipe);
841 		kmem_free(buf, size);
842 	}
843 }
844 
845 Static int
846 uhso_mux_abort(struct uhso_port *hp)
847 {
848 	struct uhso_softc *sc = hp->hp_sc;
849 
850 	DPRINTF(1, "hp=%p\n", hp);
851 
852 	if (!ISSET(hp->hp_flags, UHSO_PORT_MUXPIPE))
853 		usbd_abort_pipe(hp->hp_ipipe);
854 
855 	usbd_abort_default_pipe(sc->sc_udev);
856 
857 	return (*hp->hp_clean)(hp);
858 }
859 
860 Static int
861 uhso_mux_detach(struct uhso_port *hp)
862 {
863 
864 	DPRINTF(1, "hp=%p\n", hp);
865 
866 	if (!ISSET(hp->hp_flags, UHSO_PORT_MUXPIPE)) {
867 		DPRINTF(1, "interrupt pipe closed\n");
868 		usbd_abort_pipe(hp->hp_ipipe);
869 		usbd_close_pipe(hp->hp_ipipe);
870 		kmem_free(hp->hp_ibuf, hp->hp_isize);
871 	}
872 
873 	uhso_tty_detach(hp);
874 	kmem_free(hp, sizeof(struct uhso_port));
875 	return 0;
876 }
877 
878 Static int
879 uhso_mux_init(struct uhso_port *hp)
880 {
881 
882 	DPRINTF(1, "hp=%p\n", hp);
883 
884 	CLR(hp->hp_flags, UHSO_PORT_MUXBUSY | UHSO_PORT_MUXREADY);
885 	SET(hp->hp_status, TIOCM_DSR | TIOCM_CAR);
886 	return 0;
887 }
888 
889 Static int
890 uhso_mux_clean(struct uhso_port *hp)
891 {
892 
893 	DPRINTF(1, "hp=%p\n", hp);
894 
895 	CLR(hp->hp_flags, UHSO_PORT_MUXREADY);
896 	CLR(hp->hp_status, TIOCM_DTR | TIOCM_DSR | TIOCM_CAR);
897 	return 0;
898 }
899 
900 Static int
901 uhso_mux_write(struct uhso_port *hp)
902 {
903 	struct uhso_softc *sc = hp->hp_sc;
904 	usb_device_request_t req;
905 	usbd_status status;
906 
907 	DPRINTF(5, "hp=%p, index=%d, wlen=%zd\n", hp, hp->hp_index, hp->hp_wlen);
908 
909 	req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
910 	req.bRequest = UCDC_SEND_ENCAPSULATED_COMMAND;
911 	USETW(req.wValue, 0);
912 	USETW(req.wIndex, hp->hp_index);
913 	USETW(req.wLength, hp->hp_wlen);
914 
915 	usbd_setup_default_xfer(hp->hp_wxfer, sc->sc_udev, hp, USBD_NO_TIMEOUT,
916 	    &req, hp->hp_wbuf, hp->hp_wlen, USBD_NO_COPY, hp->hp_write_cb);
917 
918 	status = usbd_transfer(hp->hp_wxfer);
919 	if (status != USBD_IN_PROGRESS) {
920 		DPRINTF(0, "non-normal status %s\n", usbd_errstr(status));
921 		return EIO;
922 	}
923 
924 	sc->sc_refcnt++;
925 	return 0;
926 }
927 
928 Static int
929 uhso_mux_read(struct uhso_port *hp)
930 {
931 	struct uhso_softc *sc = hp->hp_sc;
932 	usb_device_request_t req;
933 	usbd_status status;
934 
935 	CLR(hp->hp_flags, UHSO_PORT_MUXBUSY);
936 
937 	if (hp->hp_rlen == 0 && !ISSET(hp->hp_flags, UHSO_PORT_MUXREADY))
938 		return 0;
939 
940 	SET(hp->hp_flags, UHSO_PORT_MUXBUSY);
941 	CLR(hp->hp_flags, UHSO_PORT_MUXREADY);
942 
943 	DPRINTF(5, "hp=%p, index=%d\n", hp, hp->hp_index);
944 
945 	req.bmRequestType = UT_READ_CLASS_INTERFACE;
946 	req.bRequest = UCDC_GET_ENCAPSULATED_RESPONSE;
947 	USETW(req.wValue, 0);
948 	USETW(req.wIndex, hp->hp_index);
949 	USETW(req.wLength, hp->hp_rsize);
950 
951 	usbd_setup_default_xfer(hp->hp_rxfer, sc->sc_udev, hp, USBD_NO_TIMEOUT,
952 	    &req, hp->hp_rbuf, hp->hp_rsize, USBD_NO_COPY | USBD_SHORT_XFER_OK,
953 	    hp->hp_read_cb);
954 
955 	status = usbd_transfer(hp->hp_rxfer);
956 	if (status != USBD_IN_PROGRESS) {
957 		DPRINTF(0, "non-normal status %s\n", usbd_errstr(status));
958 		CLR(hp->hp_flags, UHSO_PORT_MUXBUSY);
959 		return EIO;
960 	}
961 
962 	sc->sc_refcnt++;
963 	return 0;
964 }
965 
966 Static int
967 uhso_mux_control(struct uhso_port *hp)
968 {
969 
970 	DPRINTF(1, "hp=%p\n", hp);
971 
972 	return 0;
973 }
974 
975 Static void
976 uhso_mux_intr(usbd_xfer_handle xfer, usbd_private_handle p, usbd_status status)
977 {
978 	struct uhso_softc *sc = p;
979 	struct uhso_port *hp;
980 	uint32_t cc;
981 	uint8_t *buf;
982 	unsigned int i;
983 
984 	if (status != USBD_NORMAL_COMPLETION) {
985 		DPRINTF(0, "non-normal status %s\n", usbd_errstr(status));
986 		return;
987 	}
988 
989 	usbd_get_xfer_status(xfer, NULL, (void **)&buf, &cc, NULL);
990 	if (cc == 0)
991 		return;
992 
993 	DPRINTF(5, "mux mask 0x%02x, cc=%u\n", buf[0], cc);
994 
995 	for (i = 0; i < __arraycount(uhso_mux_port); i++) {
996 		if (!ISSET(buf[0], __BIT(i)))
997 			continue;
998 
999 		DPRINTF(5, "mux %d port %d\n", i, uhso_mux_port[i]);
1000 		hp = sc->sc_port[uhso_mux_port[i]];
1001 		if (hp == NULL
1002 		    || hp->hp_tp == NULL
1003 		    || !ISSET(hp->hp_status, TIOCM_DTR))
1004 			continue;
1005 
1006 		SET(hp->hp_flags, UHSO_PORT_MUXREADY);
1007 		if (ISSET(hp->hp_flags, UHSO_PORT_MUXBUSY))
1008 			continue;
1009 
1010 		uhso_mux_read(hp);
1011 	}
1012 }
1013 
1014 
1015 /******************************************************************************
1016  *
1017  *	Bulk ports operate using the bulk endpoints on an interface, though
1018  *   the Modem port (at least) may have an interrupt endpoint that will pass
1019  *   CDC Notification messages with the modem status.
1020  */
1021 
1022 Static void
1023 uhso_bulk_attach(struct uhso_softc *sc, usbd_interface_handle ifh, int index)
1024 {
1025 	usb_endpoint_descriptor_t *ed;
1026 	usb_interface_descriptor_t *id;
1027 	struct uhso_port *hp;
1028 	int in, out;
1029 
1030 	ed = uhso_get_endpoint(ifh, UE_BULK, UE_DIR_IN);
1031 	if (ed == NULL) {
1032 		aprint_error_dev(sc->sc_dev, "bulk-in endpoint not found\n");
1033 		return;
1034 	}
1035 	in = ed->bEndpointAddress;
1036 
1037 	ed = uhso_get_endpoint(ifh, UE_BULK, UE_DIR_OUT);
1038 	if (ed == NULL) {
1039 		aprint_error_dev(sc->sc_dev, "bulk-out endpoint not found\n");
1040 		return;
1041 	}
1042 	out = ed->bEndpointAddress;
1043 
1044 	id = usbd_get_interface_descriptor(ifh);
1045 	if (id == NULL) {
1046 		aprint_error_dev(sc->sc_dev, "interface descriptor not found\n");
1047 		return;
1048 	}
1049 
1050 	DPRINTF(1, "bulk endpoints in=%x, out=%x\n", in, out);
1051 
1052 	if (sc->sc_port[index] != NULL) {
1053 		aprint_error_dev(sc->sc_dev, "bulk port %d is duplicate!\n",
1054 		    index);
1055 
1056 		return;
1057 	}
1058 
1059 	hp = kmem_zalloc(sizeof(struct uhso_port), KM_SLEEP);
1060 	sc->sc_port[index] = hp;
1061 
1062 	hp->hp_sc = sc;
1063 	hp->hp_ifh = ifh;
1064 	hp->hp_index = id->bInterfaceNumber;
1065 	hp->hp_raddr = in;
1066 	hp->hp_waddr = out;
1067 	hp->hp_abort = uhso_bulk_abort;
1068 	hp->hp_detach = uhso_bulk_detach;
1069 	hp->hp_init = uhso_bulk_init;
1070 	hp->hp_clean = uhso_bulk_clean;
1071 	hp->hp_write = uhso_bulk_write;
1072 	hp->hp_write_cb = uhso_tty_write_cb;
1073 	hp->hp_read = uhso_bulk_read;
1074 	hp->hp_read_cb = uhso_tty_read_cb;
1075 	hp->hp_control = uhso_bulk_control;
1076 	hp->hp_wsize = UHSO_BULK_WSIZE;
1077 	hp->hp_rsize = UHSO_BULK_RSIZE;
1078 
1079 	if (index == UHSO_PORT_MODEM) {
1080 		ed = uhso_get_endpoint(ifh, UE_INTERRUPT, UE_DIR_IN);
1081 		if (ed != NULL) {
1082 			hp->hp_iaddr = ed->bEndpointAddress;
1083 			hp->hp_isize = UGETW(ed->wMaxPacketSize);
1084 		}
1085 	}
1086 
1087 	uhso_tty_attach(hp);
1088 
1089 	aprint_normal_dev(sc->sc_dev,
1090 	    "%s (port %d) attached as bulk tty\n",
1091 	    uhso_port_name[index], index);
1092 }
1093 
1094 Static int
1095 uhso_bulk_abort(struct uhso_port *hp)
1096 {
1097 
1098 	DPRINTF(1, "hp=%p\n", hp);
1099 
1100 	return (*hp->hp_clean)(hp);
1101 }
1102 
1103 Static int
1104 uhso_bulk_detach(struct uhso_port *hp)
1105 {
1106 
1107 	DPRINTF(1, "hp=%p\n", hp);
1108 
1109 	uhso_tty_detach(hp);
1110 	kmem_free(hp, sizeof(struct uhso_port));
1111 	return 0;
1112 }
1113 
1114 Static int
1115 uhso_bulk_init(struct uhso_port *hp)
1116 {
1117 	usbd_status status;
1118 
1119 	DPRINTF(1, "hp=%p\n", hp);
1120 
1121 	if (hp->hp_isize > 0) {
1122 		hp->hp_ibuf = kmem_alloc(hp->hp_isize, KM_SLEEP);
1123 
1124 		status = usbd_open_pipe_intr(hp->hp_ifh, hp->hp_iaddr,
1125 		    USBD_SHORT_XFER_OK, &hp->hp_ipipe, hp, hp->hp_ibuf,
1126 		    hp->hp_isize, uhso_bulk_intr, USBD_DEFAULT_INTERVAL);
1127 
1128 		if (status != USBD_NORMAL_COMPLETION) {
1129 			DPRINTF(0, "interrupt pipe open failed: %s\n",
1130 			    usbd_errstr(status));
1131 
1132 			return EIO;
1133 		}
1134 	}
1135 
1136 	status = usbd_open_pipe(hp->hp_ifh, hp->hp_raddr, 0, &hp->hp_rpipe);
1137 	if (status != USBD_NORMAL_COMPLETION) {
1138 		DPRINTF(0, "read pipe open failed: %s\n", usbd_errstr(status));
1139 		return EIO;
1140 	}
1141 
1142 	status = usbd_open_pipe(hp->hp_ifh, hp->hp_waddr, 0, &hp->hp_wpipe);
1143 	if (status != USBD_NORMAL_COMPLETION) {
1144 		DPRINTF(0, "write pipe open failed: %s\n", usbd_errstr(status));
1145 		return EIO;
1146 	}
1147 
1148 	return 0;
1149 }
1150 
1151 Static int
1152 uhso_bulk_clean(struct uhso_port *hp)
1153 {
1154 
1155 	DPRINTF(1, "hp=%p\n", hp);
1156 
1157 	if (hp->hp_ipipe != NULL) {
1158 		usbd_abort_pipe(hp->hp_ipipe);
1159 		usbd_close_pipe(hp->hp_ipipe);
1160 		hp->hp_ipipe = NULL;
1161 	}
1162 
1163 	if (hp->hp_ibuf != NULL) {
1164 		kmem_free(hp->hp_ibuf, hp->hp_isize);
1165 		hp->hp_ibuf = NULL;
1166 	}
1167 
1168 	if (hp->hp_rpipe != NULL) {
1169 		usbd_abort_pipe(hp->hp_rpipe);
1170 		usbd_close_pipe(hp->hp_rpipe);
1171 		hp->hp_rpipe = NULL;
1172 	}
1173 
1174 	if (hp->hp_wpipe != NULL) {
1175 		usbd_abort_pipe(hp->hp_wpipe);
1176 		usbd_close_pipe(hp->hp_wpipe);
1177 		hp->hp_wpipe = NULL;
1178 	}
1179 
1180 	return 0;
1181 }
1182 
1183 Static int
1184 uhso_bulk_write(struct uhso_port *hp)
1185 {
1186 	struct uhso_softc *sc = hp->hp_sc;
1187 	usbd_status status;
1188 
1189 	DPRINTF(5, "hp=%p, wlen=%zd\n", hp, hp->hp_wlen);
1190 
1191 	usbd_setup_xfer(hp->hp_wxfer, hp->hp_wpipe, hp, hp->hp_wbuf,
1192 	    hp->hp_wlen, USBD_NO_COPY, USBD_NO_TIMEOUT, hp->hp_write_cb);
1193 
1194 	status = usbd_transfer(hp->hp_wxfer);
1195 	if (status != USBD_IN_PROGRESS) {
1196 		DPRINTF(0, "non-normal status %s\n", usbd_errstr(status));
1197 		return EIO;
1198 	}
1199 
1200 	sc->sc_refcnt++;
1201 	return 0;
1202 }
1203 
1204 Static int
1205 uhso_bulk_read(struct uhso_port *hp)
1206 {
1207 	struct uhso_softc *sc = hp->hp_sc;
1208 	usbd_status status;
1209 
1210 	DPRINTF(5, "hp=%p\n", hp);
1211 
1212 	usbd_setup_xfer(hp->hp_rxfer, hp->hp_rpipe, hp, hp->hp_rbuf,
1213 	    hp->hp_rsize, USBD_NO_COPY | USBD_SHORT_XFER_OK,
1214 	    USBD_NO_TIMEOUT, hp->hp_read_cb);
1215 
1216 	status = usbd_transfer(hp->hp_rxfer);
1217 	if (status != USBD_IN_PROGRESS) {
1218 		DPRINTF(0, "non-normal status %s\n", usbd_errstr(status));
1219 		return EIO;
1220 	}
1221 
1222 	sc->sc_refcnt++;
1223 	return 0;
1224 }
1225 
1226 Static int
1227 uhso_bulk_control(struct uhso_port *hp)
1228 {
1229 	struct uhso_softc *sc = hp->hp_sc;
1230 	usb_device_request_t req;
1231 	usbd_status status;
1232 	int val;
1233 
1234 	DPRINTF(1, "hp=%p\n", hp);
1235 
1236 	if (hp->hp_isize == 0)
1237 		return 0;
1238 
1239 	val = 0;
1240 	if (ISSET(hp->hp_status, TIOCM_DTR))
1241 		SET(val, UCDC_LINE_DTR);
1242 	if (ISSET(hp->hp_status, TIOCM_RTS))
1243 		SET(val, UCDC_LINE_RTS);
1244 
1245 	req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
1246 	req.bRequest = UCDC_SET_CONTROL_LINE_STATE;
1247 	USETW(req.wValue, val);
1248 	USETW(req.wIndex, hp->hp_index);
1249 	USETW(req.wLength, 0);
1250 
1251 	sc->sc_refcnt++;
1252 
1253 	status = usbd_do_request(sc->sc_udev, &req, NULL);
1254 
1255 	if (--sc->sc_refcnt < 0)
1256 		usb_detach_wakeupold(sc->sc_dev);
1257 
1258 	if (status != USBD_NORMAL_COMPLETION) {
1259 		DPRINTF(0, "non-normal status %s\n", usbd_errstr(status));
1260 		return EIO;
1261 	}
1262 
1263 	return 0;
1264 }
1265 
1266 Static void
1267 uhso_bulk_intr(usbd_xfer_handle xfer, usbd_private_handle p, usbd_status status)
1268 {
1269 	struct uhso_port *hp = p;
1270 	struct tty *tp = hp->hp_tp;
1271 	usb_cdc_notification_t *msg;
1272 	uint32_t cc;
1273 	int s, old;
1274 
1275 	if (status != USBD_NORMAL_COMPLETION) {
1276 		DPRINTF(0, "non-normal status %s\n", usbd_errstr(status));
1277 		return;
1278 	}
1279 
1280 	usbd_get_xfer_status(xfer, NULL, (void **)&msg, &cc, NULL);
1281 
1282 	if (cc < UCDC_NOTIFICATION_LENGTH
1283 	    || msg->bmRequestType != UCDC_NOTIFICATION
1284 	    || msg->bNotification != UCDC_N_SERIAL_STATE
1285 	    || UGETW(msg->wValue) != 0
1286 	    || UGETW(msg->wIndex) != hp->hp_index
1287 	    || UGETW(msg->wLength) < 1)
1288 		return;
1289 
1290 	DPRINTF(5, "state=%02x\n", msg->data[0]);
1291 
1292 	old = hp->hp_status;
1293 	CLR(hp->hp_status, TIOCM_RNG | TIOCM_DSR | TIOCM_CAR);
1294 	if (ISSET(msg->data[0], UCDC_N_SERIAL_RI))
1295 		SET(hp->hp_status, TIOCM_RNG);
1296 	if (ISSET(msg->data[0], UCDC_N_SERIAL_DSR))
1297 		SET(hp->hp_status, TIOCM_DSR);
1298 	if (ISSET(msg->data[0], UCDC_N_SERIAL_DCD))
1299 		SET(hp->hp_status, TIOCM_CAR);
1300 
1301 	if (ISSET(hp->hp_status ^ old, TIOCM_CAR)) {
1302 		s = spltty();
1303 		tp->t_linesw->l_modem(tp, ISSET(hp->hp_status, TIOCM_CAR));
1304 		splx(s);
1305 	}
1306 
1307 	if (ISSET((hp->hp_status ^ old), TIOCM_RNG | TIOCM_DSR | TIOCM_CAR))
1308 		DPRINTF(1, "RNG %s, DSR %s, DCD %s\n",
1309 		    (ISSET(hp->hp_status, TIOCM_RNG) ? "on" : "off"),
1310 		    (ISSET(hp->hp_status, TIOCM_DSR) ? "on" : "off"),
1311 		    (ISSET(hp->hp_status, TIOCM_CAR) ? "on" : "off"));
1312 }
1313 
1314 
1315 /******************************************************************************
1316  *
1317  *	TTY management
1318  *
1319  */
1320 
1321 Static void
1322 uhso_tty_attach(struct uhso_port *hp)
1323 {
1324 	struct tty *tp;
1325 
1326 	tp = tty_alloc();
1327 	tp->t_oproc = uhso_tty_start;
1328 	tp->t_param = uhso_tty_param;
1329 
1330 	hp->hp_tp = tp;
1331 	tty_attach(tp);
1332 
1333 	DPRINTF(1, "hp=%p, tp=%p\n", hp, tp);
1334 }
1335 
1336 Static void
1337 uhso_tty_detach(struct uhso_port *hp)
1338 {
1339 
1340 	DPRINTF(1, "hp=%p\n", hp);
1341 
1342 	uhso_tty_clean(hp);
1343 
1344 	tty_detach(hp->hp_tp);
1345 	tty_free(hp->hp_tp);
1346 	hp->hp_tp = NULL;
1347 }
1348 
1349 Static void
1350 uhso_tty_write_cb(usbd_xfer_handle xfer, usbd_private_handle p, usbd_status status)
1351 {
1352 	struct uhso_port *hp = p;
1353 	struct uhso_softc *sc = hp->hp_sc;
1354 	struct tty *tp = hp->hp_tp;
1355 	uint32_t cc;
1356 	int s;
1357 
1358 	if (--sc->sc_refcnt < 0)
1359 		usb_detach_wakeupold(sc->sc_dev);
1360 
1361 	if (status != USBD_NORMAL_COMPLETION) {
1362 		DPRINTF(0, "non-normal status %s\n", usbd_errstr(status));
1363 
1364 		if (status == USBD_STALLED && hp->hp_wpipe != NULL)
1365 			usbd_clear_endpoint_stall_async(hp->hp_wpipe);
1366 		else
1367 			return;
1368 	} else {
1369 		usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL);
1370 
1371 		DPRINTF(5, "wrote %d bytes (of %zd)\n", cc, hp->hp_wlen);
1372 		if (cc != hp->hp_wlen)
1373 			DPRINTF(0, "cc=%u, wlen=%zd\n", cc, hp->hp_wlen);
1374 	}
1375 
1376 	s = spltty();
1377 	CLR(tp->t_state, TS_BUSY);
1378 	tp->t_linesw->l_start(tp);
1379 	splx(s);
1380 }
1381 
1382 Static void
1383 uhso_tty_read_cb(usbd_xfer_handle xfer, usbd_private_handle p, usbd_status status)
1384 {
1385 	struct uhso_port *hp = p;
1386 	struct uhso_softc *sc = hp->hp_sc;
1387 	struct tty *tp = hp->hp_tp;
1388 	uint8_t *cp;
1389 	uint32_t cc;
1390 	int s;
1391 
1392 	if (--sc->sc_refcnt < 0)
1393 		usb_detach_wakeupold(sc->sc_dev);
1394 
1395 	if (status != USBD_NORMAL_COMPLETION) {
1396 		DPRINTF(0, "non-normal status: %s\n", usbd_errstr(status));
1397 
1398 		if (status == USBD_STALLED && hp->hp_rpipe != NULL)
1399 			usbd_clear_endpoint_stall_async(hp->hp_rpipe);
1400 		else
1401 			return;
1402 
1403 		hp->hp_rlen = 0;
1404 	} else {
1405 		usbd_get_xfer_status(xfer, NULL, (void **)&cp, &cc, NULL);
1406 
1407 		hp->hp_rlen = cc;
1408 		DPRINTF(5, "read %d bytes\n", cc);
1409 
1410 		s = spltty();
1411 		while (cc > 0) {
1412 			if (tp->t_linesw->l_rint(*cp++, tp) == -1) {
1413 				DPRINTF(0, "lost %d bytes\n", cc);
1414 				break;
1415 			}
1416 
1417 			cc--;
1418 		}
1419 		splx(s);
1420 	}
1421 
1422 	(*hp->hp_read)(hp);
1423 }
1424 
1425 
1426 /******************************************************************************
1427  *
1428  *	TTY subsystem
1429  *
1430  */
1431 
1432 int
1433 uhso_tty_open(dev_t dev, int flag, int mode, struct lwp *l)
1434 {
1435 	struct uhso_softc *sc;
1436 	struct uhso_port *hp;
1437 	struct tty *tp;
1438 	int error, s;
1439 
1440 	DPRINTF(1, "unit %d port %d\n", UHSOUNIT(dev), UHSOPORT(dev));
1441 
1442 	sc = device_lookup_private(&uhso_cd, UHSOUNIT(dev));
1443 	if (sc == NULL
1444 	    || !device_is_active(sc->sc_dev)
1445 	    || UHSOPORT(dev) >= UHSO_PORT_MAX)
1446 		return ENXIO;
1447 
1448 	hp = sc->sc_port[UHSOPORT(dev)];
1449 	if (hp == NULL || hp->hp_tp == NULL)
1450 		return ENXIO;
1451 
1452 	tp = hp->hp_tp;
1453 	if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp))
1454 		return EBUSY;
1455 
1456 	error = 0;
1457 	s = spltty();
1458 	if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
1459 		tp->t_dev = dev;
1460 		error = uhso_tty_init(hp);
1461 	}
1462 	splx(s);
1463 
1464 	if (error == 0) {
1465 		error = ttyopen(tp, UHSODIALOUT(dev), ISSET(flag, O_NONBLOCK));
1466 		if (error == 0) {
1467 			error = tp->t_linesw->l_open(dev, tp);
1468 		}
1469 	}
1470 
1471 	if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0)
1472 		uhso_tty_clean(hp);
1473 
1474 	DPRINTF(1, "sc=%p, hp=%p, tp=%p, error=%d\n", sc, hp, tp, error);
1475 
1476 	return error;
1477 }
1478 
1479 Static int
1480 uhso_tty_init(struct uhso_port *hp)
1481 {
1482 	struct uhso_softc *sc = hp->hp_sc;
1483 	struct tty *tp = hp->hp_tp;
1484 	struct termios t;
1485 	int error;
1486 
1487 	DPRINTF(1, "sc=%p, hp=%p, tp=%p\n", sc, hp, tp);
1488 
1489 	/*
1490 	 * Initialize the termios status to the defaults.  Add in the
1491 	 * sticky bits from TIOCSFLAGS.
1492 	 */
1493 	t.c_ispeed = 0;
1494 	t.c_ospeed = TTYDEF_SPEED;
1495 	t.c_cflag = TTYDEF_CFLAG;
1496 	if (ISSET(hp->hp_swflags, TIOCFLAG_CLOCAL))
1497 		SET(t.c_cflag, CLOCAL);
1498 	if (ISSET(hp->hp_swflags, TIOCFLAG_CRTSCTS))
1499 		SET(t.c_cflag, CRTSCTS);
1500 	if (ISSET(hp->hp_swflags, TIOCFLAG_MDMBUF))
1501 		SET(t.c_cflag, MDMBUF);
1502 
1503 	/* Ensure uhso_tty_param() will do something. */
1504 	tp->t_ospeed = 0;
1505 	(void)uhso_tty_param(tp, &t);
1506 
1507 	tp->t_iflag = TTYDEF_IFLAG;
1508 	tp->t_oflag = TTYDEF_OFLAG;
1509 	tp->t_lflag = TTYDEF_LFLAG;
1510 	ttychars(tp);
1511 	ttsetwater(tp);
1512 
1513 	hp->hp_status = 0;
1514 	error = (*hp->hp_init)(hp);
1515 	if (error != 0)
1516 		return error;
1517 
1518 	hp->hp_rxfer = usbd_alloc_xfer(sc->sc_udev);
1519 	if (hp->hp_rxfer == NULL)
1520 		return ENOMEM;
1521 
1522 	hp->hp_rbuf = usbd_alloc_buffer(hp->hp_rxfer, hp->hp_rsize);
1523 	if (hp->hp_rbuf == NULL)
1524 		return ENOMEM;
1525 
1526 	hp->hp_wxfer = usbd_alloc_xfer(sc->sc_udev);
1527 	if (hp->hp_wxfer == NULL)
1528 		return ENOMEM;
1529 
1530 	hp->hp_wbuf = usbd_alloc_buffer(hp->hp_wxfer, hp->hp_wsize);
1531 	if (hp->hp_wbuf == NULL)
1532 		return ENOMEM;
1533 
1534 	/*
1535 	 * Turn on DTR.  We must always do this, even if carrier is not
1536 	 * present, because otherwise we'd have to use TIOCSDTR
1537 	 * immediately after setting CLOCAL, which applications do not
1538 	 * expect.  We always assert DTR while the port is open
1539 	 * unless explicitly requested to deassert it.  Ditto RTS.
1540 	 */
1541 	uhso_tty_control(hp, TIOCMBIS, TIOCM_DTR | TIOCM_RTS);
1542 
1543 	/* and start reading */
1544 	error = (*hp->hp_read)(hp);
1545 	if (error != 0)
1546 		return error;
1547 
1548 	return 0;
1549 }
1550 
1551 int
1552 uhso_tty_close(dev_t dev, int flag, int mode, struct lwp *l)
1553 {
1554 	struct uhso_softc *sc = device_lookup_private(&uhso_cd, UHSOUNIT(dev));
1555 	struct uhso_port *hp = sc->sc_port[UHSOPORT(dev)];
1556 	struct tty *tp = hp->hp_tp;
1557 
1558 	if (!ISSET(tp->t_state, TS_ISOPEN))
1559 		return 0;
1560 
1561 	DPRINTF(1, "sc=%p, hp=%p, tp=%p\n", sc, hp, tp);
1562 
1563 	sc->sc_refcnt++;
1564 
1565 	tp->t_linesw->l_close(tp, flag);
1566 	ttyclose(tp);
1567 
1568 	if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0)
1569 		uhso_tty_clean(hp);
1570 
1571 	if (--sc->sc_refcnt < 0)
1572 		usb_detach_wakeupold(sc->sc_dev);
1573 
1574 	return 0;
1575 }
1576 
1577 Static void
1578 uhso_tty_clean(struct uhso_port *hp)
1579 {
1580 
1581 	DPRINTF(1, "hp=%p\n", hp);
1582 
1583 	if (ISSET(hp->hp_status, TIOCM_DTR)
1584 	    && ISSET(hp->hp_tp->t_cflag, HUPCL))
1585 		uhso_tty_control(hp, TIOCMBIC, TIOCM_DTR);
1586 
1587 	(*hp->hp_clean)(hp);
1588 
1589 	if (hp->hp_rxfer != NULL) {
1590 		usbd_free_xfer(hp->hp_rxfer);
1591 		hp->hp_rxfer = NULL;
1592 		hp->hp_rbuf = NULL;
1593 	}
1594 
1595 	if (hp->hp_wxfer != NULL) {
1596 		usbd_free_xfer(hp->hp_wxfer);
1597 		hp->hp_wxfer = NULL;
1598 		hp->hp_wbuf = NULL;
1599 	}
1600 }
1601 
1602 int
1603 uhso_tty_read(dev_t dev, struct uio *uio, int flag)
1604 {
1605 	struct uhso_softc *sc = device_lookup_private(&uhso_cd, UHSOUNIT(dev));
1606 	struct uhso_port *hp = sc->sc_port[UHSOPORT(dev)];
1607 	struct tty *tp = hp->hp_tp;
1608 	int error;
1609 
1610 	if (!device_is_active(sc->sc_dev))
1611 		return EIO;
1612 
1613 	DPRINTF(5, "sc=%p, hp=%p, tp=%p\n", sc, hp, tp);
1614 
1615 	sc->sc_refcnt++;
1616 
1617 	error = tp->t_linesw->l_read(tp, uio, flag);
1618 
1619 	if (--sc->sc_refcnt < 0)
1620 		usb_detach_wakeupold(sc->sc_dev);
1621 
1622 	return error;
1623 }
1624 
1625 int
1626 uhso_tty_write(dev_t dev, struct uio *uio, int flag)
1627 {
1628 	struct uhso_softc *sc = device_lookup_private(&uhso_cd, UHSOUNIT(dev));
1629 	struct uhso_port *hp = sc->sc_port[UHSOPORT(dev)];
1630 	struct tty *tp = hp->hp_tp;
1631 	int error;
1632 
1633 	if (!device_is_active(sc->sc_dev))
1634 		return EIO;
1635 
1636 	DPRINTF(5, "sc=%p, hp=%p, tp=%p\n", sc, hp, tp);
1637 
1638 	sc->sc_refcnt++;
1639 
1640 	error = tp->t_linesw->l_write(tp, uio, flag);
1641 
1642 	if (--sc->sc_refcnt < 0)
1643 		usb_detach_wakeupold(sc->sc_dev);
1644 
1645 	return error;
1646 }
1647 
1648 int
1649 uhso_tty_ioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
1650 {
1651 	struct uhso_softc *sc = device_lookup_private(&uhso_cd, UHSOUNIT(dev));
1652 	struct uhso_port *hp = sc->sc_port[UHSOPORT(dev)];
1653 	int error;
1654 
1655 	if (!device_is_active(sc->sc_dev))
1656 		return EIO;
1657 
1658 	DPRINTF(1, "sc=%p, hp=%p\n", sc, hp);
1659 
1660 	sc->sc_refcnt++;
1661 
1662 	error = uhso_tty_do_ioctl(hp, cmd, data, flag, l);
1663 
1664 	if (--sc->sc_refcnt < 0)
1665 		usb_detach_wakeupold(sc->sc_dev);
1666 
1667 	return error;
1668 }
1669 
1670 Static int
1671 uhso_tty_do_ioctl(struct uhso_port *hp, u_long cmd, void *data, int flag,
1672     struct lwp *l)
1673 {
1674 	struct tty *tp = hp->hp_tp;
1675 	int error, s;
1676 
1677 	error = tp->t_linesw->l_ioctl(tp, cmd, data, flag, l);
1678 	if (error != EPASSTHROUGH)
1679 		return error;
1680 
1681 	error = ttioctl(tp, cmd, data, flag, l);
1682 	if (error != EPASSTHROUGH)
1683 		return error;
1684 
1685 	error = 0;
1686 
1687 	s = spltty();
1688 
1689 	switch (cmd) {
1690 	case TIOCSDTR:
1691 		error = uhso_tty_control(hp, TIOCMBIS, TIOCM_DTR);
1692 		break;
1693 
1694 	case TIOCCDTR:
1695 		error = uhso_tty_control(hp, TIOCMBIC, TIOCM_DTR);
1696 		break;
1697 
1698 	case TIOCGFLAGS:
1699 		*(int *)data = hp->hp_swflags;
1700 		break;
1701 
1702 	case TIOCSFLAGS:
1703 		error = kauth_authorize_device_tty(l->l_cred,
1704 		    KAUTH_DEVICE_TTY_PRIVSET, tp);
1705 
1706 		if (error)
1707 			break;
1708 
1709 		hp->hp_swflags = *(int *)data;
1710 		break;
1711 
1712 	case TIOCMSET:
1713 	case TIOCMBIS:
1714 	case TIOCMBIC:
1715 		error = uhso_tty_control(hp, cmd, *(int *)data);
1716 		break;
1717 
1718 	case TIOCMGET:
1719 		*(int *)data = hp->hp_status;
1720 		break;
1721 
1722 	default:
1723 		error = EPASSTHROUGH;
1724 		break;
1725 	}
1726 
1727 	splx(s);
1728 
1729 	return error;
1730 }
1731 
1732 /* this is called with tty_lock held */
1733 void
1734 uhso_tty_stop(struct tty *tp, int flag)
1735 {
1736 #if 0
1737 	struct uhso_softc *sc = device_lookup_private(&uhso_cd, UHSOUNIT(tp->t_dev));
1738 	struct uhso_port *hp = sc->sc_port[UHSOPORT(tp->t_dev)];
1739 #endif
1740 }
1741 
1742 struct tty *
1743 uhso_tty_tty(dev_t dev)
1744 {
1745 	struct uhso_softc *sc = device_lookup_private(&uhso_cd, UHSOUNIT(dev));
1746 	struct uhso_port *hp = sc->sc_port[UHSOPORT(dev)];
1747 
1748 	return hp->hp_tp;
1749 }
1750 
1751 int
1752 uhso_tty_poll(dev_t dev, int events, struct lwp *l)
1753 {
1754 	struct uhso_softc *sc = device_lookup_private(&uhso_cd, UHSOUNIT(dev));
1755 	struct uhso_port *hp = sc->sc_port[UHSOPORT(dev)];
1756 	struct tty *tp = hp->hp_tp;
1757         int revents;
1758 
1759 	if (!device_is_active(sc->sc_dev))
1760                 return POLLHUP;
1761 
1762 	sc->sc_refcnt++;
1763 
1764         revents = tp->t_linesw->l_poll(tp, events, l);
1765 
1766 	if (--sc->sc_refcnt < 0)
1767 		usb_detach_wakeupold(sc->sc_dev);
1768 
1769         return revents;
1770 }
1771 
1772 Static int
1773 uhso_tty_param(struct tty *tp, struct termios *t)
1774 {
1775 	struct uhso_softc *sc = device_lookup_private(&uhso_cd, UHSOUNIT(tp->t_dev));
1776 	struct uhso_port *hp = sc->sc_port[UHSOPORT(tp->t_dev)];
1777 
1778 	if (!device_is_active(sc->sc_dev))
1779 		return EIO;
1780 
1781 	DPRINTF(1, "hp=%p, tp=%p, termios iflag=%x, oflag=%x, cflag=%x\n",
1782 	    hp, tp, t->c_iflag, t->c_oflag, t->c_cflag);
1783 
1784 	/* Check requested parameters. */
1785 	if (t->c_ispeed != 0
1786 	    && t->c_ispeed != t->c_ospeed)
1787 		return EINVAL;
1788 
1789 	/* force CLOCAL and !HUPCL for console */
1790 	if (ISSET(hp->hp_swflags, TIOCFLAG_SOFTCAR)) {
1791 		SET(t->c_cflag, CLOCAL);
1792 		CLR(t->c_cflag, HUPCL);
1793 	}
1794 
1795 	/* If there were no changes, don't do anything.  */
1796 	if (tp->t_ospeed == t->c_ospeed
1797 	    && tp->t_cflag == t->c_cflag)
1798 		return 0;
1799 
1800 	tp->t_ispeed = 0;
1801 	tp->t_ospeed = t->c_ospeed;
1802 	tp->t_cflag = t->c_cflag;
1803 
1804 	/* update tty layers idea of carrier bit */
1805 	tp->t_linesw->l_modem(tp, ISSET(hp->hp_status, TIOCM_CAR));
1806 	return 0;
1807 }
1808 
1809 /* this is called with tty_lock held */
1810 Static void
1811 uhso_tty_start(struct tty *tp)
1812 {
1813 	struct uhso_softc *sc = device_lookup_private(&uhso_cd, UHSOUNIT(tp->t_dev));
1814 	struct uhso_port *hp = sc->sc_port[UHSOPORT(tp->t_dev)];
1815 	int s;
1816 
1817 	if (!device_is_active(sc->sc_dev))
1818 		return;
1819 
1820 	s = spltty();
1821 
1822 	if (!ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)
1823 	    && ttypull(tp) != 0) {
1824 		hp->hp_wlen = q_to_b(&tp->t_outq, hp->hp_wbuf, hp->hp_wsize);
1825 		if (hp->hp_wlen > 0) {
1826 			SET(tp->t_state, TS_BUSY);
1827 			(*hp->hp_write)(hp);
1828 		}
1829 	}
1830 
1831 	splx(s);
1832 }
1833 
1834 Static int
1835 uhso_tty_control(struct uhso_port *hp, u_long cmd, int bits)
1836 {
1837 
1838 	bits &= (TIOCM_DTR | TIOCM_RTS);
1839 	DPRINTF(1, "cmd %s, DTR=%d, RTS=%d\n",
1840 	    (cmd == TIOCMBIC ? "BIC" : (cmd == TIOCMBIS ? "BIS" : "SET")),
1841 	    (bits & TIOCM_DTR) ? 1 : 0,
1842 	    (bits & TIOCM_RTS) ? 1 : 0);
1843 
1844 	switch (cmd) {
1845 	case TIOCMBIC:
1846 		CLR(hp->hp_status, bits);
1847 		break;
1848 
1849 	case TIOCMBIS:
1850 		SET(hp->hp_status, bits);
1851 		break;
1852 
1853 	case TIOCMSET:
1854 		CLR(hp->hp_status, TIOCM_DTR | TIOCM_RTS);
1855 		SET(hp->hp_status, bits);
1856 		break;
1857 	}
1858 
1859 	return (*hp->hp_control)(hp);
1860 }
1861 
1862 
1863 /******************************************************************************
1864  *
1865  *	Network Interface
1866  *
1867  */
1868 
1869 Static void
1870 uhso_ifnet_attach(struct uhso_softc *sc, usbd_interface_handle ifh, int index)
1871 {
1872 	usb_endpoint_descriptor_t *ed;
1873 	struct uhso_port *hp;
1874 	struct ifnet *ifp;
1875 	int in, out;
1876 
1877 	ed = uhso_get_endpoint(ifh, UE_BULK, UE_DIR_IN);
1878 	if (ed == NULL) {
1879 		aprint_error_dev(sc->sc_dev,
1880 		    "could not find bulk-in endpoint\n");
1881 
1882 		return;
1883 	}
1884 	in = ed->bEndpointAddress;
1885 
1886 	ed = uhso_get_endpoint(ifh, UE_BULK, UE_DIR_OUT);
1887 	if (ed == NULL) {
1888 		aprint_error_dev(sc->sc_dev,
1889 		    "could not find bulk-out endpoint\n");
1890 
1891 		return;
1892 	}
1893 	out = ed->bEndpointAddress;
1894 
1895 	DPRINTF(1, "in=%d, out=%d\n", in, out);
1896 
1897 	if (sc->sc_port[index] != NULL) {
1898 		aprint_error_dev(sc->sc_dev,
1899 		    "ifnet port %d is duplicate!\n", index);
1900 
1901 		return;
1902 	}
1903 
1904 	hp = kmem_zalloc(sizeof(struct uhso_port), KM_SLEEP);
1905 	sc->sc_port[index] = hp;
1906 
1907 	ifp = if_alloc(IFT_IP);
1908 	strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);
1909 	ifp->if_softc = hp;
1910 	ifp->if_mtu = UHSO_IFNET_MTU;
1911 	ifp->if_dlt = DLT_RAW;
1912 	ifp->if_type = IFT_IP;
1913 	ifp->if_flags = IFF_NOARP | IFF_SIMPLEX;
1914 	ifp->if_ioctl = uhso_ifnet_ioctl;
1915 	ifp->if_start = uhso_ifnet_start;
1916 	ifp->if_output = uhso_ifnet_output;
1917 	IFQ_SET_READY(&ifp->if_snd);
1918 
1919 	hp->hp_sc = sc;
1920 	hp->hp_ifp = ifp;
1921 	hp->hp_ifh = ifh;
1922 	hp->hp_raddr = in;
1923 	hp->hp_waddr = out;
1924 	hp->hp_abort = uhso_ifnet_abort;
1925 	hp->hp_detach = uhso_ifnet_detach;
1926 	hp->hp_init = uhso_bulk_init;
1927 	hp->hp_clean = uhso_bulk_clean;
1928 	hp->hp_write = uhso_bulk_write;
1929 	hp->hp_write_cb = uhso_ifnet_write_cb;
1930 	hp->hp_read = uhso_bulk_read;
1931 	hp->hp_read_cb = uhso_ifnet_read_cb;
1932 	hp->hp_wsize = MCLBYTES;
1933 	hp->hp_rsize = MCLBYTES;
1934 
1935 	if_attach(ifp);
1936 	if_alloc_sadl(ifp);
1937 	bpf_attach(ifp, DLT_RAW, 0);
1938 
1939 	aprint_normal_dev(sc->sc_dev, "%s (port %d) attached as ifnet\n",
1940 	    uhso_port_name[index], index);
1941 }
1942 
1943 Static int
1944 uhso_ifnet_abort(struct uhso_port *hp)
1945 {
1946 	struct ifnet *ifp = hp->hp_ifp;
1947 
1948 	/* All ifnet IO will abort when IFF_RUNNING is not set */
1949 	CLR(ifp->if_flags, IFF_RUNNING);
1950 
1951 	return (*hp->hp_clean)(hp);
1952 }
1953 
1954 Static int
1955 uhso_ifnet_detach(struct uhso_port *hp)
1956 {
1957 	struct ifnet *ifp = hp->hp_ifp;
1958 	int s;
1959 
1960 	s = splnet();
1961 	bpf_detach(ifp);
1962 	if_detach(ifp);
1963 	splx(s);
1964 
1965 	kmem_free(hp, sizeof(struct uhso_port));
1966 	return 0;
1967 }
1968 
1969 Static void
1970 uhso_ifnet_write_cb(usbd_xfer_handle xfer, usbd_private_handle p, usbd_status status)
1971 {
1972 	struct uhso_port *hp = p;
1973 	struct uhso_softc *sc= hp->hp_sc;
1974 	struct ifnet *ifp = hp->hp_ifp;
1975 	uint32_t cc;
1976 	int s;
1977 
1978 	if (--sc->sc_refcnt < 0)
1979 		usb_detach_wakeupold(sc->sc_dev);
1980 
1981 	if (!ISSET(ifp->if_flags, IFF_RUNNING))
1982 		return;
1983 
1984 	if (status != USBD_NORMAL_COMPLETION) {
1985 		DPRINTF(0, "non-normal status %s\n", usbd_errstr(status));
1986 
1987 		if (status == USBD_STALLED && hp->hp_wpipe != NULL)
1988 			usbd_clear_endpoint_stall_async(hp->hp_wpipe);
1989 		else
1990 			return;
1991 
1992 		ifp->if_oerrors++;
1993 	} else {
1994 		usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL);
1995 		DPRINTF(5, "wrote %d bytes (of %zd)\n", cc, hp->hp_wlen);
1996 
1997 		if (cc != hp->hp_wlen)
1998 			DPRINTF(0, "cc=%u, wlen=%zd\n", cc, hp->hp_wlen);
1999 
2000 		ifp->if_opackets++;
2001 	}
2002 
2003 	s = splnet();
2004 	CLR(ifp->if_flags, IFF_OACTIVE);
2005 	ifp->if_start(ifp);
2006 	splx(s);
2007 }
2008 
2009 Static void
2010 uhso_ifnet_read_cb(usbd_xfer_handle xfer, usbd_private_handle p,
2011     usbd_status status)
2012 {
2013 	struct uhso_port *hp = p;
2014 	struct uhso_softc *sc= hp->hp_sc;
2015 	struct ifnet *ifp = hp->hp_ifp;
2016 	void *cp;
2017 	uint32_t cc;
2018 
2019 	if (--sc->sc_refcnt < 0)
2020 		usb_detach_wakeupold(sc->sc_dev);
2021 
2022 	if (!ISSET(ifp->if_flags, IFF_RUNNING))
2023 		return;
2024 
2025 	if (status != USBD_NORMAL_COMPLETION) {
2026 		DPRINTF(0, "non-normal status: %s\n", usbd_errstr(status));
2027 
2028 		if (status == USBD_STALLED && hp->hp_rpipe != NULL)
2029 			usbd_clear_endpoint_stall_async(hp->hp_rpipe);
2030 		else
2031 			return;
2032 
2033 		ifp->if_ierrors++;
2034 		hp->hp_rlen = 0;
2035 	} else {
2036 		usbd_get_xfer_status(xfer, NULL, (void **)&cp, &cc, NULL);
2037 
2038 		hp->hp_rlen = cc;
2039 		DPRINTF(5, "read %d bytes\n", cc);
2040 
2041 		uhso_ifnet_input(ifp, &hp->hp_mbuf, cp, cc);
2042 	}
2043 
2044 	(*hp->hp_read)(hp);
2045 }
2046 
2047 Static void
2048 uhso_ifnet_input(struct ifnet *ifp, struct mbuf **mb, uint8_t *cp, size_t cc)
2049 {
2050 	struct mbuf *m;
2051 	size_t got, len, want;
2052 	int s;
2053 
2054 	/*
2055 	 * Several IP packets might be in the same buffer, we need to
2056 	 * separate them before handing it to the ip-stack.  We might
2057 	 * also receive partial packets which we need to defer until
2058 	 * we get more data.
2059 	 */
2060 	while (cc > 0) {
2061 		if (*mb == NULL) {
2062 			MGETHDR(m, M_DONTWAIT, MT_DATA);
2063 			if (m == NULL) {
2064 				aprint_error_ifnet(ifp, "no mbufs\n");
2065 				ifp->if_ierrors++;
2066 				break;
2067 			}
2068 
2069 			MCLGET(m, M_DONTWAIT);
2070 			if (!ISSET(m->m_flags, M_EXT)) {
2071 				aprint_error_ifnet(ifp, "no mbuf clusters\n");
2072 				ifp->if_ierrors++;
2073 				m_freem(m);
2074 				break;
2075 			}
2076 
2077 			got = 0;
2078 		} else {
2079 			m = *mb;
2080 			*mb = NULL;
2081 			got = m->m_pkthdr.len;
2082 		}
2083 
2084 		/* make sure that the incoming packet is ok */
2085 		if (got == 0)
2086 			mtod(m, uint8_t *)[0] = cp[0];
2087 
2088 		want = mtod(m, struct ip *)->ip_hl << 2;
2089 		if (mtod(m, struct ip *)->ip_v != 4
2090 		    || want != sizeof(struct ip)) {
2091 			aprint_error_ifnet(ifp, "bad IP header (v=%d, hl=%zd)\n",
2092 			    mtod(m, struct ip *)->ip_v, want);
2093 
2094 			ifp->if_ierrors++;
2095 			m_freem(m);
2096 			break;
2097 		}
2098 
2099 		/* ensure we have the IP header.. */
2100 		if (got < want) {
2101 			len = MIN(want - got, cc);
2102 			memcpy(mtod(m, uint8_t *) + got, cp, len);
2103 			got += len;
2104 			cc -= len;
2105 			cp += len;
2106 
2107 			if (got < want) {
2108 				DPRINTF(5, "waiting for IP header "
2109 					   "(got %zd want %zd)\n", got, want);
2110 
2111 				m->m_pkthdr.len = got;
2112 				*mb = m;
2113 				break;
2114 			}
2115 		}
2116 
2117 		/* ..and the packet body */
2118 		want = ntohs(mtod(m, struct ip *)->ip_len);
2119 		if (got < want) {
2120 			len = MIN(want - got, cc);
2121 			memcpy(mtod(m, uint8_t *) + got, cp, len);
2122 			got += len;
2123 			cc -= len;
2124 			cp += len;
2125 
2126 			if (got < want) {
2127 				DPRINTF(5, "waiting for IP packet "
2128 					   "(got %zd want %zd)\n", got, want);
2129 
2130 				m->m_pkthdr.len = got;
2131 				*mb = m;
2132 				break;
2133 			}
2134 		} else if (want > got) {
2135 			aprint_error_ifnet(ifp, "bad IP packet (len=%zd)\n",
2136 			    want);
2137 
2138 			ifp->if_ierrors++;
2139 			m_freem(m);
2140 			break;
2141 		}
2142 
2143 		m->m_pkthdr.rcvif = ifp;
2144 		m->m_pkthdr.len = m->m_len = got;
2145 
2146 		s = splnet();
2147 
2148 		bpf_mtap(ifp, m);
2149 
2150 		ifp->if_ipackets++;
2151 		ifp->if_ibytes += m->m_pkthdr.len;
2152 
2153 		if (IF_QFULL(&ipintrq)) {
2154 			IF_DROP(&ipintrq);
2155 			m_freem(m);
2156 		} else {
2157 			IF_ENQUEUE(&ipintrq, m);
2158 			schednetisr(NETISR_IP);
2159 		}
2160 
2161 		splx(s);
2162 	}
2163 }
2164 
2165 Static int
2166 uhso_ifnet_ioctl(struct ifnet *ifp, u_long cmd, void *data)
2167 {
2168 	struct uhso_port *hp = ifp->if_softc;
2169 	int error, s;
2170 
2171 	s = splnet();
2172 
2173 	switch (cmd) {
2174 	case SIOCINITIFADDR:
2175 		switch (((struct ifaddr *)data)->ifa_addr->sa_family) {
2176 #ifdef INET
2177 		case AF_INET:
2178 			if (!ISSET(ifp->if_flags, IFF_RUNNING)) {
2179 				SET(ifp->if_flags, IFF_UP);
2180 				error = uhso_ifnet_init(hp);
2181 				if (error != 0) {
2182 					uhso_ifnet_clean(hp);
2183 					break;
2184 				}
2185 
2186 				SET(ifp->if_flags, IFF_RUNNING);
2187 				DPRINTF(1, "hp=%p, ifp=%p INITIFADDR\n", hp, ifp);
2188 				break;
2189 			}
2190 
2191 			error = 0;
2192 			break;
2193 #endif
2194 
2195 		default:
2196 			error = EAFNOSUPPORT;
2197 			break;
2198 		}
2199 		break;
2200 
2201 	case SIOCSIFMTU:
2202 		if (((struct ifreq *)data)->ifr_mtu > hp->hp_wsize) {
2203 			error = EINVAL;
2204 			break;
2205 		}
2206 
2207 		error = ifioctl_common(ifp, cmd, data);
2208 		if (error == ENETRESET)
2209 			error = 0;
2210 
2211 		break;
2212 
2213 	case SIOCSIFFLAGS:
2214 		error = ifioctl_common(ifp, cmd, data);
2215 		if (error != 0)
2216 			break;
2217 
2218 		switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
2219 		case IFF_UP:
2220 			error = uhso_ifnet_init(hp);
2221 			if (error != 0) {
2222 				uhso_ifnet_clean(hp);
2223 				break;
2224 			}
2225 
2226 			SET(ifp->if_flags, IFF_RUNNING);
2227 			DPRINTF(1, "hp=%p, ifp=%p RUNNING\n", hp, ifp);
2228 			break;
2229 
2230 		case IFF_RUNNING:
2231 			uhso_ifnet_clean(hp);
2232 			CLR(ifp->if_flags, IFF_RUNNING);
2233 			DPRINTF(1, "hp=%p, ifp=%p STOPPED\n", hp, ifp);
2234 			break;
2235 
2236 		default:
2237 			break;
2238 		}
2239 		break;
2240 
2241 	default:
2242 		error = ifioctl_common(ifp, cmd, data);
2243 		break;
2244 	}
2245 
2246 	splx(s);
2247 
2248 	return error;
2249 }
2250 
2251 /* is only called if IFF_RUNNING not set */
2252 Static int
2253 uhso_ifnet_init(struct uhso_port *hp)
2254 {
2255 	struct uhso_softc *sc = hp->hp_sc;
2256 	int error;
2257 
2258 	DPRINTF(1, "sc=%p, hp=%p\n", sc, hp);
2259 
2260 	if (!device_is_active(sc->sc_dev))
2261 		return EIO;
2262 
2263 	error = (*hp->hp_init)(hp);
2264 	if (error != 0)
2265 		return error;
2266 
2267 	hp->hp_rxfer = usbd_alloc_xfer(sc->sc_udev);
2268 	if (hp->hp_rxfer == NULL)
2269 		return ENOMEM;
2270 
2271 	hp->hp_rbuf = usbd_alloc_buffer(hp->hp_rxfer, hp->hp_rsize);
2272 	if (hp->hp_rbuf == NULL)
2273 		return ENOMEM;
2274 
2275 	hp->hp_wxfer = usbd_alloc_xfer(sc->sc_udev);
2276 	if (hp->hp_wxfer == NULL)
2277 		return ENOMEM;
2278 
2279 	hp->hp_wbuf = usbd_alloc_buffer(hp->hp_wxfer, hp->hp_wsize);
2280 	if (hp->hp_wbuf == NULL)
2281 		return ENOMEM;
2282 
2283 	error = (*hp->hp_read)(hp);
2284 	if (error != 0)
2285 		return error;
2286 
2287 	return 0;
2288 }
2289 
2290 Static void
2291 uhso_ifnet_clean(struct uhso_port *hp)
2292 {
2293 
2294 	DPRINTF(1, "hp=%p\n", hp);
2295 
2296 	(*hp->hp_clean)(hp);
2297 
2298 	if (hp->hp_rxfer != NULL) {
2299 		usbd_free_xfer(hp->hp_rxfer);
2300 		hp->hp_rxfer = NULL;
2301 		hp->hp_rbuf = NULL;
2302 	}
2303 
2304 	if (hp->hp_wxfer != NULL) {
2305 		usbd_free_xfer(hp->hp_wxfer);
2306 		hp->hp_wxfer = NULL;
2307 		hp->hp_wbuf = NULL;
2308 	}
2309 }
2310 
2311 /* called at splnet() with IFF_OACTIVE not set */
2312 Static void
2313 uhso_ifnet_start(struct ifnet *ifp)
2314 {
2315 	struct uhso_port *hp = ifp->if_softc;
2316 	struct mbuf *m;
2317 
2318 	KASSERT(!ISSET(ifp->if_flags, IFF_OACTIVE));
2319 
2320 	if (!ISSET(ifp->if_flags, IFF_RUNNING))
2321 		return;
2322 
2323 	if (IFQ_IS_EMPTY(&ifp->if_snd)) {
2324 		DPRINTF(5, "finished sending\n");
2325 		return;
2326 	}
2327 
2328 	SET(ifp->if_flags, IFF_OACTIVE);
2329 	IFQ_DEQUEUE(&ifp->if_snd, m);
2330 	hp->hp_wlen = m->m_pkthdr.len;
2331 	if (hp->hp_wlen > hp->hp_wsize) {
2332 		aprint_error_ifnet(ifp,
2333 		    "packet too long (%zd > %zd), truncating\n",
2334 		    hp->hp_wlen, hp->hp_wsize);
2335 
2336 		hp->hp_wlen = hp->hp_wsize;
2337 	}
2338 
2339 	bpf_mtap(ifp, m);
2340 
2341 	m_copydata(m, 0, hp->hp_wlen, hp->hp_wbuf);
2342 	m_freem(m);
2343 
2344 	if ((*hp->hp_write)(hp) != 0) {
2345 		ifp->if_oerrors++;
2346 		CLR(ifp->if_flags, IFF_OACTIVE);
2347 	}
2348 }
2349 
2350 Static int
2351 uhso_ifnet_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
2352     struct rtentry *rt0)
2353 {
2354 	ALTQ_DECL(struct altq_pktattr pktattr);
2355 	int error;
2356 
2357 	if (!ISSET(ifp->if_flags, IFF_RUNNING))
2358 		return EIO;
2359 
2360 	IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr);
2361 
2362 	switch (dst->sa_family) {
2363 #ifdef INET
2364 	case AF_INET:
2365 		error = ifq_enqueue(ifp, m ALTQ_COMMA ALTQ_DECL(&pktattr));
2366 		break;
2367 #endif
2368 
2369 	default:
2370 		DPRINTF(0, "unsupported address family %d\n", dst->sa_family);
2371 		error = EAFNOSUPPORT;
2372 		m_freem(m);
2373 		break;
2374 	}
2375 
2376 	return error;
2377 }
2378