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