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