xref: /openbsd-src/sys/dev/usb/if_urndis.c (revision d13be5d47e4149db2549a9828e244d59dbc43f15)
1 /*	$OpenBSD: if_urndis.c,v 1.32 2011/07/20 13:11:41 jasper 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  * All rights reserved.
8  *
9  * Permission to use, copy, modify, and distribute this software for any
10  * purpose with or without fee is hereby granted, provided that the above
11  * copyright notice and this permission notice appear in all copies.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20  */
21 
22 #include <sys/cdefs.h>
23 
24 #include "bpfilter.h"
25 
26 #include <sys/param.h>
27 #include <sys/systm.h>
28 #include <sys/sockio.h>
29 #include <sys/rwlock.h>
30 #include <sys/mbuf.h>
31 #include <sys/kernel.h>
32 #include <sys/proc.h>
33 #include <sys/socket.h>
34 
35 #include <sys/device.h>
36 
37 #include <machine/bus.h>
38 
39 #include <net/if.h>
40 #include <net/if_dl.h>
41 #include <net/if_media.h>
42 
43 #if NBPFILTER > 0
44 #include <net/bpf.h>
45 #endif
46 
47 #ifdef INET
48 #include <netinet/in.h>
49 #include <netinet/in_systm.h>
50 #include <netinet/in_var.h>
51 #include <netinet/ip.h>
52 #include <netinet/if_ether.h>
53 #endif
54 
55 #include <dev/usb/usb.h>
56 #include <dev/usb/usbdi.h>
57 #include <dev/usb/usbdi_util.h>
58 #include <dev/usb/usbdivar.h>
59 #include <dev/usb/usbdevs.h>
60 #include <dev/usb/usbcdc.h>
61 
62 #include <dev/usb/if_urndisreg.h>
63 
64 #ifdef URNDIS_DEBUG
65 #define DPRINTF(x)      do { printf x; } while (0)
66 #else
67 #define DPRINTF(x)
68 #endif
69 
70 #define DEVNAME(sc)	((sc)->sc_dev.dv_xname)
71 
72 int urndis_newbuf(struct urndis_softc *, struct urndis_chain *);
73 
74 int urndis_ioctl(struct ifnet *, u_long, caddr_t);
75 #if 0
76 void urndis_watchdog(struct ifnet *);
77 #endif
78 
79 void urndis_start(struct ifnet *);
80 void urndis_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
81 void urndis_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
82 int urndis_rx_list_init(struct urndis_softc *);
83 int urndis_tx_list_init(struct urndis_softc *);
84 
85 void urndis_init(struct urndis_softc *);
86 void urndis_stop(struct urndis_softc *);
87 
88 usbd_status urndis_ctrl_msg(struct urndis_softc *, uint8_t, uint8_t,
89     uint16_t, uint16_t, void *, size_t);
90 usbd_status urndis_ctrl_send(struct urndis_softc *, void *, size_t);
91 struct urndis_comp_hdr *urndis_ctrl_recv(struct urndis_softc *);
92 
93 u_int32_t urndis_ctrl_handle(struct urndis_softc *,
94     struct urndis_comp_hdr *, void **, size_t *);
95 u_int32_t urndis_ctrl_handle_init(struct urndis_softc *,
96     const struct urndis_comp_hdr *);
97 u_int32_t urndis_ctrl_handle_query(struct urndis_softc *,
98     const struct urndis_comp_hdr *, void **, size_t *);
99 u_int32_t urndis_ctrl_handle_reset(struct urndis_softc *,
100     const struct urndis_comp_hdr *);
101 
102 u_int32_t urndis_ctrl_init(struct urndis_softc *);
103 u_int32_t urndis_ctrl_halt(struct urndis_softc *);
104 u_int32_t urndis_ctrl_query(struct urndis_softc *, u_int32_t, void *, size_t,
105     void **, size_t *);
106 u_int32_t urndis_ctrl_set(struct urndis_softc *, u_int32_t, void *, size_t);
107 u_int32_t urndis_ctrl_set_param(struct urndis_softc *, const char *, u_int32_t,
108     void *, size_t);
109 #if 0
110 u_int32_t urndis_ctrl_reset(struct urndis_softc *);
111 u_int32_t urndis_ctrl_keepalive(struct urndis_softc *);
112 #endif
113 
114 int urndis_encap(struct urndis_softc *, struct mbuf *, int);
115 void urndis_decap(struct urndis_softc *, struct urndis_chain *, u_int32_t);
116 
117 int urndis_match(struct device *, void *, void *);
118 void urndis_attach(struct device *, struct device *, void *);
119 int urndis_detach(struct device *, int);
120 int urndis_activate(struct device *, int);
121 
122 struct cfdriver urndis_cd = {
123 	NULL, "urndis", DV_IFNET
124 };
125 
126 struct cfattach urndis_ca = {
127 	sizeof(struct urndis_softc),
128 	urndis_match,
129 	urndis_attach,
130 	urndis_detach,
131 	urndis_activate,
132 };
133 
134 /*
135  * Supported devices that we can't match by class IDs.
136  */
137 static const struct usb_devno urndis_devs[] = {
138 	{ USB_VENDOR_HTC,	USB_PRODUCT_HTC_ANDROID },
139 	{ USB_VENDOR_SAMSUNG2,	USB_PRODUCT_SAMSUNG2_ANDROID },
140 	{ USB_VENDOR_SAMSUNG2,	USB_PRODUCT_SAMSUNG2_ANDROID2 }
141 };
142 
143 usbd_status
144 urndis_ctrl_msg(struct urndis_softc *sc, uint8_t rt, uint8_t r,
145     uint16_t index, uint16_t value, void *buf, size_t buflen)
146 {
147 	usb_device_request_t req;
148 
149 	req.bmRequestType = rt;
150 	req.bRequest = r;
151 	USETW(req.wValue, value);
152 	USETW(req.wIndex, index);
153 	USETW(req.wLength, buflen);
154 
155 	return usbd_do_request(sc->sc_udev, &req, buf);
156 }
157 
158 usbd_status
159 urndis_ctrl_send(struct urndis_softc *sc, void *buf, size_t len)
160 {
161 	usbd_status err;
162 
163 	if (sc->sc_dying)
164 		return(0);
165 
166 	err = urndis_ctrl_msg(sc, UT_WRITE_CLASS_INTERFACE, UR_GET_STATUS,
167 	    sc->sc_ifaceno_ctl, 0, buf, len);
168 
169 	if (err != USBD_NORMAL_COMPLETION)
170 		printf("%s: %s\n", DEVNAME(sc), usbd_errstr(err));
171 
172 	return err;
173 }
174 
175 struct urndis_comp_hdr *
176 urndis_ctrl_recv(struct urndis_softc *sc)
177 {
178 #define RNDIS_RESPONSE_LEN 0x400
179 	struct urndis_comp_hdr	*hdr;
180 	char			*buf;
181 	usbd_status		 err;
182 
183 	buf = malloc(RNDIS_RESPONSE_LEN, M_TEMP, M_WAITOK | M_CANFAIL);
184 	if (buf == NULL) {
185 		printf("%s: out of memory\n", DEVNAME(sc));
186 		return NULL;
187 	}
188 
189 	err = urndis_ctrl_msg(sc, UT_READ_CLASS_INTERFACE, UR_CLEAR_FEATURE,
190 	    sc->sc_ifaceno_ctl, 0, buf, RNDIS_RESPONSE_LEN);
191 
192 	if (err != USBD_NORMAL_COMPLETION && err != USBD_SHORT_XFER) {
193 		printf("%s: %s\n", DEVNAME(sc), usbd_errstr(err));
194 		free(buf, M_TEMP);
195 		return NULL;
196 	}
197 
198 	hdr = (struct urndis_comp_hdr *)buf;
199 	DPRINTF(("%s: urndis_ctrl_recv: type 0x%x len %u\n",
200 	    DEVNAME(sc),
201 	    letoh32(hdr->rm_type),
202 	    letoh32(hdr->rm_len)));
203 
204 	if (letoh32(hdr->rm_len) > RNDIS_RESPONSE_LEN) {
205 		printf("%s: ctrl message error: wrong size %u > %u\n",
206 		    DEVNAME(sc),
207 		    letoh32(hdr->rm_len),
208 		    RNDIS_RESPONSE_LEN);
209 		free(buf, M_TEMP);
210 		return NULL;
211 	}
212 
213 	return hdr;
214 }
215 
216 u_int32_t
217 urndis_ctrl_handle(struct urndis_softc *sc, struct urndis_comp_hdr *hdr,
218     void **buf, size_t *bufsz)
219 {
220 	u_int32_t rval;
221 
222 	DPRINTF(("%s: urndis_ctrl_handle\n", DEVNAME(sc)));
223 
224 	if (buf && bufsz) {
225 		*buf = NULL;
226 		*bufsz = 0;
227 	}
228 
229 	switch (letoh32(hdr->rm_type)) {
230 		case REMOTE_NDIS_INITIALIZE_CMPLT:
231 			rval = urndis_ctrl_handle_init(sc, hdr);
232 			break;
233 
234 		case REMOTE_NDIS_QUERY_CMPLT:
235 			rval = urndis_ctrl_handle_query(sc, hdr, buf, bufsz);
236 			break;
237 
238 		case REMOTE_NDIS_RESET_CMPLT:
239 			rval = urndis_ctrl_handle_reset(sc, hdr);
240 			break;
241 
242 		case REMOTE_NDIS_KEEPALIVE_CMPLT:
243 		case REMOTE_NDIS_SET_CMPLT:
244 			rval = letoh32(hdr->rm_status);
245 			break;
246 
247 		default:
248 			printf("%s: ctrl message error: unknown event 0x%x\n",
249 			    DEVNAME(sc), letoh32(hdr->rm_type));
250 			rval = RNDIS_STATUS_FAILURE;
251 	}
252 
253 	free(hdr, M_TEMP);
254 
255 	return rval;
256 }
257 
258 u_int32_t
259 urndis_ctrl_handle_init(struct urndis_softc *sc,
260     const struct urndis_comp_hdr *hdr)
261 {
262 	const struct urndis_init_comp	*msg;
263 
264 	msg = (struct urndis_init_comp *) hdr;
265 
266 	DPRINTF(("%s: urndis_ctrl_handle_init: len %u rid %u status 0x%x "
267 	    "ver_major %u ver_minor %u devflags 0x%x medium 0x%x pktmaxcnt %u "
268 	    "pktmaxsz %u align %u aflistoffset %u aflistsz %u\n",
269 	    DEVNAME(sc),
270 	    letoh32(msg->rm_len),
271 	    letoh32(msg->rm_rid),
272 	    letoh32(msg->rm_status),
273 	    letoh32(msg->rm_ver_major),
274 	    letoh32(msg->rm_ver_minor),
275 	    letoh32(msg->rm_devflags),
276 	    letoh32(msg->rm_medium),
277 	    letoh32(msg->rm_pktmaxcnt),
278 	    letoh32(msg->rm_pktmaxsz),
279 	    letoh32(msg->rm_align),
280 	    letoh32(msg->rm_aflistoffset),
281 	    letoh32(msg->rm_aflistsz)));
282 
283 	if (letoh32(msg->rm_status) != RNDIS_STATUS_SUCCESS) {
284 		printf("%s: init failed 0x%x\n",
285 		    DEVNAME(sc),
286 		    letoh32(msg->rm_status));
287 
288 		return letoh32(msg->rm_status);
289 	}
290 
291 	if (letoh32(msg->rm_devflags) != RNDIS_DF_CONNECTIONLESS) {
292 		printf("%s: wrong device type (current type: 0x%x)\n",
293 		    DEVNAME(sc),
294 		    letoh32(msg->rm_devflags));
295 
296 		return RNDIS_STATUS_FAILURE;
297 	}
298 
299 	if (letoh32(msg->rm_medium) != RNDIS_MEDIUM_802_3) {
300 		printf("%s: medium not 802.3 (current medium: 0x%x)\n",
301 		    DEVNAME(sc), letoh32(msg->rm_medium));
302 
303 		return RNDIS_STATUS_FAILURE;
304 	}
305 
306 	sc->sc_lim_pktsz = letoh32(msg->rm_pktmaxsz);
307 
308 	return letoh32(msg->rm_status);
309 }
310 
311 u_int32_t
312 urndis_ctrl_handle_query(struct urndis_softc *sc,
313     const struct urndis_comp_hdr *hdr, void **buf, size_t *bufsz)
314 {
315 	const struct urndis_query_comp	*msg;
316 
317 	msg = (struct urndis_query_comp *) hdr;
318 
319 	DPRINTF(("%s: urndis_ctrl_handle_query: len %u rid %u status 0x%x "
320 	    "buflen %u bufoff %u\n",
321 	    DEVNAME(sc),
322 	    letoh32(msg->rm_len),
323 	    letoh32(msg->rm_rid),
324 	    letoh32(msg->rm_status),
325 	    letoh32(msg->rm_infobuflen),
326 	    letoh32(msg->rm_infobufoffset)));
327 
328 	if (buf && bufsz) {
329 		*buf = NULL;
330 		*bufsz = 0;
331 	}
332 
333 	if (letoh32(msg->rm_status) != RNDIS_STATUS_SUCCESS) {
334 		printf("%s: query failed 0x%x\n",
335 		    DEVNAME(sc),
336 		    letoh32(msg->rm_status));
337 
338 		return letoh32(msg->rm_status);
339 	}
340 
341 	if (letoh32(msg->rm_infobuflen) + letoh32(msg->rm_infobufoffset) +
342 	    RNDIS_HEADER_OFFSET > letoh32(msg->rm_len)) {
343 		printf("%s: ctrl message error: invalid query info "
344 		    "len/offset/end_position(%d/%d/%d) -> "
345 		    "go out of buffer limit %d\n",
346 		    DEVNAME(sc),
347 		    letoh32(msg->rm_infobuflen),
348 		    letoh32(msg->rm_infobufoffset),
349 		    letoh32(msg->rm_infobuflen) +
350 		    letoh32(msg->rm_infobufoffset) + RNDIS_HEADER_OFFSET,
351 		    letoh32(msg->rm_len));
352 		return RNDIS_STATUS_FAILURE;
353 	}
354 
355 	if (buf && bufsz) {
356 		*buf = malloc(letoh32(msg->rm_infobuflen),
357 		    M_TEMP, M_WAITOK | M_CANFAIL);
358 		if (*buf == NULL) {
359 			printf("%s: out of memory\n", DEVNAME(sc));
360 			return RNDIS_STATUS_FAILURE;
361 		} else {
362 			char *p;
363 			*bufsz = letoh32(msg->rm_infobuflen);
364 
365 			p = (char *)&msg->rm_rid;
366 			p += letoh32(msg->rm_infobufoffset);
367 			memcpy(*buf, p, letoh32(msg->rm_infobuflen));
368 		}
369 	}
370 
371 	return letoh32(msg->rm_status);
372 }
373 
374 u_int32_t
375 urndis_ctrl_handle_reset(struct urndis_softc *sc,
376     const struct urndis_comp_hdr *hdr)
377 {
378 	const struct urndis_reset_comp	*msg;
379 	u_int32_t			 rval;
380 
381 	msg = (struct urndis_reset_comp *) hdr;
382 
383 	rval = letoh32(msg->rm_status);
384 
385 	DPRINTF(("%s: urndis_ctrl_handle_reset: len %u status 0x%x "
386 	    "adrreset %u\n",
387 	    DEVNAME(sc),
388 	    letoh32(msg->rm_len),
389 	    rval,
390 	    letoh32(msg->rm_adrreset)));
391 
392 	if (rval != RNDIS_STATUS_SUCCESS) {
393 		printf("%s: reset failed 0x%x\n", DEVNAME(sc), rval);
394 		return rval;
395 	}
396 
397 	if (letoh32(msg->rm_adrreset) != 0) {
398 		u_int32_t filter;
399 
400 		filter = htole32(sc->sc_filter);
401 		rval = urndis_ctrl_set(sc, OID_GEN_CURRENT_PACKET_FILTER,
402 		    &filter, sizeof(filter));
403 		if (rval != RNDIS_STATUS_SUCCESS) {
404 			printf("%s: unable to reset data filters\n",
405 			    DEVNAME(sc));
406 			return rval;
407 		}
408 	}
409 
410 	return rval;
411 }
412 
413 u_int32_t
414 urndis_ctrl_init(struct urndis_softc *sc)
415 {
416 	struct urndis_init_req	*msg;
417 	u_int32_t		 rval;
418 	struct urndis_comp_hdr	*hdr;
419 
420 	msg = malloc(sizeof(*msg), M_TEMP, M_WAITOK);
421 	if (msg == NULL) {
422 		printf("%s: out of memory\n", DEVNAME(sc));
423 		return RNDIS_STATUS_FAILURE;
424 	}
425 
426 	msg->rm_type = htole32(REMOTE_NDIS_INITIALIZE_MSG);
427 	msg->rm_len = htole32(sizeof(*msg));
428 	msg->rm_rid = htole32(0);
429 	msg->rm_ver_major = htole32(1);
430 	msg->rm_ver_minor = htole32(1);
431 	msg->rm_max_xfersz = htole32(RNDIS_BUFSZ);
432 
433 	DPRINTF(("%s: urndis_ctrl_init send: type %u len %u rid %u ver_major %u "
434 	    "ver_minor %u max_xfersz %u\n",
435 	    DEVNAME(sc),
436 	    letoh32(msg->rm_type),
437 	    letoh32(msg->rm_len),
438 	    letoh32(msg->rm_rid),
439 	    letoh32(msg->rm_ver_major),
440 	    letoh32(msg->rm_ver_minor),
441 	    letoh32(msg->rm_max_xfersz)));
442 
443 	rval = urndis_ctrl_send(sc, msg, sizeof(*msg));
444 	free(msg, M_TEMP);
445 
446 	if (rval != RNDIS_STATUS_SUCCESS) {
447 		printf("%s: init failed\n", DEVNAME(sc));
448 		return rval;
449 	}
450 
451 	if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
452 		printf("%s: unable to get init response\n", DEVNAME(sc));
453 		return RNDIS_STATUS_FAILURE;
454 	}
455 	rval = urndis_ctrl_handle(sc, hdr, NULL, NULL);
456 
457 	return rval;
458 }
459 
460 u_int32_t
461 urndis_ctrl_halt(struct urndis_softc *sc)
462 {
463 	struct urndis_halt_req	*msg;
464 	u_int32_t		 rval;
465 
466 	msg = malloc(sizeof(*msg), M_TEMP, M_WAITOK);
467 	if (msg == NULL) {
468 		printf("%s: out of memory\n", DEVNAME(sc));
469 		return RNDIS_STATUS_FAILURE;
470 	}
471 
472 	msg->rm_type = htole32(REMOTE_NDIS_HALT_MSG);
473 	msg->rm_len = htole32(sizeof(*msg));
474 	msg->rm_rid = 0;
475 
476 	DPRINTF(("%s: urndis_ctrl_halt send: type %u len %u rid %u\n",
477 	    DEVNAME(sc),
478 	    letoh32(msg->rm_type),
479 	    letoh32(msg->rm_len),
480 	    letoh32(msg->rm_rid)));
481 
482 	rval = urndis_ctrl_send(sc, msg, sizeof(*msg));
483 	free(msg, M_TEMP);
484 
485 	if (rval != RNDIS_STATUS_SUCCESS)
486 		printf("%s: halt failed\n", DEVNAME(sc));
487 
488 	return rval;
489 }
490 
491 u_int32_t
492 urndis_ctrl_query(struct urndis_softc *sc, u_int32_t oid,
493     void *qbuf, size_t qlen,
494     void **rbuf, size_t *rbufsz)
495 {
496 	struct urndis_query_req	*msg;
497 	u_int32_t		 rval;
498 	struct urndis_comp_hdr	*hdr;
499 
500 	msg = malloc(sizeof(*msg) + qlen, M_TEMP, M_WAITOK);
501 	if (msg == NULL) {
502 		printf("%s: out of memory\n", DEVNAME(sc));
503 		return RNDIS_STATUS_FAILURE;
504 	}
505 
506 	msg->rm_type = htole32(REMOTE_NDIS_QUERY_MSG);
507 	msg->rm_len = htole32(sizeof(*msg) + qlen);
508 	msg->rm_rid = 0; /* XXX */
509 	msg->rm_oid = htole32(oid);
510 	msg->rm_infobuflen = htole32(qlen);
511 	if (qlen != 0) {
512 		msg->rm_infobufoffset = htole32(20);
513 		memcpy((char*)msg + 20, qbuf, qlen);
514 	} else
515 		msg->rm_infobufoffset = 0;
516 	msg->rm_devicevchdl = 0;
517 
518 	DPRINTF(("%s: urndis_ctrl_query send: type %u len %u rid %u oid 0x%x "
519 	    "infobuflen %u infobufoffset %u devicevchdl %u\n",
520 	    DEVNAME(sc),
521 	    letoh32(msg->rm_type),
522 	    letoh32(msg->rm_len),
523 	    letoh32(msg->rm_rid),
524 	    letoh32(msg->rm_oid),
525 	    letoh32(msg->rm_infobuflen),
526 	    letoh32(msg->rm_infobufoffset),
527 	    letoh32(msg->rm_devicevchdl)));
528 
529 	rval = urndis_ctrl_send(sc, msg, sizeof(*msg));
530 	free(msg, M_TEMP);
531 
532 	if (rval != RNDIS_STATUS_SUCCESS) {
533 		printf("%s: query failed\n", DEVNAME(sc));
534 		return rval;
535 	}
536 
537 	if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
538 		printf("%s: unable to get query response\n", DEVNAME(sc));
539 		return RNDIS_STATUS_FAILURE;
540 	}
541 	rval = urndis_ctrl_handle(sc, hdr, rbuf, rbufsz);
542 
543 	return rval;
544 }
545 
546 u_int32_t
547 urndis_ctrl_set(struct urndis_softc *sc, u_int32_t oid, void *buf, size_t len)
548 {
549 	struct urndis_set_req	*msg;
550 	u_int32_t		 rval;
551 	struct urndis_comp_hdr	*hdr;
552 
553 	msg = malloc(sizeof(*msg) + len, M_TEMP, M_WAITOK);
554 	if (msg == NULL) {
555 		printf("%s: out of memory\n", DEVNAME(sc));
556 		return RNDIS_STATUS_FAILURE;
557 	}
558 
559 	msg->rm_type = htole32(REMOTE_NDIS_SET_MSG);
560 	msg->rm_len = htole32(sizeof(*msg) + len);
561 	msg->rm_rid = 0; /* XXX */
562 	msg->rm_oid = htole32(oid);
563 	msg->rm_infobuflen = htole32(len);
564 	if (len != 0) {
565 		msg->rm_infobufoffset = htole32(20);
566 		memcpy((char*)msg + 20, buf, len);
567 	} else
568 		msg->rm_infobufoffset = 0;
569 	msg->rm_devicevchdl = 0;
570 
571 	DPRINTF(("%s: urndis_ctrl_set send: type %u len %u rid %u oid 0x%x "
572 	    "infobuflen %u infobufoffset %u devicevchdl %u\n",
573 	    DEVNAME(sc),
574 	    letoh32(msg->rm_type),
575 	    letoh32(msg->rm_len),
576 	    letoh32(msg->rm_rid),
577 	    letoh32(msg->rm_oid),
578 	    letoh32(msg->rm_infobuflen),
579 	    letoh32(msg->rm_infobufoffset),
580 	    letoh32(msg->rm_devicevchdl)));
581 
582 	rval = urndis_ctrl_send(sc, msg, sizeof(*msg));
583 	free(msg, M_TEMP);
584 
585 	if (rval != RNDIS_STATUS_SUCCESS) {
586 		printf("%s: set failed\n", DEVNAME(sc));
587 		return rval;
588 	}
589 
590 	if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
591 		printf("%s: unable to get set response\n", DEVNAME(sc));
592 		return RNDIS_STATUS_FAILURE;
593 	}
594 	rval = urndis_ctrl_handle(sc, hdr, NULL, NULL);
595 	if (rval != RNDIS_STATUS_SUCCESS)
596 		printf("%s: set failed 0x%x\n", DEVNAME(sc), rval);
597 
598 	return rval;
599 }
600 
601 u_int32_t
602 urndis_ctrl_set_param(struct urndis_softc *sc,
603     const char *name,
604     u_int32_t type,
605     void *buf,
606     size_t len)
607 {
608 	struct urndis_set_parameter	*param;
609 	u_int32_t			 rval;
610 	size_t				 namelen, tlen;
611 
612 	if (name)
613 		namelen = strlen(name);
614 	else
615 		namelen = 0;
616 	tlen = sizeof(*param) + len + namelen;
617 	param = malloc(tlen, M_TEMP, M_WAITOK);
618 	if (param == NULL) {
619 		printf("%s: out of memory\n", DEVNAME(sc));
620 		return RNDIS_STATUS_FAILURE;
621 	}
622 
623 	param->rm_namelen = htole32(namelen);
624 	param->rm_valuelen = htole32(len);
625 	param->rm_type = htole32(type);
626 	if (namelen != 0) {
627 		param->rm_nameoffset = htole32(20);
628 		memcpy(param + 20, name, namelen);
629 	} else
630 		param->rm_nameoffset = 0;
631 	if (len != 0) {
632 		param->rm_valueoffset = htole32(20 + namelen);
633 		memcpy(param + 20 + namelen, buf, len);
634 	} else
635 		param->rm_valueoffset = 0;
636 
637 	DPRINTF(("%s: urndis_ctrl_set_param send: nameoffset %u namelen %u "
638 	    "type 0x%x valueoffset %u valuelen %u\n",
639 	    DEVNAME(sc),
640 	    letoh32(param->rm_nameoffset),
641 	    letoh32(param->rm_namelen),
642 	    letoh32(param->rm_type),
643 	    letoh32(param->rm_valueoffset),
644 	    letoh32(param->rm_valuelen)));
645 
646 	rval = urndis_ctrl_set(sc, OID_GEN_RNDIS_CONFIG_PARAMETER, param, tlen);
647 	free(param, M_TEMP);
648 	if (rval != RNDIS_STATUS_SUCCESS)
649 		printf("%s: set param failed 0x%x\n", DEVNAME(sc), rval);
650 
651 	return rval;
652 }
653 
654 #if 0
655 /* XXX : adrreset, get it from response */
656 u_int32_t
657 urndis_ctrl_reset(struct urndis_softc *sc)
658 {
659 	struct urndis_reset_req		*reset;
660 	u_int32_t			 rval;
661 	struct urndis_comp_hdr		*hdr;
662 
663 	reset = malloc(sizeof(*reset), M_TEMP, M_WAITOK);
664 	if (reset == NULL) {
665 		printf("%s: out of memory\n", DEVNAME(sc));
666 		return RNDIS_STATUS_FAILURE;
667 	}
668 
669 	reset->rm_type = htole32(REMOTE_NDIS_RESET_MSG);
670 	reset->rm_len = htole32(sizeof(*reset));
671 	reset->rm_rid = 0; /* XXX rm_rid == reserved ... remove ? */
672 
673 	DPRINTF(("%s: urndis_ctrl_reset send: type %u len %u rid %u\n",
674 	    DEVNAME(sc),
675 	    letoh32(reset->rm_type),
676 	    letoh32(reset->rm_len),
677 	    letoh32(reset->rm_rid)));
678 
679 	rval = urndis_ctrl_send(sc, reset, sizeof(*reset));
680 	free(reset, M_TEMP);
681 
682 	if (rval != RNDIS_STATUS_SUCCESS) {
683 		printf("%s: reset failed\n", DEVNAME(sc));
684 		return rval;
685 	}
686 
687 	if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
688 		printf("%s: unable to get reset response\n", DEVNAME(sc));
689 		return RNDIS_STATUS_FAILURE;
690 	}
691 	rval = urndis_ctrl_handle(sc, hdr, NULL, NULL);
692 
693 	return rval;
694 }
695 
696 u_int32_t
697 urndis_ctrl_keepalive(struct urndis_softc *sc)
698 {
699 	struct urndis_keepalive_req	*keep;
700 	u_int32_t			 rval;
701 	struct urndis_comp_hdr		*hdr;
702 
703 	keep = malloc(sizeof(*keep), M_TEMP, M_WAITOK);
704 	if (keep == NULL) {
705 		printf("%s: out of memory\n", DEVNAME(sc));
706 		return RNDIS_STATUS_FAILURE;
707 	}
708 
709 	keep->rm_type = htole32(REMOTE_NDIS_KEEPALIVE_MSG);
710 	keep->rm_len = htole32(sizeof(*keep));
711 	keep->rm_rid = 0; /* XXX rm_rid == reserved ... remove ? */
712 
713 	DPRINTF(("%s: urndis_ctrl_keepalive: type %u len %u rid %u\n",
714 	    DEVNAME(sc),
715 	    letoh32(keep->rm_type),
716 	    letoh32(keep->rm_len),
717 	    letoh32(keep->rm_rid)));
718 
719 	rval = urndis_ctrl_send(sc, keep, sizeof(*keep));
720 	free(keep, M_TEMP);
721 
722 	if (rval != RNDIS_STATUS_SUCCESS) {
723 		printf("%s: keepalive failed\n", DEVNAME(sc));
724 		return rval;
725 	}
726 
727 	if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
728 		printf("%s: unable to get keepalive response\n", DEVNAME(sc));
729 		return RNDIS_STATUS_FAILURE;
730 	}
731 	rval = urndis_ctrl_handle(sc, hdr, NULL, NULL);
732 	if (rval != RNDIS_STATUS_SUCCESS) {
733 		printf("%s: keepalive failed 0x%x\n", DEVNAME(sc), rval);
734 		urndis_ctrl_reset(sc);
735 	}
736 
737 	return rval;
738 }
739 #endif
740 
741 int
742 urndis_encap(struct urndis_softc *sc, struct mbuf *m, int idx)
743 {
744 	struct urndis_chain		*c;
745 	usbd_status			 err;
746 	struct urndis_packet_msg		*msg;
747 
748 	c = &sc->sc_data.sc_tx_chain[idx];
749 
750 	msg = (struct urndis_packet_msg *)c->sc_buf;
751 
752 	memset(msg, 0, sizeof(*msg));
753 	msg->rm_type = htole32(REMOTE_NDIS_PACKET_MSG);
754 	msg->rm_len = htole32(sizeof(*msg) + m->m_pkthdr.len);
755 
756 	msg->rm_dataoffset = htole32(RNDIS_DATA_OFFSET);
757 	msg->rm_datalen = htole32(m->m_pkthdr.len);
758 
759 	m_copydata(m, 0, m->m_pkthdr.len,
760 	    ((char*)msg + RNDIS_DATA_OFFSET + RNDIS_HEADER_OFFSET));
761 
762 	DPRINTF(("%s: urndis_encap type 0x%x len %u data(off %u len %u)\n",
763 	    DEVNAME(sc),
764 	    letoh32(msg->rm_type),
765 	    letoh32(msg->rm_len),
766 	    letoh32(msg->rm_dataoffset),
767 	    letoh32(msg->rm_datalen)));
768 
769 	c->sc_mbuf = m;
770 
771 	usbd_setup_xfer(c->sc_xfer, sc->sc_bulkout_pipe, c, c->sc_buf,
772 	    letoh32(msg->rm_len), USBD_FORCE_SHORT_XFER | USBD_NO_COPY, 10000,
773 	    urndis_txeof);
774 
775 	/* Transmit */
776 	err = usbd_transfer(c->sc_xfer);
777 	if (err != USBD_IN_PROGRESS) {
778 		urndis_stop(sc);
779 		return(EIO);
780 	}
781 
782 	sc->sc_data.sc_tx_cnt++;
783 
784 	return(0);
785 }
786 
787 void
788 urndis_decap(struct urndis_softc *sc, struct urndis_chain *c, u_int32_t len)
789 {
790 	struct mbuf		*m;
791 	struct urndis_packet_msg	*msg;
792 	struct ifnet		*ifp;
793 	int			 s;
794 	int			 offset;
795 
796 	ifp = GET_IFP(sc);
797 	offset = 0;
798 
799 	while (len > 0) {
800 		msg = (struct urndis_packet_msg *)((char*)c->sc_buf + offset);
801 		m = c->sc_mbuf;
802 
803 		DPRINTF(("%s: urndis_decap buffer size left %u\n", DEVNAME(sc),
804 		    len));
805 
806 		if (len < sizeof(*msg)) {
807 			printf("%s: urndis_decap invalid buffer len %u < "
808 			    "minimum header %u\n",
809 			    DEVNAME(sc),
810 			    len,
811 			    sizeof(*msg));
812 			return;
813 		}
814 
815 		DPRINTF(("%s: urndis_decap len %u data(off:%u len:%u) "
816 		    "oobdata(off:%u len:%u nb:%u) perpacket(off:%u len:%u)\n",
817 		    DEVNAME(sc),
818 		    letoh32(msg->rm_len),
819 		    letoh32(msg->rm_dataoffset),
820 		    letoh32(msg->rm_datalen),
821 		    letoh32(msg->rm_oobdataoffset),
822 		    letoh32(msg->rm_oobdatalen),
823 		    letoh32(msg->rm_oobdataelements),
824 		    letoh32(msg->rm_pktinfooffset),
825 		    letoh32(msg->rm_pktinfooffset)));
826 
827 		if (letoh32(msg->rm_type) != REMOTE_NDIS_PACKET_MSG) {
828 			printf("%s: urndis_decap invalid type 0x%x != 0x%x\n",
829 			    DEVNAME(sc),
830 			    letoh32(msg->rm_type),
831 			    REMOTE_NDIS_PACKET_MSG);
832 			return;
833 		}
834 		if (letoh32(msg->rm_len) < sizeof(*msg)) {
835 			printf("%s: urndis_decap invalid msg len %u < %u\n",
836 			    DEVNAME(sc),
837 			    letoh32(msg->rm_len),
838 			    sizeof(*msg));
839 			return;
840 		}
841 		if (letoh32(msg->rm_len) > len) {
842 			printf("%s: urndis_decap invalid msg len %u > buffer "
843 			    "len %u\n",
844 			    DEVNAME(sc),
845 			    letoh32(msg->rm_len),
846 			    len);
847 			return;
848 		}
849 
850 		if (letoh32(msg->rm_dataoffset) +
851 		    letoh32(msg->rm_datalen) + RNDIS_HEADER_OFFSET
852 		        > letoh32(msg->rm_len)) {
853 			printf("%s: urndis_decap invalid data "
854 			    "len/offset/end_position(%u/%u/%u) -> "
855 			    "go out of receive buffer limit %u\n",
856 			    DEVNAME(sc),
857 			    letoh32(msg->rm_datalen),
858 			    letoh32(msg->rm_dataoffset),
859 			    letoh32(msg->rm_dataoffset) +
860 			    letoh32(msg->rm_datalen) + RNDIS_HEADER_OFFSET,
861 			    letoh32(msg->rm_len));
862 			return;
863 		}
864 
865 		if (letoh32(msg->rm_datalen) < sizeof(struct ether_header)) {
866 			ifp->if_ierrors++;
867 			printf("%s: urndis_decap invalid ethernet size "
868 			    "%d < %d\n",
869 			    DEVNAME(sc),
870 			    letoh32(msg->rm_datalen),
871 			    sizeof(struct ether_header));
872 			return;
873 		}
874 
875 		memcpy(mtod(m, char*),
876 		    ((char*)&msg->rm_dataoffset + letoh32(msg->rm_dataoffset)),
877 		    letoh32(msg->rm_datalen));
878 		m->m_pkthdr.len = m->m_len = letoh32(msg->rm_datalen);
879 
880 		ifp->if_ipackets++;
881 		m->m_pkthdr.rcvif = ifp;
882 
883 		s = splnet();
884 
885 		if (urndis_newbuf(sc, c) == ENOBUFS) {
886 			ifp->if_ierrors++;
887 		} else {
888 
889 #if NBPFILTER > 0
890 			if (ifp->if_bpf)
891 				bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
892 #endif
893 
894 			ether_input_mbuf(ifp, m);
895 
896 		}
897 		splx(s);
898 
899 		offset += letoh32(msg->rm_len);
900 		len -= letoh32(msg->rm_len);
901 	}
902 }
903 
904 int
905 urndis_newbuf(struct urndis_softc *sc, struct urndis_chain *c)
906 {
907 	struct mbuf *m_new = NULL;
908 
909 	MGETHDR(m_new, M_DONTWAIT, MT_DATA);
910 	if (m_new == NULL) {
911 		printf("%s: no memory for rx list -- packet dropped!\n",
912 		    DEVNAME(sc));
913 		return (ENOBUFS);
914 	}
915 	MCLGET(m_new, M_DONTWAIT);
916 	if (!(m_new->m_flags & M_EXT)) {
917 		printf("%s: no memory for rx list -- packet dropped!\n",
918 		    DEVNAME(sc));
919 		m_freem(m_new);
920 		return (ENOBUFS);
921 	}
922 	m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
923 
924 	m_adj(m_new, ETHER_ALIGN);
925 	c->sc_mbuf = m_new;
926 	return (0);
927 }
928 
929 int
930 urndis_rx_list_init(struct urndis_softc *sc)
931 {
932 	struct urndis_cdata	*cd;
933 	struct urndis_chain	*c;
934 	int			 i;
935 
936 	cd = &sc->sc_data;
937 	for (i = 0; i < RNDIS_RX_LIST_CNT; i++) {
938 		c = &cd->sc_rx_chain[i];
939 		c->sc_softc = sc;
940 		c->sc_idx = i;
941 
942 		if (urndis_newbuf(sc, c) == ENOBUFS)
943 			return (ENOBUFS);
944 
945 		if (c->sc_xfer == NULL) {
946 			c->sc_xfer = usbd_alloc_xfer(sc->sc_udev);
947 			if (c->sc_xfer == NULL)
948 				return (ENOBUFS);
949 			c->sc_buf = usbd_alloc_buffer(c->sc_xfer,
950 			    RNDIS_BUFSZ);
951 			if (c->sc_buf == NULL)
952 				return (ENOBUFS);
953 		}
954 	}
955 
956 	return (0);
957 }
958 
959 int
960 urndis_tx_list_init(struct urndis_softc *sc)
961 {
962 	struct urndis_cdata	*cd;
963 	struct urndis_chain	*c;
964 	int			 i;
965 
966 	cd = &sc->sc_data;
967 	for (i = 0; i < RNDIS_TX_LIST_CNT; i++) {
968 		c = &cd->sc_tx_chain[i];
969 		c->sc_softc = sc;
970 		c->sc_idx = i;
971 		c->sc_mbuf = NULL;
972 		if (c->sc_xfer == NULL) {
973 			c->sc_xfer = usbd_alloc_xfer(sc->sc_udev);
974 			if (c->sc_xfer == NULL)
975 				return (ENOBUFS);
976 			c->sc_buf = usbd_alloc_buffer(c->sc_xfer,
977 			    RNDIS_BUFSZ);
978 			if (c->sc_buf == NULL)
979 				return (ENOBUFS);
980 		}
981 	}
982 	return (0);
983 }
984 
985 int
986 urndis_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
987 {
988 	struct urndis_softc	*sc;
989 	struct ifaddr		*ifa;
990 	int			 s, error;
991 
992 	sc = ifp->if_softc;
993 	ifa = (struct ifaddr *)data;
994 	error = 0;
995 
996 	if (sc->sc_dying)
997 		return (EIO);
998 
999 	s = splnet();
1000 
1001 	switch(command) {
1002 	case SIOCSIFADDR:
1003 		ifp->if_flags |= IFF_UP;
1004 		urndis_init(sc);
1005 
1006 		switch (ifa->ifa_addr->sa_family) {
1007 		case AF_INET:
1008 			arp_ifinit(&sc->sc_arpcom, ifa);
1009 			break;
1010 		}
1011 		break;
1012 
1013 	case SIOCSIFFLAGS:
1014 		if (ifp->if_flags & IFF_UP) {
1015 			if (!(ifp->if_flags & IFF_RUNNING))
1016 				urndis_init(sc);
1017 		} else {
1018 			if (ifp->if_flags & IFF_RUNNING)
1019 				urndis_stop(sc);
1020 		}
1021 		error = 0;
1022 		break;
1023 
1024 	default:
1025 		error = ether_ioctl(ifp, &sc->sc_arpcom, command, data);
1026 		break;
1027 	}
1028 
1029 	if (error == ENETRESET)
1030 		error = 0;
1031 
1032 	splx(s);
1033 	return (error);
1034 }
1035 
1036 #if 0
1037 void
1038 urndis_watchdog(struct ifnet *ifp)
1039 {
1040 	struct urndis_softc *sc;
1041 
1042 	sc = ifp->if_softc;
1043 
1044 	if (sc->sc_dying)
1045 		return;
1046 
1047 	ifp->if_oerrors++;
1048 	printf("%s: watchdog timeout\n", DEVNAME(sc));
1049 
1050 	urndis_ctrl_keepalive(sc);
1051 }
1052 #endif
1053 
1054 void
1055 urndis_init(struct urndis_softc *sc)
1056 {
1057 	struct ifnet		*ifp;
1058 	int			 i, s;
1059 	usbd_status		 err;
1060 
1061 
1062 	ifp = GET_IFP(sc);
1063 	if (ifp->if_flags & IFF_RUNNING)
1064 		return;
1065 
1066 	if (urndis_ctrl_init(sc) != RNDIS_STATUS_SUCCESS)
1067 		return;
1068 
1069 	s = splnet();
1070 
1071 	if (urndis_tx_list_init(sc) == ENOBUFS) {
1072 		printf("%s: tx list init failed\n",
1073 		    DEVNAME(sc));
1074 		splx(s);
1075 		return;
1076 	}
1077 
1078 	if (urndis_rx_list_init(sc) == ENOBUFS) {
1079 		printf("%s: rx list init failed\n",
1080 		    DEVNAME(sc));
1081 		splx(s);
1082 		return;
1083 	}
1084 
1085 	err = usbd_open_pipe(sc->sc_iface_data, sc->sc_bulkin_no,
1086 	    USBD_EXCLUSIVE_USE, &sc->sc_bulkin_pipe);
1087 	if (err) {
1088 		printf("%s: open rx pipe failed: %s\n", DEVNAME(sc),
1089 		    usbd_errstr(err));
1090 		splx(s);
1091 		return;
1092 	}
1093 
1094 	err = usbd_open_pipe(sc->sc_iface_data, sc->sc_bulkout_no,
1095 	    USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe);
1096 	if (err) {
1097 		printf("%s: open tx pipe failed: %s\n", DEVNAME(sc),
1098 		    usbd_errstr(err));
1099 		splx(s);
1100 		return;
1101 	}
1102 
1103 	for (i = 0; i < RNDIS_RX_LIST_CNT; i++) {
1104 		struct urndis_chain *c;
1105 
1106 		c = &sc->sc_data.sc_rx_chain[i];
1107 		usbd_setup_xfer(c->sc_xfer, sc->sc_bulkin_pipe, c,
1108 		    c->sc_buf, RNDIS_BUFSZ,
1109 		    USBD_SHORT_XFER_OK | USBD_NO_COPY,
1110 		    USBD_NO_TIMEOUT, urndis_rxeof);
1111 		usbd_transfer(c->sc_xfer);
1112 	}
1113 
1114 	ifp->if_flags |= IFF_RUNNING;
1115 	ifp->if_flags &= ~IFF_OACTIVE;
1116 
1117 	splx(s);
1118 }
1119 
1120 void
1121 urndis_stop(struct urndis_softc *sc)
1122 {
1123 	usbd_status	 err;
1124 	struct ifnet	*ifp;
1125 	int		 i;
1126 
1127 	ifp = GET_IFP(sc);
1128 	ifp->if_timer = 0;
1129 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1130 
1131 	if (sc->sc_bulkin_pipe != NULL) {
1132 		err = usbd_abort_pipe(sc->sc_bulkin_pipe);
1133 		if (err)
1134 			printf("%s: abort rx pipe failed: %s\n",
1135 			    DEVNAME(sc), usbd_errstr(err));
1136 		err = usbd_close_pipe(sc->sc_bulkin_pipe);
1137 		if (err)
1138 			printf("%s: close rx pipe failed: %s\n",
1139 			    DEVNAME(sc), usbd_errstr(err));
1140 		sc->sc_bulkin_pipe = NULL;
1141 	}
1142 
1143 	if (sc->sc_bulkout_pipe != NULL) {
1144 		err = usbd_abort_pipe(sc->sc_bulkout_pipe);
1145 		if (err)
1146 			printf("%s: abort tx pipe failed: %s\n",
1147 			    DEVNAME(sc), usbd_errstr(err));
1148 		err = usbd_close_pipe(sc->sc_bulkout_pipe);
1149 		if (err)
1150 			printf("%s: close tx pipe failed: %s\n",
1151 			    DEVNAME(sc), usbd_errstr(err));
1152 		sc->sc_bulkout_pipe = NULL;
1153 	}
1154 
1155 	for (i = 0; i < RNDIS_RX_LIST_CNT; i++) {
1156 		if (sc->sc_data.sc_rx_chain[i].sc_mbuf != NULL) {
1157 			m_freem(sc->sc_data.sc_rx_chain[i].sc_mbuf);
1158 			sc->sc_data.sc_rx_chain[i].sc_mbuf = NULL;
1159 		}
1160 		if (sc->sc_data.sc_rx_chain[i].sc_xfer != NULL) {
1161 			usbd_free_xfer(sc->sc_data.sc_rx_chain[i].sc_xfer);
1162 			sc->sc_data.sc_rx_chain[i].sc_xfer = NULL;
1163 		}
1164 	}
1165 
1166 	for (i = 0; i < RNDIS_TX_LIST_CNT; i++) {
1167 		if (sc->sc_data.sc_tx_chain[i].sc_mbuf != NULL) {
1168 			m_freem(sc->sc_data.sc_tx_chain[i].sc_mbuf);
1169 			sc->sc_data.sc_tx_chain[i].sc_mbuf = NULL;
1170 		}
1171 		if (sc->sc_data.sc_tx_chain[i].sc_xfer != NULL) {
1172 			usbd_free_xfer(sc->sc_data.sc_tx_chain[i].sc_xfer);
1173 			sc->sc_data.sc_tx_chain[i].sc_xfer = NULL;
1174 		}
1175 	}
1176 }
1177 
1178 void
1179 urndis_start(struct ifnet *ifp)
1180 {
1181 	struct urndis_softc	*sc;
1182 	struct mbuf		*m_head = NULL;
1183 
1184 	sc = ifp->if_softc;
1185 
1186 	if (sc->sc_dying || (ifp->if_flags & IFF_OACTIVE))
1187 		return;
1188 
1189 	IFQ_POLL(&ifp->if_snd, m_head);
1190 	if (m_head == NULL)
1191 		return;
1192 
1193 	if (urndis_encap(sc, m_head, 0)) {
1194 		ifp->if_flags |= IFF_OACTIVE;
1195 		return;
1196 	}
1197 	IFQ_DEQUEUE(&ifp->if_snd, m_head);
1198 
1199 	/*
1200 	 * If there's a BPF listener, bounce a copy of this frame
1201 	 * to him.
1202 	 */
1203 #if NBPFILTER > 0
1204 	if (ifp->if_bpf)
1205 		bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT);
1206 #endif
1207 
1208 	ifp->if_flags |= IFF_OACTIVE;
1209 
1210 	/*
1211 	 * Set a timeout in case the chip goes out to lunch.
1212 	 */
1213 	ifp->if_timer = 5;
1214 
1215 	return;
1216 }
1217 
1218 void
1219 urndis_rxeof(usbd_xfer_handle xfer,
1220     usbd_private_handle priv,
1221     usbd_status status)
1222 {
1223 	struct urndis_chain	*c;
1224 	struct urndis_softc	*sc;
1225 	struct ifnet		*ifp;
1226 	u_int32_t		 total_len;
1227 
1228 	c = priv;
1229 	sc = c->sc_softc;
1230 	ifp = GET_IFP(sc);
1231 	total_len = 0;
1232 
1233 	if (sc->sc_dying || !(ifp->if_flags & IFF_RUNNING))
1234 		return;
1235 
1236 	if (status != USBD_NORMAL_COMPLETION) {
1237 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
1238 			return;
1239 		if (usbd_ratecheck(&sc->sc_rx_notice)) {
1240 			printf("%s: usb errors on rx: %s\n",
1241 			    DEVNAME(sc), usbd_errstr(status));
1242 		}
1243 		if (status == USBD_STALLED)
1244 			usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe);
1245 
1246 		goto done;
1247 	}
1248 
1249 	usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
1250 	urndis_decap(sc, c, total_len);
1251 
1252 done:
1253 	/* Setup new transfer. */
1254 	usbd_setup_xfer(c->sc_xfer, sc->sc_bulkin_pipe, c, c->sc_buf,
1255 	    RNDIS_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
1256 	    urndis_rxeof);
1257 	usbd_transfer(c->sc_xfer);
1258 }
1259 
1260 void
1261 urndis_txeof(usbd_xfer_handle xfer,
1262     usbd_private_handle priv,
1263     usbd_status status)
1264 {
1265 	struct urndis_chain	*c;
1266 	struct urndis_softc	*sc;
1267 	struct ifnet		*ifp;
1268 	usbd_status		 err;
1269 	int			 s;
1270 
1271 	c = priv;
1272 	sc = c->sc_softc;
1273 	ifp = GET_IFP(sc);
1274 
1275 	DPRINTF(("%s: urndis_txeof\n", DEVNAME(sc)));
1276 
1277 	if (sc->sc_dying)
1278 		return;
1279 
1280 	s = splnet();
1281 
1282 	ifp->if_timer = 0;
1283 	ifp->if_flags &= ~IFF_OACTIVE;
1284 
1285 	if (status != USBD_NORMAL_COMPLETION) {
1286 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
1287 			splx(s);
1288 			return;
1289 		}
1290 		ifp->if_oerrors++;
1291 		printf("%s: usb error on tx: %s\n", DEVNAME(sc),
1292 		    usbd_errstr(status));
1293 		if (status == USBD_STALLED)
1294 			usbd_clear_endpoint_stall_async(sc->sc_bulkout_pipe);
1295 		splx(s);
1296 		return;
1297 	}
1298 
1299 	usbd_get_xfer_status(c->sc_xfer, NULL, NULL, NULL, &err);
1300 
1301 	if (c->sc_mbuf != NULL) {
1302 		m_freem(c->sc_mbuf);
1303 		c->sc_mbuf = NULL;
1304 	}
1305 
1306 	if (err)
1307 		ifp->if_oerrors++;
1308 	else
1309 		ifp->if_opackets++;
1310 
1311 	if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
1312 		urndis_start(ifp);
1313 
1314 	splx(s);
1315 }
1316 
1317 int
1318 urndis_match(struct device *parent, void *match, void *aux)
1319 {
1320 	struct usb_attach_arg		*uaa;
1321 	usb_interface_descriptor_t	*id;
1322 
1323 	uaa = aux;
1324 
1325 	if (!uaa->iface)
1326 		return (UMATCH_NONE);
1327 
1328 	id = usbd_get_interface_descriptor(uaa->iface);
1329 	if (id == NULL)
1330 		return (UMATCH_NONE);
1331 
1332 	if (id->bInterfaceClass == UICLASS_WIRELESS &&
1333 	    id->bInterfaceSubClass == UISUBCLASS_RF &&
1334 	    id->bInterfaceProtocol == UIPROTO_RNDIS)
1335 		return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO);
1336 
1337 	return (usb_lookup(urndis_devs, uaa->vendor, uaa->product) != NULL) ?
1338 	    UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
1339 }
1340 
1341 void
1342 urndis_attach(struct device *parent, struct device *self, void *aux)
1343 {
1344 	struct urndis_softc		*sc;
1345 	struct usb_attach_arg		*uaa;
1346 	struct ifnet			*ifp;
1347 	usb_interface_descriptor_t	*id;
1348 	usb_endpoint_descriptor_t	*ed;
1349 	usb_config_descriptor_t		*cd;
1350 	usb_cdc_union_descriptor_t	*ud;
1351 	const usb_descriptor_t		*desc;
1352 	usbd_desc_iter_t		 iter;
1353 	int				 if_ctl, if_data;
1354 	int				 i, j, altcnt;
1355 	int				 s;
1356 	u_char				 eaddr[ETHER_ADDR_LEN];
1357 	void				*buf;
1358 	size_t				 bufsz;
1359 	u_int32_t			 filter;
1360 
1361 	sc = (void *)self;
1362 	uaa = aux;
1363 
1364 	sc->sc_udev = uaa->device;
1365 	sc->sc_iface_ctl = uaa->iface;
1366 	id = usbd_get_interface_descriptor(sc->sc_iface_ctl);
1367 	if_ctl = id->bInterfaceNumber;
1368 	sc->sc_ifaceno_ctl = if_ctl;
1369 	if_data = -1;
1370 
1371 	usb_desc_iter_init(sc->sc_udev, &iter);
1372 	while ((desc = usb_desc_iter_next(&iter)) != NULL) {
1373 
1374 		if (desc->bDescriptorType != UDESC_CS_INTERFACE) {
1375 			continue;
1376 		}
1377 		switch (desc->bDescriptorSubtype) {
1378 		case UDESCSUB_CDC_UNION:
1379 			ud = (usb_cdc_union_descriptor_t *)desc;
1380 			/* XXX bail out when found first? */
1381 			if (if_data == -1)
1382 				if_data = ud->bSlaveInterface[0];
1383 			break;
1384 		}
1385 	}
1386 
1387 	if (if_data == -1) {
1388 		DPRINTF(("urndis_attach: no union interface\n"));
1389 		sc->sc_iface_data = sc->sc_iface_ctl;
1390 	} else {
1391 		DPRINTF(("urndis_attach: union interface: ctl %u, data %u\n",
1392 		    if_ctl, if_data));
1393 		for (i = 0; i < uaa->nifaces; i++) {
1394 			if (usbd_iface_claimed(sc->sc_udev, i))
1395 				continue;
1396 			id = usbd_get_interface_descriptor(uaa->ifaces[i]);
1397 			if (id && id->bInterfaceNumber == if_data) {
1398 				sc->sc_iface_data = uaa->ifaces[i];
1399 				usbd_claim_iface(sc->sc_udev, i);
1400 			}
1401 		}
1402 	}
1403 
1404 	if (sc->sc_iface_data == NULL) {
1405 		printf("%s: no data interface\n", DEVNAME(sc));
1406 		return;
1407 	}
1408 
1409 	id = usbd_get_interface_descriptor(sc->sc_iface_data);
1410 	cd = usbd_get_config_descriptor(sc->sc_udev);
1411 	altcnt = usbd_get_no_alts(cd, id->bInterfaceNumber);
1412 
1413 	for (j = 0; j < altcnt; j++) {
1414 		if (usbd_set_interface(sc->sc_iface_data, j)) {
1415 			printf("%s: interface alternate setting %u failed\n",
1416 			    DEVNAME(sc), j);
1417 			return;
1418 		}
1419 		/* Find endpoints. */
1420 		id = usbd_get_interface_descriptor(sc->sc_iface_data);
1421 		sc->sc_bulkin_no = sc->sc_bulkout_no = -1;
1422 		for (i = 0; i < id->bNumEndpoints; i++) {
1423 			ed = usbd_interface2endpoint_descriptor(
1424 			    sc->sc_iface_data, i);
1425 			if (!ed) {
1426 				printf("%s: no descriptor for bulk endpoint "
1427 				    "%u\n", DEVNAME(sc), i);
1428 				return;
1429 			}
1430 			if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
1431 			    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
1432 				sc->sc_bulkin_no = ed->bEndpointAddress;
1433 			}
1434 			else if (
1435 			    UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
1436 			    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
1437 				sc->sc_bulkout_no = ed->bEndpointAddress;
1438 			}
1439 		}
1440 
1441 		if (sc->sc_bulkin_no != -1 && sc->sc_bulkout_no != -1) {
1442 			DPRINTF(("%s: in=0x%x, out=0x%x\n",
1443 			    DEVNAME(sc),
1444 			    sc->sc_bulkin_no,
1445 			    sc->sc_bulkout_no));
1446 			goto found;
1447 		}
1448 	}
1449 
1450 	if (sc->sc_bulkin_no == -1)
1451 		printf("%s: could not find data bulk in\n", DEVNAME(sc));
1452 	if (sc->sc_bulkout_no == -1 )
1453 		printf("%s: could not find data bulk out\n", DEVNAME(sc));
1454 	return;
1455 
1456 	found:
1457 
1458 	ifp = GET_IFP(sc);
1459 	ifp->if_softc = sc;
1460 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1461 	ifp->if_start = urndis_start;
1462 	ifp->if_ioctl = urndis_ioctl;
1463 #if 0
1464 	ifp->if_watchdog = urndis_watchdog;
1465 #endif
1466 
1467 	strlcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ);
1468 
1469 	IFQ_SET_READY(&ifp->if_snd);
1470 
1471 	urndis_init(sc);
1472 
1473 	s = splnet();
1474 
1475 	if (urndis_ctrl_query(sc, OID_802_3_PERMANENT_ADDRESS, NULL, 0,
1476 	    &buf, &bufsz) != RNDIS_STATUS_SUCCESS) {
1477 		printf("%s: unable to get hardware address\n", DEVNAME(sc));
1478 		urndis_stop(sc);
1479 		splx(s);
1480 		return;
1481 	}
1482 
1483 	if (bufsz == ETHER_ADDR_LEN) {
1484 		memcpy(eaddr, buf, ETHER_ADDR_LEN);
1485 		printf("%s: address %s\n", DEVNAME(sc), ether_sprintf(eaddr));
1486 		free(buf, M_TEMP);
1487 	} else {
1488 		printf("%s: invalid address\n", DEVNAME(sc));
1489 		free(buf, M_TEMP);
1490 		urndis_stop(sc);
1491 		splx(s);
1492 		return;
1493 	}
1494 
1495 	/* Initialize packet filter */
1496 	sc->sc_filter = RNDIS_PACKET_TYPE_BROADCAST;
1497 	sc->sc_filter |= RNDIS_PACKET_TYPE_ALL_MULTICAST;
1498 	filter = htole32(sc->sc_filter);
1499 	if (urndis_ctrl_set(sc, OID_GEN_CURRENT_PACKET_FILTER, &filter,
1500 	    sizeof(filter)) != RNDIS_STATUS_SUCCESS) {
1501 		printf("%s: unable to set data filters\n", DEVNAME(sc));
1502 		urndis_stop(sc);
1503 		splx(s);
1504 		return;
1505 	}
1506 
1507 	bcopy(eaddr, (char *)&sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);
1508 
1509 	if_attach(ifp);
1510 	ether_ifattach(ifp);
1511 	sc->sc_attached = 1;
1512 
1513 	splx(s);
1514 }
1515 
1516 int
1517 urndis_detach(struct device *self, int flags)
1518 {
1519 	struct urndis_softc	*sc;
1520 	struct ifnet		*ifp;
1521 	int			 s;
1522 
1523 	sc = (void*)self;
1524 
1525 	DPRINTF(("urndis_detach: %s flags %u\n", DEVNAME(sc),
1526 	    flags));
1527 
1528 	if (!sc->sc_attached)
1529 		return 0;
1530 
1531 	s = splusb();
1532 
1533 	ifp = GET_IFP(sc);
1534 
1535 	if (ifp->if_softc != NULL) {
1536 		ether_ifdetach(ifp);
1537 		if_detach(ifp);
1538 	}
1539 
1540 	urndis_stop(sc);
1541 	sc->sc_attached = 0;
1542 
1543 	splx(s);
1544 
1545 	return 0;
1546 }
1547 
1548 int
1549 urndis_activate(struct device *self, int devact)
1550 {
1551 	struct urndis_softc *sc;
1552 
1553 	sc = (struct urndis_softc *)self;
1554 
1555 	switch (devact) {
1556 	case DVACT_DEACTIVATE:
1557 		sc->sc_dying = 1;
1558 		break;
1559 	}
1560 
1561 	return 0;
1562 }
1563 
1564