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