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