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