if_urndis.c revision 1.27 1 /* $NetBSD: if_urndis.c,v 1.27 2019/08/10 02:17:36 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.27 2019/08/10 02:17:36 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 (usbnet_isdying(un))
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 (usbnet_isdying(un))
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 (usbnet_isdying(un))
870 err = EIO;
871 else {
872 usbnet_stop(un, ifp, 1);
873 err = usbnet_init_rx_tx(un);
874 usbnet_set_link(un, err == 0);
875 }
876 usbnet_unlock(un);
877
878 return err;
879 }
880
881 static int
882 urndis_init(struct ifnet *ifp)
883 {
884 struct usbnet *un = ifp->if_softc;
885
886 return urndis_init_un(ifp, un);
887 }
888
889 static int
890 urndis_match(device_t parent, cfdata_t match, void *aux)
891 {
892 struct usbif_attach_arg *uiaa = aux;
893 usb_interface_descriptor_t *id;
894
895 if (!uiaa->uiaa_iface)
896 return UMATCH_NONE;
897
898 id = usbd_get_interface_descriptor(uiaa->uiaa_iface);
899 if (id == NULL)
900 return UMATCH_NONE;
901
902 if (id->bInterfaceClass == UICLASS_WIRELESS &&
903 id->bInterfaceSubClass == UISUBCLASS_RF &&
904 id->bInterfaceProtocol == UIPROTO_RNDIS)
905 return UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO;
906
907 return usb_lookup(urndis_devs, uiaa->uiaa_vendor, uiaa->uiaa_product) != NULL ?
908 UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
909 }
910
911 static void
912 urndis_attach(device_t parent, device_t self, void *aux)
913 {
914 struct urndis_softc *sc = device_private(self);
915 struct usbnet * const un = &sc->sc_un;
916 struct usbif_attach_arg *uiaa = aux;
917 struct usbd_device *dev = uiaa->uiaa_device;
918 usb_interface_descriptor_t *id;
919 usb_endpoint_descriptor_t *ed;
920 usb_config_descriptor_t *cd;
921 struct usbd_interface *iface_ctl;
922 const usb_cdc_union_descriptor_t *ud;
923 const usb_cdc_header_descriptor_t *desc;
924 usbd_desc_iter_t iter;
925 int if_ctl, if_data;
926 int i, j, altcnt;
927 void *buf;
928 size_t bufsz;
929 uint32_t filter;
930 char *devinfop;
931
932 /* Switch to usbnet for device_private() */
933 self->dv_private = un;
934
935 aprint_naive("\n");
936 aprint_normal("\n");
937 devinfop = usbd_devinfo_alloc(dev, 0);
938 aprint_normal_dev(self, "%s\n", devinfop);
939 usbd_devinfo_free(devinfop);
940
941 un->un_dev = self;
942 un->un_udev = dev;
943 un->un_sc = sc;
944 un->un_ops = &urndis_ops;
945 un->un_rx_xfer_flags = USBD_SHORT_XFER_OK;
946 un->un_tx_xfer_flags = USBD_FORCE_SHORT_XFER;
947 un->un_rx_list_cnt = RNDIS_RX_LIST_CNT;
948 un->un_tx_list_cnt = RNDIS_TX_LIST_CNT;
949 un->un_rx_bufsz = RNDIS_BUFSZ;
950 un->un_tx_bufsz = RNDIS_BUFSZ;
951
952 iface_ctl = uiaa->uiaa_iface;
953 un->un_iface = uiaa->uiaa_iface;
954 id = usbd_get_interface_descriptor(iface_ctl);
955 if_ctl = id->bInterfaceNumber;
956 sc->sc_ifaceno_ctl = if_ctl;
957 if_data = -1;
958
959 usb_desc_iter_init(un->un_udev, &iter);
960 while ((desc = (const void *)usb_desc_iter_next(&iter)) != NULL) {
961
962 if (desc->bDescriptorType != UDESC_CS_INTERFACE) {
963 continue;
964 }
965 switch (desc->bDescriptorSubtype) {
966 case UDESCSUB_CDC_UNION:
967 /* XXX bail out when found first? */
968 ud = (const usb_cdc_union_descriptor_t *)desc;
969 if (if_data == -1)
970 if_data = ud->bSlaveInterface[0];
971 break;
972 }
973 }
974
975 if (if_data == -1) {
976 DPRINTF(("urndis_attach: no union interface\n"));
977 un->un_iface = iface_ctl;
978 } else {
979 DPRINTF(("urndis_attach: union interface: ctl %u, data %u\n",
980 if_ctl, if_data));
981 for (i = 0; i < uiaa->uiaa_nifaces; i++) {
982 if (uiaa->uiaa_ifaces[i] != NULL) {
983 id = usbd_get_interface_descriptor(
984 uiaa->uiaa_ifaces[i]);
985 if (id != NULL && id->bInterfaceNumber ==
986 if_data) {
987 un->un_iface = uiaa->uiaa_ifaces[i];
988 uiaa->uiaa_ifaces[i] = NULL;
989 }
990 }
991 }
992 }
993
994 if (un->un_iface == NULL) {
995 aprint_error("%s: no data interface\n", DEVNAME(un));
996 return;
997 }
998
999 id = usbd_get_interface_descriptor(un->un_iface);
1000 cd = usbd_get_config_descriptor(un->un_udev);
1001 altcnt = usbd_get_no_alts(cd, id->bInterfaceNumber);
1002
1003 for (j = 0; j < altcnt; j++) {
1004 if (usbd_set_interface(un->un_iface, j)) {
1005 aprint_error("%s: interface alternate setting %u "
1006 "failed\n", DEVNAME(un), j);
1007 return;
1008 }
1009 /* Find endpoints. */
1010 id = usbd_get_interface_descriptor(un->un_iface);
1011 un->un_ed[USBNET_ENDPT_RX] = un->un_ed[USBNET_ENDPT_TX] = 0;
1012 for (i = 0; i < id->bNumEndpoints; i++) {
1013 ed = usbd_interface2endpoint_descriptor(
1014 un->un_iface, i);
1015 if (!ed) {
1016 aprint_error("%s: no descriptor for bulk "
1017 "endpoint %u\n", DEVNAME(un), i);
1018 return;
1019 }
1020 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
1021 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
1022 un->un_ed[USBNET_ENDPT_RX] = ed->bEndpointAddress;
1023 }
1024 else if (
1025 UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
1026 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
1027 un->un_ed[USBNET_ENDPT_TX] = ed->bEndpointAddress;
1028 }
1029 }
1030
1031 if (un->un_ed[USBNET_ENDPT_RX] != 0 && un->un_ed[USBNET_ENDPT_TX] != 0) {
1032 DPRINTF(("%s: in=0x%x, out=0x%x\n",
1033 DEVNAME(un),
1034 un->un_ed[USBNET_ENDPT_RX],
1035 sc->sc_bulkout_no));
1036 break;
1037 }
1038 }
1039
1040 if (un->un_ed[USBNET_ENDPT_RX] == 0)
1041 aprint_error("%s: could not find data bulk in\n", DEVNAME(un));
1042 if (un->un_ed[USBNET_ENDPT_TX] == 0)
1043 aprint_error("%s: could not find data bulk out\n",DEVNAME(un));
1044 if (un->un_ed[USBNET_ENDPT_RX] == 0 || un->un_ed[USBNET_ENDPT_TX] == 0)
1045 return;
1046
1047 struct ifnet *ifp = usbnet_ifp(un);
1048 #if 0
1049 ifp->if_watchdog = urndis_watchdog;
1050 #endif
1051
1052 usbnet_attach(un, "urndisdet");
1053
1054 urndis_init_un(ifp, un);
1055
1056 if (urndis_ctrl_query(un, OID_802_3_PERMANENT_ADDRESS, NULL, 0,
1057 &buf, &bufsz) != RNDIS_STATUS_SUCCESS) {
1058 aprint_error("%s: unable to get hardware address\n",
1059 DEVNAME(un));
1060 usbnet_lock(un);
1061 usbnet_stop(un, ifp, 1);
1062 usbnet_unlock(un);
1063 return;
1064 }
1065
1066 if (bufsz == ETHER_ADDR_LEN) {
1067 memcpy(un->un_eaddr, buf, ETHER_ADDR_LEN);
1068 kmem_free(buf, bufsz);
1069 } else {
1070 aprint_error("%s: invalid address\n", DEVNAME(un));
1071 kmem_free(buf, bufsz);
1072 usbnet_lock(un);
1073 usbnet_stop(un, ifp, 1);
1074 usbnet_unlock(un);
1075 return;
1076 }
1077
1078 /* Initialize packet filter */
1079 sc->sc_filter = RNDIS_PACKET_TYPE_BROADCAST;
1080 sc->sc_filter |= RNDIS_PACKET_TYPE_ALL_MULTICAST;
1081 filter = htole32(sc->sc_filter);
1082 if (urndis_ctrl_set(un, OID_GEN_CURRENT_PACKET_FILTER, &filter,
1083 sizeof(filter)) != RNDIS_STATUS_SUCCESS) {
1084 aprint_error("%s: unable to set data filters\n", DEVNAME(un));
1085 usbnet_lock(un);
1086 usbnet_stop(un, ifp, 1);
1087 usbnet_unlock(un);
1088 return;
1089 }
1090
1091 /* Turn off again now it has been identified. */
1092 usbnet_lock(un);
1093 usbnet_stop(un, ifp, 1);
1094 usbnet_unlock(un);
1095
1096 usbnet_attach_ifp(un, false, IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST,
1097 0, 0);
1098 }
1099