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