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