1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (C) 2012 Ben Gray <bgray@freebsd.org>. 5 * Copyright (C) 2018 The FreeBSD Foundation. 6 * Copyright (c) 2019 Edward Tomasz Napierala <trasz@FreeBSD.org> 7 * 8 * This software was developed by Arshan Khanifar <arshankhanifar@gmail.com> 9 * under sponsorship from the FreeBSD Foundation. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 /* 34 * Universal Serial Bus Communications Class Subclass Specification 35 * for Ethernet Emulation Model Devices: 36 * 37 * https://usb.org/sites/default/files/CDC_EEM10.pdf 38 */ 39 40 #include <sys/cdefs.h> 41 __FBSDID("$FreeBSD$"); 42 43 #include <sys/gsb_crc32.h> 44 #include <sys/eventhandler.h> 45 #include <sys/stdint.h> 46 #include <sys/stddef.h> 47 #include <sys/queue.h> 48 #include <sys/systm.h> 49 #include <sys/socket.h> 50 #include <sys/kernel.h> 51 #include <sys/bus.h> 52 #include <sys/module.h> 53 #include <sys/lock.h> 54 #include <sys/mutex.h> 55 #include <sys/condvar.h> 56 #include <sys/sysctl.h> 57 #include <sys/sx.h> 58 #include <sys/unistd.h> 59 #include <sys/callout.h> 60 #include <sys/malloc.h> 61 #include <sys/priv.h> 62 63 #include <net/if.h> 64 #include <net/if_var.h> 65 66 #include <dev/usb/usb.h> 67 #include <dev/usb/usbdi.h> 68 #include <dev/usb/usbdi_util.h> 69 #include <dev/usb/usb_cdc.h> 70 #include "usbdevs.h" 71 72 #define USB_DEBUG_VAR cdceem_debug 73 #include <dev/usb/usb_debug.h> 74 #include <dev/usb/usb_process.h> 75 #include <dev/usb/usb_msctest.h> 76 #include "usb_if.h" 77 78 #include <dev/usb/net/usb_ethernet.h> 79 80 #define CDCEEM_FRAMES_MAX 1 81 #define CDCEEM_ECHO_MAX 1024 82 83 #define CDCEEM_ECHO_PAYLOAD \ 84 "ICH DALEKOPIS FALSZUJE GDY PROBY XQV NIE WYTRZYMUJE 1234567890" 85 86 enum { 87 CDCEEM_BULK_RX, 88 CDCEEM_BULK_TX, 89 CDCEEM_N_TRANSFER, 90 }; 91 92 struct cdceem_softc { 93 struct usb_ether sc_ue; 94 struct mtx sc_mtx; 95 int sc_flags; 96 struct usb_xfer *sc_xfer[CDCEEM_N_TRANSFER]; 97 size_t sc_echo_len; 98 char sc_echo_buffer[CDCEEM_ECHO_MAX]; 99 }; 100 101 #define CDCEEM_SC_FLAGS_ECHO_RESPONSE_PENDING 0x1 102 #define CDCEEM_SC_FLAGS_ECHO_PENDING 0x2 103 104 static SYSCTL_NODE(_hw_usb, OID_AUTO, cdceem, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 105 "USB CDC EEM"); 106 static int cdceem_debug = 1; 107 SYSCTL_INT(_hw_usb_cdceem, OID_AUTO, debug, CTLFLAG_RWTUN, 108 &cdceem_debug, 0, "Debug level"); 109 static int cdceem_send_echoes = 0; 110 SYSCTL_INT(_hw_usb_cdceem, OID_AUTO, send_echoes, CTLFLAG_RWTUN, 111 &cdceem_send_echoes, 0, "Send an Echo command"); 112 static int cdceem_send_fake_crc = 0; 113 SYSCTL_INT(_hw_usb_cdceem, OID_AUTO, send_fake_crc, CTLFLAG_RWTUN, 114 &cdceem_send_fake_crc, 0, "Use 0xdeadbeef instead of CRC"); 115 116 #define CDCEEM_DEBUG(S, X, ...) \ 117 do { \ 118 if (cdceem_debug > 1) { \ 119 device_printf(S->sc_ue.ue_dev, "%s: " X "\n", \ 120 __func__, ## __VA_ARGS__); \ 121 } \ 122 } while (0) 123 124 #define CDCEEM_WARN(S, X, ...) \ 125 do { \ 126 if (cdceem_debug > 0) { \ 127 device_printf(S->sc_ue.ue_dev, \ 128 "WARNING: %s: " X "\n", \ 129 __func__, ## __VA_ARGS__); \ 130 } \ 131 } while (0) 132 133 #define CDCEEM_LOCK(X) mtx_lock(&(X)->sc_mtx) 134 #define CDCEEM_UNLOCK(X) mtx_unlock(&(X)->sc_mtx) 135 136 #define CDCEEM_TYPE_CMD (0x1 << 15) 137 138 #define CDCEEM_CMD_MASK (0x7 << 11) 139 140 #define CDCEEM_CMD_ECHO (0x0 << 11) 141 #define CDCEEM_CMD_ECHO_RESPONSE (0x1 << 11) 142 #define CDCEEM_CMD_SUSPEND_HINT (0x2 << 11) 143 #define CDCEEM_CMD_RESPONSE_HINT (0x3 << 11) 144 #define CDCEEM_CMD_RESPONSE_COMPLETE_HINT (0x4 << 11) 145 #define CDCEEM_CMD_TICKLE (0x5 << 11) 146 147 #define CDCEEM_CMD_RESERVED (0x1 << 14) 148 149 #define CDCEEM_ECHO_LEN_MASK 0x3ff 150 151 #define CDCEEM_DATA_CRC (0x1 << 14) 152 #define CDCEEM_DATA_LEN_MASK 0x3fff 153 154 static device_probe_t cdceem_probe; 155 static device_attach_t cdceem_attach; 156 static device_detach_t cdceem_detach; 157 static device_suspend_t cdceem_suspend; 158 static device_resume_t cdceem_resume; 159 160 static usb_callback_t cdceem_bulk_write_callback; 161 static usb_callback_t cdceem_bulk_read_callback; 162 163 static uether_fn_t cdceem_attach_post; 164 static uether_fn_t cdceem_init; 165 static uether_fn_t cdceem_stop; 166 static uether_fn_t cdceem_start; 167 static uether_fn_t cdceem_setmulti; 168 static uether_fn_t cdceem_setpromisc; 169 170 static uint32_t cdceem_m_crc32(struct mbuf *, uint32_t, uint32_t); 171 172 static const struct usb_config cdceem_config[CDCEEM_N_TRANSFER] = { 173 [CDCEEM_BULK_TX] = { 174 .type = UE_BULK, 175 .endpoint = UE_ADDR_ANY, 176 .direction = UE_DIR_TX, 177 .bufsize = 16 * (MCLBYTES + 16), 178 .flags = {.pipe_bof = 1,.force_short_xfer = 1,}, 179 .callback = cdceem_bulk_write_callback, 180 .timeout = 10000, /* 10 seconds */ 181 .usb_mode = USB_MODE_DUAL, 182 }, 183 184 [CDCEEM_BULK_RX] = { 185 .type = UE_BULK, 186 .endpoint = UE_ADDR_ANY, 187 .direction = UE_DIR_RX, 188 .bufsize = 20480, /* bytes */ 189 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, 190 .callback = cdceem_bulk_read_callback, 191 .timeout = 0, /* no timeout */ 192 .usb_mode = USB_MODE_DUAL, 193 }, 194 }; 195 196 static device_method_t cdceem_methods[] = { 197 /* Device interface */ 198 DEVMETHOD(device_probe, cdceem_probe), 199 DEVMETHOD(device_attach, cdceem_attach), 200 DEVMETHOD(device_detach, cdceem_detach), 201 DEVMETHOD(device_suspend, cdceem_suspend), 202 DEVMETHOD(device_resume, cdceem_resume), 203 204 DEVMETHOD_END 205 }; 206 207 static driver_t cdceem_driver = { 208 .name = "cdceem", 209 .methods = cdceem_methods, 210 .size = sizeof(struct cdceem_softc), 211 }; 212 213 static devclass_t cdceem_devclass; 214 215 static const STRUCT_USB_DUAL_ID cdceem_dual_devs[] = { 216 {USB_IFACE_CLASS(UICLASS_CDC), 217 USB_IFACE_SUBCLASS(UISUBCLASS_ETHERNET_EMULATION_MODEL), 218 0}, 219 }; 220 221 DRIVER_MODULE(cdceem, uhub, cdceem_driver, cdceem_devclass, NULL, NULL); 222 MODULE_VERSION(cdceem, 1); 223 MODULE_DEPEND(cdceem, uether, 1, 1, 1); 224 MODULE_DEPEND(cdceem, usb, 1, 1, 1); 225 MODULE_DEPEND(cdceem, ether, 1, 1, 1); 226 USB_PNP_DUAL_INFO(cdceem_dual_devs); 227 228 static const struct usb_ether_methods cdceem_ue_methods = { 229 .ue_attach_post = cdceem_attach_post, 230 .ue_start = cdceem_start, 231 .ue_init = cdceem_init, 232 .ue_stop = cdceem_stop, 233 .ue_setmulti = cdceem_setmulti, 234 .ue_setpromisc = cdceem_setpromisc, 235 }; 236 237 static int 238 cdceem_probe(device_t dev) 239 { 240 struct usb_attach_arg *uaa; 241 int error; 242 243 uaa = device_get_ivars(dev); 244 error = usbd_lookup_id_by_uaa(cdceem_dual_devs, 245 sizeof(cdceem_dual_devs), uaa); 246 247 return (error); 248 } 249 250 static void 251 cdceem_attach_post(struct usb_ether *ue) 252 { 253 254 return; 255 } 256 257 static int 258 cdceem_attach(device_t dev) 259 { 260 struct cdceem_softc *sc; 261 struct usb_ether *ue; 262 struct usb_attach_arg *uaa; 263 int error; 264 uint8_t iface_index; 265 266 sc = device_get_softc(dev); 267 ue = &sc->sc_ue; 268 uaa = device_get_ivars(dev); 269 270 device_set_usb_desc(dev); 271 272 mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF); 273 274 /* Setup the endpoints. */ 275 iface_index = 0; 276 error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer, 277 cdceem_config, CDCEEM_N_TRANSFER, sc, &sc->sc_mtx); 278 if (error != 0) { 279 CDCEEM_WARN(sc, 280 "allocating USB transfers failed, error %d", error); 281 mtx_destroy(&sc->sc_mtx); 282 return (error); 283 } 284 285 /* Random MAC address. */ 286 arc4rand(ue->ue_eaddr, ETHER_ADDR_LEN, 0); 287 ue->ue_eaddr[0] &= ~0x01; /* unicast */ 288 ue->ue_eaddr[0] |= 0x02; /* locally administered */ 289 290 ue->ue_sc = sc; 291 ue->ue_dev = dev; 292 ue->ue_udev = uaa->device; 293 ue->ue_mtx = &sc->sc_mtx; 294 ue->ue_methods = &cdceem_ue_methods; 295 296 error = uether_ifattach(ue); 297 if (error != 0) { 298 CDCEEM_WARN(sc, "could not attach interface, error %d", error); 299 usbd_transfer_unsetup(sc->sc_xfer, CDCEEM_N_TRANSFER); 300 mtx_destroy(&sc->sc_mtx); 301 return (error); 302 } 303 304 return (0); 305 } 306 307 static int 308 cdceem_detach(device_t dev) 309 { 310 struct cdceem_softc *sc = device_get_softc(dev); 311 struct usb_ether *ue = &sc->sc_ue; 312 313 /* Stop all USB transfers first. */ 314 usbd_transfer_unsetup(sc->sc_xfer, CDCEEM_N_TRANSFER); 315 uether_ifdetach(ue); 316 mtx_destroy(&sc->sc_mtx); 317 318 return (0); 319 } 320 321 static void 322 cdceem_handle_cmd(struct usb_xfer *xfer, uint16_t hdr, int *offp) 323 { 324 struct cdceem_softc *sc; 325 struct usb_page_cache *pc; 326 int actlen, off; 327 uint16_t pktlen; 328 329 off = *offp; 330 sc = usbd_xfer_softc(xfer); 331 pc = usbd_xfer_get_frame(xfer, 0); 332 usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); 333 334 if (hdr & CDCEEM_CMD_RESERVED) { 335 CDCEEM_WARN(sc, "received command header %#x " 336 "with Reserved bit set; ignoring", hdr); 337 return; 338 } 339 340 switch (hdr & CDCEEM_CMD_MASK) { 341 case CDCEEM_CMD_ECHO: 342 pktlen = hdr & CDCEEM_ECHO_LEN_MASK; 343 CDCEEM_DEBUG(sc, "received Echo, length %d", pktlen); 344 345 if (pktlen > (actlen - off)) { 346 CDCEEM_WARN(sc, 347 "bad Echo length %d, should be at most %d", 348 pktlen, actlen - off); 349 break; 350 } 351 352 if (pktlen > sizeof(sc->sc_echo_buffer)) { 353 CDCEEM_WARN(sc, 354 "Echo length %u too big, must be less than %zd", 355 pktlen, sizeof(sc->sc_echo_buffer)); 356 break; 357 } 358 359 sc->sc_flags |= CDCEEM_SC_FLAGS_ECHO_RESPONSE_PENDING; 360 sc->sc_echo_len = pktlen; 361 usbd_copy_out(pc, off, sc->sc_echo_buffer, pktlen); 362 off += pktlen; 363 break; 364 365 case CDCEEM_CMD_ECHO_RESPONSE: 366 pktlen = hdr & CDCEEM_ECHO_LEN_MASK; 367 CDCEEM_DEBUG(sc, "received Echo Response, length %d", pktlen); 368 369 if (pktlen > (actlen - off)) { 370 CDCEEM_WARN(sc, 371 "bad Echo Response length %d, " 372 "should be at most %d", 373 pktlen, actlen - off); 374 break; 375 } 376 377 if (pktlen != sizeof(CDCEEM_ECHO_PAYLOAD)) { 378 CDCEEM_WARN(sc, "received Echo Response with bad " 379 "length %hu, should be %zd", 380 pktlen, sizeof(CDCEEM_ECHO_PAYLOAD)); 381 break; 382 } 383 384 usbd_copy_out(pc, off, sc->sc_echo_buffer, pktlen); 385 off += pktlen; 386 387 if (memcmp(sc->sc_echo_buffer, CDCEEM_ECHO_PAYLOAD, 388 sizeof(CDCEEM_ECHO_PAYLOAD)) != 0) { 389 CDCEEM_WARN(sc, 390 "received Echo Response payload does not match"); 391 } else { 392 CDCEEM_DEBUG(sc, "received Echo Response is valid"); 393 } 394 break; 395 396 case CDCEEM_CMD_SUSPEND_HINT: 397 CDCEEM_DEBUG(sc, "received SuspendHint; ignoring"); 398 break; 399 400 case CDCEEM_CMD_RESPONSE_HINT: 401 CDCEEM_DEBUG(sc, "received ResponseHint; ignoring"); 402 break; 403 404 case CDCEEM_CMD_RESPONSE_COMPLETE_HINT: 405 CDCEEM_DEBUG(sc, "received ResponseCompleteHint; ignoring"); 406 break; 407 408 case CDCEEM_CMD_TICKLE: 409 CDCEEM_DEBUG(sc, "received Tickle; ignoring"); 410 break; 411 412 default: 413 CDCEEM_WARN(sc, 414 "received unknown command %u, header %#x; ignoring", 415 (hdr & CDCEEM_CMD_MASK >> 11), hdr); 416 break; 417 } 418 419 *offp = off; 420 } 421 422 static void 423 cdceem_handle_data(struct usb_xfer *xfer, uint16_t hdr, int *offp) 424 { 425 struct cdceem_softc *sc; 426 struct usb_page_cache *pc; 427 struct usb_ether *ue; 428 struct ifnet *ifp; 429 struct mbuf *m; 430 int actlen, off; 431 uint32_t computed_crc, received_crc; 432 uint16_t pktlen; 433 434 off = *offp; 435 sc = usbd_xfer_softc(xfer); 436 pc = usbd_xfer_get_frame(xfer, 0); 437 ue = &sc->sc_ue; 438 ifp = uether_getifp(ue); 439 usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); 440 441 pktlen = hdr & CDCEEM_DATA_LEN_MASK; 442 CDCEEM_DEBUG(sc, "received Data, CRC %s, length %d", 443 (hdr & CDCEEM_DATA_CRC) ? "valid" : "absent", 444 pktlen); 445 446 if (pktlen < ETHER_HDR_LEN) { 447 CDCEEM_WARN(sc, 448 "bad ethernet frame length %d, should be at least %d", 449 pktlen, ETHER_HDR_LEN); 450 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 451 return; 452 } 453 454 if (pktlen > (actlen - off)) { 455 CDCEEM_WARN(sc, 456 "bad ethernet frame length %d, should be at most %d", 457 pktlen, actlen - off); 458 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 459 return; 460 } 461 462 m = uether_newbuf(); 463 if (m == NULL) { 464 CDCEEM_WARN(sc, "uether_newbuf() failed"); 465 if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1); 466 return; 467 } 468 469 pktlen -= 4; /* Subtract the CRC. */ 470 usbd_copy_out(pc, off, mtod(m, uint8_t *), pktlen); 471 off += pktlen; 472 473 usbd_copy_out(pc, off, &received_crc, sizeof(received_crc)); 474 off += sizeof(received_crc); 475 476 if (hdr & CDCEEM_DATA_CRC) { 477 computed_crc = cdceem_m_crc32(m, 0, pktlen); 478 } else { 479 computed_crc = be32toh(0xdeadbeef); 480 } 481 482 if (received_crc != computed_crc) { 483 CDCEEM_WARN(sc, 484 "received Data packet with wrong CRC %#x, expected %#x", 485 received_crc, computed_crc); 486 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 487 m_freem(m); 488 return; 489 } else { 490 CDCEEM_DEBUG(sc, "received correct CRC %#x", received_crc); 491 } 492 493 uether_rxmbuf(ue, m, pktlen); 494 *offp = off; 495 } 496 497 static void 498 cdceem_bulk_read_callback(struct usb_xfer *xfer, usb_error_t usb_error) 499 { 500 struct cdceem_softc *sc; 501 struct usb_page_cache *pc; 502 int actlen, aframes, off; 503 uint16_t hdr; 504 505 sc = usbd_xfer_softc(xfer); 506 usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL); 507 508 switch (USB_GET_STATE(xfer)) { 509 case USB_ST_TRANSFERRED: 510 CDCEEM_DEBUG(sc, 511 "received %u bytes in %u frames", actlen, aframes); 512 513 pc = usbd_xfer_get_frame(xfer, 0); 514 off = 0; 515 516 while (off < actlen) { 517 usbd_copy_out(pc, off, &hdr, sizeof(hdr)); 518 CDCEEM_DEBUG(sc, "hdr = %#x", hdr); 519 off += sizeof(hdr); 520 521 if (hdr == 0) { 522 CDCEEM_DEBUG(sc, "received Zero Length EEM"); 523 continue; 524 } 525 526 hdr = le16toh(hdr); 527 528 if ((hdr & CDCEEM_TYPE_CMD) != 0) { 529 cdceem_handle_cmd(xfer, hdr, &off); 530 } else { 531 cdceem_handle_data(xfer, hdr, &off); 532 } 533 534 KASSERT(off <= actlen, 535 ("%s: went past the buffer, off %d, actlen %d", 536 __func__, off, actlen)); 537 } 538 539 /* FALLTHROUGH */ 540 case USB_ST_SETUP: 541 CDCEEM_DEBUG(sc, "setup"); 542 tr_setup: 543 usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); 544 usbd_transfer_submit(xfer); 545 uether_rxflush(&sc->sc_ue); 546 break; 547 548 default: 549 CDCEEM_WARN(sc, "USB_ST_ERROR: %s", usbd_errstr(usb_error)); 550 551 if (usb_error != USB_ERR_CANCELLED) { 552 /* try to clear stall first */ 553 usbd_xfer_set_stall(xfer); 554 goto tr_setup; 555 } 556 break; 557 } 558 } 559 560 static void 561 cdceem_send_echo(struct usb_xfer *xfer, int *offp) 562 { 563 struct cdceem_softc *sc; 564 struct usb_page_cache *pc; 565 int maxlen, off; 566 uint16_t hdr; 567 568 off = *offp; 569 sc = usbd_xfer_softc(xfer); 570 pc = usbd_xfer_get_frame(xfer, 0); 571 maxlen = usbd_xfer_max_len(xfer); 572 573 CDCEEM_DEBUG(sc, "sending Echo, length %zd", 574 sizeof(CDCEEM_ECHO_PAYLOAD)); 575 576 KASSERT(off + sizeof(hdr) + sizeof(CDCEEM_ECHO_PAYLOAD) < maxlen, 577 ("%s: out of space; have %d, need %zd", __func__, maxlen, 578 off + sizeof(hdr) + sizeof(CDCEEM_ECHO_PAYLOAD))); 579 580 hdr = 0; 581 hdr |= CDCEEM_TYPE_CMD; 582 hdr |= CDCEEM_CMD_ECHO; 583 hdr |= sizeof(CDCEEM_ECHO_PAYLOAD); 584 CDCEEM_DEBUG(sc, "hdr = %#x", hdr); 585 hdr = htole16(hdr); 586 587 usbd_copy_in(pc, off, &hdr, sizeof(hdr)); 588 off += sizeof(hdr); 589 590 usbd_copy_in(pc, off, CDCEEM_ECHO_PAYLOAD, 591 sizeof(CDCEEM_ECHO_PAYLOAD)); 592 off += sizeof(CDCEEM_ECHO_PAYLOAD); 593 594 sc->sc_flags &= ~CDCEEM_SC_FLAGS_ECHO_PENDING; 595 596 *offp = off; 597 } 598 599 static void 600 cdceem_send_echo_response(struct usb_xfer *xfer, int *offp) 601 { 602 struct cdceem_softc *sc; 603 struct usb_page_cache *pc; 604 int maxlen, off; 605 uint16_t hdr; 606 607 off = *offp; 608 sc = usbd_xfer_softc(xfer); 609 pc = usbd_xfer_get_frame(xfer, 0); 610 maxlen = usbd_xfer_max_len(xfer); 611 612 KASSERT(off + sizeof(hdr) + sc->sc_echo_len < maxlen, 613 ("%s: out of space; have %d, need %zd", __func__, maxlen, 614 off + sizeof(hdr) + sc->sc_echo_len)); 615 616 CDCEEM_DEBUG(sc, "sending Echo Response, length %zd", sc->sc_echo_len); 617 618 hdr = 0; 619 hdr |= CDCEEM_TYPE_CMD; 620 hdr |= CDCEEM_CMD_ECHO_RESPONSE; 621 hdr |= sc->sc_echo_len; 622 CDCEEM_DEBUG(sc, "hdr = %#x", hdr); 623 hdr = htole16(hdr); 624 625 usbd_copy_in(pc, off, &hdr, sizeof(hdr)); 626 off += sizeof(hdr); 627 628 usbd_copy_in(pc, off, sc->sc_echo_buffer, sc->sc_echo_len); 629 off += sc->sc_echo_len; 630 631 sc->sc_flags &= ~CDCEEM_SC_FLAGS_ECHO_RESPONSE_PENDING; 632 sc->sc_echo_len = 0; 633 634 *offp = off; 635 } 636 637 static void 638 cdceem_send_data(struct usb_xfer *xfer, int *offp) 639 { 640 struct cdceem_softc *sc; 641 struct usb_page_cache *pc; 642 struct ifnet *ifp; 643 struct mbuf *m; 644 int maxlen, off; 645 uint32_t crc; 646 uint16_t hdr; 647 648 off = *offp; 649 sc = usbd_xfer_softc(xfer); 650 pc = usbd_xfer_get_frame(xfer, 0); 651 ifp = uether_getifp(&sc->sc_ue); 652 maxlen = usbd_xfer_max_len(xfer); 653 654 IFQ_DRV_DEQUEUE(&ifp->if_snd, m); 655 if (m == NULL) { 656 CDCEEM_DEBUG(sc, "no Data packets to send"); 657 return; 658 } 659 660 KASSERT((m->m_pkthdr.len & CDCEEM_DATA_LEN_MASK) == m->m_pkthdr.len, 661 ("%s: packet too long: %d, should be %d\n", __func__, 662 m->m_pkthdr.len, m->m_pkthdr.len & CDCEEM_DATA_LEN_MASK)); 663 KASSERT(off + sizeof(hdr) + m->m_pkthdr.len + 4 < maxlen, 664 ("%s: out of space; have %d, need %zd", __func__, maxlen, 665 off + sizeof(hdr) + m->m_pkthdr.len + 4)); 666 667 CDCEEM_DEBUG(sc, "sending Data, length %d + 4", m->m_pkthdr.len); 668 669 hdr = 0; 670 if (!cdceem_send_fake_crc) 671 hdr |= CDCEEM_DATA_CRC; 672 hdr |= (m->m_pkthdr.len + 4); /* +4 for CRC */ 673 CDCEEM_DEBUG(sc, "hdr = %#x", hdr); 674 hdr = htole16(hdr); 675 676 usbd_copy_in(pc, off, &hdr, sizeof(hdr)); 677 off += sizeof(hdr); 678 679 usbd_m_copy_in(pc, off, m, 0, m->m_pkthdr.len); 680 off += m->m_pkthdr.len; 681 682 if (cdceem_send_fake_crc) { 683 crc = htobe32(0xdeadbeef); 684 } else { 685 crc = cdceem_m_crc32(m, 0, m->m_pkthdr.len); 686 } 687 CDCEEM_DEBUG(sc, "CRC = %#x", crc); 688 689 usbd_copy_in(pc, off, &crc, sizeof(crc)); 690 off += sizeof(crc); 691 692 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); 693 694 /* 695 * If there's a BPF listener, bounce a copy of this frame to it. 696 */ 697 BPF_MTAP(ifp, m); 698 m_freem(m); 699 700 *offp = off; 701 } 702 703 static void 704 cdceem_bulk_write_callback(struct usb_xfer *xfer, usb_error_t usb_error) 705 { 706 struct cdceem_softc *sc; 707 struct ifnet *ifp; 708 int actlen, aframes, maxlen, off; 709 710 sc = usbd_xfer_softc(xfer); 711 maxlen = usbd_xfer_max_len(xfer); 712 713 switch (USB_GET_STATE(xfer)) { 714 case USB_ST_TRANSFERRED: 715 usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL); 716 CDCEEM_DEBUG(sc, "transferred %u bytes in %u frames", 717 actlen, aframes); 718 719 /* FALLTHROUGH */ 720 case USB_ST_SETUP: 721 CDCEEM_DEBUG(sc, "setup"); 722 tr_setup: 723 724 off = 0; 725 usbd_xfer_set_frame_offset(xfer, 0, 0); 726 727 if (sc->sc_flags & CDCEEM_SC_FLAGS_ECHO_PENDING) { 728 cdceem_send_echo(xfer, &off); 729 } else if (sc->sc_flags & CDCEEM_SC_FLAGS_ECHO_RESPONSE_PENDING) { 730 cdceem_send_echo_response(xfer, &off); 731 } else { 732 cdceem_send_data(xfer, &off); 733 } 734 735 KASSERT(off <= maxlen, 736 ("%s: went past the buffer, off %d, maxlen %d", 737 __func__, off, maxlen)); 738 739 if (off > 0) { 740 CDCEEM_DEBUG(sc, "starting transfer, length %d", off); 741 usbd_xfer_set_frame_len(xfer, 0, off); 742 usbd_transfer_submit(xfer); 743 } else { 744 CDCEEM_DEBUG(sc, "nothing to transfer"); 745 } 746 747 break; 748 749 default: 750 CDCEEM_WARN(sc, "USB_ST_ERROR: %s", usbd_errstr(usb_error)); 751 752 ifp = uether_getifp(&sc->sc_ue); 753 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 754 755 if (usb_error != USB_ERR_CANCELLED) { 756 /* try to clear stall first */ 757 usbd_xfer_set_stall(xfer); 758 goto tr_setup; 759 } 760 break; 761 } 762 } 763 764 static int32_t 765 cdceem_m_crc32_cb(void *arg, void *src, uint32_t count) 766 { 767 uint32_t *p_crc = arg; 768 769 *p_crc = crc32_raw(src, count, *p_crc); 770 return (0); 771 } 772 773 static uint32_t 774 cdceem_m_crc32(struct mbuf *m, uint32_t src_offset, uint32_t src_len) 775 { 776 uint32_t crc = 0xFFFFFFFF; 777 int error; 778 779 error = m_apply(m, src_offset, src_len, cdceem_m_crc32_cb, &crc); 780 return (crc ^ 0xFFFFFFFF); 781 } 782 783 static void 784 cdceem_start(struct usb_ether *ue) 785 { 786 struct cdceem_softc *sc; 787 788 sc = uether_getsc(ue); 789 790 /* 791 * Start the USB transfers, if not already started. 792 */ 793 usbd_transfer_start(sc->sc_xfer[CDCEEM_BULK_RX]); 794 usbd_transfer_start(sc->sc_xfer[CDCEEM_BULK_TX]); 795 } 796 797 static void 798 cdceem_init(struct usb_ether *ue) 799 { 800 struct cdceem_softc *sc; 801 struct ifnet *ifp; 802 803 sc = uether_getsc(ue); 804 ifp = uether_getifp(ue); 805 806 ifp->if_drv_flags |= IFF_DRV_RUNNING; 807 808 if (cdceem_send_echoes) 809 sc->sc_flags = CDCEEM_SC_FLAGS_ECHO_PENDING; 810 else 811 sc->sc_flags = 0; 812 813 /* 814 * Stall data write direction, which depends on USB mode. 815 * 816 * Some USB host stacks (e.g. Mac OS X) don't clears stall 817 * bit as it should, so set it in our host mode only. 818 */ 819 if (usbd_get_mode(sc->sc_ue.ue_udev) == USB_MODE_HOST) 820 usbd_xfer_set_stall(sc->sc_xfer[CDCEEM_BULK_TX]); 821 822 cdceem_start(ue); 823 } 824 825 static void 826 cdceem_stop(struct usb_ether *ue) 827 { 828 struct cdceem_softc *sc; 829 struct ifnet *ifp; 830 831 sc = uether_getsc(ue); 832 ifp = uether_getifp(ue); 833 834 ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 835 836 usbd_transfer_stop(sc->sc_xfer[CDCEEM_BULK_RX]); 837 usbd_transfer_stop(sc->sc_xfer[CDCEEM_BULK_TX]); 838 } 839 840 static void 841 cdceem_setmulti(struct usb_ether *ue) 842 { 843 /* no-op */ 844 return; 845 } 846 847 static void 848 cdceem_setpromisc(struct usb_ether *ue) 849 { 850 /* no-op */ 851 return; 852 } 853 854 static int 855 cdceem_suspend(device_t dev) 856 { 857 struct cdceem_softc *sc = device_get_softc(dev); 858 859 CDCEEM_DEBUG(sc, "go"); 860 return (0); 861 } 862 863 static int 864 cdceem_resume(device_t dev) 865 { 866 struct cdceem_softc *sc = device_get_softc(dev); 867 868 CDCEEM_DEBUG(sc, "go"); 869 return (0); 870 } 871 872