1 /* $NetBSD: if_urndis.c,v 1.39 2020/03/15 23:04:51 thorpej 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.39 2020/03/15 23:04:51 thorpej 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 int urndis_init_un(struct ifnet *, struct usbnet *); 76 77 static uint32_t urndis_ctrl_handle_init(struct usbnet *, 78 const struct rndis_comp_hdr *); 79 static uint32_t urndis_ctrl_handle_query(struct usbnet *, 80 const struct rndis_comp_hdr *, void **, size_t *); 81 static uint32_t urndis_ctrl_handle_reset(struct usbnet *, 82 const struct rndis_comp_hdr *); 83 static uint32_t urndis_ctrl_handle_status(struct usbnet *, 84 const struct rndis_comp_hdr *); 85 86 static uint32_t urndis_ctrl_set(struct usbnet *, uint32_t, void *, 87 size_t); 88 89 static int urndis_match(device_t, cfdata_t, void *); 90 static void urndis_attach(device_t, device_t, void *); 91 92 static const struct usbnet_ops urndis_ops = { 93 .uno_init = urndis_uno_init, 94 .uno_tx_prepare = urndis_uno_tx_prepare, 95 .uno_rx_loop = urndis_uno_rx_loop, 96 }; 97 98 CFATTACH_DECL_NEW(urndis, sizeof(struct urndis_softc), 99 urndis_match, urndis_attach, usbnet_detach, usbnet_activate); 100 101 /* 102 * Supported devices that we can't match by class IDs. 103 */ 104 static const struct usb_devno urndis_devs[] = { 105 { USB_VENDOR_HTC, USB_PRODUCT_HTC_ANDROID }, 106 { USB_VENDOR_SAMSUNG, USB_PRODUCT_SAMSUNG_ANDROID2 }, 107 { USB_VENDOR_SAMSUNG, USB_PRODUCT_SAMSUNG_ANDROID }, 108 }; 109 110 static usbd_status 111 urndis_ctrl_msg(struct usbnet *un, uint8_t rt, uint8_t r, 112 uint16_t index, uint16_t value, void *buf, size_t buflen) 113 { 114 usb_device_request_t req; 115 116 req.bmRequestType = rt; 117 req.bRequest = r; 118 USETW(req.wValue, value); 119 USETW(req.wIndex, index); 120 USETW(req.wLength, buflen); 121 122 return usbd_do_request(un->un_udev, &req, buf); 123 } 124 125 static usbd_status 126 urndis_ctrl_send(struct usbnet *un, void *buf, size_t len) 127 { 128 struct urndis_softc *sc = usbnet_softc(un); 129 usbd_status err; 130 131 if (usbnet_isdying(un)) 132 return(0); 133 134 err = urndis_ctrl_msg(un, UT_WRITE_CLASS_INTERFACE, UR_GET_STATUS, 135 sc->sc_ifaceno_ctl, 0, buf, len); 136 137 if (err != USBD_NORMAL_COMPLETION) 138 printf("%s: %s\n", DEVNAME(un), usbd_errstr(err)); 139 140 return err; 141 } 142 143 static struct rndis_comp_hdr * 144 urndis_ctrl_recv(struct usbnet *un) 145 { 146 struct urndis_softc *sc = usbnet_softc(un); 147 struct rndis_comp_hdr *hdr; 148 char *buf; 149 usbd_status err; 150 151 if (usbnet_isdying(un)) 152 return(0); 153 154 buf = kmem_alloc(URNDIS_RESPONSE_LEN, KM_SLEEP); 155 err = urndis_ctrl_msg(un, UT_READ_CLASS_INTERFACE, UR_CLEAR_FEATURE, 156 sc->sc_ifaceno_ctl, 0, buf, URNDIS_RESPONSE_LEN); 157 158 if (err != USBD_NORMAL_COMPLETION && err != USBD_SHORT_XFER) { 159 printf("%s: %s\n", DEVNAME(un), usbd_errstr(err)); 160 kmem_free(buf, URNDIS_RESPONSE_LEN); 161 return NULL; 162 } 163 164 hdr = (struct rndis_comp_hdr *)buf; 165 DPRINTF(("%s: urndis_ctrl_recv: type %#x len %u\n", 166 DEVNAME(un), 167 le32toh(hdr->rm_type), 168 le32toh(hdr->rm_len))); 169 170 if (le32toh(hdr->rm_len) > URNDIS_RESPONSE_LEN) { 171 printf("%s: ctrl message error: wrong size %u > %u\n", 172 DEVNAME(un), 173 le32toh(hdr->rm_len), 174 URNDIS_RESPONSE_LEN); 175 kmem_free(buf, URNDIS_RESPONSE_LEN); 176 return NULL; 177 } 178 179 return hdr; 180 } 181 182 static uint32_t 183 urndis_ctrl_handle(struct usbnet *un, struct rndis_comp_hdr *hdr, 184 void **buf, size_t *bufsz) 185 { 186 uint32_t rval; 187 188 DPRINTF(("%s: urndis_ctrl_handle\n", DEVNAME(un))); 189 190 if (buf && bufsz) { 191 *buf = NULL; 192 *bufsz = 0; 193 } 194 195 switch (le32toh(hdr->rm_type)) { 196 case REMOTE_NDIS_INITIALIZE_CMPLT: 197 rval = urndis_ctrl_handle_init(un, hdr); 198 break; 199 200 case REMOTE_NDIS_QUERY_CMPLT: 201 rval = urndis_ctrl_handle_query(un, hdr, buf, bufsz); 202 break; 203 204 case REMOTE_NDIS_RESET_CMPLT: 205 rval = urndis_ctrl_handle_reset(un, hdr); 206 break; 207 208 case REMOTE_NDIS_KEEPALIVE_CMPLT: 209 case REMOTE_NDIS_SET_CMPLT: 210 rval = le32toh(hdr->rm_status); 211 break; 212 213 case REMOTE_NDIS_INDICATE_STATUS_MSG: 214 rval = urndis_ctrl_handle_status(un, hdr); 215 break; 216 217 default: 218 printf("%s: ctrl message error: unknown event %#x\n", 219 DEVNAME(un), le32toh(hdr->rm_type)); 220 rval = RNDIS_STATUS_FAILURE; 221 } 222 223 kmem_free(hdr, URNDIS_RESPONSE_LEN); 224 225 return rval; 226 } 227 228 static uint32_t 229 urndis_ctrl_handle_init(struct usbnet *un, const struct rndis_comp_hdr *hdr) 230 { 231 struct urndis_softc *sc = usbnet_softc(un); 232 const struct rndis_init_comp *msg; 233 234 msg = (const struct rndis_init_comp *) hdr; 235 236 DPRINTF(("%s: urndis_ctrl_handle_init: len %u rid %u status %#x " 237 "ver_major %u ver_minor %u devflags %#x medium %#x pktmaxcnt %u " 238 "pktmaxsz %u align %u aflistoffset %u aflistsz %u\n", 239 DEVNAME(un), 240 le32toh(msg->rm_len), 241 le32toh(msg->rm_rid), 242 le32toh(msg->rm_status), 243 le32toh(msg->rm_ver_major), 244 le32toh(msg->rm_ver_minor), 245 le32toh(msg->rm_devflags), 246 le32toh(msg->rm_medium), 247 le32toh(msg->rm_pktmaxcnt), 248 le32toh(msg->rm_pktmaxsz), 249 le32toh(msg->rm_align), 250 le32toh(msg->rm_aflistoffset), 251 le32toh(msg->rm_aflistsz))); 252 253 if (le32toh(msg->rm_status) != RNDIS_STATUS_SUCCESS) { 254 printf("%s: init failed %#x\n", 255 DEVNAME(un), 256 le32toh(msg->rm_status)); 257 258 return le32toh(msg->rm_status); 259 } 260 261 if (le32toh(msg->rm_devflags) != RNDIS_DF_CONNECTIONLESS) { 262 printf("%s: wrong device type (current type: %#x)\n", 263 DEVNAME(un), 264 le32toh(msg->rm_devflags)); 265 266 return RNDIS_STATUS_FAILURE; 267 } 268 269 if (le32toh(msg->rm_medium) != RNDIS_MEDIUM_802_3) { 270 printf("%s: medium not 802.3 (current medium: %#x)\n", 271 DEVNAME(un), le32toh(msg->rm_medium)); 272 273 return RNDIS_STATUS_FAILURE; 274 } 275 276 if (le32toh(msg->rm_ver_major) != RNDIS_MAJOR_VERSION || 277 le32toh(msg->rm_ver_minor) != RNDIS_MINOR_VERSION) { 278 printf("%s: version not %u.%u (current version: %u.%u)\n", 279 DEVNAME(un), RNDIS_MAJOR_VERSION, RNDIS_MINOR_VERSION, 280 le32toh(msg->rm_ver_major), le32toh(msg->rm_ver_minor)); 281 282 return RNDIS_STATUS_FAILURE; 283 } 284 285 sc->sc_maxppt = le32toh(msg->rm_pktmaxcnt); 286 sc->sc_maxtsz = le32toh(msg->rm_pktmaxsz); 287 sc->sc_palign = 1U << le32toh(msg->rm_align); 288 289 return le32toh(msg->rm_status); 290 } 291 292 static uint32_t 293 urndis_ctrl_handle_query(struct usbnet *un, 294 const struct rndis_comp_hdr *hdr, void **buf, size_t *bufsz) 295 { 296 const struct rndis_query_comp *msg; 297 298 msg = (const struct rndis_query_comp *) hdr; 299 300 DPRINTF(("%s: urndis_ctrl_handle_query: len %u rid %u status %#x " 301 "buflen %u bufoff %u\n", 302 DEVNAME(un), 303 le32toh(msg->rm_len), 304 le32toh(msg->rm_rid), 305 le32toh(msg->rm_status), 306 le32toh(msg->rm_infobuflen), 307 le32toh(msg->rm_infobufoffset))); 308 309 if (buf && bufsz) { 310 *buf = NULL; 311 *bufsz = 0; 312 } 313 314 if (le32toh(msg->rm_status) != RNDIS_STATUS_SUCCESS) { 315 printf("%s: query failed %#x\n", 316 DEVNAME(un), 317 le32toh(msg->rm_status)); 318 319 return le32toh(msg->rm_status); 320 } 321 322 if (le32toh(msg->rm_infobuflen) + le32toh(msg->rm_infobufoffset) + 323 RNDIS_HEADER_OFFSET > le32toh(msg->rm_len)) { 324 printf("%s: ctrl message error: invalid query info " 325 "len/offset/end_position(%u/%u/%u) -> " 326 "go out of buffer limit %u\n", 327 DEVNAME(un), 328 le32toh(msg->rm_infobuflen), 329 le32toh(msg->rm_infobufoffset), 330 le32toh(msg->rm_infobuflen) + 331 le32toh(msg->rm_infobufoffset) + (uint32_t)RNDIS_HEADER_OFFSET, 332 le32toh(msg->rm_len)); 333 return RNDIS_STATUS_FAILURE; 334 } 335 336 if (buf && bufsz) { 337 const char *p; 338 339 *buf = kmem_alloc(le32toh(msg->rm_infobuflen), KM_SLEEP); 340 *bufsz = le32toh(msg->rm_infobuflen); 341 342 p = (const char *)&msg->rm_rid; 343 p += le32toh(msg->rm_infobufoffset); 344 memcpy(*buf, p, le32toh(msg->rm_infobuflen)); 345 } 346 347 return le32toh(msg->rm_status); 348 } 349 350 static uint32_t 351 urndis_ctrl_handle_reset(struct usbnet *un, const struct rndis_comp_hdr *hdr) 352 { 353 struct urndis_softc *sc = usbnet_softc(un); 354 const struct rndis_reset_comp *msg; 355 uint32_t rval; 356 357 msg = (const struct rndis_reset_comp *) hdr; 358 359 rval = le32toh(msg->rm_status); 360 361 DPRINTF(("%s: urndis_ctrl_handle_reset: len %u status %#x " 362 "adrreset %u\n", 363 DEVNAME(un), 364 le32toh(msg->rm_len), 365 rval, 366 le32toh(msg->rm_adrreset))); 367 368 if (rval != RNDIS_STATUS_SUCCESS) { 369 printf("%s: reset failed %#x\n", DEVNAME(un), rval); 370 return rval; 371 } 372 373 if (le32toh(msg->rm_adrreset) != 0) { 374 uint32_t filter; 375 376 filter = htole32(sc->sc_filter); 377 rval = urndis_ctrl_set(un, OID_GEN_CURRENT_PACKET_FILTER, 378 &filter, sizeof(filter)); 379 if (rval != RNDIS_STATUS_SUCCESS) { 380 printf("%s: unable to reset data filters\n", 381 DEVNAME(un)); 382 return rval; 383 } 384 } 385 386 return rval; 387 } 388 389 static uint32_t 390 urndis_ctrl_handle_status(struct usbnet *un, 391 const struct rndis_comp_hdr *hdr) 392 { 393 const struct rndis_status_msg *msg; 394 uint32_t rval; 395 396 msg = (const struct rndis_status_msg *)hdr; 397 398 rval = le32toh(msg->rm_status); 399 400 DPRINTF(("%s: urndis_ctrl_handle_status: len %u status %#x " 401 "stbuflen %u\n", 402 DEVNAME(un), 403 le32toh(msg->rm_len), 404 rval, 405 le32toh(msg->rm_stbuflen))); 406 407 switch (rval) { 408 case RNDIS_STATUS_MEDIA_CONNECT: 409 case RNDIS_STATUS_MEDIA_DISCONNECT: 410 case RNDIS_STATUS_OFFLOAD_CURRENT_CONFIG: 411 rval = RNDIS_STATUS_SUCCESS; 412 break; 413 414 default: 415 printf("%s: status %#x\n", DEVNAME(un), rval); 416 } 417 418 return rval; 419 } 420 421 static uint32_t 422 urndis_ctrl_init(struct usbnet *un) 423 { 424 struct rndis_init_req *msg; 425 uint32_t rval; 426 struct rndis_comp_hdr *hdr; 427 428 msg = kmem_alloc(sizeof(*msg), KM_SLEEP); 429 msg->rm_type = htole32(REMOTE_NDIS_INITIALIZE_MSG); 430 msg->rm_len = htole32(sizeof(*msg)); 431 msg->rm_rid = htole32(0); 432 msg->rm_ver_major = htole32(RNDIS_MAJOR_VERSION); 433 msg->rm_ver_minor = htole32(RNDIS_MINOR_VERSION); 434 msg->rm_max_xfersz = htole32(RNDIS_BUFSZ); 435 436 DPRINTF(("%s: urndis_ctrl_init send: type %u len %u rid %u ver_major %u " 437 "ver_minor %u max_xfersz %u\n", 438 DEVNAME(un), 439 le32toh(msg->rm_type), 440 le32toh(msg->rm_len), 441 le32toh(msg->rm_rid), 442 le32toh(msg->rm_ver_major), 443 le32toh(msg->rm_ver_minor), 444 le32toh(msg->rm_max_xfersz))); 445 446 rval = urndis_ctrl_send(un, msg, sizeof(*msg)); 447 kmem_free(msg, sizeof(*msg)); 448 449 if (rval != RNDIS_STATUS_SUCCESS) { 450 printf("%s: init failed\n", DEVNAME(un)); 451 return rval; 452 } 453 454 if ((hdr = urndis_ctrl_recv(un)) == NULL) { 455 printf("%s: unable to get init response\n", DEVNAME(un)); 456 return RNDIS_STATUS_FAILURE; 457 } 458 rval = urndis_ctrl_handle(un, hdr, NULL, NULL); 459 460 return rval; 461 } 462 463 #if 0 464 static uint32_t 465 urndis_ctrl_halt(struct usbnet *un) 466 { 467 struct rndis_halt_req *msg; 468 uint32_t rval; 469 470 msg = kmem_alloc(sizeof(*msg), KM_SLEEP); 471 msg->rm_type = htole32(REMOTE_NDIS_HALT_MSG); 472 msg->rm_len = htole32(sizeof(*msg)); 473 msg->rm_rid = 0; 474 475 DPRINTF(("%s: urndis_ctrl_halt send: type %u len %u rid %u\n", 476 DEVNAME(un), 477 le32toh(msg->rm_type), 478 le32toh(msg->rm_len), 479 le32toh(msg->rm_rid))); 480 481 rval = urndis_ctrl_send(un, msg, sizeof(*msg)); 482 kmem_free(msg, sizeof(*msg)); 483 484 if (rval != RNDIS_STATUS_SUCCESS) 485 printf("%s: halt failed\n", DEVNAME(un)); 486 487 return rval; 488 } 489 #endif 490 491 static uint32_t 492 urndis_ctrl_query(struct usbnet *un, uint32_t oid, 493 void *qbuf, size_t qlen, 494 void **rbuf, size_t *rbufsz) 495 { 496 struct rndis_query_req *msg; 497 uint32_t rval; 498 struct rndis_comp_hdr *hdr; 499 500 msg = kmem_alloc(sizeof(*msg) + qlen, KM_SLEEP); 501 msg->rm_type = htole32(REMOTE_NDIS_QUERY_MSG); 502 msg->rm_len = htole32(sizeof(*msg) + qlen); 503 msg->rm_rid = 0; /* XXX */ 504 msg->rm_oid = htole32(oid); 505 msg->rm_infobuflen = htole32(qlen); 506 if (qlen != 0) { 507 msg->rm_infobufoffset = htole32(20); 508 memcpy((char*)msg + 20, qbuf, qlen); 509 } else 510 msg->rm_infobufoffset = 0; 511 msg->rm_devicevchdl = 0; 512 513 DPRINTF(("%s: urndis_ctrl_query send: type %u len %u rid %u oid %#x " 514 "infobuflen %u infobufoffset %u devicevchdl %u\n", 515 DEVNAME(un), 516 le32toh(msg->rm_type), 517 le32toh(msg->rm_len), 518 le32toh(msg->rm_rid), 519 le32toh(msg->rm_oid), 520 le32toh(msg->rm_infobuflen), 521 le32toh(msg->rm_infobufoffset), 522 le32toh(msg->rm_devicevchdl))); 523 524 rval = urndis_ctrl_send(un, msg, sizeof(*msg)); 525 kmem_free(msg, sizeof(*msg) + qlen); 526 527 if (rval != RNDIS_STATUS_SUCCESS) { 528 printf("%s: query failed\n", DEVNAME(un)); 529 return rval; 530 } 531 532 if ((hdr = urndis_ctrl_recv(un)) == NULL) { 533 printf("%s: unable to get query response\n", DEVNAME(un)); 534 return RNDIS_STATUS_FAILURE; 535 } 536 rval = urndis_ctrl_handle(un, hdr, rbuf, rbufsz); 537 538 return rval; 539 } 540 541 static uint32_t 542 urndis_ctrl_set(struct usbnet *un, uint32_t oid, void *buf, size_t len) 543 { 544 struct rndis_set_req *msg; 545 uint32_t rval; 546 struct rndis_comp_hdr *hdr; 547 548 msg = kmem_alloc(sizeof(*msg) + len, KM_SLEEP); 549 msg->rm_type = htole32(REMOTE_NDIS_SET_MSG); 550 msg->rm_len = htole32(sizeof(*msg) + len); 551 msg->rm_rid = 0; /* XXX */ 552 msg->rm_oid = htole32(oid); 553 msg->rm_infobuflen = htole32(len); 554 if (len != 0) { 555 msg->rm_infobufoffset = htole32(20); 556 memcpy((char*)msg + 20, buf, len); 557 } else 558 msg->rm_infobufoffset = 0; 559 msg->rm_devicevchdl = 0; 560 561 DPRINTF(("%s: urndis_ctrl_set send: type %u len %u rid %u oid %#x " 562 "infobuflen %u infobufoffset %u devicevchdl %u\n", 563 DEVNAME(un), 564 le32toh(msg->rm_type), 565 le32toh(msg->rm_len), 566 le32toh(msg->rm_rid), 567 le32toh(msg->rm_oid), 568 le32toh(msg->rm_infobuflen), 569 le32toh(msg->rm_infobufoffset), 570 le32toh(msg->rm_devicevchdl))); 571 572 rval = urndis_ctrl_send(un, msg, sizeof(*msg)); 573 kmem_free(msg, sizeof(*msg) + len); 574 575 if (rval != RNDIS_STATUS_SUCCESS) { 576 printf("%s: set failed\n", DEVNAME(un)); 577 return rval; 578 } 579 580 if ((hdr = urndis_ctrl_recv(un)) == NULL) { 581 printf("%s: unable to get set response\n", DEVNAME(un)); 582 return RNDIS_STATUS_FAILURE; 583 } 584 rval = urndis_ctrl_handle(un, hdr, NULL, NULL); 585 if (rval != RNDIS_STATUS_SUCCESS) 586 printf("%s: set failed %#x\n", DEVNAME(un), rval); 587 588 return rval; 589 } 590 591 #if 0 592 static uint32_t 593 urndis_ctrl_set_param(struct urndis_softc *un, 594 const char *name, 595 uint32_t type, 596 void *buf, 597 size_t len) 598 { 599 struct rndis_set_parameter *param; 600 uint32_t rval; 601 size_t namelen, tlen; 602 603 if (name) 604 namelen = strlen(name); 605 else 606 namelen = 0; 607 tlen = sizeof(*param) + len + namelen; 608 param = kmem_alloc(tlen, KM_SLEEP); 609 param->rm_namelen = htole32(namelen); 610 param->rm_valuelen = htole32(len); 611 param->rm_type = htole32(type); 612 if (namelen != 0) { 613 param->rm_nameoffset = htole32(20); 614 memcpy(param + 20, name, namelen); 615 } else 616 param->rm_nameoffset = 0; 617 if (len != 0) { 618 param->rm_valueoffset = htole32(20 + namelen); 619 memcpy(param + 20 + namelen, buf, len); 620 } else 621 param->rm_valueoffset = 0; 622 623 DPRINTF(("%s: urndis_ctrl_set_param send: nameoffset %u namelen %u " 624 "type %#x valueoffset %u valuelen %u\n", 625 DEVNAME(un), 626 le32toh(param->rm_nameoffset), 627 le32toh(param->rm_namelen), 628 le32toh(param->rm_type), 629 le32toh(param->rm_valueoffset), 630 le32toh(param->rm_valuelen))); 631 632 rval = urndis_ctrl_set(un, OID_GEN_RNDIS_CONFIG_PARAMETER, param, tlen); 633 kmem_free(param, tlen); 634 if (rval != RNDIS_STATUS_SUCCESS) 635 printf("%s: set param failed %#x\n", DEVNAME(un), rval); 636 637 return rval; 638 } 639 640 /* XXX : adrreset, get it from response */ 641 static uint32_t 642 urndis_ctrl_reset(struct usbnet *un) 643 { 644 struct rndis_reset_req *reset; 645 uint32_t rval; 646 struct rndis_comp_hdr *hdr; 647 648 reset = kmem_alloc(sizeof(*reset), KM_SLEEP); 649 reset->rm_type = htole32(REMOTE_NDIS_RESET_MSG); 650 reset->rm_len = htole32(sizeof(*reset)); 651 reset->rm_rid = 0; /* XXX rm_rid == reserved ... remove ? */ 652 653 DPRINTF(("%s: urndis_ctrl_reset send: type %u len %u rid %u\n", 654 DEVNAME(un), 655 le32toh(reset->rm_type), 656 le32toh(reset->rm_len), 657 le32toh(reset->rm_rid))); 658 659 rval = urndis_ctrl_send(un, reset, sizeof(*reset)); 660 kmem_free(reset, sizeof(*reset)); 661 662 if (rval != RNDIS_STATUS_SUCCESS) { 663 printf("%s: reset failed\n", DEVNAME(un)); 664 return rval; 665 } 666 667 if ((hdr = urndis_ctrl_recv(un)) == NULL) { 668 printf("%s: unable to get reset response\n", DEVNAME(un)); 669 return RNDIS_STATUS_FAILURE; 670 } 671 rval = urndis_ctrl_handle(un, hdr, NULL, NULL); 672 673 return rval; 674 } 675 676 static uint32_t 677 urndis_ctrl_keepalive(struct usbnet *un) 678 { 679 struct rndis_keepalive_req *keep; 680 uint32_t rval; 681 struct rndis_comp_hdr *hdr; 682 683 keep = kmem_alloc(sizeof(*keep), KM_SLEEP); 684 keep->rm_type = htole32(REMOTE_NDIS_KEEPALIVE_MSG); 685 keep->rm_len = htole32(sizeof(*keep)); 686 keep->rm_rid = 0; /* XXX rm_rid == reserved ... remove ? */ 687 688 DPRINTF(("%s: urndis_ctrl_keepalive: type %u len %u rid %u\n", 689 DEVNAME(un), 690 le32toh(keep->rm_type), 691 le32toh(keep->rm_len), 692 le32toh(keep->rm_rid))); 693 694 rval = urndis_ctrl_send(un, keep, sizeof(*keep)); 695 kmem_free(keep, sizeof(*keep)); 696 697 if (rval != RNDIS_STATUS_SUCCESS) { 698 printf("%s: keepalive failed\n", DEVNAME(un)); 699 return rval; 700 } 701 702 if ((hdr = urndis_ctrl_recv(un)) == NULL) { 703 printf("%s: unable to get keepalive response\n", DEVNAME(un)); 704 return RNDIS_STATUS_FAILURE; 705 } 706 rval = urndis_ctrl_handle(un, hdr, NULL, NULL); 707 if (rval != RNDIS_STATUS_SUCCESS) { 708 printf("%s: keepalive failed %#x\n", DEVNAME(un), rval); 709 urndis_ctrl_reset(un); 710 } 711 712 return rval; 713 } 714 #endif 715 716 static unsigned 717 urndis_uno_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c) 718 { 719 struct rndis_packet_msg *msg; 720 721 if ((unsigned)m->m_pkthdr.len > un->un_tx_bufsz - sizeof(*msg)) 722 return 0; 723 724 msg = (struct rndis_packet_msg *)c->unc_buf; 725 726 memset(msg, 0, sizeof(*msg)); 727 msg->rm_type = htole32(REMOTE_NDIS_PACKET_MSG); 728 msg->rm_len = htole32(sizeof(*msg) + m->m_pkthdr.len); 729 730 msg->rm_dataoffset = htole32(RNDIS_DATA_OFFSET); 731 msg->rm_datalen = htole32(m->m_pkthdr.len); 732 733 m_copydata(m, 0, m->m_pkthdr.len, 734 ((char*)msg + RNDIS_DATA_OFFSET + RNDIS_HEADER_OFFSET)); 735 736 DPRINTF(("%s: %s type %#x len %u data(off %u len %u)\n", 737 __func__, 738 DEVNAME(un), 739 le32toh(msg->rm_type), 740 le32toh(msg->rm_len), 741 le32toh(msg->rm_dataoffset), 742 le32toh(msg->rm_datalen))); 743 744 return le32toh(msg->rm_len); 745 } 746 747 static void 748 urndis_uno_rx_loop(struct usbnet * un, struct usbnet_chain *c, 749 uint32_t total_len) 750 { 751 struct rndis_packet_msg *msg; 752 struct ifnet *ifp = usbnet_ifp(un); 753 int offset; 754 755 offset = 0; 756 757 while (total_len > 1) { 758 msg = (struct rndis_packet_msg *)((char*)c->unc_buf + offset); 759 760 DPRINTF(("%s: %s buffer size left %u\n", DEVNAME(un), __func__, 761 total_len)); 762 763 if (total_len < sizeof(*msg)) { 764 printf("%s: urndis_decap invalid buffer total_len %u < " 765 "minimum header %zu\n", 766 DEVNAME(un), 767 total_len, 768 sizeof(*msg)); 769 return; 770 } 771 772 DPRINTF(("%s: urndis_decap total_len %u data(off:%u len:%u) " 773 "oobdata(off:%u len:%u nb:%u) perpacket(off:%u len:%u)\n", 774 DEVNAME(un), 775 le32toh(msg->rm_len), 776 le32toh(msg->rm_dataoffset), 777 le32toh(msg->rm_datalen), 778 le32toh(msg->rm_oobdataoffset), 779 le32toh(msg->rm_oobdatalen), 780 le32toh(msg->rm_oobdataelements), 781 le32toh(msg->rm_pktinfooffset), 782 le32toh(msg->rm_pktinfooffset))); 783 784 if (le32toh(msg->rm_type) != REMOTE_NDIS_PACKET_MSG) { 785 printf("%s: urndis_decap invalid type %#x != %#x\n", 786 DEVNAME(un), 787 le32toh(msg->rm_type), 788 REMOTE_NDIS_PACKET_MSG); 789 return; 790 } 791 if (le32toh(msg->rm_len) < sizeof(*msg)) { 792 printf("%s: urndis_decap invalid msg len %u < %zu\n", 793 DEVNAME(un), 794 le32toh(msg->rm_len), 795 sizeof(*msg)); 796 return; 797 } 798 if (le32toh(msg->rm_len) > total_len) { 799 printf("%s: urndis_decap invalid msg len %u > buffer " 800 "total_len %u\n", 801 DEVNAME(un), 802 le32toh(msg->rm_len), 803 total_len); 804 return; 805 } 806 807 if (le32toh(msg->rm_dataoffset) + 808 le32toh(msg->rm_datalen) + RNDIS_HEADER_OFFSET 809 > le32toh(msg->rm_len)) { 810 printf("%s: urndis_decap invalid data " 811 "len/offset/end_position(%u/%u/%u) -> " 812 "go out of receive buffer limit %u\n", 813 DEVNAME(un), 814 le32toh(msg->rm_datalen), 815 le32toh(msg->rm_dataoffset), 816 le32toh(msg->rm_dataoffset) + 817 le32toh(msg->rm_datalen) + (uint32_t)RNDIS_HEADER_OFFSET, 818 le32toh(msg->rm_len)); 819 return; 820 } 821 822 if (le32toh(msg->rm_datalen) < sizeof(struct ether_header)) { 823 if_statinc(ifp, if_ierrors); 824 printf("%s: urndis_decap invalid ethernet size " 825 "%d < %zu\n", 826 DEVNAME(un), 827 le32toh(msg->rm_datalen), 828 sizeof(struct ether_header)); 829 return; 830 } 831 832 usbnet_enqueue(un, 833 ((char*)&msg->rm_dataoffset + le32toh(msg->rm_dataoffset)), 834 le32toh(msg->rm_datalen), 0, 0, 0); 835 836 offset += le32toh(msg->rm_len); 837 total_len -= le32toh(msg->rm_len); 838 } 839 } 840 841 #if 0 842 static void 843 urndis_watchdog(struct ifnet *ifp) 844 { 845 struct urndis_softc *sc = usbnet_softc(un); 846 847 if (un->un_dying) 848 return; 849 850 if_statinc(ifp, if_oerrors); 851 printf("%s: watchdog timeout\n", DEVNAME(un)); 852 853 urndis_ctrl_keepalive(un); 854 } 855 #endif 856 857 static int 858 urndis_init_un(struct ifnet *ifp, struct usbnet *un) 859 { 860 int err; 861 862 if (ifp->if_flags & IFF_RUNNING) 863 return 0; 864 865 err = urndis_ctrl_init(un); 866 if (err != RNDIS_STATUS_SUCCESS) 867 return EIO; 868 869 usbnet_lock_core(un); 870 if (usbnet_isdying(un)) 871 err = EIO; 872 else { 873 usbnet_stop(un, ifp, 1); 874 err = usbnet_init_rx_tx(un); 875 usbnet_set_link(un, err == 0); 876 } 877 usbnet_unlock_core(un); 878 879 return err; 880 } 881 882 static int 883 urndis_uno_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 KASSERT((void *)sc == 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=%#x, out=%#x\n", 1033 DEVNAME(un), 1034 un->un_ed[USBNET_ENDPT_RX], 1035 un->un_ed[USBNET_ENDPT_TX])); 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 #if 0 1048 ifp->if_watchdog = urndis_watchdog; 1049 #endif 1050 1051 usbnet_attach(un, "urndisdet"); 1052 1053 struct ifnet *ifp = usbnet_ifp(un); 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_core(un); 1061 usbnet_stop(un, ifp, 1); 1062 usbnet_unlock_core(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 if (buf && bufsz) 1072 kmem_free(buf, bufsz); 1073 usbnet_lock_core(un); 1074 usbnet_stop(un, ifp, 1); 1075 usbnet_unlock_core(un); 1076 return; 1077 } 1078 1079 /* Initialize packet filter */ 1080 sc->sc_filter = RNDIS_PACKET_TYPE_BROADCAST; 1081 sc->sc_filter |= RNDIS_PACKET_TYPE_ALL_MULTICAST; 1082 filter = htole32(sc->sc_filter); 1083 if (urndis_ctrl_set(un, OID_GEN_CURRENT_PACKET_FILTER, &filter, 1084 sizeof(filter)) != RNDIS_STATUS_SUCCESS) { 1085 aprint_error("%s: unable to set data filters\n", DEVNAME(un)); 1086 usbnet_lock_core(un); 1087 usbnet_stop(un, ifp, 1); 1088 usbnet_unlock_core(un); 1089 return; 1090 } 1091 1092 /* Turn off again now it has been identified. */ 1093 usbnet_lock_core(un); 1094 usbnet_stop(un, ifp, 1); 1095 usbnet_unlock_core(un); 1096 1097 usbnet_attach_ifp(un, IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST, 1098 0, NULL); 1099 } 1100 1101 #ifdef _MODULE 1102 #include "ioconf.c" 1103 #endif 1104 1105 USBNET_MODULE(urndis) 1106