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