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