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