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