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, 0, "USB CDC EEM"); 105 static int cdceem_debug = 1; 106 SYSCTL_INT(_hw_usb_cdceem, OID_AUTO, debug, CTLFLAG_RWTUN, 107 &cdceem_debug, 0, "Debug level"); 108 static int cdceem_send_echoes = 0; 109 SYSCTL_INT(_hw_usb_cdceem, OID_AUTO, send_echoes, CTLFLAG_RWTUN, 110 &cdceem_send_echoes, 0, "Send an Echo command"); 111 static int cdceem_send_fake_crc = 0; 112 SYSCTL_INT(_hw_usb_cdceem, OID_AUTO, send_fake_crc, CTLFLAG_RWTUN, 113 &cdceem_send_fake_crc, 0, "Use 0xdeadbeef instead of CRC"); 114 115 #define CDCEEM_DEBUG(S, X, ...) \ 116 do { \ 117 if (cdceem_debug > 1) { \ 118 device_printf(S->sc_ue.ue_dev, "%s: " X "\n", \ 119 __func__, ## __VA_ARGS__); \ 120 } \ 121 } while (0) 122 123 #define CDCEEM_WARN(S, X, ...) \ 124 do { \ 125 if (cdceem_debug > 0) { \ 126 device_printf(S->sc_ue.ue_dev, \ 127 "WARNING: %s: " X "\n", \ 128 __func__, ## __VA_ARGS__); \ 129 } \ 130 } while (0) 131 132 #define CDCEEM_LOCK(X) mtx_lock(&(X)->sc_mtx) 133 #define CDCEEM_UNLOCK(X) mtx_unlock(&(X)->sc_mtx) 134 135 #define CDCEEM_TYPE_CMD (0x1 << 15) 136 137 #define CDCEEM_CMD_MASK (0x7 << 11) 138 139 #define CDCEEM_CMD_ECHO (0x0 << 11) 140 #define CDCEEM_CMD_ECHO_RESPONSE (0x1 << 11) 141 #define CDCEEM_CMD_SUSPEND_HINT (0x2 << 11) 142 #define CDCEEM_CMD_RESPONSE_HINT (0x3 << 11) 143 #define CDCEEM_CMD_RESPONSE_COMPLETE_HINT (0x4 << 11) 144 #define CDCEEM_CMD_TICKLE (0x5 << 11) 145 146 #define CDCEEM_CMD_RESERVED (0x1 << 14) 147 148 #define CDCEEM_ECHO_LEN_MASK 0x3ff 149 150 #define CDCEEM_DATA_CRC (0x1 << 14) 151 #define CDCEEM_DATA_LEN_MASK 0x3fff 152 153 static device_probe_t cdceem_probe; 154 static device_attach_t cdceem_attach; 155 static device_detach_t cdceem_detach; 156 static device_suspend_t cdceem_suspend; 157 static device_resume_t cdceem_resume; 158 159 static usb_callback_t cdceem_bulk_write_callback; 160 static usb_callback_t cdceem_bulk_read_callback; 161 162 static uether_fn_t cdceem_attach_post; 163 static uether_fn_t cdceem_init; 164 static uether_fn_t cdceem_stop; 165 static uether_fn_t cdceem_start; 166 static uether_fn_t cdceem_setmulti; 167 static uether_fn_t cdceem_setpromisc; 168 169 static uint32_t cdceem_m_crc32(struct mbuf *, uint32_t, uint32_t); 170 171 static const struct usb_config cdceem_config[CDCEEM_N_TRANSFER] = { 172 [CDCEEM_BULK_TX] = { 173 .type = UE_BULK, 174 .endpoint = UE_ADDR_ANY, 175 .direction = UE_DIR_TX, 176 .bufsize = 16 * (MCLBYTES + 16), 177 .flags = {.pipe_bof = 1,.force_short_xfer = 1,}, 178 .callback = cdceem_bulk_write_callback, 179 .timeout = 10000, /* 10 seconds */ 180 .usb_mode = USB_MODE_DUAL, 181 }, 182 183 [CDCEEM_BULK_RX] = { 184 .type = UE_BULK, 185 .endpoint = UE_ADDR_ANY, 186 .direction = UE_DIR_RX, 187 .bufsize = 20480, /* bytes */ 188 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, 189 .callback = cdceem_bulk_read_callback, 190 .timeout = 0, /* no timeout */ 191 .usb_mode = USB_MODE_DUAL, 192 }, 193 }; 194 195 static device_method_t cdceem_methods[] = { 196 /* Device interface */ 197 DEVMETHOD(device_probe, cdceem_probe), 198 DEVMETHOD(device_attach, cdceem_attach), 199 DEVMETHOD(device_detach, cdceem_detach), 200 DEVMETHOD(device_suspend, cdceem_suspend), 201 DEVMETHOD(device_resume, cdceem_resume), 202 203 DEVMETHOD_END 204 }; 205 206 static driver_t cdceem_driver = { 207 .name = "cdceem", 208 .methods = cdceem_methods, 209 .size = sizeof(struct cdceem_softc), 210 }; 211 212 static devclass_t cdceem_devclass; 213 214 static const STRUCT_USB_DUAL_ID cdceem_dual_devs[] = { 215 {USB_IFACE_CLASS(UICLASS_CDC), 216 USB_IFACE_SUBCLASS(UISUBCLASS_ETHERNET_EMULATION_MODEL), 217 0}, 218 }; 219 220 DRIVER_MODULE(cdceem, uhub, cdceem_driver, cdceem_devclass, NULL, NULL); 221 MODULE_VERSION(cdceem, 1); 222 MODULE_DEPEND(cdceem, uether, 1, 1, 1); 223 MODULE_DEPEND(cdceem, usb, 1, 1, 1); 224 MODULE_DEPEND(cdceem, ether, 1, 1, 1); 225 USB_PNP_DUAL_INFO(cdceem_dual_devs); 226 227 static const struct usb_ether_methods cdceem_ue_methods = { 228 .ue_attach_post = cdceem_attach_post, 229 .ue_start = cdceem_start, 230 .ue_init = cdceem_init, 231 .ue_stop = cdceem_stop, 232 .ue_setmulti = cdceem_setmulti, 233 .ue_setpromisc = cdceem_setpromisc, 234 }; 235 236 static int 237 cdceem_probe(device_t dev) 238 { 239 struct usb_attach_arg *uaa; 240 int error; 241 242 uaa = device_get_ivars(dev); 243 error = usbd_lookup_id_by_uaa(cdceem_dual_devs, 244 sizeof(cdceem_dual_devs), uaa); 245 246 return (error); 247 } 248 249 static void 250 cdceem_attach_post(struct usb_ether *ue) 251 { 252 253 return; 254 } 255 256 static int 257 cdceem_attach(device_t dev) 258 { 259 struct cdceem_softc *sc; 260 struct usb_ether *ue; 261 struct usb_attach_arg *uaa; 262 int error; 263 uint8_t iface_index; 264 265 sc = device_get_softc(dev); 266 ue = &sc->sc_ue; 267 uaa = device_get_ivars(dev); 268 269 device_set_usb_desc(dev); 270 271 mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF); 272 273 /* Setup the endpoints. */ 274 iface_index = 0; 275 error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer, 276 cdceem_config, CDCEEM_N_TRANSFER, sc, &sc->sc_mtx); 277 if (error != 0) { 278 CDCEEM_WARN(sc, 279 "allocating USB transfers failed, error %d", error); 280 mtx_destroy(&sc->sc_mtx); 281 return (error); 282 } 283 284 /* Random MAC address. */ 285 arc4rand(ue->ue_eaddr, ETHER_ADDR_LEN, 0); 286 ue->ue_eaddr[0] &= ~0x01; /* unicast */ 287 ue->ue_eaddr[0] |= 0x02; /* locally administered */ 288 289 ue->ue_sc = sc; 290 ue->ue_dev = dev; 291 ue->ue_udev = uaa->device; 292 ue->ue_mtx = &sc->sc_mtx; 293 ue->ue_methods = &cdceem_ue_methods; 294 295 error = uether_ifattach(ue); 296 if (error != 0) { 297 CDCEEM_WARN(sc, "could not attach interface, error %d", error); 298 usbd_transfer_unsetup(sc->sc_xfer, CDCEEM_N_TRANSFER); 299 mtx_destroy(&sc->sc_mtx); 300 return (error); 301 } 302 303 return (0); 304 } 305 306 static int 307 cdceem_detach(device_t dev) 308 { 309 struct cdceem_softc *sc = device_get_softc(dev); 310 struct usb_ether *ue = &sc->sc_ue; 311 312 /* Stop all USB transfers first. */ 313 usbd_transfer_unsetup(sc->sc_xfer, CDCEEM_N_TRANSFER); 314 uether_ifdetach(ue); 315 mtx_destroy(&sc->sc_mtx); 316 317 return (0); 318 } 319 320 static void 321 cdceem_handle_cmd(struct usb_xfer *xfer, uint16_t hdr, int *offp) 322 { 323 struct cdceem_softc *sc; 324 struct usb_page_cache *pc; 325 int actlen, off; 326 uint16_t pktlen; 327 328 off = *offp; 329 sc = usbd_xfer_softc(xfer); 330 pc = usbd_xfer_get_frame(xfer, 0); 331 usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); 332 333 if (hdr & CDCEEM_CMD_RESERVED) { 334 CDCEEM_WARN(sc, "received command header %#x " 335 "with Reserved bit set; ignoring", hdr); 336 return; 337 } 338 339 switch (hdr & CDCEEM_CMD_MASK) { 340 case CDCEEM_CMD_ECHO: 341 pktlen = hdr & CDCEEM_ECHO_LEN_MASK; 342 CDCEEM_DEBUG(sc, "received Echo, length %d", pktlen); 343 344 if (pktlen > (actlen - off)) { 345 CDCEEM_WARN(sc, 346 "bad Echo length %d, should be at most %d", 347 pktlen, actlen - off); 348 break; 349 } 350 351 if (pktlen > sizeof(sc->sc_echo_buffer)) { 352 CDCEEM_WARN(sc, 353 "Echo length %u too big, must be less than %zd", 354 pktlen, sizeof(sc->sc_echo_buffer)); 355 break; 356 } 357 358 sc->sc_flags |= CDCEEM_SC_FLAGS_ECHO_RESPONSE_PENDING; 359 sc->sc_echo_len = pktlen; 360 usbd_copy_out(pc, off, sc->sc_echo_buffer, pktlen); 361 off += pktlen; 362 break; 363 364 case CDCEEM_CMD_ECHO_RESPONSE: 365 pktlen = hdr & CDCEEM_ECHO_LEN_MASK; 366 CDCEEM_DEBUG(sc, "received Echo Response, length %d", pktlen); 367 368 if (pktlen > (actlen - off)) { 369 CDCEEM_WARN(sc, 370 "bad Echo Response length %d, " 371 "should be at most %d", 372 pktlen, actlen - off); 373 break; 374 } 375 376 if (pktlen != sizeof(CDCEEM_ECHO_PAYLOAD)) { 377 CDCEEM_WARN(sc, "received Echo Response with bad " 378 "length %hu, should be %zd", 379 pktlen, sizeof(CDCEEM_ECHO_PAYLOAD)); 380 break; 381 } 382 383 usbd_copy_out(pc, off, sc->sc_echo_buffer, pktlen); 384 off += pktlen; 385 386 if (memcmp(sc->sc_echo_buffer, CDCEEM_ECHO_PAYLOAD, 387 sizeof(CDCEEM_ECHO_PAYLOAD)) != 0) { 388 CDCEEM_WARN(sc, 389 "received Echo Response payload does not match"); 390 } else { 391 CDCEEM_DEBUG(sc, "received Echo Response is valid"); 392 } 393 break; 394 395 case CDCEEM_CMD_SUSPEND_HINT: 396 CDCEEM_DEBUG(sc, "received SuspendHint; ignoring"); 397 break; 398 399 case CDCEEM_CMD_RESPONSE_HINT: 400 CDCEEM_DEBUG(sc, "received ResponseHint; ignoring"); 401 break; 402 403 case CDCEEM_CMD_RESPONSE_COMPLETE_HINT: 404 CDCEEM_DEBUG(sc, "received ResponseCompleteHint; ignoring"); 405 break; 406 407 case CDCEEM_CMD_TICKLE: 408 CDCEEM_DEBUG(sc, "received Tickle; ignoring"); 409 break; 410 411 default: 412 CDCEEM_WARN(sc, 413 "received unknown command %u, header %#x; ignoring", 414 (hdr & CDCEEM_CMD_MASK >> 11), hdr); 415 break; 416 } 417 418 *offp = off; 419 } 420 421 static void 422 cdceem_handle_data(struct usb_xfer *xfer, uint16_t hdr, int *offp) 423 { 424 struct cdceem_softc *sc; 425 struct usb_page_cache *pc; 426 struct usb_ether *ue; 427 struct ifnet *ifp; 428 struct mbuf *m; 429 int actlen, off; 430 uint32_t computed_crc, received_crc; 431 uint16_t pktlen; 432 433 off = *offp; 434 sc = usbd_xfer_softc(xfer); 435 pc = usbd_xfer_get_frame(xfer, 0); 436 ue = &sc->sc_ue; 437 ifp = uether_getifp(ue); 438 usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); 439 440 pktlen = hdr & CDCEEM_DATA_LEN_MASK; 441 CDCEEM_DEBUG(sc, "received Data, CRC %s, length %d", 442 (hdr & CDCEEM_DATA_CRC) ? "valid" : "absent", 443 pktlen); 444 445 if (pktlen < ETHER_HDR_LEN) { 446 CDCEEM_WARN(sc, 447 "bad ethernet frame length %d, should be at least %d", 448 pktlen, ETHER_HDR_LEN); 449 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 450 return; 451 } 452 453 if (pktlen > (actlen - off)) { 454 CDCEEM_WARN(sc, 455 "bad ethernet frame length %d, should be at most %d", 456 pktlen, actlen - off); 457 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 458 return; 459 } 460 461 m = uether_newbuf(); 462 if (m == NULL) { 463 CDCEEM_WARN(sc, "uether_newbuf() failed"); 464 if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1); 465 return; 466 } 467 468 pktlen -= 4; /* Subtract the CRC. */ 469 usbd_copy_out(pc, off, mtod(m, uint8_t *), pktlen); 470 off += pktlen; 471 472 usbd_copy_out(pc, off, &received_crc, sizeof(received_crc)); 473 off += sizeof(received_crc); 474 475 if (hdr & CDCEEM_DATA_CRC) { 476 computed_crc = cdceem_m_crc32(m, 0, pktlen); 477 } else { 478 computed_crc = be32toh(0xdeadbeef); 479 } 480 481 if (received_crc != computed_crc) { 482 CDCEEM_WARN(sc, 483 "received Data packet with wrong CRC %#x, expected %#x", 484 received_crc, computed_crc); 485 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 486 m_freem(m); 487 return; 488 } else { 489 CDCEEM_DEBUG(sc, "received correct CRC %#x", received_crc); 490 } 491 492 uether_rxmbuf(ue, m, pktlen); 493 *offp = off; 494 } 495 496 static void 497 cdceem_bulk_read_callback(struct usb_xfer *xfer, usb_error_t usb_error) 498 { 499 struct cdceem_softc *sc; 500 struct usb_page_cache *pc; 501 int actlen, aframes, off; 502 uint16_t hdr; 503 504 sc = usbd_xfer_softc(xfer); 505 usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL); 506 507 switch (USB_GET_STATE(xfer)) { 508 case USB_ST_TRANSFERRED: 509 CDCEEM_DEBUG(sc, 510 "received %u bytes in %u frames", actlen, aframes); 511 512 pc = usbd_xfer_get_frame(xfer, 0); 513 off = 0; 514 515 while (off < actlen) { 516 usbd_copy_out(pc, off, &hdr, sizeof(hdr)); 517 CDCEEM_DEBUG(sc, "hdr = %#x", hdr); 518 off += sizeof(hdr); 519 520 if (hdr == 0) { 521 CDCEEM_DEBUG(sc, "received Zero Length EEM"); 522 continue; 523 } 524 525 hdr = le16toh(hdr); 526 527 if ((hdr & CDCEEM_TYPE_CMD) != 0) { 528 cdceem_handle_cmd(xfer, hdr, &off); 529 } else { 530 cdceem_handle_data(xfer, hdr, &off); 531 } 532 533 KASSERT(off <= actlen, 534 ("%s: went past the buffer, off %d, actlen %d", 535 __func__, off, actlen)); 536 } 537 538 /* FALLTHROUGH */ 539 case USB_ST_SETUP: 540 CDCEEM_DEBUG(sc, "setup"); 541 tr_setup: 542 usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); 543 usbd_transfer_submit(xfer); 544 uether_rxflush(&sc->sc_ue); 545 break; 546 547 default: 548 CDCEEM_WARN(sc, "USB_ST_ERROR: %s", usbd_errstr(usb_error)); 549 550 if (usb_error != USB_ERR_CANCELLED) { 551 /* try to clear stall first */ 552 usbd_xfer_set_stall(xfer); 553 goto tr_setup; 554 } 555 break; 556 } 557 } 558 559 static void 560 cdceem_send_echo(struct usb_xfer *xfer, int *offp) 561 { 562 struct cdceem_softc *sc; 563 struct usb_page_cache *pc; 564 int maxlen, off; 565 uint16_t hdr; 566 567 off = *offp; 568 sc = usbd_xfer_softc(xfer); 569 pc = usbd_xfer_get_frame(xfer, 0); 570 maxlen = usbd_xfer_max_len(xfer); 571 572 CDCEEM_DEBUG(sc, "sending Echo, length %zd", 573 sizeof(CDCEEM_ECHO_PAYLOAD)); 574 575 KASSERT(off + sizeof(hdr) + sizeof(CDCEEM_ECHO_PAYLOAD) < maxlen, 576 ("%s: out of space; have %d, need %zd", __func__, maxlen, 577 off + sizeof(hdr) + sizeof(CDCEEM_ECHO_PAYLOAD))); 578 579 hdr = 0; 580 hdr |= CDCEEM_TYPE_CMD; 581 hdr |= CDCEEM_CMD_ECHO; 582 hdr |= sizeof(CDCEEM_ECHO_PAYLOAD); 583 CDCEEM_DEBUG(sc, "hdr = %#x", hdr); 584 hdr = htole16(hdr); 585 586 usbd_copy_in(pc, off, &hdr, sizeof(hdr)); 587 off += sizeof(hdr); 588 589 usbd_copy_in(pc, off, CDCEEM_ECHO_PAYLOAD, 590 sizeof(CDCEEM_ECHO_PAYLOAD)); 591 off += sizeof(CDCEEM_ECHO_PAYLOAD); 592 593 sc->sc_flags &= ~CDCEEM_SC_FLAGS_ECHO_PENDING; 594 595 *offp = off; 596 } 597 598 static void 599 cdceem_send_echo_response(struct usb_xfer *xfer, int *offp) 600 { 601 struct cdceem_softc *sc; 602 struct usb_page_cache *pc; 603 int maxlen, off; 604 uint16_t hdr; 605 606 off = *offp; 607 sc = usbd_xfer_softc(xfer); 608 pc = usbd_xfer_get_frame(xfer, 0); 609 maxlen = usbd_xfer_max_len(xfer); 610 611 KASSERT(off + sizeof(hdr) + sc->sc_echo_len < maxlen, 612 ("%s: out of space; have %d, need %zd", __func__, maxlen, 613 off + sizeof(hdr) + sc->sc_echo_len)); 614 615 CDCEEM_DEBUG(sc, "sending Echo Response, length %zd", sc->sc_echo_len); 616 617 hdr = 0; 618 hdr |= CDCEEM_TYPE_CMD; 619 hdr |= CDCEEM_CMD_ECHO_RESPONSE; 620 hdr |= sc->sc_echo_len; 621 CDCEEM_DEBUG(sc, "hdr = %#x", hdr); 622 hdr = htole16(hdr); 623 624 usbd_copy_in(pc, off, &hdr, sizeof(hdr)); 625 off += sizeof(hdr); 626 627 usbd_copy_in(pc, off, sc->sc_echo_buffer, sc->sc_echo_len); 628 off += sc->sc_echo_len; 629 630 sc->sc_flags &= ~CDCEEM_SC_FLAGS_ECHO_RESPONSE_PENDING; 631 sc->sc_echo_len = 0; 632 633 *offp = off; 634 } 635 636 static void 637 cdceem_send_data(struct usb_xfer *xfer, int *offp) 638 { 639 struct cdceem_softc *sc; 640 struct usb_page_cache *pc; 641 struct ifnet *ifp; 642 struct mbuf *m; 643 int maxlen, off; 644 uint32_t crc; 645 uint16_t hdr; 646 647 off = *offp; 648 sc = usbd_xfer_softc(xfer); 649 pc = usbd_xfer_get_frame(xfer, 0); 650 ifp = uether_getifp(&sc->sc_ue); 651 maxlen = usbd_xfer_max_len(xfer); 652 653 IFQ_DRV_DEQUEUE(&ifp->if_snd, m); 654 if (m == NULL) { 655 CDCEEM_DEBUG(sc, "no Data packets to send"); 656 return; 657 } 658 659 KASSERT((m->m_pkthdr.len & CDCEEM_DATA_LEN_MASK) == m->m_pkthdr.len, 660 ("%s: packet too long: %d, should be %d\n", __func__, 661 m->m_pkthdr.len, m->m_pkthdr.len & CDCEEM_DATA_LEN_MASK)); 662 KASSERT(off + sizeof(hdr) + m->m_pkthdr.len + 4 < maxlen, 663 ("%s: out of space; have %d, need %zd", __func__, maxlen, 664 off + sizeof(hdr) + m->m_pkthdr.len + 4)); 665 666 CDCEEM_DEBUG(sc, "sending Data, length %d + 4", m->m_pkthdr.len); 667 668 hdr = 0; 669 if (!cdceem_send_fake_crc) 670 hdr |= CDCEEM_DATA_CRC; 671 hdr |= (m->m_pkthdr.len + 4); /* +4 for CRC */ 672 CDCEEM_DEBUG(sc, "hdr = %#x", hdr); 673 hdr = htole16(hdr); 674 675 usbd_copy_in(pc, off, &hdr, sizeof(hdr)); 676 off += sizeof(hdr); 677 678 usbd_m_copy_in(pc, off, m, 0, m->m_pkthdr.len); 679 off += m->m_pkthdr.len; 680 681 if (cdceem_send_fake_crc) { 682 crc = htobe32(0xdeadbeef); 683 } else { 684 crc = cdceem_m_crc32(m, 0, m->m_pkthdr.len); 685 } 686 CDCEEM_DEBUG(sc, "CRC = %#x", crc); 687 688 usbd_copy_in(pc, off, &crc, sizeof(crc)); 689 off += sizeof(crc); 690 691 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); 692 693 /* 694 * If there's a BPF listener, bounce a copy of this frame to it. 695 */ 696 BPF_MTAP(ifp, m); 697 m_freem(m); 698 699 *offp = off; 700 } 701 702 static void 703 cdceem_bulk_write_callback(struct usb_xfer *xfer, usb_error_t usb_error) 704 { 705 struct cdceem_softc *sc; 706 struct ifnet *ifp; 707 int actlen, aframes, maxlen, off; 708 709 sc = usbd_xfer_softc(xfer); 710 maxlen = usbd_xfer_max_len(xfer); 711 712 switch (USB_GET_STATE(xfer)) { 713 case USB_ST_TRANSFERRED: 714 usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL); 715 CDCEEM_DEBUG(sc, "transferred %u bytes in %u frames", 716 actlen, aframes); 717 718 /* FALLTHROUGH */ 719 case USB_ST_SETUP: 720 CDCEEM_DEBUG(sc, "setup"); 721 tr_setup: 722 723 off = 0; 724 usbd_xfer_set_frame_offset(xfer, 0, 0); 725 726 if (sc->sc_flags & CDCEEM_SC_FLAGS_ECHO_PENDING) { 727 cdceem_send_echo(xfer, &off); 728 } else if (sc->sc_flags & CDCEEM_SC_FLAGS_ECHO_RESPONSE_PENDING) { 729 cdceem_send_echo_response(xfer, &off); 730 } else { 731 cdceem_send_data(xfer, &off); 732 } 733 734 KASSERT(off <= maxlen, 735 ("%s: went past the buffer, off %d, maxlen %d", 736 __func__, off, maxlen)); 737 738 if (off > 0) { 739 CDCEEM_DEBUG(sc, "starting transfer, length %d", off); 740 usbd_xfer_set_frame_len(xfer, 0, off); 741 usbd_transfer_submit(xfer); 742 } else { 743 CDCEEM_DEBUG(sc, "nothing to transfer"); 744 } 745 746 break; 747 748 default: 749 CDCEEM_WARN(sc, "USB_ST_ERROR: %s", usbd_errstr(usb_error)); 750 751 ifp = uether_getifp(&sc->sc_ue); 752 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 753 754 if (usb_error != USB_ERR_CANCELLED) { 755 /* try to clear stall first */ 756 usbd_xfer_set_stall(xfer); 757 goto tr_setup; 758 } 759 break; 760 } 761 } 762 763 static int32_t 764 cdceem_m_crc32_cb(void *arg, void *src, uint32_t count) 765 { 766 uint32_t *p_crc = arg; 767 768 *p_crc = crc32_raw(src, count, *p_crc); 769 return (0); 770 } 771 772 static uint32_t 773 cdceem_m_crc32(struct mbuf *m, uint32_t src_offset, uint32_t src_len) 774 { 775 uint32_t crc = 0xFFFFFFFF; 776 int error; 777 778 error = m_apply(m, src_offset, src_len, cdceem_m_crc32_cb, &crc); 779 return (crc ^ 0xFFFFFFFF); 780 } 781 782 static void 783 cdceem_start(struct usb_ether *ue) 784 { 785 struct cdceem_softc *sc; 786 787 sc = uether_getsc(ue); 788 789 /* 790 * Start the USB transfers, if not already started. 791 */ 792 usbd_transfer_start(sc->sc_xfer[CDCEEM_BULK_RX]); 793 usbd_transfer_start(sc->sc_xfer[CDCEEM_BULK_TX]); 794 } 795 796 static void 797 cdceem_init(struct usb_ether *ue) 798 { 799 struct cdceem_softc *sc; 800 struct ifnet *ifp; 801 802 sc = uether_getsc(ue); 803 ifp = uether_getifp(ue); 804 805 ifp->if_drv_flags |= IFF_DRV_RUNNING; 806 807 if (cdceem_send_echoes) 808 sc->sc_flags = CDCEEM_SC_FLAGS_ECHO_PENDING; 809 else 810 sc->sc_flags = 0; 811 812 /* 813 * Stall data write direction, which depends on USB mode. 814 * 815 * Some USB host stacks (e.g. Mac OS X) don't clears stall 816 * bit as it should, so set it in our host mode only. 817 */ 818 if (usbd_get_mode(sc->sc_ue.ue_udev) == USB_MODE_HOST) 819 usbd_xfer_set_stall(sc->sc_xfer[CDCEEM_BULK_TX]); 820 821 cdceem_start(ue); 822 } 823 824 static void 825 cdceem_stop(struct usb_ether *ue) 826 { 827 struct cdceem_softc *sc; 828 struct ifnet *ifp; 829 830 sc = uether_getsc(ue); 831 ifp = uether_getifp(ue); 832 833 ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 834 835 usbd_transfer_stop(sc->sc_xfer[CDCEEM_BULK_RX]); 836 usbd_transfer_stop(sc->sc_xfer[CDCEEM_BULK_TX]); 837 } 838 839 static void 840 cdceem_setmulti(struct usb_ether *ue) 841 { 842 /* no-op */ 843 return; 844 } 845 846 static void 847 cdceem_setpromisc(struct usb_ether *ue) 848 { 849 /* no-op */ 850 return; 851 } 852 853 static int 854 cdceem_suspend(device_t dev) 855 { 856 struct cdceem_softc *sc = device_get_softc(dev); 857 858 CDCEEM_DEBUG(sc, "go"); 859 return (0); 860 } 861 862 static int 863 cdceem_resume(device_t dev) 864 { 865 struct cdceem_softc *sc = device_get_softc(dev); 866 867 CDCEEM_DEBUG(sc, "go"); 868 return (0); 869 } 870 871