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