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