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