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