1/* $NetBSD: if_cdce.c,v 1.4 2004/10/24 12:50:54 augustss Exp $ */ 2 3/*- 4 * SPDX-License-Identifier: BSD-4-Clause 5 * 6 * Copyright (c) 1997, 1998, 1999, 2000-2003 Bill Paul <wpaul@windriver.com> 7 * Copyright (c) 2003-2005 Craig Boston 8 * Copyright (c) 2004 Daniel Hartmeier 9 * Copyright (c) 2009 Hans Petter Selasky 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by Bill Paul. 23 * 4. Neither the name of the author nor the names of any co-contributors 24 * may be used to endorse or promote products derived from this software 25 * without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul, THE VOICES IN HIS HEAD OR 31 * THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 32 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 33 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 34 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 35 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 36 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 37 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40/* 41 * USB Communication Device Class (Ethernet Networking Control Model) 42 * http://www.usb.org/developers/devclass_docs/usbcdc11.pdf 43 */ 44 45/* 46 * USB Network Control Model (NCM) 47 * http://www.usb.org/developers/devclass_docs/NCM10.zip 48 */ 49 50#include <sys/cdefs.h> 51 52#include "los_crc32.h" 53 54#include "implementation/global_implementation.h" 55#include "usb_ethernet.h" 56#include "if_cdcereg.h" 57 58static device_probe_t cdce_probe; 59static device_attach_t cdce_attach; 60static device_detach_t cdce_detach; 61static device_suspend_t cdce_suspend; 62static device_resume_t cdce_resume; 63static usb_handle_request_t cdce_handle_request; 64 65static usb_callback_t cdce_bulk_write_callback; 66static usb_callback_t cdce_bulk_read_callback; 67static usb_callback_t cdce_intr_read_callback; 68static usb_callback_t cdce_intr_write_callback; 69 70#if CDCE_HAVE_NCM 71static usb_callback_t cdce_ncm_bulk_write_callback; 72static usb_callback_t cdce_ncm_bulk_read_callback; 73#endif 74 75static uether_fn_t cdce_attach_post; 76static uether_fn_t cdce_init; 77static uether_fn_t cdce_stop; 78static uether_fn_t cdce_start; 79static uether_fn_t cdce_setmulti; 80static uether_fn_t cdce_setpromisc; 81 82static uint32_t cdce_m_crc32(struct pbuf *, uint32_t, uint32_t); 83 84#undef USB_DEBUG_VAR 85#define USB_DEBUG_VAR cdce_debug 86#ifdef LOSCFG_USB_DEBUG 87static int cdce_debug = 0; 88void 89usb_cdce_debug_func(int level) 90{ 91 cdce_debug = level; 92 PRINTK("The level of usb cdce debug is %d\n", level); 93} 94DEBUG_MODULE(cdce, usb_cdce_debug_func); 95#endif 96 97static const struct usb_config cdce_config[CDCE_N_TRANSFER] = { 98 [CDCE_BULK_RX] = { 99 .type = UE_BULK, 100 .endpoint = UE_ADDR_ANY, 101 .direction = UE_DIR_RX, 102 .if_index = 0, 103 .frames = CDCE_FRAMES_MAX, 104 .bufsize = (CDCE_FRAMES_MAX * MCLBYTES), 105 .flags = {.pipe_bof = 1,.short_frames_ok = 1,.short_xfer_ok = 1,.ext_buffer = 1,}, 106 .callback = cdce_bulk_read_callback, 107 .timeout = 0, /* no timeout */ 108 .usb_mode = USB_MODE_DUAL, /* both modes */ 109 }, 110 111 [CDCE_BULK_TX] = { 112 .type = UE_BULK, 113 .endpoint = UE_ADDR_ANY, 114 .direction = UE_DIR_TX, 115 .if_index = 0, 116 .frames = CDCE_FRAMES_MAX, 117 .bufsize = (CDCE_FRAMES_MAX * MCLBYTES), 118 .flags = {.pipe_bof = 1,.force_short_xfer = 1,.ext_buffer = 1,}, 119 .callback = cdce_bulk_write_callback, 120 .timeout = 10000, /* 10 seconds */ 121 .usb_mode = USB_MODE_DUAL, /* both modes */ 122 }, 123 124 [CDCE_INTR_RX] = { 125 .type = UE_INTERRUPT, 126 .endpoint = UE_ADDR_ANY, 127 .direction = UE_DIR_RX, 128 .if_index = 1, 129 .bufsize = CDCE_IND_SIZE_MAX, 130 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,.no_pipe_ok = 1,}, 131 .callback = cdce_intr_read_callback, 132 .timeout = 0, 133 .usb_mode = USB_MODE_HOST, 134 }, 135 136 [CDCE_INTR_TX] = { 137 .type = UE_INTERRUPT, 138 .endpoint = UE_ADDR_ANY, 139 .direction = UE_DIR_TX, 140 .if_index = 1, 141 .bufsize = CDCE_IND_SIZE_MAX, 142 .flags = {.pipe_bof = 1,.force_short_xfer = 1,.no_pipe_ok = 1,}, 143 .callback = cdce_intr_write_callback, 144 .timeout = 10000, /* 10 seconds */ 145 .usb_mode = USB_MODE_DEVICE, 146 }, 147}; 148 149#if CDCE_HAVE_NCM 150static const struct usb_config cdce_ncm_config[CDCE_N_TRANSFER] = { 151 [CDCE_BULK_RX] = { 152 .type = UE_BULK, 153 .endpoint = UE_ADDR_ANY, 154 .direction = UE_DIR_RX, 155 .if_index = 0, 156 .frames = CDCE_NCM_RX_FRAMES_MAX, 157 .bufsize = (CDCE_NCM_RX_FRAMES_MAX * CDCE_NCM_RX_MAXLEN), 158 .flags = {.pipe_bof = 1,.short_frames_ok = 1,.short_xfer_ok = 1,}, 159 .callback = cdce_ncm_bulk_read_callback, 160 .timeout = 0, /* no timeout */ 161 .usb_mode = USB_MODE_DUAL, /* both modes */ 162 }, 163 164 [CDCE_BULK_TX] = { 165 .type = UE_BULK, 166 .endpoint = UE_ADDR_ANY, 167 .direction = UE_DIR_TX, 168 .if_index = 0, 169 .frames = CDCE_NCM_TX_FRAMES_MAX, 170 .bufsize = (CDCE_NCM_TX_FRAMES_MAX * CDCE_NCM_TX_MAXLEN), 171 .flags = {.pipe_bof = 1,}, 172 .callback = cdce_ncm_bulk_write_callback, 173 .timeout = 10000, /* 10 seconds */ 174 .usb_mode = USB_MODE_DUAL, /* both modes */ 175 }, 176 177 [CDCE_INTR_RX] = { 178 .type = UE_INTERRUPT, 179 .endpoint = UE_ADDR_ANY, 180 .direction = UE_DIR_RX, 181 .if_index = 1, 182 .bufsize = CDCE_IND_SIZE_MAX, 183 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,.no_pipe_ok = 1,}, 184 .callback = cdce_intr_read_callback, 185 .timeout = 0, 186 .usb_mode = USB_MODE_HOST, 187 }, 188 189 [CDCE_INTR_TX] = { 190 .type = UE_INTERRUPT, 191 .endpoint = UE_ADDR_ANY, 192 .direction = UE_DIR_TX, 193 .if_index = 1, 194 .bufsize = CDCE_IND_SIZE_MAX, 195 .flags = {.pipe_bof = 1,.force_short_xfer = 1,.no_pipe_ok = 1,}, 196 .callback = cdce_intr_write_callback, 197 .timeout = 10000, /* 10 seconds */ 198 .usb_mode = USB_MODE_DEVICE, 199 }, 200}; 201#endif 202 203static device_method_t cdce_methods[] = { 204 /* USB interface */ 205 DEVMETHOD(usb_handle_request, cdce_handle_request), 206 207 /* Device interface */ 208 DEVMETHOD(device_probe, cdce_probe), 209 DEVMETHOD(device_attach, cdce_attach), 210 DEVMETHOD(device_detach, cdce_detach), 211 DEVMETHOD(device_suspend, cdce_suspend), 212 DEVMETHOD(device_resume, cdce_resume), 213 214 DEVMETHOD_END 215}; 216 217static driver_t cdce_driver = { 218 .name = "cdce", 219 .methods = cdce_methods, 220 .size = sizeof(struct cdce_softc), 221}; 222 223static devclass_t cdce_devclass; 224 225DRIVER_MODULE(cdce, uhub, cdce_driver, cdce_devclass, NULL, 0); 226 227static const struct usb_ether_methods cdce_ue_methods = { 228 .ue_attach_post = cdce_attach_post, 229 .ue_start = cdce_start, 230 .ue_init = cdce_init, 231 .ue_stop = cdce_stop, 232 .ue_setmulti = cdce_setmulti, 233 .ue_setpromisc = cdce_setpromisc, 234}; 235 236static const STRUCT_USB_HOST_ID cdce_host_devs[] = { 237 238}; 239 240static const STRUCT_USB_DUAL_ID cdce_dual_devs[] = { 241 {USB_IF_CSI(UICLASS_CDC, UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0)}, 242 {USB_IF_CSI(UICLASS_CDC, UISUBCLASS_MOBILE_DIRECT_LINE_MODEL, 0)}, 243 {USB_IF_CSI(UICLASS_CDC, UISUBCLASS_NETWORK_CONTROL_MODEL, 0)}, 244}; 245 246#if CDCE_HAVE_NCM 247/*------------------------------------------------------------------------* 248 * cdce_ncm_init 249 * 250 * Return values: 251 * 0: Success 252 * Else: Failure 253 *------------------------------------------------------------------------*/ 254static uint8_t 255cdce_ncm_init(struct cdce_softc *sc) 256{ 257 struct usb_ncm_parameters temp; 258 struct usb_device_request req; 259 struct usb_ncm_func_descriptor *ufd; 260 uint8_t value[8]; 261 int err; 262 263 DPRINTFN(1, "\n"); 264 265 ufd = usbd_find_descriptor(sc->sc_ue.ue_udev, NULL, 266 sc->sc_ifaces_index[1], UDESC_CS_INTERFACE, 0xFF, 267 UCDC_NCM_FUNC_DESC_SUBTYPE, 0xFF); 268 269 /* verify length of NCM functional descriptor */ 270 if (ufd != NULL) { 271 if (ufd->bLength < sizeof(*ufd)) 272 ufd = NULL; 273 else 274 DPRINTFN(1, "Found NCM functional descriptor.\n"); 275 } 276 277 req.bmRequestType = UT_READ_CLASS_INTERFACE; 278 req.bRequest = UCDC_NCM_GET_NTB_PARAMETERS; 279 USETW(req.wValue, 0); 280 req.wIndex[0] = sc->sc_ifaces_index[1]; 281 req.wIndex[1] = 0; 282 USETW(req.wLength, sizeof(temp)); 283 284 err = usbd_do_request_flags(sc->sc_ue.ue_udev, NULL, &req, 285 &temp, 0, NULL, 1000 /* ms */); 286 if (err){ 287 DPRINTFN(1, "request error!\n"); 288 return (1); 289 } 290 /* Read correct set of parameters according to device mode */ 291 DPRINTFN(1, "line %d!\n",__LINE__); 292 293 if (usbd_get_mode(sc->sc_ue.ue_udev) == USB_MODE_HOST) { 294 sc->sc_ncm.rx_max = UGETDW(temp.dwNtbInMaxSize); 295 sc->sc_ncm.tx_max = UGETDW(temp.dwNtbOutMaxSize); 296 sc->sc_ncm.tx_remainder = UGETW(temp.wNdpOutPayloadRemainder); 297 sc->sc_ncm.tx_modulus = UGETW(temp.wNdpOutDivisor); 298 sc->sc_ncm.tx_struct_align = UGETW(temp.wNdpOutAlignment); 299 sc->sc_ncm.tx_nframe = UGETW(temp.wNtbOutMaxDatagrams); 300 } else { 301 sc->sc_ncm.rx_max = UGETDW(temp.dwNtbOutMaxSize); 302 sc->sc_ncm.tx_max = UGETDW(temp.dwNtbInMaxSize); 303 sc->sc_ncm.tx_remainder = UGETW(temp.wNdpInPayloadRemainder); 304 sc->sc_ncm.tx_modulus = UGETW(temp.wNdpInDivisor); 305 sc->sc_ncm.tx_struct_align = UGETW(temp.wNdpInAlignment); 306 sc->sc_ncm.tx_nframe = UGETW(temp.wNtbOutMaxDatagrams); 307 } 308 309 /* Verify maximum receive length */ 310 311 if ((sc->sc_ncm.rx_max < 32) || 312 (sc->sc_ncm.rx_max > CDCE_NCM_RX_MAXLEN)) { 313 DPRINTFN(1, "Using default maximum receive length\n"); 314 sc->sc_ncm.rx_max = CDCE_NCM_RX_MAXLEN; 315 } 316 317 /* Verify maximum transmit length */ 318 319 if ((sc->sc_ncm.tx_max < 32) || 320 (sc->sc_ncm.tx_max > CDCE_NCM_TX_MAXLEN)) { 321 DPRINTFN(1, "Using default maximum transmit length\n"); 322 sc->sc_ncm.tx_max = CDCE_NCM_TX_MAXLEN; 323 } 324 325 /* 326 * Verify that the structure alignment is: 327 * - power of two 328 * - not greater than the maximum transmit length 329 * - not less than four bytes 330 */ 331 if ((sc->sc_ncm.tx_struct_align < 4) || 332 (sc->sc_ncm.tx_struct_align != 333 ((-sc->sc_ncm.tx_struct_align) & sc->sc_ncm.tx_struct_align)) || 334 (sc->sc_ncm.tx_struct_align >= sc->sc_ncm.tx_max)) { 335 DPRINTFN(1, "Using default other alignment: 4 bytes\n"); 336 sc->sc_ncm.tx_struct_align = 4; 337 } 338 339 /* 340 * Verify that the payload alignment is: 341 * - power of two 342 * - not greater than the maximum transmit length 343 * - not less than four bytes 344 */ 345 if ((sc->sc_ncm.tx_modulus < 4) || 346 (sc->sc_ncm.tx_modulus != 347 ((-sc->sc_ncm.tx_modulus) & sc->sc_ncm.tx_modulus)) || 348 (sc->sc_ncm.tx_modulus >= sc->sc_ncm.tx_max)) { 349 DPRINTFN(1, "Using default transmit modulus: 4 bytes\n"); 350 sc->sc_ncm.tx_modulus = 4; 351 } 352 353 /* Verify that the payload remainder */ 354 355 if ((sc->sc_ncm.tx_remainder >= sc->sc_ncm.tx_modulus)) { 356 DPRINTFN(1, "Using default transmit remainder: 0 bytes\n"); 357 sc->sc_ncm.tx_remainder = 0; 358 } 359 360 /* 361 * Offset the TX remainder so that IP packet payload starts at 362 * the tx_modulus. This is not too clear in the specification. 363 */ 364 365 sc->sc_ncm.tx_remainder = 366 (sc->sc_ncm.tx_remainder - ETHER_HDR_LEN) & 367 (sc->sc_ncm.tx_modulus - 1); 368 369 /* Verify max datagrams */ 370 371 if (sc->sc_ncm.tx_nframe == 0 || 372 sc->sc_ncm.tx_nframe > (CDCE_NCM_SUBFRAMES_MAX - 1)) { 373 DPRINTFN(1, "Using default max " 374 "subframes: %u units\n", CDCE_NCM_SUBFRAMES_MAX - 1); 375 /* need to reserve one entry for zero padding */ 376 sc->sc_ncm.tx_nframe = (CDCE_NCM_SUBFRAMES_MAX - 1); 377 } 378 379 /* Additional configuration, will fail in device side mode, which is OK. */ 380 381 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 382 req.bRequest = UCDC_NCM_SET_NTB_INPUT_SIZE; 383 USETW(req.wValue, 0); 384 req.wIndex[0] = sc->sc_ifaces_index[1]; 385 req.wIndex[1] = 0; 386 387 if ((ufd != NULL) && 388 (ufd->bmNetworkCapabilities & UCDC_NCM_CAP_MAX_DGRAM)) { 389 USETW(req.wLength, 8); 390 USETDW(value, sc->sc_ncm.rx_max); 391 USETW(value + 4, (CDCE_NCM_SUBFRAMES_MAX - 1)); 392 USETW(value + 6, 0); 393 } else { 394 USETW(req.wLength, 4); 395 USETDW(value, sc->sc_ncm.rx_max); 396 } 397 398 err = usbd_do_request_flags(sc->sc_ue.ue_udev, NULL, &req, 399 &value, 0, NULL, 1000 /* ms */); 400 if (err) { 401 DPRINTFN(1, "Setting input size " 402 "to %u failed.\n", sc->sc_ncm.rx_max); 403 } 404 405 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 406 req.bRequest = UCDC_NCM_SET_CRC_MODE; 407 USETW(req.wValue, 0); /* no CRC */ 408 req.wIndex[0] = sc->sc_ifaces_index[1]; 409 req.wIndex[1] = 0; 410 USETW(req.wLength, 0); 411 412 err = usbd_do_request_flags(sc->sc_ue.ue_udev, NULL, &req, 413 NULL, 0, NULL, 1000 /* ms */); 414 if (err) { 415 DPRINTFN(1, "Setting CRC mode to off failed.\n"); 416 } 417 418 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 419 req.bRequest = UCDC_NCM_SET_NTB_FORMAT; 420 USETW(req.wValue, 0); /* NTB-16 */ 421 req.wIndex[0] = sc->sc_ifaces_index[1]; 422 req.wIndex[1] = 0; 423 USETW(req.wLength, 0); 424 425 err = usbd_do_request_flags(sc->sc_ue.ue_udev, NULL, &req, 426 NULL, 0, NULL, 1000 /* ms */); 427 if (err) { 428 DPRINTFN(1, "Setting NTB format to 16-bit failed.\n"); 429 } 430 431 DPRINTFN(1, " -->end!\n"); 432 433 return (0); /* success */ 434} 435#endif 436 437static int 438cdce_probe(device_t dev) 439{ 440 struct usb_attach_arg *uaa = (struct usb_attach_arg *)device_get_ivars(dev); 441 int error; 442 443 error = usbd_lookup_id_by_uaa(cdce_host_devs, sizeof(cdce_host_devs), uaa); 444 445 if (error) 446 error = usbd_lookup_id_by_uaa(cdce_dual_devs, sizeof(cdce_dual_devs), uaa); 447 return (error); 448} 449 450static void 451cdce_attach_post(struct usb_ether *ue) 452{ 453 /* no-op */ 454 return; 455} 456 457static int 458cdce_attach(device_t dev) 459{ 460 struct cdce_softc *sc = (struct cdce_softc *)device_get_softc(dev); 461 struct usb_ether *ue = &sc->sc_ue; 462 struct usb_attach_arg *uaa = (struct usb_attach_arg *)device_get_ivars(dev); 463 struct usb_interface *iface; 464 const struct usb_cdc_union_descriptor *ud; 465 const struct usb_interface_descriptor *id; 466 const struct usb_cdc_ethernet_descriptor *ued; 467 const struct usb_config *pcfg; 468 uint32_t seed; 469 usb_error_t error; 470 uint8_t i; 471 uint8_t data_iface_no; 472 char eaddr_str[5 * NETIF_MAX_HWADDR_LEN]; /* approx */ 473 474 DPRINTFN(1, "\n"); 475 476 sc->sc_flags = USB_GET_DRIVER_INFO(uaa); 477 sc->sc_ue.ue_udev = uaa->device; 478 479 device_set_usb_desc(dev); 480 481 mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF); 482 483 ud = (const struct usb_cdc_union_descriptor *)usbd_find_descriptor 484 (uaa->device, NULL, uaa->info.bIfaceIndex, UDESC_CS_INTERFACE, 485 0xFF, UDESCSUB_CDC_UNION, 0xFF); 486 487 if ((ud == NULL) || (ud->bLength < sizeof(*ud)) || 488 (sc->sc_flags & CDCE_FLAG_NO_UNION)) { 489 DPRINTFN(1, "No union descriptor!\n"); 490 sc->sc_ifaces_index[0] = uaa->info.bIfaceIndex; 491 sc->sc_ifaces_index[1] = uaa->info.bIfaceIndex; 492 goto alloc_transfers; 493 } 494 data_iface_no = ud->bSlaveInterface[0]; 495 DPRINTFN(1, "data_iface_no = %d!\n", data_iface_no); 496 497 for (i = 0;; i++) { 498 iface = usbd_get_iface(uaa->device, i); 499 500 if (iface) { 501 id = usbd_get_interface_descriptor(iface); 502 503 if (id && (id->bInterfaceNumber == data_iface_no)) { 504 sc->sc_ifaces_index[0] = i; 505 sc->sc_ifaces_index[1] = uaa->info.bIfaceIndex; 506 DPRINTFN(1, "index 0 = %d, index 1 = %d!\n", i, uaa->info.bIfaceIndex); 507 usbd_set_parent_iface(uaa->device, i, uaa->info.bIfaceIndex); 508 break; 509 } 510 } else { 511 device_printf(dev, "no data interface found\n"); 512 goto detach; 513 } 514 } 515 516 /* 517 * <quote> 518 * 519 * The Data Class interface of a networking device shall have 520 * a minimum of two interface settings. The first setting 521 * (the default interface setting) includes no endpoints and 522 * therefore no networking traffic is exchanged whenever the 523 * default interface setting is selected. One or more 524 * additional interface settings are used for normal 525 * operation, and therefore each includes a pair of endpoints 526 * (one IN, and one OUT) to exchange network traffic. Select 527 * an alternate interface setting to initialize the network 528 * aspects of the device and to enable the exchange of 529 * network traffic. 530 * 531 * </quote> 532 * 533 * Some devices, most notably cable modems, include interface 534 * settings that have no IN or OUT endpoint, therefore loop 535 * through the list of all available interface settings 536 * looking for one with both IN and OUT endpoints. 537 */ 538 539alloc_transfers: 540 541 pcfg = cdce_config; /* Default Configuration */ 542 543 for (i = 0; i != 32; i++) { 544 error = usbd_set_alt_interface_index(uaa->device, 545 sc->sc_ifaces_index[0], i); 546 if (error) { 547 break; 548 } 549 550#if CDCE_HAVE_NCM 551 if ((i == 0) && (cdce_ncm_init(sc) == 0)) 552 pcfg = cdce_ncm_config; 553#endif 554 error = usbd_transfer_setup(uaa->device, 555 sc->sc_ifaces_index, sc->sc_xfer, 556 pcfg, CDCE_N_TRANSFER, sc, &sc->sc_mtx); 557 558 if (error == 0) { 559 break; 560 } 561 } 562 563 if (error || (i == 32)) { 564 device_printf(dev, "No valid alternate " 565 "setting found\n"); 566 goto detach; 567 } 568 569 ued = (const struct usb_cdc_ethernet_descriptor *)usbd_find_descriptor 570 (uaa->device, NULL, uaa->info.bIfaceIndex, UDESC_CS_INTERFACE, 571 0xFF, UDESCSUB_CDC_ENF, 0xFF); 572 573 if ((ued == NULL) || (ued->bLength < sizeof(*ued))) { 574 error = USB_ERR_INVAL; 575 } else { 576 error = usbd_req_get_string_any(uaa->device, NULL, 577 eaddr_str, sizeof(eaddr_str), ued->iMacAddress); 578 } 579 580 if (error) { 581 /* fake MAC address */ 582 583 device_printf(dev, "faking MAC address\n"); 584 seed = CUR_TICKS; 585 (void)memcpy_s(&sc->sc_ue.ue_eaddr[1], (NETIF_MAX_HWADDR_LEN - 2), &seed, sizeof(uint32_t)); 586 sc->sc_ue.ue_eaddr[0] = 0x2a; 587 sc->sc_ue.ue_eaddr[5] = device_get_unit(dev); 588 589 } else { 590 (void)memset_s(sc->sc_ue.ue_eaddr, sizeof(sc->sc_ue.ue_eaddr), 0, sizeof(sc->sc_ue.ue_eaddr)); 591 592 for (i = 0; i != (NETIF_MAX_HWADDR_LEN * 2); i++) { 593 char c = eaddr_str[i]; 594 595 if (('0' <= c) && (c <= '9')) 596 c -= '0'; 597 else if (c != 0) 598 c -= 'A' - 10; 599 else 600 break; 601 602 c &= 0xf; 603 604 if ((i & 1) == 0) 605 c <<= 4; 606 sc->sc_ue.ue_eaddr[i / 2] |= c; 607 } 608 609 if (uaa->usb_mode == USB_MODE_DEVICE) { 610 /* 611 * Do not use the same MAC address like the peer ! 612 */ 613 sc->sc_ue.ue_eaddr[5] ^= 0xFF; 614 } 615 } 616 617 ue->ue_sc = sc; 618 ue->ue_dev = dev; 619 ue->ue_udev = uaa->device; 620 ue->ue_mtx = &sc->sc_mtx; 621 ue->ue_methods = &cdce_ue_methods; 622 623 error = (usb_error_t)uether_ifattach(ue); 624 if (error) { 625 device_printf(dev, "could not attach interface\n"); 626 goto detach; 627 } 628 return (0); /* success */ 629 630detach: 631 (void)cdce_detach(dev); 632 return (ENXIO); /* failure */ 633} 634 635static int 636cdce_detach(device_t dev) 637{ 638 struct cdce_softc *sc = (struct cdce_softc *)device_get_softc(dev); 639 struct usb_ether *ue = &sc->sc_ue; 640 641 /* stop all USB transfers first */ 642 usbd_transfer_unsetup(sc->sc_xfer, CDCE_N_TRANSFER); 643 uether_ifdetach(ue); 644 mtx_destroy(&sc->sc_mtx); 645 646 return (0); 647} 648 649static void 650cdce_start(struct usb_ether *ue) 651{ 652 struct cdce_softc *sc = (struct cdce_softc *)uether_getsc(ue); 653 654 DPRINTFN(1, "\n"); 655 /* 656 * Start the USB transfers, if not already started: 657 */ 658 usbd_transfer_start(sc->sc_xfer[CDCE_BULK_TX]); 659 usbd_transfer_start(sc->sc_xfer[CDCE_BULK_RX]); 660} 661 662static void 663cdce_free_queue(struct pbuf **ppm, uint8_t n) 664{ 665 uint8_t x; 666 for (x = 0; x != n; x++) { 667 if (ppm[x] != NULL) { 668 uether_freebuf(ppm[x]); 669 ppm[x] = NULL; 670 } 671 } 672} 673 674/* 675 * There is something wrong with the original function and delete the code; 676 * If you want to use, you should realize it again. 677 */ 678int 679pbuf_append(struct pbuf *m0, int length, void* cp) 680{ 681 return (0); 682} 683 684 685 686static void 687cdce_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) 688{ 689 struct cdce_softc *sc = (struct cdce_softc *)usbd_xfer_softc(xfer); 690 struct usb_ether *ue = &sc->sc_ue; 691 struct pbuf *m; 692 uint32_t crc; 693 uint8_t x; 694 int actlen, aframes; 695 696 DPRINTFN(10, "\n"); 697 698 usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL); 699 700 switch (USB_GET_STATE(xfer)) { 701 case USB_ST_TRANSFERRED: 702 DPRINTFN(10, "transfer complete: %u bytes in %u frames\n",actlen, aframes); 703 704 /* free all previous TX buffers */ 705 cdce_free_queue(sc->sc_tx_buf, CDCE_FRAMES_MAX); 706 707 /* FALLTHROUGH */ 708 case USB_ST_SETUP: 709tr_setup: 710 for (x = 0; x != CDCE_FRAMES_MAX; x++) { 711 UE_LOCK(ue); 712 IF_DEQUEUE(&(ue->ue_txq), m); 713 UE_UNLOCK(ue); 714 if (m == NULL) 715 break; 716 717 if (sc->sc_flags & CDCE_FLAG_ZAURUS) { 718 /* 719 * Zaurus wants a 32-bit CRC appended 720 * to every frame 721 */ 722 723 crc = cdce_m_crc32(m, 0, m->len); 724 crc = htole32(crc); 725 726 if (!pbuf_append(m, 4, (void *)&crc)) { 727 free(m); 728 continue; 729 } 730 } 731 732 sc->sc_tx_buf[x] = m; 733 usbd_xfer_set_frame_data(xfer, x, m->payload, m->len); 734 735 /* 736 * If there's a BPF listener, bounce a copy of 737 * this frame to him: 738 */ 739 } 740 if (x != 0) { 741 usbd_xfer_set_frames(xfer, x); 742 usbd_transfer_submit(xfer); 743 } 744 break; 745 746 default: /* Error */ 747 DPRINTFN(11, "transfer error, %s\n",usbd_errstr(error)); 748 PRINTK("transfer error, %s\n",usbd_errstr(error)); 749 750 /* free all previous TX buffers */ 751 cdce_free_queue(sc->sc_tx_buf, CDCE_FRAMES_MAX); 752 753 if (error != USB_ERR_CANCELLED) { 754 /* try to clear stall first */ 755 usbd_xfer_set_stall(xfer); 756 goto tr_setup; 757 } 758 break; 759 } 760} 761 762static uint32_t 763cdce_m_crc32(struct pbuf *m, uint32_t src_offset, uint32_t src_len) 764{ 765 uint32_t crc = 0xFFFFFFFF; 766 767 crc = crc32(crc, m->payload, src_len); 768 return (crc ^ 0xFFFFFFFF); 769} 770 771static void 772cdce_init(struct usb_ether *ue) 773{ 774 struct cdce_softc *sc = (struct cdce_softc *)uether_getsc(ue); 775 struct los_eth_driver *ifp = ue->ue_drv_sc; 776 struct eth_drv_sc *drv_sc = (struct eth_drv_sc *)ifp->driver_context; 777 778 DPRINTFN(1, "\n"); 779 780 CDCE_LOCK_ASSERT(sc, MA_OWNED); 781 782 drv_sc->state |= IFF_DRV_RUNNING; 783 784 /* start interrupt transfer */ 785 usbd_transfer_start(sc->sc_xfer[CDCE_INTR_RX]); 786 usbd_transfer_start(sc->sc_xfer[CDCE_INTR_TX]); 787 788 /* 789 * Stall data write direction, which depends on USB mode. 790 * 791 * Some USB host stacks (e.g. Mac OS X) don't clears stall 792 * bit as it should, so set it in our host mode only. 793 */ 794 if (usbd_get_mode(sc->sc_ue.ue_udev) == USB_MODE_HOST) 795 usbd_xfer_set_stall(sc->sc_xfer[CDCE_BULK_TX]); 796 797 /* start data transfers */ 798 cdce_start(ue); 799} 800 801static void 802cdce_stop(struct usb_ether *ue) 803{ 804 struct cdce_softc *sc = (struct cdce_softc *)uether_getsc(ue); 805 struct los_eth_driver *ifp = ue->ue_drv_sc; 806 struct eth_drv_sc *drv_sc = (struct eth_drv_sc *)ifp->driver_context; 807 808 DPRINTFN(1, "\n"); 809 810 CDCE_LOCK_ASSERT(sc, MA_OWNED); 811 812 drv_sc->state &= ~IFF_DRV_RUNNING; 813 814 /* 815 * stop all the transfers, if not already stopped: 816 */ 817 usbd_transfer_stop(sc->sc_xfer[CDCE_BULK_RX]); 818 usbd_transfer_stop(sc->sc_xfer[CDCE_BULK_TX]); 819 usbd_transfer_stop(sc->sc_xfer[CDCE_INTR_RX]); 820 usbd_transfer_stop(sc->sc_xfer[CDCE_INTR_TX]); 821} 822 823static void 824cdce_setmulti(struct usb_ether *ue) 825{ 826 /* no-op */ 827 return; 828} 829 830static void 831cdce_setpromisc(struct usb_ether *ue) 832{ 833 /* no-op */ 834 return; 835} 836 837static int 838cdce_suspend(device_t dev) 839{ 840 device_printf(dev, "Suspending\n"); 841 return (0); 842} 843 844static int 845cdce_resume(device_t dev) 846{ 847 device_printf(dev, "Resuming\n"); 848 return (0); 849} 850 851static void 852cdce_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) 853{ 854 struct cdce_softc *sc = (struct cdce_softc *)usbd_xfer_softc(xfer); 855 struct pbuf *m; 856 uint8_t x; 857 int actlen; 858 int aframes; 859 int len; 860 861 DPRINTFN(1, "\n"); 862 usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL); 863 864 switch (USB_GET_STATE(xfer)) { 865 case USB_ST_TRANSFERRED: 866 867 DPRINTF("received %u bytes in %u frames\n", actlen, aframes); 868 869 for (x = 0; x != aframes; x++) { 870 m = sc->sc_rx_buf[x]; 871 sc->sc_rx_buf[x] = NULL; 872 len = usbd_xfer_frame_len(xfer, x); 873 874 /* Strip off CRC added by Zaurus, if any */ 875 if ((sc->sc_flags & CDCE_FLAG_ZAURUS) && len >= 14) 876 len -= 4; 877 878 if (len < (int)sizeof(struct ether_header)) { 879 uether_freebuf(m); 880 continue; 881 } 882 /* queue up mbuf */ 883 (void)uether_rxmbuf(&sc->sc_ue, m, len); 884 } 885 886 /* FALLTHROUGH */ 887 case USB_ST_SETUP: 888 /* 889 * TODO: Implement support for multi frame transfers, 890 * when the USB hardware supports it. 891 */ 892 for (x = 0; x != 1; x++) { /* why x is alway 0? */ 893 if (sc->sc_rx_buf[x] == NULL) { 894 m = uether_newbuf(MAX_ETH_MSG); 895 if (m == NULL) 896 goto tr_stall; 897 sc->sc_rx_buf[x] = m; 898 } else { 899 m = sc->sc_rx_buf[x]; 900 } 901 902 DPRINTFN(1, "new buffer length %d\n", m->len); 903 usbd_xfer_set_frame_data(xfer, x, m->payload, m->len); 904 } 905 /* set number of frames and start hardware */ 906 usbd_xfer_set_frames(xfer, x); 907 usbd_transfer_submit(xfer); 908 /* flush any received frames */ 909 uether_rxflush(&sc->sc_ue); 910 break; 911 912 default: /* Error */ 913 DPRINTF("error = %s\n",usbd_errstr(error)); 914 915 if (error != USB_ERR_CANCELLED) { 916tr_stall: 917 /* try to clear stall first */ 918 usbd_xfer_set_stall(xfer); 919 usbd_xfer_set_frames(xfer, 0); 920 usbd_transfer_submit(xfer); 921 break; 922 } 923 924 /* need to free the RX-mbufs when we are cancelled */ 925 cdce_free_queue(sc->sc_rx_buf, CDCE_FRAMES_MAX); 926 break; 927 } 928} 929 930static void 931cdce_intr_read_callback(struct usb_xfer *xfer, usb_error_t error) 932{ 933 int actlen; 934 935 DPRINTFN(1, "\n"); 936 937 usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); 938 939 switch (USB_GET_STATE(xfer)) { 940 case USB_ST_TRANSFERRED: 941 942 DPRINTF("cdce_intr_read_callback Received %d bytes\n", actlen); 943 944 /* TODO: decode some indications */ 945 946 /* FALLTHROUGH */ 947 case USB_ST_SETUP: 948tr_setup: 949 usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); 950 usbd_transfer_submit(xfer); 951 break; 952 953 default: /* Error */ 954 if (error != USB_ERR_CANCELLED) { 955 /* start clear stall */ 956 usbd_xfer_set_stall(xfer); 957 goto tr_setup; 958 } 959 break; 960 } 961} 962 963static void 964cdce_intr_write_callback(struct usb_xfer *xfer, usb_error_t error) 965{ 966 struct cdce_softc *sc = usbd_xfer_softc(xfer); 967 struct usb_cdc_notification req; 968 struct usb_page_cache *pc; 969 uint32_t speed; 970 int actlen; 971 972 DPRINTFN(1, "\n"); 973 974 usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); 975 976 switch (USB_GET_STATE(xfer)) { 977 case USB_ST_TRANSFERRED: 978 979 DPRINTF("Transferred %d bytes\n", actlen); 980 981 switch (sc->sc_notify_state) { 982 case CDCE_NOTIFY_NETWORK_CONNECTION: 983 sc->sc_notify_state = CDCE_NOTIFY_SPEED_CHANGE; 984 break; 985 case CDCE_NOTIFY_SPEED_CHANGE: 986 sc->sc_notify_state = CDCE_NOTIFY_DONE; 987 break; 988 default: 989 break; 990 } 991 /* FALLTHROUGH */ 992 case USB_ST_SETUP: 993tr_setup: 994 /* 995 * Inform host about connection. Required according to USB CDC 996 * specification and communicating to Mac OS X USB host stack. 997 * Some of the values seems ignored by Mac OS X though. 998 */ 999 if (sc->sc_notify_state == CDCE_NOTIFY_NETWORK_CONNECTION) { 1000 req.bmRequestType = UCDC_NOTIFICATION; 1001 req.bNotification = UCDC_N_NETWORK_CONNECTION; 1002 req.wIndex[0] = sc->sc_ifaces_index[1]; 1003 req.wIndex[1] = 0; 1004 USETW(req.wValue, 1); /* Connected */ 1005 USETW(req.wLength, 0); 1006 1007 pc = usbd_xfer_get_frame(xfer, 0); 1008 usbd_copy_in(pc, 0, &req, sizeof(req)); 1009 usbd_xfer_set_frame_len(xfer, 0, sizeof(req)); 1010 usbd_xfer_set_frames(xfer, 1); 1011 usbd_transfer_submit(xfer); 1012 } else if (sc->sc_notify_state == CDCE_NOTIFY_SPEED_CHANGE) { 1013 req.bmRequestType = UCDC_NOTIFICATION; 1014 req.bNotification = UCDC_N_CONNECTION_SPEED_CHANGE; 1015 req.wIndex[0] = sc->sc_ifaces_index[1]; 1016 req.wIndex[1] = 0; 1017 USETW(req.wValue, 0); 1018 USETW(req.wLength, 8); 1019 1020 /* Peak theoretical bulk trasfer rate in bits/s */ 1021 if (usbd_get_speed(sc->sc_ue.ue_udev) != USB_SPEED_FULL) 1022 speed = (13 * 512 * 8 * 1000 * 8); 1023 else 1024 speed = (19 * 64 * 1 * 1000 * 8); 1025 1026 USETDW(req.data + 0, speed); /* Upstream bit rate */ 1027 USETDW(req.data + 4, speed); /* Downstream bit rate */ 1028 1029 pc = usbd_xfer_get_frame(xfer, 0); 1030 usbd_copy_in(pc, 0, &req, sizeof(req)); 1031 usbd_xfer_set_frame_len(xfer, 0, sizeof(req)); 1032 usbd_xfer_set_frames(xfer, 1); 1033 usbd_transfer_submit(xfer); 1034 } 1035 break; 1036 1037 default: /* Error */ 1038 if (error != USB_ERR_CANCELLED) { 1039 /* start clear stall */ 1040 usbd_xfer_set_stall(xfer); 1041 goto tr_setup; 1042 } 1043 break; 1044 } 1045} 1046 1047static int 1048cdce_handle_request(device_t dev, 1049 const void *preq, void **pptr, uint16_t *plen, 1050 uint16_t offset, uint8_t *pstate) 1051{ 1052 struct cdce_softc *sc = device_get_softc(dev); 1053 const struct usb_device_request *req = preq; 1054 uint8_t is_complete = *pstate; 1055 1056 /* 1057 * When Mac OS X resumes after suspending it expects 1058 * to be notified again after this request. 1059 */ 1060 if (req->bmRequestType == UT_WRITE_CLASS_INTERFACE && \ 1061 req->bRequest == UCDC_NCM_SET_ETHERNET_PACKET_FILTER) { 1062 if (is_complete == 1) { 1063 mtx_lock(&sc->sc_mtx); 1064 sc->sc_notify_state = CDCE_NOTIFY_SPEED_CHANGE; 1065 usbd_transfer_start(sc->sc_xfer[CDCE_INTR_TX]); 1066 mtx_unlock(&sc->sc_mtx); 1067 } 1068 1069 return (0); 1070 } 1071 1072 return (ENXIO); /* use builtin handler */ 1073} 1074 1075#if CDCE_HAVE_NCM 1076static void 1077cdce_ncm_tx_zero(struct usb_page_cache *pc, 1078 uint32_t start, uint32_t end) 1079{ 1080 DPRINTFN(1, "\n"); 1081 1082 if (start >= CDCE_NCM_TX_MAXLEN) 1083 return; 1084 if (end > CDCE_NCM_TX_MAXLEN) 1085 end = CDCE_NCM_TX_MAXLEN; 1086 1087 usbd_frame_zero(pc, start, end - start); 1088} 1089 1090static uint8_t 1091cdce_ncm_fill_tx_frames(struct usb_xfer *xfer, uint8_t index) 1092{ 1093 struct cdce_softc *sc = usbd_xfer_softc(xfer); 1094 struct usb_ether *ue = &sc->sc_ue; 1095 struct usb_page_cache *pc = usbd_xfer_get_frame(xfer, index); 1096 struct pbuf *m; 1097 uint32_t rem; 1098 uint32_t offset; 1099 uint32_t last_offset; 1100 uint16_t n; 1101 uint8_t retval; 1102 1103 DPRINTFN(1, "\n"); 1104 1105 usbd_xfer_set_frame_offset(xfer, index * CDCE_NCM_TX_MAXLEN, index); 1106 1107 offset = sizeof(sc->sc_ncm.hdr) + 1108 sizeof(sc->sc_ncm.dpt) + sizeof(sc->sc_ncm.dp); 1109 1110 /* Store last valid offset before alignment */ 1111 last_offset = offset; 1112 1113 /* Align offset */ 1114 offset = CDCE_NCM_ALIGN(sc->sc_ncm.tx_remainder, 1115 offset, sc->sc_ncm.tx_modulus); 1116 1117 /* Zero pad */ 1118 cdce_ncm_tx_zero(pc, last_offset, offset); 1119 1120 /* buffer full */ 1121 retval = 2; 1122 1123 for (n = 0; n != sc->sc_ncm.tx_nframe; n++) { 1124 /* check if end of transmit buffer is reached */ 1125 1126 if (offset >= sc->sc_ncm.tx_max) 1127 break; 1128 1129 /* compute maximum buffer size */ 1130 1131 rem = sc->sc_ncm.tx_max - offset; 1132 1133 IF_DEQUEUE(&(ue->ue_txq), m); 1134 1135 if (m == NULL) { 1136 /* buffer not full */ 1137 retval = 1; 1138 break; 1139 } 1140 1141 if (m->len > (int)rem) { 1142 if (n == 0) { 1143 /* The frame won't fit in our buffer */ 1144 DPRINTFN(1, "Frame too big to be transmitted!\n"); 1145 pbuf_free(m); 1146 n--; 1147 continue; 1148 } 1149 /* Wait till next buffer becomes ready */ 1150 IF_PREPEND(&(ue->ue_txq), m); 1151 break; 1152 } 1153 usbd_copy_in(pc, offset, m->payload, m->len); 1154 1155 USETW(sc->sc_ncm.dp[n].wFrameLength, m->len); 1156 USETW(sc->sc_ncm.dp[n].wFrameIndex, offset); 1157 1158 /* Update offset */ 1159 offset += m->len; 1160 1161 /* Store last valid offset before alignment */ 1162 last_offset = offset; 1163 1164 /* Align offset */ 1165 offset = CDCE_NCM_ALIGN(sc->sc_ncm.tx_remainder, 1166 offset, sc->sc_ncm.tx_modulus); 1167 1168 /* Zero pad */ 1169 cdce_ncm_tx_zero(pc, last_offset, offset); 1170 1171 /* Free mbuf */ 1172 pbuf_free(m); 1173 } 1174 1175 if (n == 0) 1176 return (0); 1177 1178 rem = (sizeof(sc->sc_ncm.dpt) + (4 * n) + 4); 1179 1180 USETW(sc->sc_ncm.dpt.wLength, rem); 1181 1182 /* zero the rest of the data pointer entries */ 1183 for (; n != CDCE_NCM_SUBFRAMES_MAX; n++) { 1184 USETW(sc->sc_ncm.dp[n].wFrameLength, 0); 1185 USETW(sc->sc_ncm.dp[n].wFrameIndex, 0); 1186 } 1187 1188 offset = last_offset; 1189 1190 /* Align offset */ 1191 offset = CDCE_NCM_ALIGN(0, offset, CDCE_NCM_TX_MINLEN); 1192 1193 /* Optimise, save bandwidth and force short termination */ 1194 if (offset >= sc->sc_ncm.tx_max) 1195 offset = sc->sc_ncm.tx_max; 1196 else 1197 offset ++; 1198 1199 /* Zero pad */ 1200 cdce_ncm_tx_zero(pc, last_offset, offset); 1201 1202 /* set frame length */ 1203 usbd_xfer_set_frame_len(xfer, index, offset); 1204 1205 /* Fill out 16-bit header */ 1206 sc->sc_ncm.hdr.dwSignature[0] = 'N'; 1207 sc->sc_ncm.hdr.dwSignature[1] = 'C'; 1208 sc->sc_ncm.hdr.dwSignature[2] = 'M'; 1209 sc->sc_ncm.hdr.dwSignature[3] = 'H'; 1210 USETW(sc->sc_ncm.hdr.wHeaderLength, sizeof(sc->sc_ncm.hdr)); 1211 USETW(sc->sc_ncm.hdr.wBlockLength, offset); 1212 USETW(sc->sc_ncm.hdr.wSequence, sc->sc_ncm.tx_seq); 1213 USETW(sc->sc_ncm.hdr.wDptIndex, sizeof(sc->sc_ncm.hdr)); 1214 1215 sc->sc_ncm.tx_seq++; 1216 1217 /* Fill out 16-bit frame table header */ 1218 sc->sc_ncm.dpt.dwSignature[0] = 'N'; 1219 sc->sc_ncm.dpt.dwSignature[1] = 'C'; 1220 sc->sc_ncm.dpt.dwSignature[2] = 'M'; 1221 sc->sc_ncm.dpt.dwSignature[3] = '0'; 1222 USETW(sc->sc_ncm.dpt.wNextNdpIndex, 0); /* reserved */ 1223 1224 usbd_copy_in(pc, 0, &(sc->sc_ncm.hdr), sizeof(sc->sc_ncm.hdr)); 1225 usbd_copy_in(pc, sizeof(sc->sc_ncm.hdr), &(sc->sc_ncm.dpt), 1226 sizeof(sc->sc_ncm.dpt)); 1227 usbd_copy_in(pc, sizeof(sc->sc_ncm.hdr) + sizeof(sc->sc_ncm.dpt), 1228 &(sc->sc_ncm.dp), sizeof(sc->sc_ncm.dp)); 1229 return (retval); 1230} 1231 1232static void 1233cdce_ncm_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) 1234{ 1235 uint16_t x; 1236 uint8_t temp; 1237 int actlen; 1238 int aframes; 1239 1240 DPRINTFN(1, "\n"); 1241 1242 switch (USB_GET_STATE(xfer)) { 1243 case USB_ST_TRANSFERRED: 1244 1245 usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL); 1246 1247 DPRINTFN(10, "transfer complete: " 1248 "%u bytes in %u frames\n", actlen, aframes); 1249 1250 case USB_ST_SETUP: 1251 for (x = 0; x != CDCE_NCM_TX_FRAMES_MAX; x++) { 1252 temp = cdce_ncm_fill_tx_frames(xfer, x); 1253 if (temp == 0) 1254 break; 1255 if (temp == 1) { 1256 x++; 1257 break; 1258 } 1259 } 1260 1261 if (x != 0) { 1262#ifdef LOSCFG_USB_DEBUG 1263 usbd_xfer_set_interval(xfer, cdce_tx_interval); 1264#endif 1265 usbd_xfer_set_frames(xfer, x); 1266 usbd_transfer_submit(xfer); 1267 } 1268 break; 1269 1270 default: /* Error */ 1271 DPRINTFN(10, "Transfer error: %s\n", 1272 usbd_errstr(error)); 1273 1274 if (error != USB_ERR_CANCELLED) { 1275 /* try to clear stall first */ 1276 usbd_xfer_set_stall(xfer); 1277 usbd_xfer_set_frames(xfer, 0); 1278 usbd_transfer_submit(xfer); 1279 } 1280 break; 1281 } 1282} 1283 1284static void 1285cdce_ncm_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) 1286{ 1287 struct cdce_softc *sc = usbd_xfer_softc(xfer); 1288 struct usb_page_cache *pc = usbd_xfer_get_frame(xfer, 0); 1289 struct pbuf *m; 1290 int sumdata; 1291 int sumlen; 1292 int actlen; 1293 int aframes; 1294 int temp; 1295 int nframes; 1296 int x; 1297 int offset; 1298 1299 DPRINTFN(1, "\n"); 1300 1301 switch (USB_GET_STATE(xfer)) { 1302 case USB_ST_TRANSFERRED: 1303 1304 usbd_xfer_status(xfer, &actlen, &sumlen, &aframes, NULL); 1305 1306 DPRINTFN(1, "received %u bytes in %u frames\n", 1307 actlen, aframes); 1308 1309 if (actlen < (int)(sizeof(sc->sc_ncm.hdr) + 1310 sizeof(sc->sc_ncm.dpt))) { 1311 DPRINTFN(1, "frame too short\n"); 1312 goto tr_setup; 1313 } 1314 usbd_copy_out(pc, 0, &(sc->sc_ncm.hdr), 1315 sizeof(sc->sc_ncm.hdr)); 1316 1317 if ((sc->sc_ncm.hdr.dwSignature[0] != 'N') || 1318 (sc->sc_ncm.hdr.dwSignature[1] != 'C') || 1319 (sc->sc_ncm.hdr.dwSignature[2] != 'M') || 1320 (sc->sc_ncm.hdr.dwSignature[3] != 'H')) { 1321 DPRINTFN(1, "invalid HDR signature: " 1322 "0x%02x:0x%02x:0x%02x:0x%02x\n", 1323 sc->sc_ncm.hdr.dwSignature[0], 1324 sc->sc_ncm.hdr.dwSignature[1], 1325 sc->sc_ncm.hdr.dwSignature[2], 1326 sc->sc_ncm.hdr.dwSignature[3]); 1327 goto tr_stall; 1328 } 1329 temp = UGETW(sc->sc_ncm.hdr.wBlockLength); 1330 if (temp > sumlen) { 1331 DPRINTFN(1, "unsupported block length %u/%u\n", 1332 temp, sumlen); 1333 goto tr_stall; 1334 } 1335 temp = UGETW(sc->sc_ncm.hdr.wDptIndex); 1336 if ((int)(temp + sizeof(sc->sc_ncm.dpt)) > actlen) { 1337 DPRINTFN(1, "invalid DPT index: 0x%04x\n", temp); 1338 goto tr_stall; 1339 } 1340 usbd_copy_out(pc, temp, &(sc->sc_ncm.dpt), 1341 sizeof(sc->sc_ncm.dpt)); 1342 1343 if ((sc->sc_ncm.dpt.dwSignature[0] != 'N') || 1344 (sc->sc_ncm.dpt.dwSignature[1] != 'C') || 1345 (sc->sc_ncm.dpt.dwSignature[2] != 'M') || 1346 (sc->sc_ncm.dpt.dwSignature[3] != '0')) { 1347 DPRINTFN(1, "invalid DPT signature" 1348 "0x%02x:0x%02x:0x%02x:0x%02x\n", 1349 sc->sc_ncm.dpt.dwSignature[0], 1350 sc->sc_ncm.dpt.dwSignature[1], 1351 sc->sc_ncm.dpt.dwSignature[2], 1352 sc->sc_ncm.dpt.dwSignature[3]); 1353 goto tr_stall; 1354 } 1355 nframes = UGETW(sc->sc_ncm.dpt.wLength) / 4; 1356 1357 /* Subtract size of header and last zero padded entry */ 1358 if (nframes >= (2 + 1)) 1359 nframes -= (2 + 1); 1360 else 1361 nframes = 0; 1362 1363 DPRINTFN(1, "nframes = %u\n", nframes); 1364 1365 temp += sizeof(sc->sc_ncm.dpt); 1366 1367 if ((temp + (4 * nframes)) > actlen) 1368 goto tr_stall; 1369 1370 if (nframes > CDCE_NCM_SUBFRAMES_MAX) { 1371 DPRINTFN(1, "Truncating number of frames from %u to %u\n", 1372 nframes, CDCE_NCM_SUBFRAMES_MAX); 1373 nframes = CDCE_NCM_SUBFRAMES_MAX; 1374 } 1375 usbd_copy_out(pc, temp, &(sc->sc_ncm.dp), (4 * nframes)); 1376 1377 sumdata = 0; 1378 1379 for (x = 0; x != nframes; x++) { 1380 1381 offset = UGETW(sc->sc_ncm.dp[x].wFrameIndex); 1382 temp = UGETW(sc->sc_ncm.dp[x].wFrameLength); 1383 1384 if ((offset == 0) || 1385 (temp < (int)sizeof(struct ether_header)) || 1386 (temp > (MCLBYTES - ETHER_ALIGN))) { 1387 DPRINTFN(1, "NULL frame detected at %d\n", x); 1388 m = NULL; 1389 /* silently ignore this frame */ 1390 continue; 1391 } else if ((offset + temp) > actlen) { 1392 DPRINTFN(1, "invalid frame " 1393 "detected at %d\n", x); 1394 m = NULL; 1395 /* silently ignore this frame */ 1396 continue; 1397 } else { 1398 /* if the tmep here is fragmentary,you could do deallocation */ 1399 m = pbuf_alloc(PBUF_RAW, temp+ETH_PAD_SIZE, PBUF_RAM); 1400 } 1401 1402 DPRINTFN(16, "frame %u, offset = %u, length = %u \n", 1403 x, offset, temp); 1404 1405 /* check if we have a buffer */ 1406 if (m) { 1407 #if ETH_PAD_SIZE 1408 pbuf_header(m, -ETH_PAD_SIZE); /* drop the padding word */ 1409 #endif 1410 1411 usbd_copy_out(pc, offset, m->payload, temp); 1412 1413 #if ETH_PAD_SIZE 1414 pbuf_header(m, ETH_PAD_SIZE); /* drop the padding word */ 1415 #endif 1416 1417 /* enqueue */ 1418 uether_rxmbuf(&sc->sc_ue, m, temp); 1419 1420 sumdata += temp; 1421 } 1422 } 1423 1424 DPRINTFN(1, "Efficiency: %u/%u bytes\n", sumdata, actlen); 1425 1426 case USB_ST_SETUP: 1427tr_setup: 1428 usbd_xfer_set_frame_len(xfer, 0, sc->sc_ncm.rx_max); 1429 usbd_xfer_set_frames(xfer, 1); 1430 usbd_transfer_submit(xfer); 1431 uether_rxflush(&sc->sc_ue); /* must be last */ 1432 break; 1433 1434 default: /* Error */ 1435 DPRINTFN(1, "error = %s\n", 1436 usbd_errstr(error)); 1437 1438 if (error != USB_ERR_CANCELLED) { 1439tr_stall: 1440 /* try to clear stall first */ 1441 usbd_xfer_set_stall(xfer); 1442 usbd_xfer_set_frames(xfer, 0); 1443 usbd_transfer_submit(xfer); 1444 } 1445 break; 1446 } 1447} 1448#endif 1449 1450#undef USB_DEBUG_VAR 1451