xref: /dragonfly/sys/bus/u4b/net/if_urndis.c (revision 0ca59c34)
1 /*	$OpenBSD: if_urndis.c,v 1.46 2013/12/09 15:45:29 pirofti Exp $ */
2 
3 /*
4  * Copyright (c) 2010 Jonathan Armani <armani@openbsd.org>
5  * Copyright (c) 2010 Fabien Romano <fabien@openbsd.org>
6  * Copyright (c) 2010 Michael Knudsen <mk@openbsd.org>
7  * Copyright (c) 2014 Hans Petter Selasky <hselasky@freebsd.org>
8  * All rights reserved.
9  *
10  * Permission to use, copy, modify, and distribute this software for any
11  * purpose with or without fee is hereby granted, provided that the above
12  * copyright notice and this permission notice appear in all copies.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
15  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
17  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
20  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21  *
22  * $FreeBSD: head/sys/dev/usb/net/if_urndis.c 261544 2014-02-06 10:47:47Z hselasky $
23  */
24 
25 #include <sys/stdint.h>
26 #include <sys/param.h>
27 #include <sys/queue.h>
28 #include <sys/types.h>
29 #include <sys/systm.h>
30 #include <sys/socket.h>
31 #include <sys/kernel.h>
32 #include <sys/bus.h>
33 #include <sys/module.h>
34 #include <sys/lock.h>
35 #include <sys/condvar.h>
36 #include <sys/sysctl.h>
37 #include <sys/unistd.h>
38 #include <sys/callout.h>
39 #include <sys/malloc.h>
40 #include <sys/priv.h>
41 
42 #include <net/if.h>
43 #include <net/if_var.h>
44 #include <net/ifq_var.h>
45 
46 #include <bus/u4b/usb.h>
47 #include <bus/u4b/usbdi.h>
48 #include <bus/u4b/usbdi_util.h>
49 #include "usbdevs.h"
50 
51 #define	USB_DEBUG_VAR urndis_debug
52 #include <bus/u4b/usb_debug.h>
53 #include <bus/u4b/usb_process.h>
54 #include "usb_if.h"
55 
56 #include <bus/u4b/net/usb_ethernet.h>
57 #include <bus/u4b/net/if_urndisreg.h>
58 
59 #include <bus/u4b/usb_cdc.h>
60 
61 static device_probe_t urndis_probe;
62 static device_attach_t urndis_attach;
63 static device_detach_t urndis_detach;
64 static device_suspend_t urndis_suspend;
65 static device_resume_t urndis_resume;
66 
67 static usb_callback_t urndis_bulk_write_callback;
68 static usb_callback_t urndis_bulk_read_callback;
69 static usb_callback_t urndis_intr_read_callback;
70 
71 static uether_fn_t urndis_attach_post;
72 static uether_fn_t urndis_init;
73 static uether_fn_t urndis_stop;
74 static uether_fn_t urndis_start;
75 static uether_fn_t urndis_setmulti;
76 static uether_fn_t urndis_setpromisc;
77 
78 static uint32_t urndis_ctrl_query(struct urndis_softc *, uint32_t, const void **, uint16_t *);
79 static uint32_t urndis_ctrl_set(struct urndis_softc *, uint32_t, struct urndis_set_req *, uint16_t);
80 static uint32_t urndis_ctrl_handle_init(struct urndis_softc *, const struct urndis_comp_hdr *);
81 static uint32_t urndis_ctrl_handle_query(struct urndis_softc *, const struct urndis_comp_hdr *, const void **, uint16_t *);
82 static uint32_t urndis_ctrl_handle_reset(struct urndis_softc *, const struct urndis_comp_hdr *);
83 static uint32_t urndis_ctrl_init(struct urndis_softc *);
84 
85 #ifdef USB_DEBUG
86 static int urndis_debug = 0;
87 static	SYSCTL_NODE(_hw_usb, OID_AUTO, urndis, CTLFLAG_RW, 0, "USB RNDIS-Ethernet");
88 SYSCTL_INT(_hw_usb_urndis, OID_AUTO, debug, CTLFLAG_RW, &urndis_debug, 0,
89     "Debug level");
90 #endif
91 
92 static const struct usb_config urndis_config[URNDIS_N_TRANSFER] = {
93 
94 	[URNDIS_BULK_RX] = {
95 		.type = UE_BULK,
96 		.endpoint = UE_ADDR_ANY,
97 		.direction = UE_DIR_RX,
98 		.if_index = 0,
99 		.frames = 1,
100 		.bufsize = RNDIS_RX_MAXLEN,
101 		.flags = {.short_xfer_ok = 1,},
102 		.callback = urndis_bulk_read_callback,
103 		.timeout = 0,		/* no timeout */
104 		.usb_mode = USB_MODE_HOST,
105 	},
106 
107 	[URNDIS_BULK_TX] = {
108 		.type = UE_BULK,
109 		.endpoint = UE_ADDR_ANY,
110 		.direction = UE_DIR_TX,
111 		.if_index = 0,
112 		.frames = RNDIS_TX_FRAMES_MAX,
113 		.bufsize = (RNDIS_TX_FRAMES_MAX * RNDIS_TX_MAXLEN),
114 		.flags = {
115 			.force_short_xfer = 1,
116 		},
117 		.callback = urndis_bulk_write_callback,
118 		.timeout = 10000,	/* 10 seconds */
119 		.usb_mode = USB_MODE_HOST,
120 	},
121 
122 	[URNDIS_INTR_RX] = {
123 		.type = UE_INTERRUPT,
124 		.endpoint = UE_ADDR_ANY,
125 		.direction = UE_DIR_RX,
126 		.if_index = 1,
127 		.bufsize = 0,	/* use wMaxPacketSize */
128 		.flags = {.short_xfer_ok = 1,.no_pipe_ok = 1,},
129 		.callback = urndis_intr_read_callback,
130 		.timeout = 0,
131 		.usb_mode = USB_MODE_HOST,
132 	},
133 };
134 
135 static device_method_t urndis_methods[] = {
136 	/* Device interface */
137 	DEVMETHOD(device_probe, urndis_probe),
138 	DEVMETHOD(device_attach, urndis_attach),
139 	DEVMETHOD(device_detach, urndis_detach),
140 	DEVMETHOD(device_suspend, urndis_suspend),
141 	DEVMETHOD(device_resume, urndis_resume),
142 
143 	DEVMETHOD_END
144 };
145 
146 static driver_t urndis_driver = {
147 	.name = "urndis",
148 	.methods = urndis_methods,
149 	.size = sizeof(struct urndis_softc),
150 };
151 
152 static devclass_t urndis_devclass;
153 
154 DRIVER_MODULE(urndis, uhub, urndis_driver, urndis_devclass, NULL, NULL);
155 MODULE_VERSION(urndis, 1);
156 MODULE_DEPEND(urndis, uether, 1, 1, 1);
157 MODULE_DEPEND(urndis, usb, 1, 1, 1);
158 MODULE_DEPEND(urndis, ether, 1, 1, 1);
159 
160 static const struct usb_ether_methods urndis_ue_methods = {
161 	.ue_attach_post = urndis_attach_post,
162 	.ue_start = urndis_start,
163 	.ue_init = urndis_init,
164 	.ue_stop = urndis_stop,
165 	.ue_setmulti = urndis_setmulti,
166 	.ue_setpromisc = urndis_setpromisc,
167 };
168 
169 static const STRUCT_USB_HOST_ID urndis_host_devs[] = {
170 	/* Generic RNDIS class match */
171 	{USB_IFACE_CLASS(UICLASS_WIRELESS), USB_IFACE_SUBCLASS(UISUBCLASS_RF),
172 	USB_IFACE_PROTOCOL(UIPROTO_RNDIS)},
173 	{USB_IFACE_CLASS(UICLASS_IAD), USB_IFACE_SUBCLASS(UISUBCLASS_SYNC),
174 	USB_IFACE_PROTOCOL(UIPROTO_ACTIVESYNC)},
175 	/* HP-WebOS */
176 	{USB_VENDOR(USB_VENDOR_PALM), USB_IFACE_CLASS(UICLASS_CDC),
177 		USB_IFACE_SUBCLASS(UISUBCLASS_ABSTRACT_CONTROL_MODEL),
178 		USB_IFACE_PROTOCOL(0xff)},
179 };
180 
181 static const STRUCT_USB_HOST_ID urndis_non_huawei_host_devs[] = {
182 	{USB_IFACE_CLASS(UICLASS_CDC),
183 	USB_IFACE_SUBCLASS(UISUBCLASS_ABSTRACT_CONTROL_MODEL),
184 	USB_IFACE_PROTOCOL(0xff)},
185 };
186 
187 static int
188 urndis_probe(device_t dev)
189 {
190 	int res;
191 	struct usb_attach_arg *uaa = device_get_ivars(dev);
192 
193 	res = usbd_lookup_id_by_uaa(urndis_host_devs,
194 	    sizeof(urndis_host_devs), uaa);
195 	if (res == 0)
196 		return(0);
197 	if (uaa->info.idVendor == USB_VENDOR_HUAWEI)
198 		return(ENXIO);
199 	return (usbd_lookup_id_by_uaa(urndis_non_huawei_host_devs,
200 		sizeof(urndis_non_huawei_host_devs), uaa));
201 }
202 
203 static void
204 urndis_attach_post(struct usb_ether *ue)
205 {
206 	/* no-op */
207 	return;
208 }
209 
210 static int
211 urndis_attach(device_t dev)
212 {
213 	struct urndis_softc *sc = device_get_softc(dev);
214 	struct usb_ether *ue = &sc->sc_ue;
215 	struct usb_attach_arg *uaa = device_get_ivars(dev);
216 	struct usb_cdc_cm_descriptor *cmd;
217 	struct {
218 		struct urndis_set_req hdr;
219 		uint32_t filter;
220 	} msg_filter;
221 	const void *buf;
222 	uint16_t bufsz;
223 	uint8_t iface_index[2] = { uaa->info.bIfaceIndex + 1, uaa->info.bIfaceIndex };
224 	int error;
225 	uint8_t i;
226 
227 	sc->sc_ue.ue_udev = uaa->device;
228 	sc->sc_ifaceno_ctl = uaa->info.bIfaceNum;
229 
230 	cmd = usbd_find_descriptor(uaa->device, NULL, uaa->info.bIfaceIndex,
231 	    UDESC_CS_INTERFACE, 0xFF, UDESCSUB_CDC_CM, 0xFF);
232 	if (cmd != NULL) {
233 		DPRINTF("Call Mode Descriptor found, dataif=%d\n", cmd->bDataInterface);
234 		iface_index[0] = cmd->bDataInterface;
235 	}
236 
237 	device_set_usb_desc(dev);
238 
239 	lockinit(&sc->sc_lock, device_get_nameunit(dev), 0, LK_CANRECURSE);
240 
241 	/* scan the alternate settings looking for a valid one */
242 
243 	for (i = 0; i != 32; i++) {
244 
245 		error = usbd_set_alt_interface_index(uaa->device,
246 		    iface_index[0], i);
247 
248 		if (error != 0)
249 			break;
250 
251 		error = usbd_transfer_setup(uaa->device,
252 		    iface_index, sc->sc_xfer, urndis_config,
253 		    URNDIS_N_TRANSFER, sc, &sc->sc_lock);
254 
255 		if (error == 0)
256 			break;
257 	}
258 
259 	if ((error != 0) || (i == 32)) {
260 		device_printf(dev, "No valid alternate "
261 		    "setting found\n");
262 		goto detach;
263 	}
264 	URNDIS_LOCK(sc);
265 	error = urndis_ctrl_query(sc, OID_802_3_PERMANENT_ADDRESS, &buf, &bufsz);
266 	URNDIS_UNLOCK(sc);
267 
268 	if (error != (int)RNDIS_STATUS_SUCCESS) {
269 		device_printf(dev, "Unable to get hardware address\n");
270 		goto detach;
271 	}
272 	if (bufsz != ETHER_ADDR_LEN) {
273 		device_printf(dev, "Invalid address length: %d bytes\n", bufsz);
274 		goto detach;
275 	}
276 	memcpy(&sc->sc_ue.ue_eaddr, buf, ETHER_ADDR_LEN);
277 
278 	/* Initialize packet filter */
279 	sc->sc_filter = RNDIS_PACKET_TYPE_BROADCAST |
280 	    RNDIS_PACKET_TYPE_ALL_MULTICAST;
281 	msg_filter.filter = htole32(sc->sc_filter);
282 
283 	URNDIS_LOCK(sc);
284 	error = urndis_ctrl_set(sc, OID_GEN_CURRENT_PACKET_FILTER,
285 	    &msg_filter.hdr, sizeof(msg_filter));
286 	URNDIS_UNLOCK(sc);
287 
288 	if (error != (int)RNDIS_STATUS_SUCCESS) {
289 		device_printf(dev, "Unable to set data filters\n");
290 		goto detach;
291 	}
292 	ue->ue_sc = sc;
293 	ue->ue_dev = dev;
294 	ue->ue_udev = uaa->device;
295 	ue->ue_lock = &sc->sc_lock;
296 	ue->ue_methods = &urndis_ue_methods;
297 
298 	error = uether_ifattach(ue);
299 	if (error) {
300 		device_printf(dev, "Could not attach interface\n");
301 		goto detach;
302 	}
303 
304 	URNDIS_LOCK(sc);
305 	/* start interrupt endpoint, if any */
306 	usbd_transfer_start(sc->sc_xfer[URNDIS_INTR_RX]);
307 	URNDIS_UNLOCK(sc);
308 
309 	return (0);			/* success */
310 
311 detach:
312 	urndis_detach(dev);
313 	return (ENXIO);			/* failure */
314 }
315 
316 static int
317 urndis_detach(device_t dev)
318 {
319 	struct urndis_softc *sc = device_get_softc(dev);
320 	struct usb_ether *ue = &sc->sc_ue;
321 
322 	/* stop all USB transfers first */
323 	usbd_transfer_unsetup(sc->sc_xfer, URNDIS_N_TRANSFER);
324 
325 	uether_ifdetach(ue);
326 
327 	lockuninit(&sc->sc_lock);
328 
329 	return (0);
330 }
331 
332 static void
333 urndis_start(struct usb_ether *ue)
334 {
335 	struct urndis_softc *sc = uether_getsc(ue);
336 
337 	/*
338 	 * Start the USB transfers, if not already started:
339 	 */
340 	usbd_transfer_start(sc->sc_xfer[URNDIS_BULK_TX]);
341 	usbd_transfer_start(sc->sc_xfer[URNDIS_BULK_RX]);
342 }
343 
344 static void
345 urndis_init(struct usb_ether *ue)
346 {
347 	struct urndis_softc *sc = uether_getsc(ue);
348 	struct ifnet *ifp = uether_getifp(ue);
349 
350 	URNDIS_LOCK_ASSERT(sc);
351 
352 	ifp->if_flags |= IFF_RUNNING;
353 
354 	urndis_ctrl_init(sc);
355 
356 	/* stall data write direction, which depends on USB mode */
357 	usbd_xfer_set_stall(sc->sc_xfer[URNDIS_BULK_TX]);
358 
359 	/* start data transfers */
360 	urndis_start(ue);
361 }
362 
363 static void
364 urndis_stop(struct usb_ether *ue)
365 {
366 	struct urndis_softc *sc = uether_getsc(ue);
367 	struct ifnet *ifp = uether_getifp(ue);
368 
369 	URNDIS_LOCK_ASSERT(sc);
370 
371 	ifp->if_flags &= ~IFF_RUNNING;
372 
373 	/*
374 	 * stop all the transfers, if not already stopped:
375 	 */
376 	usbd_transfer_stop(sc->sc_xfer[URNDIS_BULK_RX]);
377 	usbd_transfer_stop(sc->sc_xfer[URNDIS_BULK_TX]);
378 }
379 
380 static void
381 urndis_setmulti(struct usb_ether *ue)
382 {
383 	/* no-op */
384 	return;
385 }
386 
387 static void
388 urndis_setpromisc(struct usb_ether *ue)
389 {
390 	/* no-op */
391 	return;
392 }
393 
394 static int
395 urndis_suspend(device_t dev)
396 {
397 	device_printf(dev, "Suspending\n");
398 	return (0);
399 }
400 
401 static int
402 urndis_resume(device_t dev)
403 {
404 	device_printf(dev, "Resuming\n");
405 	return (0);
406 }
407 
408 static usb_error_t
409 urndis_ctrl_msg(struct urndis_softc *sc, uint8_t rt, uint8_t r,
410     uint16_t index, uint16_t value, void *buf, uint16_t buflen)
411 {
412 	usb_device_request_t req;
413 
414 	req.bmRequestType = rt;
415 	req.bRequest = r;
416 	USETW(req.wValue, value);
417 	USETW(req.wIndex, index);
418 	USETW(req.wLength, buflen);
419 
420 	return (usbd_do_request_flags(sc->sc_ue.ue_udev,
421 	    &sc->sc_lock, &req, buf, (rt & UT_READ) ?
422 	    USB_SHORT_XFER_OK : 0, NULL, 2000 /* ms */ ));
423 }
424 
425 static usb_error_t
426 urndis_ctrl_send(struct urndis_softc *sc, void *buf, uint16_t len)
427 {
428 	usb_error_t err;
429 
430 	err = urndis_ctrl_msg(sc, UT_WRITE_CLASS_INTERFACE, UR_GET_STATUS,
431 	    sc->sc_ifaceno_ctl, 0, buf, len);
432 
433 	DPRINTF("%s\n", usbd_errstr(err));
434 
435 	return (err);
436 }
437 
438 static struct urndis_comp_hdr *
439 urndis_ctrl_recv(struct urndis_softc *sc)
440 {
441 	struct urndis_comp_hdr *hdr;
442 	usb_error_t err;
443 
444 	err = urndis_ctrl_msg(sc, UT_READ_CLASS_INTERFACE, UR_CLEAR_FEATURE,
445 	    sc->sc_ifaceno_ctl, 0, sc->sc_response_buf, RNDIS_RESPONSE_LEN);
446 
447 	if (err != USB_ERR_NORMAL_COMPLETION)
448 		return (NULL);
449 
450 	hdr = (struct urndis_comp_hdr *)sc->sc_response_buf;
451 
452 	DPRINTF("type 0x%x len %u\n", le32toh(hdr->rm_type),
453 	    le32toh(hdr->rm_len));
454 
455 	if (le32toh(hdr->rm_len) > RNDIS_RESPONSE_LEN) {
456 		DPRINTF("ctrl message error: wrong size %u > %u\n",
457 		    le32toh(hdr->rm_len), RNDIS_RESPONSE_LEN);
458 		return (NULL);
459 	}
460 	return (hdr);
461 }
462 
463 static uint32_t
464 urndis_ctrl_handle(struct urndis_softc *sc, struct urndis_comp_hdr *hdr,
465     const void **buf, uint16_t *bufsz)
466 {
467 	uint32_t rval;
468 
469 	DPRINTF("\n");
470 
471 	if (buf != NULL && bufsz != NULL) {
472 		*buf = NULL;
473 		*bufsz = 0;
474 	}
475 	switch (le32toh(hdr->rm_type)) {
476 	case REMOTE_NDIS_INITIALIZE_CMPLT:
477 		rval = urndis_ctrl_handle_init(sc, hdr);
478 		break;
479 
480 	case REMOTE_NDIS_QUERY_CMPLT:
481 		rval = urndis_ctrl_handle_query(sc, hdr, buf, bufsz);
482 		break;
483 
484 	case REMOTE_NDIS_RESET_CMPLT:
485 		rval = urndis_ctrl_handle_reset(sc, hdr);
486 		break;
487 
488 	case REMOTE_NDIS_KEEPALIVE_CMPLT:
489 	case REMOTE_NDIS_SET_CMPLT:
490 		rval = le32toh(hdr->rm_status);
491 		break;
492 
493 	default:
494 		DPRINTF("ctrl message error: unknown event 0x%x\n",
495 		    le32toh(hdr->rm_type));
496 		rval = RNDIS_STATUS_FAILURE;
497 		break;
498 	}
499 	return (rval);
500 }
501 
502 static uint32_t
503 urndis_ctrl_handle_init(struct urndis_softc *sc,
504     const struct urndis_comp_hdr *hdr)
505 {
506 	const struct urndis_init_comp *msg;
507 
508 	msg = (const struct urndis_init_comp *)hdr;
509 
510 	DPRINTF("len %u rid %u status 0x%x "
511 	    "ver_major %u ver_minor %u devflags 0x%x medium 0x%x pktmaxcnt %u "
512 	    "pktmaxsz %u align %u aflistoffset %u aflistsz %u\n",
513 	    le32toh(msg->rm_len),
514 	    le32toh(msg->rm_rid),
515 	    le32toh(msg->rm_status),
516 	    le32toh(msg->rm_ver_major),
517 	    le32toh(msg->rm_ver_minor),
518 	    le32toh(msg->rm_devflags),
519 	    le32toh(msg->rm_medium),
520 	    le32toh(msg->rm_pktmaxcnt),
521 	    le32toh(msg->rm_pktmaxsz),
522 	    le32toh(msg->rm_align),
523 	    le32toh(msg->rm_aflistoffset),
524 	    le32toh(msg->rm_aflistsz));
525 
526 	if (le32toh(msg->rm_status) != RNDIS_STATUS_SUCCESS) {
527 		DPRINTF("init failed 0x%x\n", le32toh(msg->rm_status));
528 		return (le32toh(msg->rm_status));
529 	}
530 	if (le32toh(msg->rm_devflags) != RNDIS_DF_CONNECTIONLESS) {
531 		DPRINTF("wrong device type (current type: 0x%x)\n",
532 		    le32toh(msg->rm_devflags));
533 		return (RNDIS_STATUS_FAILURE);
534 	}
535 	if (le32toh(msg->rm_medium) != RNDIS_MEDIUM_802_3) {
536 		DPRINTF("medium not 802.3 (current medium: 0x%x)\n",
537 		    le32toh(msg->rm_medium));
538 		return (RNDIS_STATUS_FAILURE);
539 	}
540 	sc->sc_lim_pktsz = le32toh(msg->rm_pktmaxsz);
541 
542 	return (le32toh(msg->rm_status));
543 }
544 
545 static uint32_t
546 urndis_ctrl_handle_query(struct urndis_softc *sc,
547     const struct urndis_comp_hdr *hdr, const void **buf, uint16_t *bufsz)
548 {
549 	const struct urndis_query_comp *msg;
550 	uint64_t limit;
551 
552 	msg = (const struct urndis_query_comp *)hdr;
553 
554 	DPRINTF("len %u rid %u status 0x%x "
555 	    "buflen %u bufoff %u\n",
556 	    le32toh(msg->rm_len),
557 	    le32toh(msg->rm_rid),
558 	    le32toh(msg->rm_status),
559 	    le32toh(msg->rm_infobuflen),
560 	    le32toh(msg->rm_infobufoffset));
561 
562 	if (buf != NULL && bufsz != NULL) {
563 		*buf = NULL;
564 		*bufsz = 0;
565 	}
566 	if (le32toh(msg->rm_status) != RNDIS_STATUS_SUCCESS) {
567 		DPRINTF("query failed 0x%x\n", le32toh(msg->rm_status));
568 		return (le32toh(msg->rm_status));
569 	}
570 	limit = le32toh(msg->rm_infobuflen);
571 	limit += le32toh(msg->rm_infobufoffset);
572 	limit += RNDIS_HEADER_OFFSET;
573 
574 	if (limit > (uint64_t)le32toh(msg->rm_len)) {
575 		DPRINTF("ctrl message error: invalid query info "
576 		    "len/offset/end_position(%u/%u/%u) -> "
577 		    "go out of buffer limit %u\n",
578 		    le32toh(msg->rm_infobuflen),
579 		    le32toh(msg->rm_infobufoffset),
580 		    le32toh(msg->rm_infobuflen) +
581 		    le32toh(msg->rm_infobufoffset) + RNDIS_HEADER_OFFSET,
582 		    le32toh(msg->rm_len));
583 		return (RNDIS_STATUS_FAILURE);
584 	}
585 	if (buf != NULL && bufsz != NULL) {
586 		*buf = ((const uint8_t *)msg) + RNDIS_HEADER_OFFSET + le32toh(msg->rm_infobufoffset);
587 		*bufsz = le32toh(msg->rm_infobuflen);
588 	}
589 	return (le32toh(msg->rm_status));
590 }
591 
592 static uint32_t
593 urndis_ctrl_handle_reset(struct urndis_softc *sc,
594     const struct urndis_comp_hdr *hdr)
595 {
596 	const struct urndis_reset_comp *msg;
597 	uint32_t rval;
598 
599 	msg = (const struct urndis_reset_comp *)hdr;
600 
601 	rval = le32toh(msg->rm_status);
602 
603 	DPRINTF("len %u status 0x%x "
604 	    "adrreset %u\n",
605 	    le32toh(msg->rm_len),
606 	    rval,
607 	    le32toh(msg->rm_adrreset));
608 
609 	if (rval != RNDIS_STATUS_SUCCESS) {
610 		DPRINTF("reset failed 0x%x\n", rval);
611 		return (rval);
612 	}
613 	if (msg->rm_adrreset != 0) {
614 		struct {
615 			struct urndis_set_req hdr;
616 			uint32_t filter;
617 		} msg_filter;
618 
619 		msg_filter.filter = htole32(sc->sc_filter);
620 
621 		rval = urndis_ctrl_set(sc, OID_GEN_CURRENT_PACKET_FILTER,
622 		    &msg_filter.hdr, sizeof(msg_filter));
623 
624 		if (rval != RNDIS_STATUS_SUCCESS) {
625 			DPRINTF("unable to reset data filters\n");
626 			return (rval);
627 		}
628 	}
629 	return (rval);
630 }
631 
632 static uint32_t
633 urndis_ctrl_init(struct urndis_softc *sc)
634 {
635 	struct urndis_init_req msg;
636 	struct urndis_comp_hdr *hdr;
637 	uint32_t rval;
638 
639 	msg.rm_type = htole32(REMOTE_NDIS_INITIALIZE_MSG);
640 	msg.rm_len = htole32(sizeof(msg));
641 	msg.rm_rid = htole32(0);
642 	msg.rm_ver_major = htole32(1);
643 	msg.rm_ver_minor = htole32(1);
644 	msg.rm_max_xfersz = htole32(RNDIS_RX_MAXLEN);
645 
646 	DPRINTF("type %u len %u rid %u ver_major %u "
647 	    "ver_minor %u max_xfersz %u\n",
648 	    le32toh(msg.rm_type),
649 	    le32toh(msg.rm_len),
650 	    le32toh(msg.rm_rid),
651 	    le32toh(msg.rm_ver_major),
652 	    le32toh(msg.rm_ver_minor),
653 	    le32toh(msg.rm_max_xfersz));
654 
655 	rval = urndis_ctrl_send(sc, &msg, sizeof(msg));
656 
657 	if (rval != RNDIS_STATUS_SUCCESS) {
658 		DPRINTF("init failed\n");
659 		return (rval);
660 	}
661 	if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
662 		DPRINTF("unable to get init response\n");
663 		return (RNDIS_STATUS_FAILURE);
664 	}
665 	rval = urndis_ctrl_handle(sc, hdr, NULL, NULL);
666 
667 	return (rval);
668 }
669 
670 #if 0
671 static uint32_t
672 urndis_ctrl_halt(struct urndis_softc *sc)
673 {
674 	struct urndis_halt_req msg;
675 	uint32_t rval;
676 
677 	msg.rm_type = htole32(REMOTE_NDIS_HALT_MSG);
678 	msg.rm_len = htole32(sizeof(msg));
679 	msg.rm_rid = 0;
680 
681 	DPRINTF("type %u len %u rid %u\n",
682 	    le32toh(msg.rm_type),
683 	    le32toh(msg.rm_len),
684 	    le32toh(msg.rm_rid));
685 
686 	rval = urndis_ctrl_send(sc, &msg, sizeof(msg));
687 
688 	if (rval != RNDIS_STATUS_SUCCESS)
689 		printf("halt failed\n");
690 
691 	return (rval);
692 }
693 
694 #endif
695 
696 static uint32_t
697 urndis_ctrl_query(struct urndis_softc *sc, uint32_t oid, const void **rbuf, uint16_t *rbufsz)
698 {
699 	struct urndis_query_req msg;
700 	uint32_t rval;
701 	struct urndis_comp_hdr *hdr;
702 
703 	msg.rm_type = htole32(REMOTE_NDIS_QUERY_MSG);
704 	msg.rm_len = htole32(sizeof(msg));
705 	msg.rm_rid = 0;			/* XXX */
706 	msg.rm_oid = htole32(oid);
707 	msg.rm_infobuflen = htole32(0);
708 	msg.rm_infobufoffset = 0;
709 	msg.rm_devicevchdl = 0;
710 
711 	DPRINTF("type %u len %u rid %u oid 0x%x "
712 	    "infobuflen %u infobufoffset %u devicevchdl %u\n",
713 	    le32toh(msg.rm_type),
714 	    le32toh(msg.rm_len),
715 	    le32toh(msg.rm_rid),
716 	    le32toh(msg.rm_oid),
717 	    le32toh(msg.rm_infobuflen),
718 	    le32toh(msg.rm_infobufoffset),
719 	    le32toh(msg.rm_devicevchdl));
720 
721 	rval = urndis_ctrl_send(sc, &msg, sizeof(msg));
722 
723 	if (rval != RNDIS_STATUS_SUCCESS) {
724 		DPRINTF("query failed\n");
725 		return (rval);
726 	}
727 	if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
728 		DPRINTF("unable to get query response\n");
729 		return (RNDIS_STATUS_FAILURE);
730 	}
731 	rval = urndis_ctrl_handle(sc, hdr, rbuf, rbufsz);
732 
733 	return (rval);
734 }
735 
736 static uint32_t
737 urndis_ctrl_set(struct urndis_softc *sc, uint32_t oid, struct urndis_set_req *msg, uint16_t len)
738 {
739 	struct urndis_comp_hdr *hdr;
740 	uint32_t rval;
741 	uint32_t datalen = len - sizeof(*msg);
742 
743 	msg->rm_type = htole32(REMOTE_NDIS_SET_MSG);
744 	msg->rm_len = htole32(len);
745 	msg->rm_rid = 0;		/* XXX */
746 	msg->rm_oid = htole32(oid);
747 	msg->rm_infobuflen = htole32(datalen);
748 	if (datalen != 0) {
749 		msg->rm_infobufoffset = htole32(sizeof(*msg) - RNDIS_HEADER_OFFSET);
750 	} else {
751 		msg->rm_infobufoffset = 0;
752 	}
753 	msg->rm_devicevchdl = 0;
754 
755 	DPRINTF("type %u len %u rid %u oid 0x%x "
756 	    "infobuflen %u infobufoffset %u devicevchdl %u\n",
757 	    le32toh(msg->rm_type),
758 	    le32toh(msg->rm_len),
759 	    le32toh(msg->rm_rid),
760 	    le32toh(msg->rm_oid),
761 	    le32toh(msg->rm_infobuflen),
762 	    le32toh(msg->rm_infobufoffset),
763 	    le32toh(msg->rm_devicevchdl));
764 
765 	rval = urndis_ctrl_send(sc, msg, len);
766 
767 	if (rval != RNDIS_STATUS_SUCCESS) {
768 		DPRINTF("set failed\n");
769 		return (rval);
770 	}
771 	if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
772 		DPRINTF("unable to get set response\n");
773 		return (RNDIS_STATUS_FAILURE);
774 	}
775 	rval = urndis_ctrl_handle(sc, hdr, NULL, NULL);
776 	if (rval != RNDIS_STATUS_SUCCESS)
777 		DPRINTF("set failed 0x%x\n", rval);
778 
779 	return (rval);
780 }
781 
782 static void
783 urndis_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
784 {
785 	struct urndis_softc *sc = usbd_xfer_softc(xfer);
786 	struct usb_page_cache *pc = usbd_xfer_get_frame(xfer, 0);
787 	struct ifnet *ifp = uether_getifp(&sc->sc_ue);
788 	struct urndis_packet_msg msg;
789 	struct mbuf *m;
790 	int actlen;
791 	int aframes;
792 	int offset;
793 
794 	switch (USB_GET_STATE(xfer)) {
795 	case USB_ST_TRANSFERRED:
796 
797 		usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL);
798 
799 		DPRINTFN(1, "received %u bytes in %u frames\n", actlen, aframes);
800 
801 		for (offset = 0; actlen >= (uint32_t)sizeof(msg);) {
802 
803 			/* copy out header */
804 			usbd_copy_out(pc, offset, &msg, sizeof(msg));
805 
806 			if (le32toh(0x1234567U) != 0x1234567U) {
807 				/* swap endianness */
808 				msg.rm_type = le32toh(msg.rm_type);
809 				msg.rm_len = le32toh(msg.rm_len);
810 				msg.rm_dataoffset = le32toh(msg.rm_dataoffset);
811 				msg.rm_datalen = le32toh(msg.rm_datalen);
812 				msg.rm_oobdataoffset = le32toh(msg.rm_oobdataoffset);
813 				msg.rm_oobdatalen = le32toh(msg.rm_oobdatalen);
814 				msg.rm_oobdataelements = le32toh(msg.rm_oobdataelements);
815 				msg.rm_pktinfooffset = le32toh(msg.rm_pktinfooffset);
816 				msg.rm_pktinfolen = le32toh(msg.rm_pktinfolen);
817 				msg.rm_vchandle = le32toh(msg.rm_vchandle);
818 				msg.rm_reserved = le32toh(msg.rm_reserved);
819 			}
820 
821 			DPRINTF("len %u data(off:%u len:%u) "
822 			    "oobdata(off:%u len:%u nb:%u) perpacket(off:%u len:%u)\n",
823 			    msg.rm_len, msg.rm_dataoffset, msg.rm_datalen,
824 			    msg.rm_oobdataoffset, msg.rm_oobdatalen,
825 			    msg.rm_oobdataelements, msg.rm_pktinfooffset,
826 			    msg.rm_pktinfooffset);
827 
828 			/* sanity check the RNDIS header */
829 			if (msg.rm_type != REMOTE_NDIS_PACKET_MSG) {
830 				DPRINTF("invalid type 0x%x != 0x%x\n",
831 				    msg.rm_type, REMOTE_NDIS_PACKET_MSG);
832 				goto tr_setup;
833 			} else if (msg.rm_len < (uint32_t)sizeof(msg)) {
834 				DPRINTF("invalid msg len %u < %u\n",
835 				    msg.rm_len, (unsigned)sizeof(msg));
836 				goto tr_setup;
837 			} else if (msg.rm_len > (uint32_t)actlen) {
838 				DPRINTF("invalid msg len %u > buffer "
839 				    "len %u\n", msg.rm_len, actlen);
840 				goto tr_setup;
841 			} else if (msg.rm_dataoffset >= (uint32_t)actlen) {
842 				DPRINTF("invalid msg dataoffset %u > buffer "
843 				    "dataoffset %u\n", msg.rm_dataoffset, actlen);
844 				goto tr_setup;
845 			} else if (msg.rm_datalen > (uint32_t)actlen) {
846 				DPRINTF("invalid msg datalen %u > buffer "
847 				    "datalen %u\n", msg.rm_datalen, actlen);
848 				goto tr_setup;
849 			} else if ((msg.rm_dataoffset + msg.rm_datalen +
850 			    (uint32_t)__offsetof(struct urndis_packet_msg,
851 			    rm_dataoffset)) > (uint32_t)actlen) {
852 				DPRINTF("invalid dataoffset %u larger than %u\n",
853 				    msg.rm_dataoffset + msg.rm_datalen +
854 				    (uint32_t)__offsetof(struct urndis_packet_msg,
855 				    rm_dataoffset), actlen);
856 				goto tr_setup;
857 			} else if (msg.rm_datalen < (uint32_t)sizeof(struct ether_header)) {
858 				IFNET_STAT_INC(ifp, ierrors, 1);
859 				DPRINTF("invalid ethernet size "
860 				    "%u < %u\n", msg.rm_datalen, (unsigned)sizeof(struct ether_header));
861 				goto tr_setup;
862 			} else if (msg.rm_datalen > (uint32_t)MCLBYTES) {
863 				IFNET_STAT_INC(ifp, ierrors, 1);
864 				DPRINTF("invalid ethernet size "
865 				    "%u > %u\n",
866 				    msg.rm_datalen, (unsigned)MCLBYTES);
867 				goto tr_setup;
868 			} else if (msg.rm_datalen > (uint32_t)(MHLEN - ETHER_ALIGN)) {
869 				m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
870 			} else {
871 				m = m_gethdr(M_NOWAIT, MT_DATA);
872 			}
873 
874 			/* check if we have a buffer */
875 			if (m != NULL) {
876 				m_adj(m, ETHER_ALIGN);
877 
878 				usbd_copy_out(pc, offset + msg.rm_dataoffset +
879 				    __offsetof(struct urndis_packet_msg,
880 				    rm_dataoffset), m->m_data, msg.rm_datalen);
881 
882 				/* enqueue */
883 				uether_rxmbuf(&sc->sc_ue, m, msg.rm_datalen);
884 			} else {
885 				IFNET_STAT_INC(ifp, ierrors, 1);
886 			}
887 			offset += msg.rm_len;
888 			actlen -= msg.rm_len;
889 		}
890 
891 	case USB_ST_SETUP:
892 tr_setup:
893 		usbd_xfer_set_frame_len(xfer, 0, RNDIS_RX_MAXLEN);
894 		usbd_xfer_set_frames(xfer, 1);
895 		usbd_transfer_submit(xfer);
896 		uether_rxflush(&sc->sc_ue);	/* must be last */
897 		break;
898 
899 	default:			/* Error */
900 		DPRINTFN(1, "error = %s\n", usbd_errstr(error));
901 
902 		if (error != USB_ERR_CANCELLED) {
903 			/* try to clear stall first */
904 			usbd_xfer_set_stall(xfer);
905 			usbd_xfer_set_frames(xfer, 0);
906 			usbd_transfer_submit(xfer);
907 		}
908 		break;
909 	}
910 }
911 
912 static void
913 urndis_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
914 {
915 	struct urndis_packet_msg msg;
916 	struct urndis_softc *sc = usbd_xfer_softc(xfer);
917 	struct ifnet *ifp = uether_getifp(&sc->sc_ue);
918 	struct mbuf *m;
919 	unsigned x;
920 	int actlen;
921 	int aframes;
922 
923 	usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL);
924 
925 	DPRINTFN(1, "\n");
926 
927 	switch (USB_GET_STATE(xfer)) {
928 	case USB_ST_TRANSFERRED:
929 		DPRINTFN(11, "%u bytes in %u frames\n", actlen, aframes);
930 
931 		ifq_clr_oactive(&ifp->if_snd);
932 		IFNET_STAT_INC(ifp, opackets, 1);
933 
934 		/* FALLTHROUGH */
935 	case USB_ST_SETUP:
936 tr_setup:
937 		if (ifq_is_oactive(&ifp->if_snd)) {
938 			return;
939 		}
940 		memset(&msg, 0, sizeof(msg));
941 
942 		for (x = 0; x != RNDIS_TX_FRAMES_MAX; x++) {
943 			struct usb_page_cache *pc = usbd_xfer_get_frame(xfer, x);
944 
945 			usbd_xfer_set_frame_offset(xfer, x * RNDIS_TX_MAXLEN, x);
946 
947 	next_pkt:
948 			m = ifq_dequeue(&ifp->if_snd);
949 
950 			if (m == NULL)
951 				break;
952 
953 			if ((m->m_pkthdr.len + sizeof(msg)) > RNDIS_TX_MAXLEN) {
954 				DPRINTF("Too big packet\n");
955 				IFNET_STAT_INC(ifp, oerrors, 1);
956 
957 				/* Free buffer */
958 				m_freem(m);
959 				goto next_pkt;
960 			}
961 			msg.rm_type = htole32(REMOTE_NDIS_PACKET_MSG);
962 			msg.rm_len = htole32(sizeof(msg) + m->m_pkthdr.len);
963 
964 			msg.rm_dataoffset = htole32(RNDIS_DATA_OFFSET);
965 			msg.rm_datalen = htole32(m->m_pkthdr.len);
966 
967 			/* copy in all data */
968 			usbd_copy_in(pc, 0, &msg, sizeof(msg));
969 			usbd_m_copy_in(pc, sizeof(msg), m, 0, m->m_pkthdr.len);
970 			usbd_xfer_set_frame_len(xfer, x, sizeof(msg) + m->m_pkthdr.len);
971 
972 			/*
973 			 * If there's a BPF listener, bounce a copy of
974 			 * this frame to him:
975 			 */
976 			BPF_MTAP(ifp, m);
977 
978 			/* Free buffer */
979 			m_freem(m);
980 		}
981 		if (x != 0) {
982 			usbd_xfer_set_frames(xfer, x);
983 			usbd_transfer_submit(xfer);
984 			ifq_set_oactive(&ifp->if_snd);
985 		}
986 		break;
987 
988 	default:			/* Error */
989 		DPRINTFN(11, "transfer error, %s\n", usbd_errstr(error));
990 
991 		/* count output errors */
992 		IFNET_STAT_INC(ifp, oerrors, 1);
993 		ifq_clr_oactive(&ifp->if_snd);
994 		if (error != USB_ERR_CANCELLED) {
995 			/* try to clear stall first */
996 			usbd_xfer_set_stall(xfer);
997 			goto tr_setup;
998 		}
999 		break;
1000 	}
1001 }
1002 
1003 static void
1004 urndis_intr_read_callback(struct usb_xfer *xfer, usb_error_t error)
1005 {
1006 	int actlen;
1007 
1008 	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
1009 
1010 	switch (USB_GET_STATE(xfer)) {
1011 	case USB_ST_TRANSFERRED:
1012 
1013 		DPRINTF("Received %d bytes\n", actlen);
1014 
1015 		/* TODO: decode some indications */
1016 
1017 		/* FALLTHROUGH */
1018 	case USB_ST_SETUP:
1019 tr_setup:
1020 		usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
1021 		usbd_transfer_submit(xfer);
1022 		break;
1023 
1024 	default:			/* Error */
1025 		if (error != USB_ERR_CANCELLED) {
1026 			/* start clear stall */
1027 			usbd_xfer_set_stall(xfer);
1028 			goto tr_setup;
1029 		}
1030 		break;
1031 	}
1032 }
1033