1 /* $NetBSD: if_urndis.c,v 1.34 2019/10/31 11:59:40 maya 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.34 2019/10/31 11:59:40 maya 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_init(struct ifnet *); 70 static void urndis_rx_loop(struct usbnet *, struct usbnet_chain *, uint32_t); 71 static unsigned urndis_tx_prepare(struct usbnet *, struct mbuf *, 72 struct usbnet_chain *); 73 74 static int urndis_init_un(struct ifnet *, struct usbnet *); 75 76 static uint32_t urndis_ctrl_handle_init(struct usbnet *, 77 const struct rndis_comp_hdr *); 78 static uint32_t urndis_ctrl_handle_query(struct usbnet *, 79 const struct rndis_comp_hdr *, void **, size_t *); 80 static uint32_t urndis_ctrl_handle_reset(struct usbnet *, 81 const struct rndis_comp_hdr *); 82 static uint32_t urndis_ctrl_handle_status(struct usbnet *, 83 const struct rndis_comp_hdr *); 84 85 static uint32_t urndis_ctrl_set(struct usbnet *, uint32_t, void *, 86 size_t); 87 88 static int urndis_match(device_t, cfdata_t, void *); 89 static void urndis_attach(device_t, device_t, void *); 90 91 static struct usbnet_ops urndis_ops = { 92 .uno_init = urndis_init, 93 .uno_tx_prepare = urndis_tx_prepare, 94 .uno_rx_loop = urndis_rx_loop, 95 }; 96 97 CFATTACH_DECL_NEW(urndis, sizeof(struct urndis_softc), 98 urndis_match, urndis_attach, usbnet_detach, usbnet_activate); 99 100 /* 101 * Supported devices that we can't match by class IDs. 102 */ 103 static const struct usb_devno urndis_devs[] = { 104 { USB_VENDOR_HTC, USB_PRODUCT_HTC_ANDROID }, 105 { USB_VENDOR_SAMSUNG, USB_PRODUCT_SAMSUNG_ANDROID2 }, 106 { USB_VENDOR_SAMSUNG, USB_PRODUCT_SAMSUNG_ANDROID }, 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 0x%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 0x%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 0x%x " 236 "ver_major %u ver_minor %u devflags 0x%x medium 0x%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 0x%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: 0x%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: 0x%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 0x%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 0x%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 0x%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 0x%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 0x%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 0x%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 0x%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 0x%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 0x%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 0x%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 0x%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 0x%x\n", DEVNAME(un), rval); 708 urndis_ctrl_reset(un); 709 } 710 711 return rval; 712 } 713 #endif 714 715 static unsigned 716 urndis_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c) 717 { 718 struct rndis_packet_msg *msg; 719 720 usbnet_isowned_tx(un); 721 722 if ((unsigned)m->m_pkthdr.len > un->un_tx_bufsz - sizeof(*msg)) 723 return 0; 724 725 msg = (struct rndis_packet_msg *)c->unc_buf; 726 727 memset(msg, 0, sizeof(*msg)); 728 msg->rm_type = htole32(REMOTE_NDIS_PACKET_MSG); 729 msg->rm_len = htole32(sizeof(*msg) + m->m_pkthdr.len); 730 731 msg->rm_dataoffset = htole32(RNDIS_DATA_OFFSET); 732 msg->rm_datalen = htole32(m->m_pkthdr.len); 733 734 m_copydata(m, 0, m->m_pkthdr.len, 735 ((char*)msg + RNDIS_DATA_OFFSET + RNDIS_HEADER_OFFSET)); 736 737 DPRINTF(("%s: %s type 0x%x len %u data(off %u len %u)\n", 738 __func__, 739 DEVNAME(un), 740 le32toh(msg->rm_type), 741 le32toh(msg->rm_len), 742 le32toh(msg->rm_dataoffset), 743 le32toh(msg->rm_datalen))); 744 745 return le32toh(msg->rm_len); 746 } 747 748 static void 749 urndis_rx_loop(struct usbnet * un, struct usbnet_chain *c, 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 0x%x != 0x%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 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 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(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(un); 878 879 return err; 880 } 881 882 static int 883 urndis_init(struct ifnet *ifp) 884 { 885 struct usbnet *un = ifp->if_softc; 886 887 return urndis_init_un(ifp, un); 888 } 889 890 static int 891 urndis_match(device_t parent, cfdata_t match, void *aux) 892 { 893 struct usbif_attach_arg *uiaa = aux; 894 usb_interface_descriptor_t *id; 895 896 if (!uiaa->uiaa_iface) 897 return UMATCH_NONE; 898 899 id = usbd_get_interface_descriptor(uiaa->uiaa_iface); 900 if (id == NULL) 901 return UMATCH_NONE; 902 903 if (id->bInterfaceClass == UICLASS_WIRELESS && 904 id->bInterfaceSubClass == UISUBCLASS_RF && 905 id->bInterfaceProtocol == UIPROTO_RNDIS) 906 return UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO; 907 908 return usb_lookup(urndis_devs, uiaa->uiaa_vendor, uiaa->uiaa_product) != NULL ? 909 UMATCH_VENDOR_PRODUCT : UMATCH_NONE; 910 } 911 912 static void 913 urndis_attach(device_t parent, device_t self, void *aux) 914 { 915 struct urndis_softc *sc = device_private(self); 916 struct usbnet * const un = &sc->sc_un; 917 struct usbif_attach_arg *uiaa = aux; 918 struct usbd_device *dev = uiaa->uiaa_device; 919 usb_interface_descriptor_t *id; 920 usb_endpoint_descriptor_t *ed; 921 usb_config_descriptor_t *cd; 922 struct usbd_interface *iface_ctl; 923 const usb_cdc_union_descriptor_t *ud; 924 const usb_cdc_header_descriptor_t *desc; 925 usbd_desc_iter_t iter; 926 int if_ctl, if_data; 927 int i, j, altcnt; 928 void *buf; 929 size_t bufsz; 930 uint32_t filter; 931 char *devinfop; 932 933 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=0x%x, out=0x%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(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 if (buf && bufsz) 1072 kmem_free(buf, bufsz); 1073 usbnet_lock(un); 1074 usbnet_stop(un, ifp, 1); 1075 usbnet_unlock(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(un); 1087 usbnet_stop(un, ifp, 1); 1088 usbnet_unlock(un); 1089 return; 1090 } 1091 1092 /* Turn off again now it has been identified. */ 1093 usbnet_lock(un); 1094 usbnet_stop(un, ifp, 1); 1095 usbnet_unlock(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