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