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