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