if_urndis.c revision 1.26 1 /* $NetBSD: if_urndis.c,v 1.26 2019/08/09 06:38:39 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.26 2019/08/09 06:38:39 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/kmem.h>
33 #include <sys/kernel.h>
34
35 #include <dev/usb/usbnet.h>
36 #include <dev/usb/usbdevs.h>
37 #include <dev/usb/usbcdc.h>
38
39 #include <dev/ic/rndisreg.h>
40
41 #define RNDIS_RX_LIST_CNT 1
42 #define RNDIS_TX_LIST_CNT 1
43 #define RNDIS_BUFSZ 1562
44
45 struct urndis_softc {
46 struct usbnet sc_un;
47
48 int sc_ifaceno_ctl;
49
50 /* RNDIS device info */
51 uint32_t sc_filter;
52 uint32_t sc_maxppt;
53 uint32_t sc_maxtsz;
54 uint32_t sc_palign;
55 };
56
57 #ifdef URNDIS_DEBUG
58 #define DPRINTF(x) do { printf x; } while (0)
59 #else
60 #define DPRINTF(x)
61 #endif
62
63 #define DEVNAME(un) (device_xname(un->un_dev))
64
65 #define URNDIS_RESPONSE_LEN 0x400
66
67 #if 0
68 static void urndis_watchdog(struct ifnet *);
69 #endif
70
71 static int urndis_init(struct ifnet *);
72 static void urndis_rx_loop(struct usbnet *, struct usbd_xfer *,
73 struct usbnet_chain *, uint32_t);
74 static unsigned urndis_tx_prepare(struct usbnet *, struct mbuf *,
75 struct usbnet_chain *);
76
77 static int urndis_init_un(struct ifnet *, struct usbnet *);
78
79 static uint32_t urndis_ctrl_handle_init(struct usbnet *,
80 const struct rndis_comp_hdr *);
81 static uint32_t urndis_ctrl_handle_query(struct usbnet *,
82 const struct rndis_comp_hdr *, void **, size_t *);
83 static uint32_t urndis_ctrl_handle_reset(struct usbnet *,
84 const struct rndis_comp_hdr *);
85 static uint32_t urndis_ctrl_handle_status(struct usbnet *,
86 const struct rndis_comp_hdr *);
87
88 static uint32_t urndis_ctrl_set(struct usbnet *, uint32_t, void *,
89 size_t);
90
91 static int urndis_match(device_t, cfdata_t, void *);
92 static void urndis_attach(device_t, device_t, void *);
93
94 static struct usbnet_ops urndis_ops = {
95 .uno_init = urndis_init,
96 .uno_tx_prepare = urndis_tx_prepare,
97 .uno_rx_loop = urndis_rx_loop,
98 };
99
100 CFATTACH_DECL_NEW(urndis, sizeof(struct urndis_softc),
101 urndis_match, urndis_attach, usbnet_detach, usbnet_activate);
102
103 /*
104 * Supported devices that we can't match by class IDs.
105 */
106 static const struct usb_devno urndis_devs[] = {
107 { USB_VENDOR_HTC, USB_PRODUCT_HTC_ANDROID },
108 { USB_VENDOR_SAMSUNG, USB_PRODUCT_SAMSUNG_ANDROID2 },
109 { USB_VENDOR_SAMSUNG, USB_PRODUCT_SAMSUNG_ANDROID },
110 };
111
112 static usbd_status
113 urndis_ctrl_msg(struct usbnet *un, uint8_t rt, uint8_t r,
114 uint16_t index, uint16_t value, void *buf, size_t buflen)
115 {
116 usb_device_request_t req;
117
118 req.bmRequestType = rt;
119 req.bRequest = r;
120 USETW(req.wValue, value);
121 USETW(req.wIndex, index);
122 USETW(req.wLength, buflen);
123
124 return usbd_do_request(un->un_udev, &req, buf);
125 }
126
127 static usbd_status
128 urndis_ctrl_send(struct usbnet *un, void *buf, size_t len)
129 {
130 struct urndis_softc *sc = usbnet_softc(un);
131 usbd_status err;
132
133 if (un->un_dying)
134 return(0);
135
136 err = urndis_ctrl_msg(un, UT_WRITE_CLASS_INTERFACE, UR_GET_STATUS,
137 sc->sc_ifaceno_ctl, 0, buf, len);
138
139 if (err != USBD_NORMAL_COMPLETION)
140 printf("%s: %s\n", DEVNAME(un), usbd_errstr(err));
141
142 return err;
143 }
144
145 static struct rndis_comp_hdr *
146 urndis_ctrl_recv(struct usbnet *un)
147 {
148 struct urndis_softc *sc = usbnet_softc(un);
149 struct rndis_comp_hdr *hdr;
150 char *buf;
151 usbd_status err;
152
153 if (un->un_dying)
154 return(0);
155
156 buf = kmem_alloc(URNDIS_RESPONSE_LEN, KM_SLEEP);
157 err = urndis_ctrl_msg(un, UT_READ_CLASS_INTERFACE, UR_CLEAR_FEATURE,
158 sc->sc_ifaceno_ctl, 0, buf, URNDIS_RESPONSE_LEN);
159
160 if (err != USBD_NORMAL_COMPLETION && err != USBD_SHORT_XFER) {
161 printf("%s: %s\n", DEVNAME(un), usbd_errstr(err));
162 kmem_free(buf, URNDIS_RESPONSE_LEN);
163 return NULL;
164 }
165
166 hdr = (struct rndis_comp_hdr *)buf;
167 DPRINTF(("%s: urndis_ctrl_recv: type 0x%x len %u\n",
168 DEVNAME(un),
169 le32toh(hdr->rm_type),
170 le32toh(hdr->rm_len)));
171
172 if (le32toh(hdr->rm_len) > URNDIS_RESPONSE_LEN) {
173 printf("%s: ctrl message error: wrong size %u > %u\n",
174 DEVNAME(un),
175 le32toh(hdr->rm_len),
176 URNDIS_RESPONSE_LEN);
177 kmem_free(buf, URNDIS_RESPONSE_LEN);
178 return NULL;
179 }
180
181 return hdr;
182 }
183
184 static uint32_t
185 urndis_ctrl_handle(struct usbnet *un, struct rndis_comp_hdr *hdr,
186 void **buf, size_t *bufsz)
187 {
188 uint32_t rval;
189
190 DPRINTF(("%s: urndis_ctrl_handle\n", DEVNAME(un)));
191
192 if (buf && bufsz) {
193 *buf = NULL;
194 *bufsz = 0;
195 }
196
197 switch (le32toh(hdr->rm_type)) {
198 case REMOTE_NDIS_INITIALIZE_CMPLT:
199 rval = urndis_ctrl_handle_init(un, hdr);
200 break;
201
202 case REMOTE_NDIS_QUERY_CMPLT:
203 rval = urndis_ctrl_handle_query(un, hdr, buf, bufsz);
204 break;
205
206 case REMOTE_NDIS_RESET_CMPLT:
207 rval = urndis_ctrl_handle_reset(un, hdr);
208 break;
209
210 case REMOTE_NDIS_KEEPALIVE_CMPLT:
211 case REMOTE_NDIS_SET_CMPLT:
212 rval = le32toh(hdr->rm_status);
213 break;
214
215 case REMOTE_NDIS_INDICATE_STATUS_MSG:
216 rval = urndis_ctrl_handle_status(un, hdr);
217 break;
218
219 default:
220 printf("%s: ctrl message error: unknown event 0x%x\n",
221 DEVNAME(un), le32toh(hdr->rm_type));
222 rval = RNDIS_STATUS_FAILURE;
223 }
224
225 kmem_free(hdr, URNDIS_RESPONSE_LEN);
226
227 return rval;
228 }
229
230 static uint32_t
231 urndis_ctrl_handle_init(struct usbnet *un, const struct rndis_comp_hdr *hdr)
232 {
233 struct urndis_softc *sc = usbnet_softc(un);
234 const struct rndis_init_comp *msg;
235
236 msg = (const struct rndis_init_comp *) hdr;
237
238 DPRINTF(("%s: urndis_ctrl_handle_init: len %u rid %u status 0x%x "
239 "ver_major %u ver_minor %u devflags 0x%x medium 0x%x pktmaxcnt %u "
240 "pktmaxsz %u align %u aflistoffset %u aflistsz %u\n",
241 DEVNAME(un),
242 le32toh(msg->rm_len),
243 le32toh(msg->rm_rid),
244 le32toh(msg->rm_status),
245 le32toh(msg->rm_ver_major),
246 le32toh(msg->rm_ver_minor),
247 le32toh(msg->rm_devflags),
248 le32toh(msg->rm_medium),
249 le32toh(msg->rm_pktmaxcnt),
250 le32toh(msg->rm_pktmaxsz),
251 le32toh(msg->rm_align),
252 le32toh(msg->rm_aflistoffset),
253 le32toh(msg->rm_aflistsz)));
254
255 if (le32toh(msg->rm_status) != RNDIS_STATUS_SUCCESS) {
256 printf("%s: init failed 0x%x\n",
257 DEVNAME(un),
258 le32toh(msg->rm_status));
259
260 return le32toh(msg->rm_status);
261 }
262
263 if (le32toh(msg->rm_devflags) != RNDIS_DF_CONNECTIONLESS) {
264 printf("%s: wrong device type (current type: 0x%x)\n",
265 DEVNAME(un),
266 le32toh(msg->rm_devflags));
267
268 return RNDIS_STATUS_FAILURE;
269 }
270
271 if (le32toh(msg->rm_medium) != RNDIS_MEDIUM_802_3) {
272 printf("%s: medium not 802.3 (current medium: 0x%x)\n",
273 DEVNAME(un), le32toh(msg->rm_medium));
274
275 return RNDIS_STATUS_FAILURE;
276 }
277
278 if (le32toh(msg->rm_ver_major) != RNDIS_MAJOR_VERSION ||
279 le32toh(msg->rm_ver_minor) != RNDIS_MINOR_VERSION) {
280 printf("%s: version not %u.%u (current version: %u.%u)\n",
281 DEVNAME(un), RNDIS_MAJOR_VERSION, RNDIS_MINOR_VERSION,
282 le32toh(msg->rm_ver_major), le32toh(msg->rm_ver_minor));
283
284 return RNDIS_STATUS_FAILURE;
285 }
286
287 sc->sc_maxppt = le32toh(msg->rm_pktmaxcnt);
288 sc->sc_maxtsz = le32toh(msg->rm_pktmaxsz);
289 sc->sc_palign = 1U << le32toh(msg->rm_align);
290
291 return le32toh(msg->rm_status);
292 }
293
294 static uint32_t
295 urndis_ctrl_handle_query(struct usbnet *un,
296 const struct rndis_comp_hdr *hdr, void **buf, size_t *bufsz)
297 {
298 const struct rndis_query_comp *msg;
299
300 msg = (const struct rndis_query_comp *) hdr;
301
302 DPRINTF(("%s: urndis_ctrl_handle_query: len %u rid %u status 0x%x "
303 "buflen %u bufoff %u\n",
304 DEVNAME(un),
305 le32toh(msg->rm_len),
306 le32toh(msg->rm_rid),
307 le32toh(msg->rm_status),
308 le32toh(msg->rm_infobuflen),
309 le32toh(msg->rm_infobufoffset)));
310
311 if (buf && bufsz) {
312 *buf = NULL;
313 *bufsz = 0;
314 }
315
316 if (le32toh(msg->rm_status) != RNDIS_STATUS_SUCCESS) {
317 printf("%s: query failed 0x%x\n",
318 DEVNAME(un),
319 le32toh(msg->rm_status));
320
321 return le32toh(msg->rm_status);
322 }
323
324 if (le32toh(msg->rm_infobuflen) + le32toh(msg->rm_infobufoffset) +
325 RNDIS_HEADER_OFFSET > le32toh(msg->rm_len)) {
326 printf("%s: ctrl message error: invalid query info "
327 "len/offset/end_position(%u/%u/%u) -> "
328 "go out of buffer limit %u\n",
329 DEVNAME(un),
330 le32toh(msg->rm_infobuflen),
331 le32toh(msg->rm_infobufoffset),
332 le32toh(msg->rm_infobuflen) +
333 le32toh(msg->rm_infobufoffset) + (uint32_t)RNDIS_HEADER_OFFSET,
334 le32toh(msg->rm_len));
335 return RNDIS_STATUS_FAILURE;
336 }
337
338 if (buf && bufsz) {
339 const char *p;
340
341 *buf = kmem_alloc(le32toh(msg->rm_infobuflen), KM_SLEEP);
342 *bufsz = le32toh(msg->rm_infobuflen);
343
344 p = (const char *)&msg->rm_rid;
345 p += le32toh(msg->rm_infobufoffset);
346 memcpy(*buf, p, le32toh(msg->rm_infobuflen));
347 }
348
349 return le32toh(msg->rm_status);
350 }
351
352 static uint32_t
353 urndis_ctrl_handle_reset(struct usbnet *un, const struct rndis_comp_hdr *hdr)
354 {
355 struct urndis_softc *sc = usbnet_softc(un);
356 const struct rndis_reset_comp *msg;
357 uint32_t rval;
358
359 msg = (const struct rndis_reset_comp *) hdr;
360
361 rval = le32toh(msg->rm_status);
362
363 DPRINTF(("%s: urndis_ctrl_handle_reset: len %u status 0x%x "
364 "adrreset %u\n",
365 DEVNAME(un),
366 le32toh(msg->rm_len),
367 rval,
368 le32toh(msg->rm_adrreset)));
369
370 if (rval != RNDIS_STATUS_SUCCESS) {
371 printf("%s: reset failed 0x%x\n", DEVNAME(un), rval);
372 return rval;
373 }
374
375 if (le32toh(msg->rm_adrreset) != 0) {
376 uint32_t filter;
377
378 filter = htole32(sc->sc_filter);
379 rval = urndis_ctrl_set(un, OID_GEN_CURRENT_PACKET_FILTER,
380 &filter, sizeof(filter));
381 if (rval != RNDIS_STATUS_SUCCESS) {
382 printf("%s: unable to reset data filters\n",
383 DEVNAME(un));
384 return rval;
385 }
386 }
387
388 return rval;
389 }
390
391 static uint32_t
392 urndis_ctrl_handle_status(struct usbnet *un,
393 const struct rndis_comp_hdr *hdr)
394 {
395 const struct rndis_status_msg *msg;
396 uint32_t rval;
397
398 msg = (const struct rndis_status_msg *)hdr;
399
400 rval = le32toh(msg->rm_status);
401
402 DPRINTF(("%s: urndis_ctrl_handle_status: len %u status 0x%x "
403 "stbuflen %u\n",
404 DEVNAME(un),
405 le32toh(msg->rm_len),
406 rval,
407 le32toh(msg->rm_stbuflen)));
408
409 switch (rval) {
410 case RNDIS_STATUS_MEDIA_CONNECT:
411 case RNDIS_STATUS_MEDIA_DISCONNECT:
412 case RNDIS_STATUS_OFFLOAD_CURRENT_CONFIG:
413 rval = RNDIS_STATUS_SUCCESS;
414 break;
415
416 default:
417 printf("%s: status 0x%x\n", DEVNAME(un), rval);
418 }
419
420 return rval;
421 }
422
423 static uint32_t
424 urndis_ctrl_init(struct usbnet *un)
425 {
426 struct rndis_init_req *msg;
427 uint32_t rval;
428 struct rndis_comp_hdr *hdr;
429
430 msg = kmem_alloc(sizeof(*msg), KM_SLEEP);
431 msg->rm_type = htole32(REMOTE_NDIS_INITIALIZE_MSG);
432 msg->rm_len = htole32(sizeof(*msg));
433 msg->rm_rid = htole32(0);
434 msg->rm_ver_major = htole32(RNDIS_MAJOR_VERSION);
435 msg->rm_ver_minor = htole32(RNDIS_MINOR_VERSION);
436 msg->rm_max_xfersz = htole32(RNDIS_BUFSZ);
437
438 DPRINTF(("%s: urndis_ctrl_init send: type %u len %u rid %u ver_major %u "
439 "ver_minor %u max_xfersz %u\n",
440 DEVNAME(un),
441 le32toh(msg->rm_type),
442 le32toh(msg->rm_len),
443 le32toh(msg->rm_rid),
444 le32toh(msg->rm_ver_major),
445 le32toh(msg->rm_ver_minor),
446 le32toh(msg->rm_max_xfersz)));
447
448 rval = urndis_ctrl_send(un, msg, sizeof(*msg));
449 kmem_free(msg, sizeof(*msg));
450
451 if (rval != RNDIS_STATUS_SUCCESS) {
452 printf("%s: init failed\n", DEVNAME(un));
453 return rval;
454 }
455
456 if ((hdr = urndis_ctrl_recv(un)) == NULL) {
457 printf("%s: unable to get init response\n", DEVNAME(un));
458 return RNDIS_STATUS_FAILURE;
459 }
460 rval = urndis_ctrl_handle(un, hdr, NULL, NULL);
461
462 return rval;
463 }
464
465 #if 0
466 static uint32_t
467 urndis_ctrl_halt(struct usbnet *un)
468 {
469 struct rndis_halt_req *msg;
470 uint32_t rval;
471
472 msg = kmem_alloc(sizeof(*msg), KM_SLEEP);
473 msg->rm_type = htole32(REMOTE_NDIS_HALT_MSG);
474 msg->rm_len = htole32(sizeof(*msg));
475 msg->rm_rid = 0;
476
477 DPRINTF(("%s: urndis_ctrl_halt send: type %u len %u rid %u\n",
478 DEVNAME(un),
479 le32toh(msg->rm_type),
480 le32toh(msg->rm_len),
481 le32toh(msg->rm_rid)));
482
483 rval = urndis_ctrl_send(un, msg, sizeof(*msg));
484 kmem_free(msg, sizeof(*msg));
485
486 if (rval != RNDIS_STATUS_SUCCESS)
487 printf("%s: halt failed\n", DEVNAME(un));
488
489 return rval;
490 }
491 #endif
492
493 static uint32_t
494 urndis_ctrl_query(struct usbnet *un, uint32_t oid,
495 void *qbuf, size_t qlen,
496 void **rbuf, size_t *rbufsz)
497 {
498 struct rndis_query_req *msg;
499 uint32_t rval;
500 struct rndis_comp_hdr *hdr;
501
502 msg = kmem_alloc(sizeof(*msg) + qlen, KM_SLEEP);
503 msg->rm_type = htole32(REMOTE_NDIS_QUERY_MSG);
504 msg->rm_len = htole32(sizeof(*msg) + qlen);
505 msg->rm_rid = 0; /* XXX */
506 msg->rm_oid = htole32(oid);
507 msg->rm_infobuflen = htole32(qlen);
508 if (qlen != 0) {
509 msg->rm_infobufoffset = htole32(20);
510 memcpy((char*)msg + 20, qbuf, qlen);
511 } else
512 msg->rm_infobufoffset = 0;
513 msg->rm_devicevchdl = 0;
514
515 DPRINTF(("%s: urndis_ctrl_query send: type %u len %u rid %u oid 0x%x "
516 "infobuflen %u infobufoffset %u devicevchdl %u\n",
517 DEVNAME(un),
518 le32toh(msg->rm_type),
519 le32toh(msg->rm_len),
520 le32toh(msg->rm_rid),
521 le32toh(msg->rm_oid),
522 le32toh(msg->rm_infobuflen),
523 le32toh(msg->rm_infobufoffset),
524 le32toh(msg->rm_devicevchdl)));
525
526 rval = urndis_ctrl_send(un, msg, sizeof(*msg));
527 kmem_free(msg, sizeof(*msg) + qlen);
528
529 if (rval != RNDIS_STATUS_SUCCESS) {
530 printf("%s: query failed\n", DEVNAME(un));
531 return rval;
532 }
533
534 if ((hdr = urndis_ctrl_recv(un)) == NULL) {
535 printf("%s: unable to get query response\n", DEVNAME(un));
536 return RNDIS_STATUS_FAILURE;
537 }
538 rval = urndis_ctrl_handle(un, hdr, rbuf, rbufsz);
539
540 return rval;
541 }
542
543 static uint32_t
544 urndis_ctrl_set(struct usbnet *un, uint32_t oid, void *buf, size_t len)
545 {
546 struct rndis_set_req *msg;
547 uint32_t rval;
548 struct rndis_comp_hdr *hdr;
549
550 msg = kmem_alloc(sizeof(*msg) + len, KM_SLEEP);
551 msg->rm_type = htole32(REMOTE_NDIS_SET_MSG);
552 msg->rm_len = htole32(sizeof(*msg) + len);
553 msg->rm_rid = 0; /* XXX */
554 msg->rm_oid = htole32(oid);
555 msg->rm_infobuflen = htole32(len);
556 if (len != 0) {
557 msg->rm_infobufoffset = htole32(20);
558 memcpy((char*)msg + 20, buf, len);
559 } else
560 msg->rm_infobufoffset = 0;
561 msg->rm_devicevchdl = 0;
562
563 DPRINTF(("%s: urndis_ctrl_set send: type %u len %u rid %u oid 0x%x "
564 "infobuflen %u infobufoffset %u devicevchdl %u\n",
565 DEVNAME(un),
566 le32toh(msg->rm_type),
567 le32toh(msg->rm_len),
568 le32toh(msg->rm_rid),
569 le32toh(msg->rm_oid),
570 le32toh(msg->rm_infobuflen),
571 le32toh(msg->rm_infobufoffset),
572 le32toh(msg->rm_devicevchdl)));
573
574 rval = urndis_ctrl_send(un, msg, sizeof(*msg));
575 kmem_free(msg, sizeof(*msg) + len);
576
577 if (rval != RNDIS_STATUS_SUCCESS) {
578 printf("%s: set failed\n", DEVNAME(un));
579 return rval;
580 }
581
582 if ((hdr = urndis_ctrl_recv(un)) == NULL) {
583 printf("%s: unable to get set response\n", DEVNAME(un));
584 return RNDIS_STATUS_FAILURE;
585 }
586 rval = urndis_ctrl_handle(un, hdr, NULL, NULL);
587 if (rval != RNDIS_STATUS_SUCCESS)
588 printf("%s: set failed 0x%x\n", DEVNAME(un), rval);
589
590 return rval;
591 }
592
593 #if 0
594 static uint32_t
595 urndis_ctrl_set_param(struct urndis_softc *un,
596 const char *name,
597 uint32_t type,
598 void *buf,
599 size_t len)
600 {
601 struct rndis_set_parameter *param;
602 uint32_t rval;
603 size_t namelen, tlen;
604
605 if (name)
606 namelen = strlen(name);
607 else
608 namelen = 0;
609 tlen = sizeof(*param) + len + namelen;
610 param = kmem_alloc(tlen, KM_SLEEP);
611 param->rm_namelen = htole32(namelen);
612 param->rm_valuelen = htole32(len);
613 param->rm_type = htole32(type);
614 if (namelen != 0) {
615 param->rm_nameoffset = htole32(20);
616 memcpy(param + 20, name, namelen);
617 } else
618 param->rm_nameoffset = 0;
619 if (len != 0) {
620 param->rm_valueoffset = htole32(20 + namelen);
621 memcpy(param + 20 + namelen, buf, len);
622 } else
623 param->rm_valueoffset = 0;
624
625 DPRINTF(("%s: urndis_ctrl_set_param send: nameoffset %u namelen %u "
626 "type 0x%x valueoffset %u valuelen %u\n",
627 DEVNAME(un),
628 le32toh(param->rm_nameoffset),
629 le32toh(param->rm_namelen),
630 le32toh(param->rm_type),
631 le32toh(param->rm_valueoffset),
632 le32toh(param->rm_valuelen)));
633
634 rval = urndis_ctrl_set(un, OID_GEN_RNDIS_CONFIG_PARAMETER, param, tlen);
635 kmem_free(param, tlen);
636 if (rval != RNDIS_STATUS_SUCCESS)
637 printf("%s: set param failed 0x%x\n", DEVNAME(un), rval);
638
639 return rval;
640 }
641
642 /* XXX : adrreset, get it from response */
643 static uint32_t
644 urndis_ctrl_reset(struct usbnet *un)
645 {
646 struct rndis_reset_req *reset;
647 uint32_t rval;
648 struct rndis_comp_hdr *hdr;
649
650 reset = kmem_alloc(sizeof(*reset), KM_SLEEP);
651 reset->rm_type = htole32(REMOTE_NDIS_RESET_MSG);
652 reset->rm_len = htole32(sizeof(*reset));
653 reset->rm_rid = 0; /* XXX rm_rid == reserved ... remove ? */
654
655 DPRINTF(("%s: urndis_ctrl_reset send: type %u len %u rid %u\n",
656 DEVNAME(un),
657 le32toh(reset->rm_type),
658 le32toh(reset->rm_len),
659 le32toh(reset->rm_rid)));
660
661 rval = urndis_ctrl_send(un, reset, sizeof(*reset));
662 kmem_free(reset, sizeof(*reset));
663
664 if (rval != RNDIS_STATUS_SUCCESS) {
665 printf("%s: reset failed\n", DEVNAME(un));
666 return rval;
667 }
668
669 if ((hdr = urndis_ctrl_recv(un)) == NULL) {
670 printf("%s: unable to get reset response\n", DEVNAME(un));
671 return RNDIS_STATUS_FAILURE;
672 }
673 rval = urndis_ctrl_handle(un, hdr, NULL, NULL);
674
675 return rval;
676 }
677
678 static uint32_t
679 urndis_ctrl_keepalive(struct usbnet *un)
680 {
681 struct rndis_keepalive_req *keep;
682 uint32_t rval;
683 struct rndis_comp_hdr *hdr;
684
685 keep = kmem_alloc(sizeof(*keep), KM_SLEEP);
686 keep->rm_type = htole32(REMOTE_NDIS_KEEPALIVE_MSG);
687 keep->rm_len = htole32(sizeof(*keep));
688 keep->rm_rid = 0; /* XXX rm_rid == reserved ... remove ? */
689
690 DPRINTF(("%s: urndis_ctrl_keepalive: type %u len %u rid %u\n",
691 DEVNAME(un),
692 le32toh(keep->rm_type),
693 le32toh(keep->rm_len),
694 le32toh(keep->rm_rid)));
695
696 rval = urndis_ctrl_send(un, keep, sizeof(*keep));
697 kmem_free(keep, sizeof(*keep));
698
699 if (rval != RNDIS_STATUS_SUCCESS) {
700 printf("%s: keepalive failed\n", DEVNAME(un));
701 return rval;
702 }
703
704 if ((hdr = urndis_ctrl_recv(un)) == NULL) {
705 printf("%s: unable to get keepalive response\n", DEVNAME(un));
706 return RNDIS_STATUS_FAILURE;
707 }
708 rval = urndis_ctrl_handle(un, hdr, NULL, NULL);
709 if (rval != RNDIS_STATUS_SUCCESS) {
710 printf("%s: keepalive failed 0x%x\n", DEVNAME(un), rval);
711 urndis_ctrl_reset(un);
712 }
713
714 return rval;
715 }
716 #endif
717
718 static unsigned
719 urndis_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c)
720 {
721 struct rndis_packet_msg *msg;
722
723 msg = (struct rndis_packet_msg *)c->unc_buf;
724
725 memset(msg, 0, sizeof(*msg));
726 msg->rm_type = htole32(REMOTE_NDIS_PACKET_MSG);
727 msg->rm_len = htole32(sizeof(*msg) + m->m_pkthdr.len);
728
729 msg->rm_dataoffset = htole32(RNDIS_DATA_OFFSET);
730 msg->rm_datalen = htole32(m->m_pkthdr.len);
731
732 m_copydata(m, 0, m->m_pkthdr.len,
733 ((char*)msg + RNDIS_DATA_OFFSET + RNDIS_HEADER_OFFSET));
734
735 DPRINTF(("%s: %s type 0x%x len %u data(off %u len %u)\n",
736 __func__,
737 DEVNAME(un),
738 le32toh(msg->rm_type),
739 le32toh(msg->rm_len),
740 le32toh(msg->rm_dataoffset),
741 le32toh(msg->rm_datalen)));
742
743 return le32toh(msg->rm_len);
744 }
745
746 static void
747 urndis_rx_loop(struct usbnet * un, struct usbd_xfer *xfer,
748 struct usbnet_chain *c, uint32_t total_len)
749 {
750 struct rndis_packet_msg *msg;
751 struct ifnet *ifp = usbnet_ifp(un);
752 int offset;
753
754 offset = 0;
755
756 while (total_len > 1) {
757 msg = (struct rndis_packet_msg *)((char*)c->unc_buf + offset);
758
759 DPRINTF(("%s: %s buffer size left %u\n", DEVNAME(un), __func__,
760 total_len));
761
762 if (total_len < sizeof(*msg)) {
763 printf("%s: urndis_decap invalid buffer total_len %u < "
764 "minimum header %zu\n",
765 DEVNAME(un),
766 total_len,
767 sizeof(*msg));
768 return;
769 }
770
771 DPRINTF(("%s: urndis_decap total_len %u data(off:%u len:%u) "
772 "oobdata(off:%u len:%u nb:%u) perpacket(off:%u len:%u)\n",
773 DEVNAME(un),
774 le32toh(msg->rm_len),
775 le32toh(msg->rm_dataoffset),
776 le32toh(msg->rm_datalen),
777 le32toh(msg->rm_oobdataoffset),
778 le32toh(msg->rm_oobdatalen),
779 le32toh(msg->rm_oobdataelements),
780 le32toh(msg->rm_pktinfooffset),
781 le32toh(msg->rm_pktinfooffset)));
782
783 if (le32toh(msg->rm_type) != REMOTE_NDIS_PACKET_MSG) {
784 printf("%s: urndis_decap invalid type 0x%x != 0x%x\n",
785 DEVNAME(un),
786 le32toh(msg->rm_type),
787 REMOTE_NDIS_PACKET_MSG);
788 return;
789 }
790 if (le32toh(msg->rm_len) < sizeof(*msg)) {
791 printf("%s: urndis_decap invalid msg len %u < %zu\n",
792 DEVNAME(un),
793 le32toh(msg->rm_len),
794 sizeof(*msg));
795 return;
796 }
797 if (le32toh(msg->rm_len) > total_len) {
798 printf("%s: urndis_decap invalid msg len %u > buffer "
799 "total_len %u\n",
800 DEVNAME(un),
801 le32toh(msg->rm_len),
802 total_len);
803 return;
804 }
805
806 if (le32toh(msg->rm_dataoffset) +
807 le32toh(msg->rm_datalen) + RNDIS_HEADER_OFFSET
808 > le32toh(msg->rm_len)) {
809 printf("%s: urndis_decap invalid data "
810 "len/offset/end_position(%u/%u/%u) -> "
811 "go out of receive buffer limit %u\n",
812 DEVNAME(un),
813 le32toh(msg->rm_datalen),
814 le32toh(msg->rm_dataoffset),
815 le32toh(msg->rm_dataoffset) +
816 le32toh(msg->rm_datalen) + (uint32_t)RNDIS_HEADER_OFFSET,
817 le32toh(msg->rm_len));
818 return;
819 }
820
821 if (le32toh(msg->rm_datalen) < sizeof(struct ether_header)) {
822 ifp->if_ierrors++;
823 printf("%s: urndis_decap invalid ethernet size "
824 "%d < %zu\n",
825 DEVNAME(un),
826 le32toh(msg->rm_datalen),
827 sizeof(struct ether_header));
828 return;
829 }
830
831 usbnet_enqueue(un,
832 ((char*)&msg->rm_dataoffset + le32toh(msg->rm_dataoffset)),
833 le32toh(msg->rm_datalen), 0, 0, 0);
834
835 offset += le32toh(msg->rm_len);
836 total_len -= le32toh(msg->rm_len);
837 }
838 }
839
840 #if 0
841 static void
842 urndis_watchdog(struct ifnet *ifp)
843 {
844 struct urndis_softc *sc = usbnet_softc(un);
845
846 if (un->un_dying)
847 return;
848
849 ifp->if_oerrors++;
850 printf("%s: watchdog timeout\n", DEVNAME(un));
851
852 urndis_ctrl_keepalive(un);
853 }
854 #endif
855
856 static int
857 urndis_init_un(struct ifnet *ifp, struct usbnet *un)
858 {
859 int err;
860
861 if (ifp->if_flags & IFF_RUNNING)
862 return 0;
863
864 err = urndis_ctrl_init(un);
865 if (err != RNDIS_STATUS_SUCCESS)
866 return EIO;
867
868 usbnet_lock(un);
869 if (un->un_dying)
870 err = EIO;
871 else {
872 usbnet_stop(un, ifp, 1);
873 err = usbnet_init_rx_tx(un);
874 if (err == 0)
875 un->un_link = true;
876 }
877 usbnet_unlock(un);
878
879 return err;
880 }
881
882 static int
883 urndis_init(struct ifnet *ifp)
884 {
885 struct usbnet *un = ifp->if_softc;
886
887 return urndis_init_un(ifp, un);
888 }
889
890 static int
891 urndis_match(device_t parent, cfdata_t match, void *aux)
892 {
893 struct usbif_attach_arg *uiaa = aux;
894 usb_interface_descriptor_t *id;
895
896 if (!uiaa->uiaa_iface)
897 return UMATCH_NONE;
898
899 id = usbd_get_interface_descriptor(uiaa->uiaa_iface);
900 if (id == NULL)
901 return UMATCH_NONE;
902
903 if (id->bInterfaceClass == UICLASS_WIRELESS &&
904 id->bInterfaceSubClass == UISUBCLASS_RF &&
905 id->bInterfaceProtocol == UIPROTO_RNDIS)
906 return UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO;
907
908 return usb_lookup(urndis_devs, uiaa->uiaa_vendor, uiaa->uiaa_product) != NULL ?
909 UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
910 }
911
912 static void
913 urndis_attach(device_t parent, device_t self, void *aux)
914 {
915 struct urndis_softc *sc = device_private(self);
916 struct usbnet * const un = &sc->sc_un;
917 struct usbif_attach_arg *uiaa = aux;
918 struct usbd_device *dev = uiaa->uiaa_device;
919 usb_interface_descriptor_t *id;
920 usb_endpoint_descriptor_t *ed;
921 usb_config_descriptor_t *cd;
922 struct usbd_interface *iface_ctl;
923 const usb_cdc_union_descriptor_t *ud;
924 const usb_cdc_header_descriptor_t *desc;
925 usbd_desc_iter_t iter;
926 int if_ctl, if_data;
927 int i, j, altcnt;
928 void *buf;
929 size_t bufsz;
930 uint32_t filter;
931 char *devinfop;
932
933 /* Switch to usbnet for device_private() */
934 self->dv_private = un;
935
936 aprint_naive("\n");
937 aprint_normal("\n");
938 devinfop = usbd_devinfo_alloc(dev, 0);
939 aprint_normal_dev(self, "%s\n", devinfop);
940 usbd_devinfo_free(devinfop);
941
942 un->un_dev = self;
943 un->un_udev = dev;
944 un->un_sc = sc;
945 un->un_ops = &urndis_ops;
946
947 iface_ctl = uiaa->uiaa_iface;
948 un->un_iface = uiaa->uiaa_iface;
949 id = usbd_get_interface_descriptor(iface_ctl);
950 if_ctl = id->bInterfaceNumber;
951 sc->sc_ifaceno_ctl = if_ctl;
952 if_data = -1;
953
954 usb_desc_iter_init(un->un_udev, &iter);
955 while ((desc = (const void *)usb_desc_iter_next(&iter)) != NULL) {
956
957 if (desc->bDescriptorType != UDESC_CS_INTERFACE) {
958 continue;
959 }
960 switch (desc->bDescriptorSubtype) {
961 case UDESCSUB_CDC_UNION:
962 /* XXX bail out when found first? */
963 ud = (const usb_cdc_union_descriptor_t *)desc;
964 if (if_data == -1)
965 if_data = ud->bSlaveInterface[0];
966 break;
967 }
968 }
969
970 if (if_data == -1) {
971 DPRINTF(("urndis_attach: no union interface\n"));
972 un->un_iface = iface_ctl;
973 } else {
974 DPRINTF(("urndis_attach: union interface: ctl %u, data %u\n",
975 if_ctl, if_data));
976 for (i = 0; i < uiaa->uiaa_nifaces; i++) {
977 if (uiaa->uiaa_ifaces[i] != NULL) {
978 id = usbd_get_interface_descriptor(
979 uiaa->uiaa_ifaces[i]);
980 if (id != NULL && id->bInterfaceNumber ==
981 if_data) {
982 un->un_iface = uiaa->uiaa_ifaces[i];
983 uiaa->uiaa_ifaces[i] = NULL;
984 }
985 }
986 }
987 }
988
989 if (un->un_iface == NULL) {
990 aprint_error("%s: no data interface\n", DEVNAME(un));
991 return;
992 }
993
994 id = usbd_get_interface_descriptor(un->un_iface);
995 cd = usbd_get_config_descriptor(un->un_udev);
996 altcnt = usbd_get_no_alts(cd, id->bInterfaceNumber);
997
998 for (j = 0; j < altcnt; j++) {
999 if (usbd_set_interface(un->un_iface, j)) {
1000 aprint_error("%s: interface alternate setting %u "
1001 "failed\n", DEVNAME(un), j);
1002 return;
1003 }
1004 /* Find endpoints. */
1005 id = usbd_get_interface_descriptor(un->un_iface);
1006 un->un_ed[USBNET_ENDPT_RX] = un->un_ed[USBNET_ENDPT_TX] = 0;
1007 for (i = 0; i < id->bNumEndpoints; i++) {
1008 ed = usbd_interface2endpoint_descriptor(
1009 un->un_iface, i);
1010 if (!ed) {
1011 aprint_error("%s: no descriptor for bulk "
1012 "endpoint %u\n", DEVNAME(un), i);
1013 return;
1014 }
1015 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
1016 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
1017 un->un_ed[USBNET_ENDPT_RX] = ed->bEndpointAddress;
1018 }
1019 else if (
1020 UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
1021 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
1022 un->un_ed[USBNET_ENDPT_TX] = ed->bEndpointAddress;
1023 }
1024 }
1025
1026 if (un->un_ed[USBNET_ENDPT_RX] != 0 && un->un_ed[USBNET_ENDPT_TX] != 0) {
1027 DPRINTF(("%s: in=0x%x, out=0x%x\n",
1028 DEVNAME(un),
1029 un->un_ed[USBNET_ENDPT_RX],
1030 sc->sc_bulkout_no));
1031 break;
1032 }
1033 }
1034
1035 if (un->un_ed[USBNET_ENDPT_RX] == 0)
1036 aprint_error("%s: could not find data bulk in\n", DEVNAME(un));
1037 if (un->un_ed[USBNET_ENDPT_TX] == 0)
1038 aprint_error("%s: could not find data bulk out\n",DEVNAME(un));
1039 if (un->un_ed[USBNET_ENDPT_RX] == 0 || un->un_ed[USBNET_ENDPT_TX] == 0)
1040 return;
1041
1042 struct ifnet *ifp = usbnet_ifp(un);
1043 #if 0
1044 ifp->if_watchdog = urndis_watchdog;
1045 #endif
1046
1047 usbnet_attach(un, "urndisdet", RNDIS_RX_LIST_CNT, RNDIS_TX_LIST_CNT,
1048 USBD_SHORT_XFER_OK, USBD_FORCE_SHORT_XFER,
1049 RNDIS_BUFSZ, RNDIS_BUFSZ);
1050
1051 urndis_init_un(ifp, un);
1052
1053 if (urndis_ctrl_query(un, OID_802_3_PERMANENT_ADDRESS, NULL, 0,
1054 &buf, &bufsz) != RNDIS_STATUS_SUCCESS) {
1055 aprint_error("%s: unable to get hardware address\n",
1056 DEVNAME(un));
1057 usbnet_lock(un);
1058 usbnet_stop(un, ifp, 1);
1059 usbnet_unlock(un);
1060 return;
1061 }
1062
1063 if (bufsz == ETHER_ADDR_LEN) {
1064 memcpy(un->un_eaddr, buf, ETHER_ADDR_LEN);
1065 kmem_free(buf, bufsz);
1066 } else {
1067 aprint_error("%s: invalid address\n", DEVNAME(un));
1068 kmem_free(buf, bufsz);
1069 usbnet_lock(un);
1070 usbnet_stop(un, ifp, 1);
1071 usbnet_unlock(un);
1072 return;
1073 }
1074
1075 /* Initialize packet filter */
1076 sc->sc_filter = RNDIS_PACKET_TYPE_BROADCAST;
1077 sc->sc_filter |= RNDIS_PACKET_TYPE_ALL_MULTICAST;
1078 filter = htole32(sc->sc_filter);
1079 if (urndis_ctrl_set(un, OID_GEN_CURRENT_PACKET_FILTER, &filter,
1080 sizeof(filter)) != RNDIS_STATUS_SUCCESS) {
1081 aprint_error("%s: unable to set data filters\n", DEVNAME(un));
1082 usbnet_lock(un);
1083 usbnet_stop(un, ifp, 1);
1084 usbnet_unlock(un);
1085 return;
1086 }
1087
1088 /* Turn off again now it has been identified. */
1089 usbnet_lock(un);
1090 usbnet_stop(un, ifp, 1);
1091 usbnet_unlock(un);
1092
1093 usbnet_attach_ifp(un, false, IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST,
1094 0, 0);
1095 }
1096