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