uhso.c revision 213803
1/*-
2 * Copyright (c) 2010 Fredrik Lindberg <fli@shapeshifter.se>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 */
26#include <sys/cdefs.h>
27__FBSDID("$FreeBSD: head/sys/dev/usb/net/uhso.c 213803 2010-10-13 20:51:06Z hselasky $");
28
29#include <sys/param.h>
30#include <sys/types.h>
31#include <sys/sockio.h>
32#include <sys/mbuf.h>
33#include <sys/malloc.h>
34#include <sys/kernel.h>
35#include <sys/module.h>
36#include <sys/socket.h>
37#include <sys/tty.h>
38#include <sys/sysctl.h>
39#include <sys/condvar.h>
40#include <sys/sx.h>
41#include <sys/proc.h>
42#include <sys/conf.h>
43#include <sys/bus.h>
44#include <sys/systm.h>
45#include <sys/limits.h>
46
47#include <machine/bus.h>
48
49#include <net/if.h>
50#include <net/if_types.h>
51#include <net/netisr.h>
52#include <net/bpf.h>
53#include <netinet/in.h>
54#include <netinet/ip.h>
55#include <netinet/ip6.h>
56
57#include <dev/usb/usb.h>
58#include <dev/usb/usbdi.h>
59#include <dev/usb/usbdi_util.h>
60#include <dev/usb/usb_cdc.h>
61#include "usbdevs.h"
62#define USB_DEBUG_VAR uhso_debug
63#include <dev/usb/usb_debug.h>
64#include <dev/usb/usb_process.h>
65#include <dev/usb/usb_busdma.h>
66#include <dev/usb/usb_msctest.h>
67
68#include <dev/usb/serial/usb_serial.h>
69
70struct uhso_tty {
71	struct uhso_softc *ht_sc;
72	struct usb_xfer	*ht_xfer[3];
73	int		ht_muxport; /* Mux. port no */
74	int		ht_open;
75	char		ht_name[32];
76};
77
78struct uhso_softc {
79	device_t		sc_dev;
80	struct usb_device	*sc_udev;
81	struct mtx		sc_mtx;
82	uint32_t		sc_type;	/* Interface definition */
83	int			sc_radio;
84
85	struct usb_xfer		*sc_xfer[3];
86	uint8_t			sc_iface_no;
87	uint8_t			sc_iface_index;
88
89	/* Control pipe */
90	struct usb_xfer	*	sc_ctrl_xfer[2];
91	uint8_t			sc_ctrl_iface_no;
92
93	/* Network */
94	struct usb_xfer		*sc_if_xfer[2];
95	struct ifnet		*sc_ifp;
96	struct mbuf		*sc_mwait;	/* Partial packet */
97	size_t			sc_waitlen;	/* No. of outstanding bytes */
98	struct ifqueue		sc_rxq;
99	struct callout		sc_c;
100
101	/* TTY related structures */
102	struct ucom_super_softc sc_super_ucom;
103	int			sc_ttys;
104	struct uhso_tty		*sc_tty;
105	struct ucom_softc	*sc_ucom;
106	int			sc_msr;
107	int			sc_lsr;
108	int			sc_line;
109};
110
111#define UHSO_MAX_MTU		2048
112
113/*
114 * There are mainly two type of cards floating around.
115 * The first one has 2,3 or 4 interfaces with a multiplexed serial port
116 * and packet interface on the first interface and bulk serial ports
117 * on the others.
118 * The second type of card has several other interfaces, their purpose
119 * can be detected during run-time.
120 */
121#define UHSO_IFACE_SPEC(usb_type, port, port_type) \
122	(((usb_type) << 24) | ((port) << 16) | (port_type))
123
124#define UHSO_IFACE_USB_TYPE(x) ((x >> 24) & 0xff)
125#define UHSO_IFACE_PORT(x) ((x >> 16) & 0xff)
126#define UHSO_IFACE_PORT_TYPE(x) (x & 0xff)
127
128/*
129 * USB interface types
130 */
131#define UHSO_IF_NET		0x01	/* Network packet interface */
132#define UHSO_IF_MUX		0x02	/* Multiplexed serial port */
133#define UHSO_IF_BULK		0x04	/* Bulk interface */
134
135/*
136 * Port types
137 */
138#define UHSO_PORT_UNKNOWN	0x00
139#define UHSO_PORT_SERIAL	0x01	/* Serial port */
140#define UHSO_PORT_NETWORK	0x02	/* Network packet interface */
141
142/*
143 * Multiplexed serial port destination sub-port names
144 */
145#define UHSO_MPORT_TYPE_CTL	0x00	/* Control port */
146#define UHSO_MPORT_TYPE_APP	0x01	/* Application */
147#define UHSO_MPORT_TYPE_PCSC	0x02
148#define UHSO_MPORT_TYPE_GPS	0x03
149#define UHSO_MPORT_TYPE_APP2	0x04	/* Secondary application */
150#define UHSO_MPORT_TYPE_MAX	UHSO_MPORT_TYPE_APP2
151#define UHSO_MPORT_TYPE_NOMAX	8	/* Max number of mux ports */
152
153/*
154 * Port definitions
155 * Note that these definitions are arbitrary and do not match the values
156 * returned by the auto config descriptor.
157 */
158#define UHSO_PORT_TYPE_UNKNOWN	0x00
159#define UHSO_PORT_TYPE_CTL	0x01
160#define UHSO_PORT_TYPE_APP	0x02
161#define UHSO_PORT_TYPE_APP2	0x03
162#define UHSO_PORT_TYPE_MODEM	0x04
163#define UHSO_PORT_TYPE_NETWORK	0x05
164#define UHSO_PORT_TYPE_DIAG	0x06
165#define UHSO_PORT_TYPE_DIAG2	0x07
166#define UHSO_PORT_TYPE_GPS	0x08
167#define UHSO_PORT_TYPE_GPSCTL	0x09
168#define UHSO_PORT_TYPE_PCSC	0x0a
169#define UHSO_PORT_TYPE_MSD	0x0b
170#define UHSO_PORT_TYPE_VOICE	0x0c
171#define UHSO_PORT_TYPE_MAX	0x0c
172
173static eventhandler_tag uhso_etag;
174
175/* Overall port type */
176static char *uhso_port[] = {
177	"Unknown",
178	"Serial",
179	"Network",
180	"Network/Serial"
181};
182
183/*
184 * Map between interface port type read from device and description type.
185 * The position in this array is a direct map to the auto config
186 * descriptor values.
187 */
188static unsigned char uhso_port_map[] = {
189	UHSO_PORT_TYPE_UNKNOWN,
190	UHSO_PORT_TYPE_DIAG,
191	UHSO_PORT_TYPE_GPS,
192	UHSO_PORT_TYPE_GPSCTL,
193	UHSO_PORT_TYPE_APP,
194	UHSO_PORT_TYPE_APP2,
195	UHSO_PORT_TYPE_CTL,
196	UHSO_PORT_TYPE_NETWORK,
197	UHSO_PORT_TYPE_MODEM,
198	UHSO_PORT_TYPE_MSD,
199	UHSO_PORT_TYPE_PCSC,
200	UHSO_PORT_TYPE_VOICE
201};
202static char uhso_port_map_max = sizeof(uhso_port_map) / sizeof(char);
203
204static unsigned char uhso_mux_port_map[] = {
205	UHSO_PORT_TYPE_CTL,
206	UHSO_PORT_TYPE_APP,
207	UHSO_PORT_TYPE_PCSC,
208	UHSO_PORT_TYPE_GPS,
209	UHSO_PORT_TYPE_APP2
210};
211
212static char *uhso_port_type[] = {
213	"Unknown",  /* Not a valid port */
214	"Control",
215	"Application",
216	"Application (Secondary)",
217	"Modem",
218	"Network",
219	"Diagnostic",
220	"Diagnostic (Secondary)",
221	"GPS",
222	"GPS Control",
223	"PC Smartcard",
224	"MSD",
225	"Voice",
226};
227
228static char *uhso_port_type_sysctl[] = {
229	"unknown",
230	"control",
231	"application",
232	"application",
233	"modem",
234	"network",
235	"diagnostic",
236	"diagnostic",
237	"gps",
238	"gps_control",
239	"pcsc",
240	"msd",
241	"voice",
242};
243
244#define UHSO_STATIC_IFACE	0x01
245#define UHSO_AUTO_IFACE		0x02
246
247/* ifnet device unit allocations */
248static struct unrhdr *uhso_ifnet_unit = NULL;
249
250static const struct usb_device_id uhso_devs[] = {
251#define	UHSO_DEV(v,p,i) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) }
252	/* Option GlobeSurfer iCON 7.2 */
253	UHSO_DEV(OPTION, GSICON72, UHSO_STATIC_IFACE),
254	/* Option iCON 225 */
255	UHSO_DEV(OPTION, GTHSDPA, UHSO_STATIC_IFACE),
256	/* Option GlobeSurfer iCON HSUPA */
257	UHSO_DEV(OPTION, GSICONHSUPA, UHSO_STATIC_IFACE),
258	/* Option GlobeTrotter HSUPA */
259	UHSO_DEV(OPTION, GTHSUPA, UHSO_STATIC_IFACE),
260	/* GE40x */
261	UHSO_DEV(OPTION, GE40X, UHSO_AUTO_IFACE),
262	UHSO_DEV(OPTION, GE40X_1, UHSO_AUTO_IFACE),
263	UHSO_DEV(OPTION, GE40X_2, UHSO_AUTO_IFACE),
264	UHSO_DEV(OPTION, GE40X_3, UHSO_AUTO_IFACE),
265	/* Option GlobeSurfer iCON 401 */
266	UHSO_DEV(OPTION, ICON401, UHSO_AUTO_IFACE),
267	/* Option GlobeTrotter Module 382 */
268	UHSO_DEV(OPTION, GMT382, UHSO_AUTO_IFACE),
269	/* Option iCON EDGE */
270	UHSO_DEV(OPTION, ICONEDGE, UHSO_STATIC_IFACE),
271	/* Option Module HSxPA */
272	UHSO_DEV(OPTION, MODHSXPA, UHSO_STATIC_IFACE),
273	/* Option iCON 321 */
274	UHSO_DEV(OPTION, ICON321, UHSO_STATIC_IFACE),
275	/* Option iCON 322 */
276	UHSO_DEV(OPTION, GTICON322, UHSO_STATIC_IFACE),
277	/* Option iCON 505 */
278	UHSO_DEV(OPTION, ICON505, UHSO_AUTO_IFACE),
279	/* Option iCON 452 */
280	UHSO_DEV(OPTION, ICON505, UHSO_AUTO_IFACE),
281#undef UHSO_DEV
282};
283
284SYSCTL_NODE(_hw_usb, OID_AUTO, uhso, CTLFLAG_RW, 0, "USB uhso");
285static int uhso_autoswitch = 1;
286SYSCTL_INT(_hw_usb_uhso, OID_AUTO, auto_switch, CTLFLAG_RW,
287    &uhso_autoswitch, 0, "Automatically switch to modem mode");
288
289#ifdef USB_DEBUG
290#ifdef UHSO_DEBUG
291static int uhso_debug = UHSO_DEBUG;
292#else
293static int uhso_debug = -1;
294#endif
295
296SYSCTL_INT(_hw_usb_uhso, OID_AUTO, debug, CTLFLAG_RW,
297    &uhso_debug, 0, "Debug level");
298
299#define UHSO_DPRINTF(n, x, ...) {\
300	if (uhso_debug >= n) {\
301		printf("%s: " x, __func__, ##__VA_ARGS__);\
302	}\
303}
304#else
305#define UHSO_DPRINTF(n, x, ...)
306#endif
307
308#ifdef UHSO_DEBUG_HEXDUMP
309# define UHSO_HEXDUMP(_buf, _len) do { \
310  { \
311        size_t __tmp; \
312        const char *__buf = (const char *)_buf; \
313        for (__tmp = 0; __tmp < _len; __tmp++) \
314                printf("%02hhx ", *__buf++); \
315    printf("\n"); \
316  } \
317} while(0)
318#else
319# define UHSO_HEXDUMP(_buf, _len)
320#endif
321
322enum {
323	UHSO_MUX_ENDPT_INTR = 0,
324	UHSO_MUX_ENDPT_MAX
325};
326
327enum {
328	UHSO_CTRL_READ = 0,
329	UHSO_CTRL_WRITE,
330	UHSO_CTRL_MAX
331};
332
333enum {
334	UHSO_IFNET_READ = 0,
335	UHSO_IFNET_WRITE,
336	UHSO_IFNET_MAX
337};
338
339enum {
340	UHSO_BULK_ENDPT_READ = 0,
341	UHSO_BULK_ENDPT_WRITE,
342	UHSO_BULK_ENDPT_INTR,
343	UHSO_BULK_ENDPT_MAX
344};
345
346static usb_callback_t uhso_mux_intr_callback;
347static usb_callback_t uhso_mux_read_callback;
348static usb_callback_t uhso_mux_write_callback;
349static usb_callback_t uhso_bs_read_callback;
350static usb_callback_t uhso_bs_write_callback;
351static usb_callback_t uhso_bs_intr_callback;
352static usb_callback_t uhso_ifnet_read_callback;
353static usb_callback_t uhso_ifnet_write_callback;
354
355/* Config used for the default control pipes */
356static const struct usb_config uhso_ctrl_config[UHSO_CTRL_MAX] = {
357	[UHSO_CTRL_READ] = {
358		.type = UE_CONTROL,
359		.endpoint = 0x00,
360		.direction = UE_DIR_ANY,
361		.flags = { .pipe_bof = 1, .short_xfer_ok = 1 },
362		.bufsize = sizeof(struct usb_device_request) + 1024,
363		.callback = &uhso_mux_read_callback
364	},
365
366	[UHSO_CTRL_WRITE] = {
367		.type = UE_CONTROL,
368		.endpoint = 0x00,
369		.direction = UE_DIR_ANY,
370		.flags = { .pipe_bof = 1, .force_short_xfer = 1 },
371		.bufsize = sizeof(struct usb_device_request) + 1024,
372		.timeout = 1000,
373		.callback = &uhso_mux_write_callback
374	}
375};
376
377/* Config for the multiplexed serial ports */
378static const struct usb_config uhso_mux_config[UHSO_MUX_ENDPT_MAX] = {
379	[UHSO_MUX_ENDPT_INTR] = {
380		.type = UE_INTERRUPT,
381		.endpoint = UE_ADDR_ANY,
382		.direction = UE_DIR_IN,
383		.flags = { .short_xfer_ok = 1 },
384		.bufsize = 0,
385		.callback = &uhso_mux_intr_callback,
386	}
387};
388
389/* Config for the raw IP-packet interface */
390static const struct usb_config uhso_ifnet_config[UHSO_IFNET_MAX] = {
391	[UHSO_IFNET_READ] = {
392		.type = UE_BULK,
393		.endpoint = UE_ADDR_ANY,
394		.direction = UE_DIR_IN,
395		.flags = { .pipe_bof = 1, .short_xfer_ok = 1 },
396		.bufsize = MCLBYTES,
397		.callback = &uhso_ifnet_read_callback
398	},
399	[UHSO_IFNET_WRITE] = {
400		.type = UE_BULK,
401		.endpoint = UE_ADDR_ANY,
402		.direction = UE_DIR_OUT,
403		.flags = { .pipe_bof = 1, .force_short_xfer = 1 },
404		.bufsize = MCLBYTES,
405		.timeout = 5 * USB_MS_HZ,
406		.callback = &uhso_ifnet_write_callback
407	}
408};
409
410/* Config for interfaces with normal bulk serial ports */
411static const struct usb_config uhso_bs_config[UHSO_BULK_ENDPT_MAX] = {
412	[UHSO_BULK_ENDPT_READ] = {
413		.type = UE_BULK,
414		.endpoint = UE_ADDR_ANY,
415		.direction = UE_DIR_IN,
416		.flags = { .pipe_bof = 1, .short_xfer_ok = 1 },
417		.bufsize = 4096,
418		.callback = &uhso_bs_read_callback
419	},
420
421	[UHSO_BULK_ENDPT_WRITE] = {
422		.type = UE_BULK,
423		.endpoint = UE_ADDR_ANY,
424		.direction = UE_DIR_OUT,
425		.flags = { .pipe_bof = 1, .force_short_xfer = 1 },
426		.bufsize = 8192,
427		.callback = &uhso_bs_write_callback
428	},
429
430	[UHSO_BULK_ENDPT_INTR] = {
431		.type = UE_INTERRUPT,
432		.endpoint = UE_ADDR_ANY,
433		.direction = UE_DIR_IN,
434		.flags = { .short_xfer_ok = 1 },
435		.bufsize = 0,
436		.callback = &uhso_bs_intr_callback,
437	}
438};
439
440static int  uhso_probe_iface(struct uhso_softc *, int,
441    int (*probe)(struct usb_device *, int));
442static int  uhso_probe_iface_auto(struct usb_device *, int);
443static int  uhso_probe_iface_static(struct usb_device *, int);
444static int  uhso_attach_muxserial(struct uhso_softc *, struct usb_interface *,
445    int type);
446static int  uhso_attach_bulkserial(struct uhso_softc *, struct usb_interface *,
447    int type);
448static int  uhso_attach_ifnet(struct uhso_softc *, struct usb_interface *,
449    int type);
450static void uhso_test_autoinst(void *, struct usb_device *,
451		struct usb_attach_arg *);
452static int  uhso_driver_loaded(struct module *, int, void *);
453static int uhso_radio_sysctl(SYSCTL_HANDLER_ARGS);
454static int uhso_radio_ctrl(struct uhso_softc *, int);
455
456static void uhso_ucom_start_read(struct ucom_softc *);
457static void uhso_ucom_stop_read(struct ucom_softc *);
458static void uhso_ucom_start_write(struct ucom_softc *);
459static void uhso_ucom_stop_write(struct ucom_softc *);
460static void uhso_ucom_cfg_get_status(struct ucom_softc *, uint8_t *, uint8_t *);
461static void uhso_ucom_cfg_set_dtr(struct ucom_softc *, uint8_t);
462static void uhso_ucom_cfg_set_rts(struct ucom_softc *, uint8_t);
463static void uhso_if_init(void *);
464static void uhso_if_start(struct ifnet *);
465static void uhso_if_stop(struct uhso_softc *);
466static int  uhso_if_ioctl(struct ifnet *, u_long, caddr_t);
467static int  uhso_if_output(struct ifnet *, struct mbuf *, struct sockaddr *,
468    struct route *);
469static void uhso_if_rxflush(void *);
470
471static device_probe_t uhso_probe;
472static device_attach_t uhso_attach;
473static device_detach_t uhso_detach;
474
475static device_method_t uhso_methods[] = {
476	DEVMETHOD(device_probe,		uhso_probe),
477	DEVMETHOD(device_attach,	uhso_attach),
478	DEVMETHOD(device_detach,	uhso_detach),
479	{ 0, 0 }
480};
481
482static driver_t uhso_driver = {
483	"uhso",
484	uhso_methods,
485	sizeof(struct uhso_softc)
486};
487
488static devclass_t uhso_devclass;
489DRIVER_MODULE(uhso, uhub, uhso_driver, uhso_devclass, uhso_driver_loaded, 0);
490MODULE_DEPEND(uhso, ucom, 1, 1, 1);
491MODULE_DEPEND(uhso, usb, 1, 1, 1);
492MODULE_VERSION(uhso, 1);
493
494static struct ucom_callback uhso_ucom_callback = {
495	.ucom_cfg_get_status = &uhso_ucom_cfg_get_status,
496	.ucom_cfg_set_dtr = &uhso_ucom_cfg_set_dtr,
497	.ucom_cfg_set_rts = &uhso_ucom_cfg_set_rts,
498	.ucom_start_read = uhso_ucom_start_read,
499	.ucom_stop_read = uhso_ucom_stop_read,
500	.ucom_start_write = uhso_ucom_start_write,
501	.ucom_stop_write = uhso_ucom_stop_write
502};
503
504static int
505uhso_probe(device_t self)
506{
507	struct usb_attach_arg *uaa = device_get_ivars(self);
508	int error;
509
510	if (uaa->usb_mode != USB_MODE_HOST)
511		return (ENXIO);
512	if (uaa->info.bConfigIndex != 0)
513		return (ENXIO);
514	if (uaa->info.bDeviceClass != 0xff)
515		return (ENXIO);
516
517	error = usbd_lookup_id_by_uaa(uhso_devs, sizeof(uhso_devs), uaa);
518	if (error != 0)
519		return (error);
520
521	/*
522	 * Probe device to see if we are able to attach
523	 * to this interface or not.
524	 */
525	if (USB_GET_DRIVER_INFO(uaa) == UHSO_AUTO_IFACE) {
526		if (uhso_probe_iface_auto(uaa->device,
527		    uaa->info.bIfaceNum) == 0)
528			return (ENXIO);
529	}
530	return (error);
531}
532
533static int
534uhso_attach(device_t self)
535{
536	struct uhso_softc *sc = device_get_softc(self);
537	struct usb_attach_arg *uaa = device_get_ivars(self);
538	struct usb_config_descriptor *cd;
539	struct usb_interface_descriptor *id;
540	struct sysctl_ctx_list *sctx;
541	struct sysctl_oid *soid;
542	struct sysctl_oid *tree = NULL, *tty_node;
543	struct ucom_softc *ucom;
544	struct uhso_tty *ht;
545	int i, error, port;
546	void *probe_f;
547	usb_error_t uerr;
548	char *desc;
549
550	sc->sc_dev = self;
551	sc->sc_udev = uaa->device;
552	mtx_init(&sc->sc_mtx, "uhso", NULL, MTX_DEF);
553
554	sc->sc_ucom = NULL;
555	sc->sc_ttys = 0;
556	sc->sc_radio = 1;
557
558	cd = usbd_get_config_descriptor(uaa->device);
559	id = usbd_get_interface_descriptor(uaa->iface);
560	sc->sc_ctrl_iface_no = id->bInterfaceNumber;
561
562	sc->sc_iface_no = uaa->info.bIfaceNum;
563	sc->sc_iface_index = uaa->info.bIfaceIndex;
564
565	/* Setup control pipe */
566	uerr = usbd_transfer_setup(uaa->device,
567	    &sc->sc_iface_index, sc->sc_ctrl_xfer,
568	    uhso_ctrl_config, UHSO_CTRL_MAX, sc, &sc->sc_mtx);
569	if (uerr) {
570		device_printf(self, "Failed to setup control pipe: %s\n",
571		    usbd_errstr(uerr));
572		goto out;
573	}
574
575	if (USB_GET_DRIVER_INFO(uaa) == UHSO_STATIC_IFACE)
576		probe_f = uhso_probe_iface_static;
577	else if (USB_GET_DRIVER_INFO(uaa) == UHSO_AUTO_IFACE)
578		probe_f = uhso_probe_iface_auto;
579	else
580		goto out;
581
582	error = uhso_probe_iface(sc, uaa->info.bIfaceNum, probe_f);
583	if (error != 0)
584		goto out;
585
586	sctx = device_get_sysctl_ctx(sc->sc_dev);
587	soid = device_get_sysctl_tree(sc->sc_dev);
588
589	SYSCTL_ADD_STRING(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "type",
590	    CTLFLAG_RD, uhso_port[UHSO_IFACE_PORT(sc->sc_type)], 0,
591	    "Port available at this interface");
592	SYSCTL_ADD_PROC(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "radio",
593	    CTLTYPE_INT | CTLFLAG_RW, sc, 0, uhso_radio_sysctl, "I", "Enable radio");
594
595	/*
596	 * The default interface description on most Option devices isn't
597	 * very helpful. So we skip device_set_usb_desc and set the
598	 * device description manually.
599	 */
600	device_set_desc_copy(self, uhso_port_type[UHSO_IFACE_PORT_TYPE(sc->sc_type)]);
601	/* Announce device */
602	device_printf(self, "<%s port> at <%s %s> on %s\n",
603	    uhso_port_type[UHSO_IFACE_PORT_TYPE(sc->sc_type)],
604	    usb_get_manufacturer(uaa->device),
605	    usb_get_product(uaa->device),
606	    device_get_nameunit(device_get_parent(self)));
607
608	if (sc->sc_ttys > 0) {
609		SYSCTL_ADD_INT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "ports",
610		    CTLFLAG_RD, &sc->sc_ttys, 0, "Number of attached serial ports");
611
612		tree = SYSCTL_ADD_NODE(sctx, SYSCTL_CHILDREN(soid), OID_AUTO,
613		    "port", CTLFLAG_RD, NULL, "Serial ports");
614	}
615
616	/*
617	 * Loop through the number of found TTYs and create sysctl
618	 * nodes for them.
619	 */
620	for (i = 0; i < sc->sc_ttys; i++) {
621		ht = &sc->sc_tty[i];
622		ucom = &sc->sc_ucom[i];
623
624		if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_MUX)
625			port = uhso_mux_port_map[ht->ht_muxport];
626		else
627			port = UHSO_IFACE_PORT_TYPE(sc->sc_type);
628
629		desc = uhso_port_type_sysctl[port];
630
631		tty_node = SYSCTL_ADD_NODE(sctx, SYSCTL_CHILDREN(tree), OID_AUTO,
632		    desc, CTLFLAG_RD, NULL, "");
633
634		ht->ht_name[0] = 0;
635		if (sc->sc_ttys == 1)
636			snprintf(ht->ht_name, 32, "cuaU%d", ucom->sc_unit);
637		else {
638			snprintf(ht->ht_name, 32, "cuaU%d.%d",
639			    ucom->sc_unit - ucom->sc_local_unit,
640			    ucom->sc_local_unit);
641		}
642
643		desc = uhso_port_type[port];
644		SYSCTL_ADD_STRING(sctx, SYSCTL_CHILDREN(tty_node), OID_AUTO,
645		    "tty", CTLFLAG_RD, ht->ht_name, 0, "");
646		SYSCTL_ADD_STRING(sctx, SYSCTL_CHILDREN(tty_node), OID_AUTO,
647		    "desc", CTLFLAG_RD, desc, 0, "");
648
649		if (bootverbose)
650			device_printf(sc->sc_dev,
651			    "\"%s\" port at %s\n", desc, ht->ht_name);
652	}
653
654	return (0);
655out:
656	uhso_detach(sc->sc_dev);
657	return (ENXIO);
658}
659
660static int
661uhso_detach(device_t self)
662{
663	struct uhso_softc *sc = device_get_softc(self);
664	int i;
665
666	usbd_transfer_unsetup(sc->sc_xfer, 3);
667	usbd_transfer_unsetup(sc->sc_ctrl_xfer, UHSO_CTRL_MAX);
668	if (sc->sc_ttys > 0) {
669		ucom_detach(&sc->sc_super_ucom, sc->sc_ucom, sc->sc_ttys);
670
671		for (i = 0; i < sc->sc_ttys; i++) {
672			if (sc->sc_tty[i].ht_muxport != -1) {
673				usbd_transfer_unsetup(sc->sc_tty[i].ht_xfer,
674				    UHSO_CTRL_MAX);
675			}
676		}
677
678		free(sc->sc_tty, M_USBDEV);
679		free(sc->sc_ucom, M_USBDEV);
680	}
681
682	if (sc->sc_ifp != NULL) {
683		callout_drain(&sc->sc_c);
684		free_unr(uhso_ifnet_unit, sc->sc_ifp->if_dunit);
685		mtx_lock(&sc->sc_mtx);
686		uhso_if_stop(sc);
687		bpfdetach(sc->sc_ifp);
688		if_detach(sc->sc_ifp);
689		if_free(sc->sc_ifp);
690		mtx_unlock(&sc->sc_mtx);
691		usbd_transfer_unsetup(sc->sc_if_xfer, UHSO_IFNET_MAX);
692	}
693
694	mtx_destroy(&sc->sc_mtx);
695	return (0);
696}
697
698static void
699uhso_test_autoinst(void *arg, struct usb_device *udev,
700    struct usb_attach_arg *uaa)
701{
702	struct usb_interface *iface;
703	struct usb_interface_descriptor *id;
704
705	if (uaa->dev_state != UAA_DEV_READY || !uhso_autoswitch)
706		return;
707
708	iface = usbd_get_iface(udev, 0);
709	if (iface == NULL)
710		return;
711	id = iface->idesc;
712	if (id == NULL || id->bInterfaceClass != UICLASS_MASS)
713		return;
714	if (usbd_lookup_id_by_uaa(uhso_devs, sizeof(uhso_devs), uaa))
715		return;		/* no device match */
716
717	if (usb_msc_eject(udev, 0, MSC_EJECT_REZERO) == 0) {
718		/* success, mark the udev as disappearing */
719		uaa->dev_state = UAA_DEV_EJECTING;
720	}
721}
722
723static int
724uhso_driver_loaded(struct module *mod, int what, void *arg)
725{
726	switch (what) {
727	case MOD_LOAD:
728		/* register our autoinstall handler */
729		uhso_etag = EVENTHANDLER_REGISTER(usb_dev_configured,
730		    uhso_test_autoinst, NULL, EVENTHANDLER_PRI_ANY);
731		/* create our unit allocator for inet devs */
732		uhso_ifnet_unit = new_unrhdr(0, INT_MAX, NULL);
733		break;
734	case MOD_UNLOAD:
735		EVENTHANDLER_DEREGISTER(usb_dev_configured, uhso_etag);
736		delete_unrhdr(uhso_ifnet_unit);
737		break;
738	default:
739		return (EOPNOTSUPP);
740	}
741	return (0);
742}
743
744/*
745 * Probe the interface type by querying the device. The elements
746 * of an array indicates the capabilities of a particular interface.
747 * Returns a bit mask with the interface capabilities.
748 */
749static int
750uhso_probe_iface_auto(struct usb_device *udev, int index)
751{
752	struct usb_device_request req;
753	usb_error_t uerr;
754	uint16_t actlen = 0;
755	char port;
756	char buf[17] = {0};
757
758	req.bmRequestType = UT_READ_VENDOR_DEVICE;
759	req.bRequest = 0x86;
760	USETW(req.wValue, 0);
761	USETW(req.wIndex, 0);
762	USETW(req.wLength, 17);
763
764	uerr = usbd_do_request_flags(udev, NULL, &req, buf,
765	    0, &actlen, USB_MS_HZ);
766	if (uerr != 0) {
767		printf("%s: usbd_do_request_flags failed, %s\n",
768		    __func__, usbd_errstr(uerr));
769		return (0);
770	}
771
772	UHSO_DPRINTF(1, "actlen=%d\n", actlen);
773	UHSO_HEXDUMP(buf, 17);
774
775	if (index < 0 || index > 16) {
776		UHSO_DPRINTF(0, "Index %d out of range\n", index);
777		return (0);
778	}
779
780	UHSO_DPRINTF(1, "index=%d, type=%x[%s]\n", index, buf[index],
781	    uhso_port_type[(int)uhso_port_map[(int)buf[index]]]);
782
783	if (buf[index] >= uhso_port_map_max)
784		port = 0;
785	else
786		port = uhso_port_map[(int)buf[index]];
787
788	switch (port) {
789	case UHSO_PORT_TYPE_NETWORK:
790		return (UHSO_IFACE_SPEC(UHSO_IF_NET | UHSO_IF_MUX,
791		    UHSO_PORT_SERIAL | UHSO_PORT_NETWORK, port));
792	case UHSO_PORT_TYPE_DIAG:
793	case UHSO_PORT_TYPE_DIAG2:
794	case UHSO_PORT_TYPE_CTL:
795	case UHSO_PORT_TYPE_APP:
796	case UHSO_PORT_TYPE_APP2:
797	case UHSO_PORT_TYPE_MODEM:
798		return (UHSO_IFACE_SPEC(UHSO_IF_BULK,
799		    UHSO_PORT_SERIAL, port));
800	case UHSO_PORT_TYPE_MSD:
801		return (0);
802	case UHSO_PORT_TYPE_UNKNOWN:
803	default:
804		return (0);
805	}
806
807	return (0);
808}
809
810/*
811 * Returns the capabilities of interfaces for devices that don't
812 * support the automatic query.
813 * Returns a bit mask with the interface capabilities.
814 */
815static int
816uhso_probe_iface_static(struct usb_device *udev, int index)
817{
818	struct usb_config_descriptor *cd;
819
820	cd = usbd_get_config_descriptor(udev);
821	if (cd->bNumInterface <= 3) {
822		/* Cards with 3 or less interfaces */
823		switch (index) {
824		case 0:
825			return UHSO_IFACE_SPEC(UHSO_IF_NET | UHSO_IF_MUX,
826			    UHSO_PORT_SERIAL | UHSO_PORT_NETWORK,
827			    UHSO_PORT_TYPE_NETWORK);
828		case 1:
829			return UHSO_IFACE_SPEC(UHSO_IF_BULK,
830			    UHSO_PORT_SERIAL, UHSO_PORT_TYPE_DIAG);
831		case 2:
832			return UHSO_IFACE_SPEC(UHSO_IF_BULK,
833			    UHSO_PORT_SERIAL, UHSO_PORT_TYPE_MODEM);
834		}
835	} else {
836		/* Cards with 4 interfaces */
837		switch (index) {
838		case 0:
839			return UHSO_IFACE_SPEC(UHSO_IF_NET | UHSO_IF_MUX,
840			    UHSO_PORT_SERIAL | UHSO_PORT_NETWORK,
841			    UHSO_PORT_TYPE_NETWORK);
842		case 1:
843			return UHSO_IFACE_SPEC(UHSO_IF_BULK,
844			    UHSO_PORT_SERIAL, UHSO_PORT_TYPE_DIAG2);
845		case 2:
846			return UHSO_IFACE_SPEC(UHSO_IF_BULK,
847			    UHSO_PORT_SERIAL, UHSO_PORT_TYPE_MODEM);
848		case 3:
849			return UHSO_IFACE_SPEC(UHSO_IF_BULK,
850			    UHSO_PORT_SERIAL, UHSO_PORT_TYPE_DIAG);
851		}
852	}
853	return (0);
854}
855
856/*
857 * Probes an interface for its particular capabilities and attaches if
858 * it's a supported interface.
859 */
860static int
861uhso_probe_iface(struct uhso_softc *sc, int index,
862    int (*probe)(struct usb_device *, int))
863{
864	struct usb_interface *iface;
865	int type, error;
866
867	UHSO_DPRINTF(1, "Probing for interface %d, probe_func=%p\n", index, probe);
868
869	type = probe(sc->sc_udev, index);
870	UHSO_DPRINTF(1, "Probe result %x\n", type);
871	if (type <= 0)
872		return (ENXIO);
873
874	sc->sc_type = type;
875	iface = usbd_get_iface(sc->sc_udev, index);
876
877	if (UHSO_IFACE_PORT_TYPE(type) == UHSO_PORT_TYPE_NETWORK) {
878		error = uhso_attach_ifnet(sc, iface, type);
879		if (error) {
880			UHSO_DPRINTF(1, "uhso_attach_ifnet failed");
881			return (ENXIO);
882		}
883
884		/*
885		 * If there is an additional interrupt endpoint on this
886		 * interface then we most likely have a multiplexed serial port
887		 * available.
888		 */
889		if (iface->idesc->bNumEndpoints < 3) {
890			sc->sc_type = UHSO_IFACE_SPEC(
891			    UHSO_IFACE_USB_TYPE(type) & ~UHSO_IF_MUX,
892			    UHSO_IFACE_PORT(type) & ~UHSO_PORT_SERIAL,
893			    UHSO_IFACE_PORT_TYPE(type));
894			return (0);
895		}
896
897		UHSO_DPRINTF(1, "Trying to attach mux. serial\n");
898		error = uhso_attach_muxserial(sc, iface, type);
899		if (error == 0 && sc->sc_ttys > 0) {
900			error = ucom_attach(&sc->sc_super_ucom, sc->sc_ucom,
901			    sc->sc_ttys, sc, &uhso_ucom_callback, &sc->sc_mtx);
902			if (error) {
903				device_printf(sc->sc_dev, "ucom_attach failed\n");
904				return (ENXIO);
905			}
906
907			mtx_lock(&sc->sc_mtx);
908			usbd_transfer_start(sc->sc_xfer[UHSO_MUX_ENDPT_INTR]);
909			mtx_unlock(&sc->sc_mtx);
910		}
911	} else if ((UHSO_IFACE_USB_TYPE(type) & UHSO_IF_BULK) &&
912	    UHSO_IFACE_PORT(type) & UHSO_PORT_SERIAL) {
913
914		error = uhso_attach_bulkserial(sc, iface, type);
915		if (error)
916			return (ENXIO);
917
918		error = ucom_attach(&sc->sc_super_ucom, sc->sc_ucom,
919		    sc->sc_ttys, sc, &uhso_ucom_callback, &sc->sc_mtx);
920		if (error) {
921			device_printf(sc->sc_dev, "ucom_attach failed\n");
922			return (ENXIO);
923		}
924	}
925	else {
926		UHSO_DPRINTF(0, "Unknown type %x\n", type);
927		return (ENXIO);
928	}
929
930	return (0);
931}
932
933static int
934uhso_radio_ctrl(struct uhso_softc *sc, int onoff)
935{
936	struct usb_device_request req;
937	usb_error_t uerr;
938
939	req.bmRequestType = UT_VENDOR;
940	req.bRequest = onoff ? 0x82 : 0x81;
941	USETW(req.wValue, 0);
942	USETW(req.wIndex, 0);
943	USETW(req.wLength, 0);
944
945	uerr = usbd_do_request(sc->sc_udev, NULL, &req, NULL);
946	if (uerr != 0) {
947		device_printf(sc->sc_dev, "usbd_do_request_flags failed: %s\n",
948		    usbd_errstr(uerr));
949		return (-1);
950	}
951	return (onoff);
952}
953
954static int
955uhso_radio_sysctl(SYSCTL_HANDLER_ARGS)
956{
957	struct uhso_softc *sc = arg1;
958	int error, radio;
959
960	radio = sc->sc_radio;
961	error = sysctl_handle_int(oidp, &radio, 0, req);
962	if (error)
963		return (error);
964	if (radio != sc->sc_radio) {
965		radio = radio != 0 ? 1 : 0;
966		error = uhso_radio_ctrl(sc, radio);
967		if (error != -1)
968			sc->sc_radio = radio;
969
970	}
971	return (0);
972}
973
974/*
975 * Expands allocated memory to fit an additional TTY.
976 * Two arrays are kept with matching indexes, one for ucom and one
977 * for our private data.
978 */
979static int
980uhso_alloc_tty(struct uhso_softc *sc)
981{
982
983	sc->sc_ttys++;
984	sc->sc_tty = reallocf(sc->sc_tty, sizeof(struct uhso_tty) * sc->sc_ttys,
985	    M_USBDEV, M_WAITOK | M_ZERO);
986	if (sc->sc_tty == NULL)
987		return (-1);
988
989	sc->sc_ucom = reallocf(sc->sc_ucom,
990	    sizeof(struct ucom_softc) * sc->sc_ttys, M_USBDEV, M_WAITOK | M_ZERO);
991	if (sc->sc_ucom == NULL)
992		return (-1);
993
994	sc->sc_tty[sc->sc_ttys - 1].ht_sc = sc;
995
996	UHSO_DPRINTF(1, "Allocated TTY %d\n", sc->sc_ttys - 1);
997	return (sc->sc_ttys - 1);
998}
999
1000/*
1001 * Attach a multiplexed serial port
1002 * Data is read/written with requests on the default control pipe. An interrupt
1003 * endpoint returns when there is new data to be read.
1004 */
1005static int
1006uhso_attach_muxserial(struct uhso_softc *sc, struct usb_interface *iface,
1007    int type)
1008{
1009	struct usb_descriptor *desc;
1010	int i, port, tty;
1011	usb_error_t uerr;
1012
1013	/*
1014	 * The class specific interface (type 0x24) descriptor subtype field
1015	 * contains a bitmask that specifies which (and how many) ports that
1016	 * are available through this multiplexed serial port.
1017 	 */
1018	desc = usbd_find_descriptor(sc->sc_udev, NULL,
1019	    iface->idesc->bInterfaceNumber, UDESC_CS_INTERFACE, 0xff, 0, 0);
1020	if (desc == NULL) {
1021		UHSO_DPRINTF(0, "Failed to find UDESC_CS_INTERFACE\n");
1022		return (ENXIO);
1023	}
1024
1025	UHSO_DPRINTF(1, "Mux port mask %x\n", desc->bDescriptorSubtype);
1026	if (desc->bDescriptorSubtype == 0)
1027		return (ENXIO);
1028
1029	/*
1030	 * The bitmask is one octet, loop through the number of
1031	 * bits that are set and create a TTY for each.
1032	 */
1033	for (i = 0; i < 8; i++) {
1034		port = (1 << i);
1035		if ((port & desc->bDescriptorSubtype) == port) {
1036			UHSO_DPRINTF(2, "Found mux port %x (%d)\n", port, i);
1037			tty = uhso_alloc_tty(sc);
1038			if (tty < 0)
1039				return (ENOMEM);
1040			sc->sc_tty[tty].ht_muxport = i;
1041			uerr = usbd_transfer_setup(sc->sc_udev,
1042			    &sc->sc_iface_index, sc->sc_tty[tty].ht_xfer,
1043			    uhso_ctrl_config, UHSO_CTRL_MAX, sc, &sc->sc_mtx);
1044			if (uerr) {
1045				device_printf(sc->sc_dev,
1046				    "Failed to setup control pipe: %s\n",
1047				    usbd_errstr(uerr));
1048				return (ENXIO);
1049			}
1050		}
1051	}
1052
1053	/* Setup the intr. endpoint */
1054	uerr = usbd_transfer_setup(sc->sc_udev,
1055	    &iface->idesc->bInterfaceNumber, sc->sc_xfer,
1056	    uhso_mux_config, 1, sc, &sc->sc_mtx);
1057	if (uerr)
1058		return (ENXIO);
1059
1060	return (0);
1061}
1062
1063/*
1064 * Interrupt callback for the multiplexed serial port. Indicates
1065 * which serial port has data waiting.
1066 */
1067static void
1068uhso_mux_intr_callback(struct usb_xfer *xfer, usb_error_t error)
1069{
1070	struct usb_page_cache *pc;
1071	struct usb_page_search res;
1072	struct uhso_softc *sc = usbd_xfer_softc(xfer);
1073	unsigned int i, mux;
1074
1075	UHSO_DPRINTF(3, "status %d\n", USB_GET_STATE(xfer));
1076
1077	switch (USB_GET_STATE(xfer)) {
1078	case USB_ST_TRANSFERRED:
1079		/*
1080		 * The multiplexed port number can be found at the first byte.
1081		 * It contains a bit mask, we transform this in to an integer.
1082		 */
1083		pc = usbd_xfer_get_frame(xfer, 0);
1084		usbd_get_page(pc, 0, &res);
1085
1086		i = *((unsigned char *)res.buffer);
1087		mux = 0;
1088		while (i >>= 1) {
1089			mux++;
1090		}
1091
1092		UHSO_DPRINTF(3, "mux port %d (%d)\n", mux, i);
1093		if (mux > UHSO_MPORT_TYPE_NOMAX)
1094			break;
1095
1096		/* Issue a read for this serial port */
1097		usbd_xfer_set_priv(
1098		    sc->sc_tty[mux].ht_xfer[UHSO_CTRL_READ],
1099		    &sc->sc_tty[mux]);
1100		usbd_transfer_start(sc->sc_tty[mux].ht_xfer[UHSO_CTRL_READ]);
1101
1102		break;
1103	case USB_ST_SETUP:
1104tr_setup:
1105		usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
1106		usbd_transfer_submit(xfer);
1107		break;
1108	default:
1109		UHSO_DPRINTF(0, "error: %s\n", usbd_errstr(error));
1110		if (error == USB_ERR_CANCELLED)
1111			break;
1112
1113		usbd_xfer_set_stall(xfer);
1114		goto tr_setup;
1115	}
1116}
1117
1118static void
1119uhso_mux_read_callback(struct usb_xfer *xfer, usb_error_t error)
1120{
1121	struct uhso_softc *sc = usbd_xfer_softc(xfer);
1122	struct usb_page_cache *pc;
1123	struct usb_device_request req;
1124	struct uhso_tty *ht;
1125	int actlen, len;
1126
1127	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
1128
1129	UHSO_DPRINTF(3, "status %d\n", USB_GET_STATE(xfer));
1130
1131	ht = usbd_xfer_get_priv(xfer);
1132	UHSO_DPRINTF(3, "ht=%p open=%d\n", ht, ht->ht_open);
1133
1134	switch (USB_GET_STATE(xfer)) {
1135	case USB_ST_TRANSFERRED:
1136		/* Got data, send to ucom */
1137		pc = usbd_xfer_get_frame(xfer, 1);
1138		len = usbd_xfer_frame_len(xfer, 1);
1139
1140		UHSO_DPRINTF(3, "got %d bytes on mux port %d\n", len,
1141		    ht->ht_muxport);
1142		if (len <= 0) {
1143			usbd_transfer_start(sc->sc_xfer[UHSO_MUX_ENDPT_INTR]);
1144			break;
1145		}
1146
1147		/* Deliver data if the TTY is open, discard otherwise */
1148		if (ht->ht_open)
1149			ucom_put_data(&sc->sc_ucom[ht->ht_muxport], pc, 0, len);
1150		/* FALLTHROUGH */
1151	case USB_ST_SETUP:
1152tr_setup:
1153		bzero(&req, sizeof(struct usb_device_request));
1154		req.bmRequestType = UT_READ_CLASS_INTERFACE;
1155		req.bRequest = UCDC_GET_ENCAPSULATED_RESPONSE;
1156		USETW(req.wValue, 0);
1157		USETW(req.wIndex, ht->ht_muxport);
1158		USETW(req.wLength, 1024);
1159
1160		pc = usbd_xfer_get_frame(xfer, 0);
1161		usbd_copy_in(pc, 0, &req, sizeof(req));
1162
1163		usbd_xfer_set_frame_len(xfer, 0, sizeof(req));
1164		usbd_xfer_set_frame_len(xfer, 1, 1024);
1165		usbd_xfer_set_frames(xfer, 2);
1166		usbd_transfer_submit(xfer);
1167		break;
1168	default:
1169		UHSO_DPRINTF(0, "error: %s\n", usbd_errstr(error));
1170		if (error == USB_ERR_CANCELLED)
1171			break;
1172		usbd_xfer_set_stall(xfer);
1173		goto tr_setup;
1174	}
1175}
1176
1177static void
1178uhso_mux_write_callback(struct usb_xfer *xfer, usb_error_t error)
1179{
1180	struct uhso_softc *sc = usbd_xfer_softc(xfer);
1181	struct uhso_tty *ht;
1182	struct usb_page_cache *pc;
1183	struct usb_device_request req;
1184	int actlen;
1185	struct usb_page_search res;
1186
1187	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
1188
1189	ht = usbd_xfer_get_priv(xfer);
1190	UHSO_DPRINTF(3, "status=%d, using mux port %d\n",
1191	    USB_GET_STATE(xfer), ht->ht_muxport);
1192
1193	switch (USB_GET_STATE(xfer)) {
1194	case USB_ST_TRANSFERRED:
1195		UHSO_DPRINTF(3, "wrote %zd data bytes to muxport %d\n",
1196		    actlen - sizeof(struct usb_device_request) ,
1197		    ht->ht_muxport);
1198		/* FALLTHROUGH */
1199	case USB_ST_SETUP:
1200		pc = usbd_xfer_get_frame(xfer, 1);
1201		if (ucom_get_data(&sc->sc_ucom[ht->ht_muxport], pc,
1202		    0, 32, &actlen)) {
1203
1204			usbd_get_page(pc, 0, &res);
1205
1206			bzero(&req, sizeof(struct usb_device_request));
1207			req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
1208			req.bRequest = UCDC_SEND_ENCAPSULATED_COMMAND;
1209			USETW(req.wValue, 0);
1210			USETW(req.wIndex, ht->ht_muxport);
1211			USETW(req.wLength, actlen);
1212
1213			pc = usbd_xfer_get_frame(xfer, 0);
1214			usbd_copy_in(pc, 0, &req, sizeof(req));
1215
1216			usbd_xfer_set_frame_len(xfer, 0, sizeof(req));
1217			usbd_xfer_set_frame_len(xfer, 1, actlen);
1218			usbd_xfer_set_frames(xfer, 2);
1219
1220			UHSO_DPRINTF(3, "Prepared %d bytes for transmit "
1221			    "on muxport %d\n", actlen, ht->ht_muxport);
1222
1223			usbd_transfer_submit(xfer);
1224		}
1225		break;
1226	default:
1227		UHSO_DPRINTF(0, "error: %s\n", usbd_errstr(error));
1228		if (error == USB_ERR_CANCELLED)
1229			break;
1230		break;
1231	}
1232}
1233
1234static int
1235uhso_attach_bulkserial(struct uhso_softc *sc, struct usb_interface *iface,
1236    int type)
1237{
1238	usb_error_t uerr;
1239	int tty;
1240
1241	/* Try attaching RD/WR/INTR first */
1242	uerr = usbd_transfer_setup(sc->sc_udev,
1243	    &iface->idesc->bInterfaceNumber, sc->sc_xfer,
1244	    uhso_bs_config, UHSO_BULK_ENDPT_MAX, sc, &sc->sc_mtx);
1245	if (uerr) {
1246		/* Try only RD/WR */
1247		uerr = usbd_transfer_setup(sc->sc_udev,
1248		    &iface->idesc->bInterfaceNumber, sc->sc_xfer,
1249		    uhso_bs_config, UHSO_BULK_ENDPT_MAX - 1, sc, &sc->sc_mtx);
1250	}
1251	if (uerr) {
1252		UHSO_DPRINTF(0, "usbd_transfer_setup failed");
1253		return (-1);
1254	}
1255
1256	tty = uhso_alloc_tty(sc);
1257	if (tty < 0) {
1258		usbd_transfer_unsetup(sc->sc_xfer, UHSO_BULK_ENDPT_MAX);
1259		return (ENOMEM);
1260	}
1261
1262	sc->sc_tty[tty].ht_muxport = -1;
1263	return (0);
1264}
1265
1266static void
1267uhso_bs_read_callback(struct usb_xfer *xfer, usb_error_t error)
1268{
1269	struct uhso_softc *sc = usbd_xfer_softc(xfer);
1270	struct usb_page_cache *pc;
1271	int actlen;
1272
1273	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
1274
1275	UHSO_DPRINTF(3, "status %d, actlen=%d\n", USB_GET_STATE(xfer), actlen);
1276
1277	switch (USB_GET_STATE(xfer)) {
1278	case USB_ST_TRANSFERRED:
1279		pc = usbd_xfer_get_frame(xfer, 0);
1280		ucom_put_data(&sc->sc_ucom[0], pc, 0, actlen);
1281		/* FALLTHROUGH */
1282	case USB_ST_SETUP:
1283tr_setup:
1284		usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
1285		usbd_transfer_submit(xfer);
1286	break;
1287	default:
1288		UHSO_DPRINTF(0, "error: %s\n", usbd_errstr(error));
1289		if (error == USB_ERR_CANCELLED)
1290			break;
1291		usbd_xfer_set_stall(xfer);
1292		goto tr_setup;
1293	}
1294}
1295
1296static void
1297uhso_bs_write_callback(struct usb_xfer *xfer, usb_error_t error)
1298{
1299	struct uhso_softc *sc = usbd_xfer_softc(xfer);
1300	struct usb_page_cache *pc;
1301	int actlen;
1302
1303	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
1304
1305	UHSO_DPRINTF(3, "status %d, actlen=%d\n", USB_GET_STATE(xfer), actlen);
1306
1307	switch (USB_GET_STATE(xfer)) {
1308	case USB_ST_TRANSFERRED:
1309	case USB_ST_SETUP:
1310tr_setup:
1311		pc = usbd_xfer_get_frame(xfer, 0);
1312		if (ucom_get_data(&sc->sc_ucom[0], pc, 0, 8192, &actlen)) {
1313			usbd_xfer_set_frame_len(xfer, 0, actlen);
1314			usbd_transfer_submit(xfer);
1315		}
1316		break;
1317	break;
1318	default:
1319		UHSO_DPRINTF(0, "error: %s\n", usbd_errstr(error));
1320		if (error == USB_ERR_CANCELLED)
1321			break;
1322		usbd_xfer_set_stall(xfer);
1323		goto tr_setup;
1324	}
1325}
1326
1327static void
1328uhso_bs_cfg(struct uhso_softc *sc)
1329{
1330	struct usb_device_request req;
1331	usb_error_t uerr;
1332
1333	if (!(UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_BULK))
1334		return;
1335
1336	req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
1337	req.bRequest = UCDC_SET_CONTROL_LINE_STATE;
1338	USETW(req.wValue, sc->sc_line);
1339	USETW(req.wIndex, sc->sc_iface_no);
1340	USETW(req.wLength, 0);
1341
1342	uerr = ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom[0], &req, NULL, 0, 1000);
1343	if (uerr != 0) {
1344		device_printf(sc->sc_dev, "failed to set ctrl line state to "
1345		    "0x%02x: %s\n", sc->sc_line, usbd_errstr(uerr));
1346	}
1347}
1348
1349static void
1350uhso_bs_intr_callback(struct usb_xfer *xfer, usb_error_t error)
1351{
1352	struct uhso_softc *sc = usbd_xfer_softc(xfer);
1353	struct usb_page_cache *pc;
1354	int actlen;
1355	struct usb_cdc_notification cdc;
1356
1357	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
1358	UHSO_DPRINTF(3, "status %d, actlen=%d\n", USB_GET_STATE(xfer), actlen);
1359
1360	switch (USB_GET_STATE(xfer)) {
1361	case USB_ST_TRANSFERRED:
1362		if (actlen < UCDC_NOTIFICATION_LENGTH) {
1363			UHSO_DPRINTF(0, "UCDC notification too short: %d\n", actlen);
1364			goto tr_setup;
1365		}
1366		else if (actlen > sizeof(struct usb_cdc_notification)) {
1367			UHSO_DPRINTF(0, "UCDC notification too large: %d\n", actlen);
1368			actlen = sizeof(struct usb_cdc_notification);
1369		}
1370
1371		pc = usbd_xfer_get_frame(xfer, 0);
1372		usbd_copy_out(pc, 0, &cdc, actlen);
1373
1374		if (UGETW(cdc.wIndex) != sc->sc_iface_no) {
1375			UHSO_DPRINTF(0, "Interface mismatch, got %d expected %d\n",
1376			    UGETW(cdc.wIndex), sc->sc_iface_no);
1377			goto tr_setup;
1378		}
1379
1380		if (cdc.bmRequestType == UCDC_NOTIFICATION &&
1381		    cdc.bNotification == UCDC_N_SERIAL_STATE) {
1382			UHSO_DPRINTF(2, "notify = 0x%02x\n", cdc.data[0]);
1383
1384			sc->sc_msr = 0;
1385			sc->sc_lsr = 0;
1386			if (cdc.data[0] & UCDC_N_SERIAL_RI)
1387				sc->sc_msr |= SER_RI;
1388			if (cdc.data[0] & UCDC_N_SERIAL_DSR)
1389				sc->sc_msr |= SER_DSR;
1390			if (cdc.data[0] & UCDC_N_SERIAL_DCD)
1391				sc->sc_msr |= SER_DCD;
1392
1393			ucom_status_change(&sc->sc_ucom[0]);
1394		}
1395	case USB_ST_SETUP:
1396tr_setup:
1397	default:
1398		if (error == USB_ERR_CANCELLED)
1399			break;
1400		usbd_xfer_set_stall(xfer);
1401		goto tr_setup;
1402	}
1403}
1404
1405static void
1406uhso_ucom_cfg_get_status(struct ucom_softc *ucom, uint8_t *lsr, uint8_t *msr)
1407{
1408	struct uhso_softc *sc = ucom->sc_parent;
1409
1410	*lsr = sc->sc_lsr;
1411	*msr = sc->sc_msr;
1412}
1413
1414static void
1415uhso_ucom_cfg_set_dtr(struct ucom_softc *ucom, uint8_t onoff)
1416{
1417	struct uhso_softc *sc = ucom->sc_parent;
1418
1419	if (!(UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_BULK))
1420		return;
1421
1422	if (onoff)
1423		sc->sc_line |= UCDC_LINE_DTR;
1424	else
1425		sc->sc_line &= ~UCDC_LINE_DTR;
1426
1427	uhso_bs_cfg(sc);
1428}
1429
1430static void
1431uhso_ucom_cfg_set_rts(struct ucom_softc *ucom, uint8_t onoff)
1432{
1433	struct uhso_softc *sc = ucom->sc_parent;
1434
1435	if (!(UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_BULK))
1436		return;
1437
1438	if (onoff)
1439		sc->sc_line |= UCDC_LINE_RTS;
1440	else
1441		sc->sc_line &= ~UCDC_LINE_RTS;
1442
1443	uhso_bs_cfg(sc);
1444}
1445
1446static void
1447uhso_ucom_start_read(struct ucom_softc *ucom)
1448{
1449	struct uhso_softc *sc = ucom->sc_parent;
1450
1451	UHSO_DPRINTF(3, "unit=%d, local_unit=%d\n",
1452	    ucom->sc_unit, ucom->sc_local_unit);
1453
1454	if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_MUX) {
1455		sc->sc_tty[ucom->sc_local_unit].ht_open = 1;
1456		usbd_transfer_start(sc->sc_xfer[UHSO_MUX_ENDPT_INTR]);
1457	}
1458	else if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_BULK) {
1459		sc->sc_tty[0].ht_open = 1;
1460		usbd_transfer_start(sc->sc_xfer[UHSO_BULK_ENDPT_READ]);
1461		if (sc->sc_xfer[UHSO_BULK_ENDPT_INTR] != NULL)
1462			usbd_transfer_start(sc->sc_xfer[UHSO_BULK_ENDPT_INTR]);
1463	}
1464}
1465
1466static void
1467uhso_ucom_stop_read(struct ucom_softc *ucom)
1468{
1469
1470	struct uhso_softc *sc = ucom->sc_parent;
1471
1472	if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_MUX) {
1473		sc->sc_tty[ucom->sc_local_unit].ht_open = 0;
1474		usbd_transfer_stop(
1475		    sc->sc_tty[ucom->sc_local_unit].ht_xfer[UHSO_CTRL_READ]);
1476	}
1477	else if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_BULK) {
1478		sc->sc_tty[0].ht_open = 0;
1479		usbd_transfer_start(sc->sc_xfer[UHSO_BULK_ENDPT_READ]);
1480		if (sc->sc_xfer[UHSO_BULK_ENDPT_INTR] != NULL)
1481			usbd_transfer_stop(sc->sc_xfer[UHSO_BULK_ENDPT_INTR]);
1482	}
1483}
1484
1485static void
1486uhso_ucom_start_write(struct ucom_softc *ucom)
1487{
1488	struct uhso_softc *sc = ucom->sc_parent;
1489
1490	if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_MUX) {
1491		UHSO_DPRINTF(3, "local unit %d\n", ucom->sc_local_unit);
1492
1493		usbd_transfer_start(sc->sc_xfer[UHSO_MUX_ENDPT_INTR]);
1494
1495		usbd_xfer_set_priv(
1496		    sc->sc_tty[ucom->sc_local_unit].ht_xfer[UHSO_CTRL_WRITE],
1497		    &sc->sc_tty[ucom->sc_local_unit]);
1498		usbd_transfer_start(
1499		    sc->sc_tty[ucom->sc_local_unit].ht_xfer[UHSO_CTRL_WRITE]);
1500
1501	}
1502	else if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_BULK) {
1503		usbd_transfer_start(sc->sc_xfer[UHSO_BULK_ENDPT_WRITE]);
1504	}
1505}
1506
1507static void
1508uhso_ucom_stop_write(struct ucom_softc *ucom)
1509{
1510	struct uhso_softc *sc = ucom->sc_parent;
1511
1512	if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_MUX) {
1513		usbd_transfer_stop(
1514		    sc->sc_tty[ucom->sc_local_unit].ht_xfer[UHSO_CTRL_WRITE]);
1515	}
1516	else if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_BULK) {
1517		usbd_transfer_stop(sc->sc_xfer[UHSO_BULK_ENDPT_WRITE]);
1518	}
1519}
1520
1521static int
1522uhso_attach_ifnet(struct uhso_softc *sc, struct usb_interface *iface, int type)
1523{
1524	struct ifnet *ifp;
1525	usb_error_t uerr;
1526	struct sysctl_ctx_list *sctx;
1527	struct sysctl_oid *soid;
1528	unsigned int devunit;
1529
1530	uerr = usbd_transfer_setup(sc->sc_udev,
1531	    &iface->idesc->bInterfaceNumber, sc->sc_if_xfer,
1532	    uhso_ifnet_config, UHSO_IFNET_MAX, sc, &sc->sc_mtx);
1533	if (uerr) {
1534		UHSO_DPRINTF(0, "usbd_transfer_setup failed: %s\n",
1535		    usbd_errstr(uerr));
1536		return (-1);
1537	}
1538
1539	sc->sc_ifp = ifp = if_alloc(IFT_OTHER);
1540	if (sc->sc_ifp == NULL) {
1541		device_printf(sc->sc_dev, "if_alloc() failed\n");
1542		return (-1);
1543	}
1544
1545	callout_init_mtx(&sc->sc_c, &sc->sc_mtx, 0);
1546	mtx_lock(&sc->sc_mtx);
1547	callout_reset(&sc->sc_c, 1, uhso_if_rxflush, sc);
1548	mtx_unlock(&sc->sc_mtx);
1549
1550	/*
1551	 * We create our own unit numbers for ifnet devices because the
1552	 * USB interface unit numbers can be at arbitrary positions yielding
1553	 * odd looking device names.
1554	 */
1555	devunit = alloc_unr(uhso_ifnet_unit);
1556
1557	if_initname(ifp, device_get_name(sc->sc_dev), devunit);
1558	ifp->if_mtu = UHSO_MAX_MTU;
1559	ifp->if_ioctl = uhso_if_ioctl;
1560	ifp->if_init = uhso_if_init;
1561	ifp->if_start = uhso_if_start;
1562	ifp->if_output = uhso_if_output;
1563	ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST | IFF_NOARP;
1564	ifp->if_softc = sc;
1565	IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
1566	ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
1567	IFQ_SET_READY(&ifp->if_snd);
1568
1569	if_attach(ifp);
1570	bpfattach(ifp, DLT_RAW, 0);
1571
1572	sctx = device_get_sysctl_ctx(sc->sc_dev);
1573	soid = device_get_sysctl_tree(sc->sc_dev);
1574	/* Unlocked read... */
1575	SYSCTL_ADD_STRING(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "netif",
1576	    CTLFLAG_RD, ifp->if_xname, 0, "Attached network interface");
1577
1578	return (0);
1579}
1580
1581static void
1582uhso_ifnet_read_callback(struct usb_xfer *xfer, usb_error_t error)
1583{
1584	struct uhso_softc *sc = usbd_xfer_softc(xfer);
1585	struct mbuf *m;
1586	struct usb_page_cache *pc;
1587	int actlen;
1588
1589	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
1590
1591	UHSO_DPRINTF(3, "status=%d, actlen=%d\n", USB_GET_STATE(xfer), actlen);
1592
1593	switch (USB_GET_STATE(xfer)) {
1594	case USB_ST_TRANSFERRED:
1595		if (actlen > 0 && (sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING)) {
1596			pc = usbd_xfer_get_frame(xfer, 0);
1597			m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
1598			usbd_copy_out(pc, 0, mtod(m, uint8_t *), actlen);
1599			m->m_pkthdr.len = m->m_len = actlen;
1600			/* Enqueue frame for further processing */
1601			_IF_ENQUEUE(&sc->sc_rxq, m);
1602			if (!callout_pending(&sc->sc_c) ||
1603			    !callout_active(&sc->sc_c)) {
1604				callout_schedule(&sc->sc_c, 1);
1605			}
1606		}
1607	/* FALLTHROUGH */
1608	case USB_ST_SETUP:
1609tr_setup:
1610		usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
1611		usbd_transfer_submit(xfer);
1612		break;
1613	default:
1614		UHSO_DPRINTF(0, "error: %s\n", usbd_errstr(error));
1615		if (error == USB_ERR_CANCELLED)
1616			break;
1617		usbd_xfer_set_stall(xfer);
1618		goto tr_setup;
1619	}
1620}
1621
1622/*
1623 * Deferred RX processing, called with mutex locked.
1624 *
1625 * Each frame we receive might contain several small ip-packets as well
1626 * as partial ip-packets. We need to separate/assemble them into individual
1627 * packets before sending them to the ip-layer.
1628 */
1629static void
1630uhso_if_rxflush(void *arg)
1631{
1632	struct uhso_softc *sc = arg;
1633	struct ifnet *ifp = sc->sc_ifp;
1634	uint8_t *cp;
1635	struct mbuf *m, *m0, *mwait;
1636	struct ip *ip;
1637#ifdef INET6
1638	struct ip6_hdr *ip6;
1639#endif
1640	uint16_t iplen;
1641	int len, isr;
1642
1643	m = NULL;
1644	mwait = sc->sc_mwait;
1645	for (;;) {
1646		if (m == NULL) {
1647			_IF_DEQUEUE(&sc->sc_rxq, m);
1648			if (m == NULL)
1649				break;
1650			UHSO_DPRINTF(3, "dequeue m=%p, len=%d\n", m, m->m_len);
1651		}
1652		mtx_unlock(&sc->sc_mtx);
1653
1654		/* Do we have a partial packet waiting? */
1655		if (mwait != NULL) {
1656			m0 = mwait;
1657			mwait = NULL;
1658
1659			UHSO_DPRINTF(3, "partial m0=%p(%d), concat w/ m=%p(%d)\n",
1660			    m0, m0->m_len, m, m->m_len);
1661			len = m->m_len + m0->m_len;
1662
1663			/* Concat mbufs and fix headers */
1664			m_cat(m0, m);
1665			m0->m_pkthdr.len = len;
1666			m->m_flags &= ~M_PKTHDR;
1667
1668			m = m_pullup(m0, sizeof(struct ip));
1669			if (m == NULL) {
1670				ifp->if_ierrors++;
1671				UHSO_DPRINTF(0, "m_pullup failed\n");
1672				mtx_lock(&sc->sc_mtx);
1673				continue;
1674			}
1675			UHSO_DPRINTF(3, "Constructed mbuf=%p, len=%d\n",
1676			    m, m->m_pkthdr.len);
1677		}
1678
1679		cp = mtod(m, uint8_t *);
1680		ip = (struct ip *)cp;
1681#ifdef INET6
1682		ip6 = (struct ip6_hdr *)cp;
1683#endif
1684
1685		/* Check for IPv4 */
1686		if (ip->ip_v == IPVERSION) {
1687			iplen = htons(ip->ip_len);
1688			isr = NETISR_IP;
1689		}
1690#ifdef INET6
1691		/* Check for IPv6 */
1692		else if ((ip6->ip6_vfc & IPV6_VERSION_MASK) == IPV6_VERSION) {
1693			iplen = htons(ip6->ip6_plen);
1694			isr = NETISR_IPV6;
1695		}
1696#endif
1697		else {
1698			UHSO_DPRINTF(0, "got unexpected ip version %d, "
1699			    "m=%p, len=%d\n", (*cp & 0xf0) >> 4, m, m->m_len);
1700			ifp->if_ierrors++;
1701			UHSO_HEXDUMP(cp, 4);
1702			m_freem(m);
1703			m = NULL;
1704			mtx_lock(&sc->sc_mtx);
1705			continue;
1706		}
1707
1708		if (iplen == 0) {
1709			UHSO_DPRINTF(0, "Zero IP length\n");
1710			ifp->if_ierrors++;
1711			m_freem(m);
1712			m = NULL;
1713			mtx_lock(&sc->sc_mtx);
1714			continue;
1715		}
1716
1717		UHSO_DPRINTF(3, "m=%p, len=%d, cp=%p, iplen=%d\n",
1718		    m, m->m_pkthdr.len, cp, iplen);
1719
1720		m0 = NULL;
1721
1722		/* More IP packets in this mbuf */
1723		if (iplen < m->m_pkthdr.len) {
1724			m0 = m;
1725
1726			/*
1727			 * Allocate a new mbuf for this IP packet and
1728			 * copy the IP-packet into it.
1729			 */
1730			m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
1731			bcopy(mtod(m0, uint8_t *), mtod(m, uint8_t *), iplen);
1732			m->m_pkthdr.len = m->m_len = iplen;
1733
1734			/* Adjust the size of the original mbuf */
1735			m_adj(m0, iplen);
1736			m0 = m_defrag(m0, M_WAIT);
1737
1738			UHSO_DPRINTF(3, "New mbuf=%p, len=%d/%d, m0=%p, "
1739			    "m0_len=%d/%d\n", m, m->m_pkthdr.len, m->m_len,
1740			    m0, m0->m_pkthdr.len, m0->m_len);
1741		}
1742		else if (iplen > m->m_pkthdr.len) {
1743			UHSO_DPRINTF(3, "Deferred mbuf=%p, len=%d\n",
1744			    m, m->m_pkthdr.len);
1745			mwait = m;
1746			m = NULL;
1747			mtx_lock(&sc->sc_mtx);
1748			continue;
1749		}
1750
1751		ifp->if_ipackets++;
1752		m->m_pkthdr.rcvif = ifp;
1753
1754		/* Dispatch to IP layer */
1755		BPF_MTAP(sc->sc_ifp, m);
1756		netisr_dispatch(isr, m);
1757		m = m0 != NULL ? m0 : NULL;
1758		mtx_lock(&sc->sc_mtx);
1759	}
1760	sc->sc_mwait = mwait;
1761}
1762
1763static void
1764uhso_ifnet_write_callback(struct usb_xfer *xfer, usb_error_t error)
1765{
1766	struct uhso_softc *sc = usbd_xfer_softc(xfer);
1767	struct ifnet *ifp = sc->sc_ifp;
1768	struct usb_page_cache *pc;
1769	struct mbuf *m;
1770	int actlen;
1771
1772	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
1773
1774	UHSO_DPRINTF(3, "status %d, actlen=%d\n", USB_GET_STATE(xfer), actlen);
1775
1776	switch (USB_GET_STATE(xfer)) {
1777	case USB_ST_TRANSFERRED:
1778		ifp->if_opackets++;
1779		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1780	case USB_ST_SETUP:
1781tr_setup:
1782		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
1783		if (m == NULL)
1784			break;
1785
1786		ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1787
1788		if (m->m_pkthdr.len > MCLBYTES)
1789			m->m_pkthdr.len = MCLBYTES;
1790
1791		usbd_xfer_set_frame_len(xfer, 0, m->m_pkthdr.len);
1792		pc = usbd_xfer_get_frame(xfer, 0);
1793		usbd_m_copy_in(pc, 0, m, 0, m->m_pkthdr.len);
1794		usbd_transfer_submit(xfer);
1795
1796		BPF_MTAP(ifp, m);
1797		m_freem(m);
1798		break;
1799	default:
1800		UHSO_DPRINTF(0, "error: %s\n", usbd_errstr(error));
1801		if (error == USB_ERR_CANCELLED)
1802			break;
1803		usbd_xfer_set_stall(xfer);
1804		goto tr_setup;
1805	}
1806}
1807
1808static int
1809uhso_if_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1810{
1811	struct uhso_softc *sc;
1812
1813	sc = ifp->if_softc;
1814
1815	switch (cmd) {
1816	case SIOCSIFFLAGS:
1817		if (ifp->if_flags & IFF_UP) {
1818			if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
1819				uhso_if_init(sc);
1820			}
1821		}
1822		else {
1823			if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
1824				mtx_lock(&sc->sc_mtx);
1825				uhso_if_stop(sc);
1826				mtx_unlock(&sc->sc_mtx);
1827			}
1828		}
1829		break;
1830	case SIOCSIFADDR:
1831	case SIOCSIFDSTADDR:
1832	case SIOCADDMULTI:
1833	case SIOCDELMULTI:
1834		break;
1835	default:
1836		return (EINVAL);
1837	}
1838	return (0);
1839}
1840
1841static void
1842uhso_if_init(void *priv)
1843{
1844	struct uhso_softc *sc = priv;
1845	struct ifnet *ifp = sc->sc_ifp;
1846
1847	mtx_lock(&sc->sc_mtx);
1848	uhso_if_stop(sc);
1849	ifp = sc->sc_ifp;
1850	ifp->if_flags |= IFF_UP;
1851	ifp->if_drv_flags |= IFF_DRV_RUNNING;
1852	mtx_unlock(&sc->sc_mtx);
1853
1854	UHSO_DPRINTF(2, "ifnet initialized\n");
1855}
1856
1857static int
1858uhso_if_output(struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst,
1859    struct route *ro)
1860{
1861	int error;
1862
1863	/* Only IPv4/6 support */
1864	if (dst->sa_family != AF_INET
1865#ifdef INET6
1866	   && dst->sa_family != AF_INET6
1867#endif
1868	 ) {
1869		return (EAFNOSUPPORT);
1870	}
1871
1872	error = (ifp->if_transmit)(ifp, m0);
1873	if (error) {
1874		ifp->if_oerrors++;
1875		return (ENOBUFS);
1876	}
1877	ifp->if_opackets++;
1878	return (0);
1879}
1880
1881static void
1882uhso_if_start(struct ifnet *ifp)
1883{
1884	struct uhso_softc *sc = ifp->if_softc;
1885
1886	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
1887		UHSO_DPRINTF(1, "Not running\n");
1888		return;
1889	}
1890
1891	mtx_lock(&sc->sc_mtx);
1892	usbd_transfer_start(sc->sc_if_xfer[UHSO_IFNET_READ]);
1893	usbd_transfer_start(sc->sc_if_xfer[UHSO_IFNET_WRITE]);
1894	mtx_unlock(&sc->sc_mtx);
1895	UHSO_DPRINTF(3, "interface started\n");
1896}
1897
1898static void
1899uhso_if_stop(struct uhso_softc *sc)
1900{
1901
1902	usbd_transfer_stop(sc->sc_if_xfer[UHSO_IFNET_READ]);
1903	usbd_transfer_stop(sc->sc_if_xfer[UHSO_IFNET_WRITE]);
1904	sc->sc_ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
1905}
1906