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