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