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