if_urndis.c revision 1.13.2.1 1 /* $NetBSD: if_urndis.c,v 1.13.2.1 2017/01/07 08:56:41 pgoyette 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 (at) openbsd.org>
6 * Copyright (c) 2010 Fabien Romano <fabien (at) openbsd.org>
7 * Copyright (c) 2010 Michael Knudsen <mk (at) 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.2.1 2017/01/07 08:56:41 pgoyette 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 m_set_rcvif(m, ifp);
872
873 s = splnet();
874
875 if (urndis_newbuf(sc, c) == ENOBUFS) {
876 ifp->if_ierrors++;
877 } else {
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