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