if_cdce.c revision 194682
1/* $NetBSD: if_cdce.c,v 1.4 2004/10/24 12:50:54 augustss Exp $ */ 2 3/*- 4 * Copyright (c) 1997, 1998, 1999, 2000-2003 Bill Paul <wpaul@windriver.com> 5 * Copyright (c) 2003-2005 Craig Boston 6 * Copyright (c) 2004 Daniel Hartmeier 7 * Copyright (c) 2009 Hans Petter Selasky 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by Bill Paul. 21 * 4. Neither the name of the author nor the names of any co-contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul, THE VOICES IN HIS HEAD OR 29 * THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 30 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 31 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 32 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 33 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 34 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 35 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38/* 39 * USB Communication Device Class (Ethernet Networking Control Model) 40 * http://www.usb.org/developers/devclass_docs/usbcdc11.pdf 41 */ 42 43#include <sys/cdefs.h> 44__FBSDID("$FreeBSD: head/sys/dev/usb/net/if_cdce.c 194682 2009-06-23 06:00:31Z thompsa $"); 45 46#include <sys/stdint.h> 47#include <sys/stddef.h> 48#include <sys/param.h> 49#include <sys/queue.h> 50#include <sys/types.h> 51#include <sys/systm.h> 52#include <sys/kernel.h> 53#include <sys/bus.h> 54#include <sys/linker_set.h> 55#include <sys/module.h> 56#include <sys/lock.h> 57#include <sys/mutex.h> 58#include <sys/condvar.h> 59#include <sys/sysctl.h> 60#include <sys/sx.h> 61#include <sys/unistd.h> 62#include <sys/callout.h> 63#include <sys/malloc.h> 64#include <sys/priv.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 cdce_debug 73#include <dev/usb/usb_debug.h> 74#include <dev/usb/usb_process.h> 75#include "usb_if.h" 76 77#include <dev/usb/net/usb_ethernet.h> 78#include <dev/usb/net/if_cdcereg.h> 79 80static device_probe_t cdce_probe; 81static device_attach_t cdce_attach; 82static device_detach_t cdce_detach; 83static device_suspend_t cdce_suspend; 84static device_resume_t cdce_resume; 85static usb_handle_request_t cdce_handle_request; 86 87static usb_callback_t cdce_bulk_write_callback; 88static usb_callback_t cdce_bulk_read_callback; 89static usb_callback_t cdce_intr_read_callback; 90static usb_callback_t cdce_intr_write_callback; 91 92static uether_fn_t cdce_attach_post; 93static uether_fn_t cdce_init; 94static uether_fn_t cdce_stop; 95static uether_fn_t cdce_start; 96static uether_fn_t cdce_setmulti; 97static uether_fn_t cdce_setpromisc; 98 99static uint32_t cdce_m_crc32(struct mbuf *, uint32_t, uint32_t); 100 101#if USB_DEBUG 102static int cdce_debug = 0; 103 104SYSCTL_NODE(_hw_usb, OID_AUTO, cdce, CTLFLAG_RW, 0, "USB CDC-Ethernet"); 105SYSCTL_INT(_hw_usb_cdce, OID_AUTO, debug, CTLFLAG_RW, &cdce_debug, 0, 106 "Debug level"); 107#endif 108 109static const struct usb_config cdce_config[CDCE_N_TRANSFER] = { 110 111 [CDCE_BULK_RX] = { 112 .type = UE_BULK, 113 .endpoint = UE_ADDR_ANY, 114 .direction = UE_DIR_RX, 115 .if_index = 0, 116 .frames = CDCE_FRAMES_MAX, 117 .bufsize = (CDCE_FRAMES_MAX * MCLBYTES), 118 .flags = {.pipe_bof = 1,.short_frames_ok = 1,.short_xfer_ok = 1,.ext_buffer = 1,}, 119 .callback = cdce_bulk_read_callback, 120 .timeout = 0, /* no timeout */ 121 .usb_mode = USB_MODE_DUAL, /* both modes */ 122 }, 123 124 [CDCE_BULK_TX] = { 125 .type = UE_BULK, 126 .endpoint = UE_ADDR_ANY, 127 .direction = UE_DIR_TX, 128 .if_index = 0, 129 .frames = CDCE_FRAMES_MAX, 130 .bufsize = (CDCE_FRAMES_MAX * MCLBYTES), 131 .flags = {.pipe_bof = 1,.force_short_xfer = 1,.ext_buffer = 1,}, 132 .callback = cdce_bulk_write_callback, 133 .timeout = 10000, /* 10 seconds */ 134 .usb_mode = USB_MODE_DUAL, /* both modes */ 135 }, 136 137 [CDCE_INTR_RX] = { 138 .type = UE_INTERRUPT, 139 .endpoint = UE_ADDR_ANY, 140 .direction = UE_DIR_RX, 141 .if_index = 1, 142 .bufsize = CDCE_IND_SIZE_MAX, 143 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,.no_pipe_ok = 1,}, 144 .callback = cdce_intr_read_callback, 145 .timeout = 0, 146 .usb_mode = USB_MODE_HOST, 147 }, 148 149 [CDCE_INTR_TX] = { 150 .type = UE_INTERRUPT, 151 .endpoint = UE_ADDR_ANY, 152 .direction = UE_DIR_TX, 153 .if_index = 1, 154 .bufsize = CDCE_IND_SIZE_MAX, 155 .flags = {.pipe_bof = 1,.force_short_xfer = 1,.no_pipe_ok = 1,}, 156 .callback = cdce_intr_write_callback, 157 .timeout = 10000, /* 10 seconds */ 158 .usb_mode = USB_MODE_DEVICE, 159 }, 160}; 161 162static device_method_t cdce_methods[] = { 163 /* USB interface */ 164 DEVMETHOD(usb_handle_request, cdce_handle_request), 165 166 /* Device interface */ 167 DEVMETHOD(device_probe, cdce_probe), 168 DEVMETHOD(device_attach, cdce_attach), 169 DEVMETHOD(device_detach, cdce_detach), 170 DEVMETHOD(device_suspend, cdce_suspend), 171 DEVMETHOD(device_resume, cdce_resume), 172 173 {0, 0} 174}; 175 176static driver_t cdce_driver = { 177 .name = "cdce", 178 .methods = cdce_methods, 179 .size = sizeof(struct cdce_softc), 180}; 181 182static devclass_t cdce_devclass; 183 184DRIVER_MODULE(cdce, uhub, cdce_driver, cdce_devclass, NULL, 0); 185MODULE_VERSION(cdce, 1); 186MODULE_DEPEND(cdce, uether, 1, 1, 1); 187MODULE_DEPEND(cdce, usb, 1, 1, 1); 188MODULE_DEPEND(cdce, ether, 1, 1, 1); 189 190static const struct usb_ether_methods cdce_ue_methods = { 191 .ue_attach_post = cdce_attach_post, 192 .ue_start = cdce_start, 193 .ue_init = cdce_init, 194 .ue_stop = cdce_stop, 195 .ue_setmulti = cdce_setmulti, 196 .ue_setpromisc = cdce_setpromisc, 197}; 198 199static const struct usb_device_id cdce_devs[] = { 200 {USB_IF_CSI(UICLASS_CDC, UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0)}, 201 {USB_IF_CSI(UICLASS_CDC, UISUBCLASS_MOBILE_DIRECT_LINE_MODEL, 0)}, 202 203 {USB_VPI(USB_VENDOR_ACERLABS, USB_PRODUCT_ACERLABS_M5632, CDCE_FLAG_NO_UNION)}, 204 {USB_VPI(USB_VENDOR_AMBIT, USB_PRODUCT_AMBIT_NTL_250, CDCE_FLAG_NO_UNION)}, 205 {USB_VPI(USB_VENDOR_COMPAQ, USB_PRODUCT_COMPAQ_IPAQLINUX, CDCE_FLAG_NO_UNION)}, 206 {USB_VPI(USB_VENDOR_GMATE, USB_PRODUCT_GMATE_YP3X00, CDCE_FLAG_NO_UNION)}, 207 {USB_VPI(USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_USBLAN, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)}, 208 {USB_VPI(USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_USBLAN2, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)}, 209 {USB_VPI(USB_VENDOR_NETCHIP, USB_PRODUCT_NETCHIP_ETHERNETGADGET, CDCE_FLAG_NO_UNION)}, 210 {USB_VPI(USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2501, CDCE_FLAG_NO_UNION)}, 211 {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5500, CDCE_FLAG_ZAURUS)}, 212 {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5600, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)}, 213 {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLA300, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)}, 214 {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLC700, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)}, 215 {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLC750, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)}, 216}; 217 218static int 219cdce_probe(device_t dev) 220{ 221 struct usb_attach_arg *uaa = device_get_ivars(dev); 222 223 return (usbd_lookup_id_by_uaa(cdce_devs, sizeof(cdce_devs), uaa)); 224} 225 226static void 227cdce_attach_post(struct usb_ether *ue) 228{ 229 /* no-op */ 230 return; 231} 232 233static int 234cdce_attach(device_t dev) 235{ 236 struct cdce_softc *sc = device_get_softc(dev); 237 struct usb_ether *ue = &sc->sc_ue; 238 struct usb_attach_arg *uaa = device_get_ivars(dev); 239 struct usb_interface *iface; 240 const struct usb_cdc_union_descriptor *ud; 241 const struct usb_interface_descriptor *id; 242 const struct usb_cdc_ethernet_descriptor *ued; 243 int error; 244 uint8_t i; 245 char eaddr_str[5 * ETHER_ADDR_LEN]; /* approx */ 246 247 sc->sc_flags = USB_GET_DRIVER_INFO(uaa); 248 249 device_set_usb_desc(dev); 250 251 mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF); 252 253 if (sc->sc_flags & CDCE_FLAG_NO_UNION) { 254 sc->sc_ifaces_index[0] = uaa->info.bIfaceIndex; 255 sc->sc_ifaces_index[1] = uaa->info.bIfaceIndex; 256 sc->sc_data_iface_no = 0; /* not used */ 257 goto alloc_transfers; 258 } 259 ud = usbd_find_descriptor 260 (uaa->device, NULL, uaa->info.bIfaceIndex, 261 UDESC_CS_INTERFACE, 0 - 1, UDESCSUB_CDC_UNION, 0 - 1); 262 263 if ((ud == NULL) || (ud->bLength < sizeof(*ud))) { 264 device_printf(dev, "no union descriptor!\n"); 265 goto detach; 266 } 267 sc->sc_data_iface_no = ud->bSlaveInterface[0]; 268 269 for (i = 0;; i++) { 270 271 iface = usbd_get_iface(uaa->device, i); 272 273 if (iface) { 274 275 id = usbd_get_interface_descriptor(iface); 276 277 if (id && (id->bInterfaceNumber == 278 sc->sc_data_iface_no)) { 279 sc->sc_ifaces_index[0] = i; 280 sc->sc_ifaces_index[1] = uaa->info.bIfaceIndex; 281 usbd_set_parent_iface(uaa->device, i, uaa->info.bIfaceIndex); 282 break; 283 } 284 } else { 285 device_printf(dev, "no data interface found!\n"); 286 goto detach; 287 } 288 } 289 290 /* 291 * <quote> 292 * 293 * The Data Class interface of a networking device shall have 294 * a minimum of two interface settings. The first setting 295 * (the default interface setting) includes no endpoints and 296 * therefore no networking traffic is exchanged whenever the 297 * default interface setting is selected. One or more 298 * additional interface settings are used for normal 299 * operation, and therefore each includes a pair of endpoints 300 * (one IN, and one OUT) to exchange network traffic. Select 301 * an alternate interface setting to initialize the network 302 * aspects of the device and to enable the exchange of 303 * network traffic. 304 * 305 * </quote> 306 * 307 * Some devices, most notably cable modems, include interface 308 * settings that have no IN or OUT endpoint, therefore loop 309 * through the list of all available interface settings 310 * looking for one with both IN and OUT endpoints. 311 */ 312 313alloc_transfers: 314 315 for (i = 0; i != 32; i++) { 316 317 error = usbd_set_alt_interface_index 318 (uaa->device, sc->sc_ifaces_index[0], i); 319 320 if (error) { 321 device_printf(dev, "no valid alternate " 322 "setting found!\n"); 323 goto detach; 324 } 325 error = usbd_transfer_setup 326 (uaa->device, sc->sc_ifaces_index, 327 sc->sc_xfer, cdce_config, CDCE_N_TRANSFER, 328 sc, &sc->sc_mtx); 329 330 if (error == 0) { 331 break; 332 } 333 } 334 335 ued = usbd_find_descriptor 336 (uaa->device, NULL, uaa->info.bIfaceIndex, 337 UDESC_CS_INTERFACE, 0 - 1, UDESCSUB_CDC_ENF, 0 - 1); 338 339 if ((ued == NULL) || (ued->bLength < sizeof(*ued))) { 340 error = USB_ERR_INVAL; 341 } else { 342 error = usbd_req_get_string_any(uaa->device, NULL, 343 eaddr_str, sizeof(eaddr_str), ued->iMacAddress); 344 } 345 346 if (error) { 347 348 /* fake MAC address */ 349 350 device_printf(dev, "faking MAC address\n"); 351 sc->sc_ue.ue_eaddr[0] = 0x2a; 352 memcpy(&sc->sc_ue.ue_eaddr[1], &ticks, sizeof(uint32_t)); 353 sc->sc_ue.ue_eaddr[5] = device_get_unit(dev); 354 355 } else { 356 357 bzero(sc->sc_ue.ue_eaddr, sizeof(sc->sc_ue.ue_eaddr)); 358 359 for (i = 0; i != (ETHER_ADDR_LEN * 2); i++) { 360 361 char c = eaddr_str[i]; 362 363 if ('0' <= c && c <= '9') 364 c -= '0'; 365 else if (c != 0) 366 c -= 'A' - 10; 367 else 368 break; 369 370 c &= 0xf; 371 372 if ((i & 1) == 0) 373 c <<= 4; 374 sc->sc_ue.ue_eaddr[i / 2] |= c; 375 } 376 377 if (uaa->usb_mode == USB_MODE_DEVICE) { 378 /* 379 * Do not use the same MAC address like the peer ! 380 */ 381 sc->sc_ue.ue_eaddr[5] ^= 0xFF; 382 } 383 } 384 385 ue->ue_sc = sc; 386 ue->ue_dev = dev; 387 ue->ue_udev = uaa->device; 388 ue->ue_mtx = &sc->sc_mtx; 389 ue->ue_methods = &cdce_ue_methods; 390 391 error = uether_ifattach(ue); 392 if (error) { 393 device_printf(dev, "could not attach interface\n"); 394 goto detach; 395 } 396 return (0); /* success */ 397 398detach: 399 cdce_detach(dev); 400 return (ENXIO); /* failure */ 401} 402 403static int 404cdce_detach(device_t dev) 405{ 406 struct cdce_softc *sc = device_get_softc(dev); 407 struct usb_ether *ue = &sc->sc_ue; 408 409 /* stop all USB transfers first */ 410 usbd_transfer_unsetup(sc->sc_xfer, CDCE_N_TRANSFER); 411 uether_ifdetach(ue); 412 mtx_destroy(&sc->sc_mtx); 413 414 return (0); 415} 416 417static void 418cdce_start(struct usb_ether *ue) 419{ 420 struct cdce_softc *sc = uether_getsc(ue); 421 422 /* 423 * Start the USB transfers, if not already started: 424 */ 425 usbd_transfer_start(sc->sc_xfer[CDCE_BULK_TX]); 426 usbd_transfer_start(sc->sc_xfer[CDCE_BULK_RX]); 427} 428 429static void 430cdce_free_queue(struct mbuf **ppm, uint8_t n) 431{ 432 uint8_t x; 433 for (x = 0; x != n; x++) { 434 if (ppm[x] != NULL) { 435 m_freem(ppm[x]); 436 ppm[x] = NULL; 437 } 438 } 439} 440 441static void 442cdce_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) 443{ 444 struct cdce_softc *sc = usbd_xfer_softc(xfer); 445 struct ifnet *ifp = uether_getifp(&sc->sc_ue); 446 struct mbuf *m; 447 struct mbuf *mt; 448 uint32_t crc; 449 uint8_t x; 450 int actlen, aframes; 451 452 usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL); 453 454 DPRINTFN(1, "\n"); 455 456 switch (USB_GET_STATE(xfer)) { 457 case USB_ST_TRANSFERRED: 458 DPRINTFN(11, "transfer complete: %u bytes in %u frames\n", 459 actlen, aframes); 460 461 ifp->if_opackets++; 462 463 /* free all previous TX buffers */ 464 cdce_free_queue(sc->sc_tx_buf, CDCE_FRAMES_MAX); 465 466 /* FALLTHROUGH */ 467 case USB_ST_SETUP: 468tr_setup: 469 for (x = 0; x != CDCE_FRAMES_MAX; x++) { 470 471 IFQ_DRV_DEQUEUE(&ifp->if_snd, m); 472 473 if (m == NULL) 474 break; 475 476 if (sc->sc_flags & CDCE_FLAG_ZAURUS) { 477 /* 478 * Zaurus wants a 32-bit CRC appended 479 * to every frame 480 */ 481 482 crc = cdce_m_crc32(m, 0, m->m_pkthdr.len); 483 crc = htole32(crc); 484 485 if (!m_append(m, 4, (void *)&crc)) { 486 m_freem(m); 487 ifp->if_oerrors++; 488 continue; 489 } 490 } 491 if (m->m_len != m->m_pkthdr.len) { 492 mt = m_defrag(m, M_DONTWAIT); 493 if (mt == NULL) { 494 m_freem(m); 495 ifp->if_oerrors++; 496 continue; 497 } 498 m = mt; 499 } 500 if (m->m_pkthdr.len > MCLBYTES) { 501 m->m_pkthdr.len = MCLBYTES; 502 } 503 sc->sc_tx_buf[x] = m; 504 usbd_xfer_set_frame_data(xfer, x, m->m_data, m->m_len); 505 506 /* 507 * If there's a BPF listener, bounce a copy of 508 * this frame to him: 509 */ 510 BPF_MTAP(ifp, m); 511 } 512 if (x != 0) { 513 usbd_xfer_set_frames(xfer, x); 514 515 usbd_transfer_submit(xfer); 516 } 517 break; 518 519 default: /* Error */ 520 DPRINTFN(11, "transfer error, %s\n", 521 usbd_errstr(error)); 522 523 /* free all previous TX buffers */ 524 cdce_free_queue(sc->sc_tx_buf, CDCE_FRAMES_MAX); 525 526 /* count output errors */ 527 ifp->if_oerrors++; 528 529 if (error != USB_ERR_CANCELLED) { 530 /* try to clear stall first */ 531 usbd_xfer_set_stall(xfer); 532 goto tr_setup; 533 } 534 break; 535 } 536} 537 538static int32_t 539cdce_m_crc32_cb(void *arg, void *src, uint32_t count) 540{ 541 uint32_t *p_crc = arg; 542 543 *p_crc = crc32_raw(src, count, *p_crc); 544 return (0); 545} 546 547static uint32_t 548cdce_m_crc32(struct mbuf *m, uint32_t src_offset, uint32_t src_len) 549{ 550 uint32_t crc = 0xFFFFFFFF; 551 int error; 552 553 error = m_apply(m, src_offset, src_len, cdce_m_crc32_cb, &crc); 554 return (crc ^ 0xFFFFFFFF); 555} 556 557static void 558cdce_init(struct usb_ether *ue) 559{ 560 struct cdce_softc *sc = uether_getsc(ue); 561 struct ifnet *ifp = uether_getifp(ue); 562 563 CDCE_LOCK_ASSERT(sc, MA_OWNED); 564 565 ifp->if_drv_flags |= IFF_DRV_RUNNING; 566 567 /* start interrupt transfer */ 568 usbd_transfer_start(sc->sc_xfer[CDCE_INTR_RX]); 569 usbd_transfer_start(sc->sc_xfer[CDCE_INTR_TX]); 570 571 /* stall data write direction, which depends on USB mode */ 572 usbd_xfer_set_stall(sc->sc_xfer[CDCE_BULK_TX]); 573 574 /* start data transfers */ 575 cdce_start(ue); 576} 577 578static void 579cdce_stop(struct usb_ether *ue) 580{ 581 struct cdce_softc *sc = uether_getsc(ue); 582 struct ifnet *ifp = uether_getifp(ue); 583 584 CDCE_LOCK_ASSERT(sc, MA_OWNED); 585 586 ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 587 588 /* 589 * stop all the transfers, if not already stopped: 590 */ 591 usbd_transfer_stop(sc->sc_xfer[CDCE_BULK_RX]); 592 usbd_transfer_stop(sc->sc_xfer[CDCE_BULK_TX]); 593 usbd_transfer_stop(sc->sc_xfer[CDCE_INTR_RX]); 594 usbd_transfer_stop(sc->sc_xfer[CDCE_INTR_TX]); 595} 596 597static void 598cdce_setmulti(struct usb_ether *ue) 599{ 600 /* no-op */ 601 return; 602} 603 604static void 605cdce_setpromisc(struct usb_ether *ue) 606{ 607 /* no-op */ 608 return; 609} 610 611static int 612cdce_suspend(device_t dev) 613{ 614 device_printf(dev, "Suspending\n"); 615 return (0); 616} 617 618static int 619cdce_resume(device_t dev) 620{ 621 device_printf(dev, "Resuming\n"); 622 return (0); 623} 624 625static void 626cdce_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) 627{ 628 struct cdce_softc *sc = usbd_xfer_softc(xfer); 629 struct mbuf *m; 630 uint8_t x; 631 int actlen, aframes, len; 632 633 usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL); 634 635 switch (USB_GET_STATE(xfer)) { 636 case USB_ST_TRANSFERRED: 637 638 DPRINTF("received %u bytes in %u frames\n", actlen, aframes); 639 640 for (x = 0; x != aframes; x++) { 641 642 m = sc->sc_rx_buf[x]; 643 sc->sc_rx_buf[x] = NULL; 644 len = usbd_xfer_frame_len(xfer, x); 645 646 /* Strip off CRC added by Zaurus, if any */ 647 if ((sc->sc_flags & CDCE_FLAG_ZAURUS) && len >= 14) 648 len -= 4; 649 650 if (len < sizeof(struct ether_header)) { 651 m_freem(m); 652 continue; 653 } 654 /* queue up mbuf */ 655 uether_rxmbuf(&sc->sc_ue, m, len); 656 } 657 658 /* FALLTHROUGH */ 659 case USB_ST_SETUP: 660 /* 661 * TODO: Implement support for multi frame transfers, 662 * when the USB hardware supports it. 663 */ 664 for (x = 0; x != 1; x++) { 665 if (sc->sc_rx_buf[x] == NULL) { 666 m = uether_newbuf(); 667 if (m == NULL) 668 goto tr_stall; 669 sc->sc_rx_buf[x] = m; 670 } else { 671 m = sc->sc_rx_buf[x]; 672 } 673 674 usbd_xfer_set_frame_data(xfer, x, m->m_data, m->m_len); 675 } 676 /* set number of frames and start hardware */ 677 usbd_xfer_set_frames(xfer, x); 678 usbd_transfer_submit(xfer); 679 /* flush any received frames */ 680 uether_rxflush(&sc->sc_ue); 681 break; 682 683 default: /* Error */ 684 DPRINTF("error = %s\n", 685 usbd_errstr(error)); 686 687 if (error != USB_ERR_CANCELLED) { 688tr_stall: 689 /* try to clear stall first */ 690 usbd_xfer_set_stall(xfer); 691 usbd_xfer_set_frames(xfer, 0); 692 usbd_transfer_submit(xfer); 693 break; 694 } 695 696 /* need to free the RX-mbufs when we are cancelled */ 697 cdce_free_queue(sc->sc_rx_buf, CDCE_FRAMES_MAX); 698 break; 699 } 700} 701 702static void 703cdce_intr_read_callback(struct usb_xfer *xfer, usb_error_t error) 704{ 705 int actlen; 706 707 usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); 708 709 switch (USB_GET_STATE(xfer)) { 710 case USB_ST_TRANSFERRED: 711 712 DPRINTF("Received %d bytes\n", actlen); 713 714 /* TODO: decode some indications */ 715 716 /* FALLTHROUGH */ 717 case USB_ST_SETUP: 718tr_setup: 719 usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); 720 usbd_transfer_submit(xfer); 721 break; 722 723 default: /* Error */ 724 if (error != USB_ERR_CANCELLED) { 725 /* start clear stall */ 726 usbd_xfer_set_stall(xfer); 727 goto tr_setup; 728 } 729 break; 730 } 731} 732 733static void 734cdce_intr_write_callback(struct usb_xfer *xfer, usb_error_t error) 735{ 736 int actlen; 737 738 usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); 739 740 switch (USB_GET_STATE(xfer)) { 741 case USB_ST_TRANSFERRED: 742 743 DPRINTF("Transferred %d bytes\n", actlen); 744 745 /* FALLTHROUGH */ 746 case USB_ST_SETUP: 747tr_setup: 748#if 0 749 usbd_xfer_set_frame_len(xfer, 0, XXX); 750 usbd_transfer_submit(xfer); 751#endif 752 break; 753 754 default: /* Error */ 755 if (error != USB_ERR_CANCELLED) { 756 /* start clear stall */ 757 usbd_xfer_set_stall(xfer); 758 goto tr_setup; 759 } 760 break; 761 } 762} 763 764static int 765cdce_handle_request(device_t dev, 766 const void *req, void **pptr, uint16_t *plen, 767 uint16_t offset, uint8_t is_complete) 768{ 769 return (ENXIO); /* use builtin handler */ 770} 771