1 /* $OpenBSD: if_cdce.c,v 1.72 2016/10/12 21:51:11 fcambus Exp $ */ 2 3 /* 4 * Copyright (c) 1997, 1998, 1999, 2000-2003 Bill Paul <wpaul@windriver.com> 5 * Copyright (c) 2003 Craig Boston 6 * Copyright (c) 2004 Daniel Hartmeier 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by Bill Paul. 20 * 4. Neither the name of the author nor the names of any co-contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul, THE VOICES IN HIS HEAD OR 28 * THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 30 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 31 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 32 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 33 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 34 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 */ 36 37 /* 38 * USB Communication Device Class (Ethernet Networking Control Model) 39 * http://www.usb.org/developers/devclass_docs/usbcdc11.pdf 40 * 41 */ 42 43 #include <bpfilter.h> 44 45 #include <sys/param.h> 46 #include <sys/systm.h> 47 #include <sys/sockio.h> 48 #include <sys/mbuf.h> 49 #include <sys/kernel.h> 50 #include <sys/socket.h> 51 #include <sys/device.h> 52 53 #include <net/if.h> 54 55 #if NBPFILTER > 0 56 #include <net/bpf.h> 57 #endif 58 59 #include <netinet/in.h> 60 #include <netinet/if_ether.h> 61 62 #include <dev/usb/usb.h> 63 #include <dev/usb/usbdi.h> 64 #include <dev/usb/usbdi_util.h> 65 #include <dev/usb/usbdevs.h> 66 #include <dev/usb/usbcdc.h> 67 68 #include <dev/usb/if_cdcereg.h> 69 70 #ifdef CDCE_DEBUG 71 #define DPRINTFN(n, x) do { if (cdcedebug > (n)) printf x; } while (0) 72 int cdcedebug = 0; 73 #else 74 #define DPRINTFN(n, x) 75 #endif 76 #define DPRINTF(x) DPRINTFN(0, x) 77 78 int cdce_tx_list_init(struct cdce_softc *); 79 int cdce_rx_list_init(struct cdce_softc *); 80 int cdce_newbuf(struct cdce_softc *, struct cdce_chain *, 81 struct mbuf *); 82 int cdce_encap(struct cdce_softc *, struct mbuf *, int); 83 void cdce_rxeof(struct usbd_xfer *, void *, usbd_status); 84 void cdce_txeof(struct usbd_xfer *, void *, usbd_status); 85 void cdce_start(struct ifnet *); 86 int cdce_ioctl(struct ifnet *, u_long, caddr_t); 87 void cdce_init(void *); 88 void cdce_watchdog(struct ifnet *); 89 void cdce_stop(struct cdce_softc *); 90 void cdce_intr(struct usbd_xfer *, void *, usbd_status); 91 static uint32_t cdce_crc32(const void *, size_t); 92 93 const struct cdce_type cdce_devs[] = { 94 {{ USB_VENDOR_ACERLABS, USB_PRODUCT_ACERLABS_M5632 }, 0 }, 95 {{ USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2501 }, 0 }, 96 {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5500 }, CDCE_CRC32 }, 97 {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_A300 }, CDCE_CRC32 }, 98 {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5600 }, CDCE_CRC32 }, 99 {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_C700 }, CDCE_CRC32 }, 100 {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_C750 }, CDCE_CRC32 }, 101 {{ USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_USBLAN }, CDCE_CRC32 }, 102 {{ USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_USBLAN2 }, CDCE_CRC32 }, 103 {{ USB_VENDOR_GMATE, USB_PRODUCT_GMATE_YP3X00 }, 0 }, 104 {{ USB_VENDOR_NETCHIP, USB_PRODUCT_NETCHIP_ETHERNETGADGET }, 0 }, 105 {{ USB_VENDOR_COMPAQ, USB_PRODUCT_COMPAQ_IPAQLINUX }, 0 }, 106 {{ USB_VENDOR_AMBIT, USB_PRODUCT_AMBIT_NTL_250 }, CDCE_SWAPUNION }, 107 }; 108 #define cdce_lookup(v, p) \ 109 ((const struct cdce_type *)usb_lookup(cdce_devs, v, p)) 110 111 int cdce_match(struct device *, void *, void *); 112 void cdce_attach(struct device *, struct device *, void *); 113 int cdce_detach(struct device *, int); 114 115 struct cfdriver cdce_cd = { 116 NULL, "cdce", DV_IFNET 117 }; 118 119 const struct cfattach cdce_ca = { 120 sizeof(struct cdce_softc), cdce_match, cdce_attach, cdce_detach 121 }; 122 123 int 124 cdce_match(struct device *parent, void *match, void *aux) 125 { 126 struct usb_attach_arg *uaa = aux; 127 usb_interface_descriptor_t *id; 128 129 if (uaa->iface == NULL) 130 return (UMATCH_NONE); 131 132 id = usbd_get_interface_descriptor(uaa->iface); 133 if (id == NULL) 134 return (UMATCH_NONE); 135 136 if (cdce_lookup(uaa->vendor, uaa->product) != NULL) 137 return (UMATCH_VENDOR_PRODUCT); 138 139 if (id->bInterfaceClass == UICLASS_CDC && 140 (id->bInterfaceSubClass == 141 UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL || 142 id->bInterfaceSubClass == UISUBCLASS_MOBILE_DIRECT_LINE_MODEL)) 143 return (UMATCH_IFACECLASS_GENERIC); 144 145 return (UMATCH_NONE); 146 } 147 148 void 149 cdce_attach(struct device *parent, struct device *self, void *aux) 150 { 151 struct cdce_softc *sc = (struct cdce_softc *)self; 152 struct usb_attach_arg *uaa = aux; 153 int s; 154 struct ifnet *ifp = GET_IFP(sc); 155 struct usbd_device *dev = uaa->device; 156 const struct cdce_type *t; 157 usb_interface_descriptor_t *id; 158 usb_endpoint_descriptor_t *ed; 159 struct usb_cdc_union_descriptor *ud; 160 struct usb_cdc_ethernet_descriptor *ethd; 161 usb_config_descriptor_t *cd; 162 const usb_descriptor_t *desc; 163 struct usbd_desc_iter iter; 164 usb_string_descriptor_t eaddr_str; 165 int i, j, numalts, len; 166 int ctl_ifcno = -1; 167 int data_ifcno = -1; 168 169 sc->cdce_udev = uaa->device; 170 sc->cdce_ctl_iface = uaa->iface; 171 id = usbd_get_interface_descriptor(sc->cdce_ctl_iface); 172 ctl_ifcno = id->bInterfaceNumber; 173 174 t = cdce_lookup(uaa->vendor, uaa->product); 175 if (t) 176 sc->cdce_flags = t->cdce_flags; 177 178 /* Get the data interface no. and capabilities */ 179 ethd = NULL; 180 usbd_desc_iter_init(dev, &iter); 181 desc = usbd_desc_iter_next(&iter); 182 while (desc) { 183 if (desc->bDescriptorType != UDESC_CS_INTERFACE) { 184 desc = usbd_desc_iter_next(&iter); 185 continue; 186 } 187 switch(desc->bDescriptorSubtype) { 188 case UDESCSUB_CDC_UNION: 189 ud = (struct usb_cdc_union_descriptor *)desc; 190 if ((sc->cdce_flags & CDCE_SWAPUNION) == 0 && 191 ud->bMasterInterface == ctl_ifcno) 192 data_ifcno = ud->bSlaveInterface[0]; 193 if ((sc->cdce_flags & CDCE_SWAPUNION) && 194 ud->bSlaveInterface[0] == ctl_ifcno) 195 data_ifcno = ud->bMasterInterface; 196 break; 197 case UDESCSUB_CDC_ENF: 198 if (ethd) { 199 printf("%s: ", sc->cdce_dev.dv_xname); 200 printf("extra ethernet descriptor\n"); 201 return; 202 } 203 ethd = (struct usb_cdc_ethernet_descriptor *)desc; 204 break; 205 } 206 desc = usbd_desc_iter_next(&iter); 207 } 208 209 if (data_ifcno == -1) { 210 DPRINTF(("cdce_attach: no union interface\n")); 211 sc->cdce_data_iface = sc->cdce_ctl_iface; 212 } else { 213 DPRINTF(("cdce_attach: union interface: ctl=%d, data=%d\n", 214 ctl_ifcno, data_ifcno)); 215 for (i = 0; i < uaa->nifaces; i++) { 216 if (usbd_iface_claimed(sc->cdce_udev, i)) 217 continue; 218 id = usbd_get_interface_descriptor(uaa->ifaces[i]); 219 if (id != NULL && id->bInterfaceNumber == data_ifcno) { 220 sc->cdce_data_iface = uaa->ifaces[i]; 221 usbd_claim_iface(sc->cdce_udev, i); 222 } 223 } 224 } 225 226 if (sc->cdce_data_iface == NULL) { 227 printf("%s: no data interface\n", sc->cdce_dev.dv_xname); 228 return; 229 } 230 231 id = usbd_get_interface_descriptor(sc->cdce_ctl_iface); 232 sc->cdce_intr_no = -1; 233 for (i = 0; i < id->bNumEndpoints && sc->cdce_intr_no == -1; i++) { 234 ed = usbd_interface2endpoint_descriptor(sc->cdce_ctl_iface, i); 235 if (!ed) { 236 printf("%s: no descriptor for interrupt endpoint %d\n", 237 sc->cdce_dev.dv_xname, i); 238 return; 239 } 240 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 241 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { 242 sc->cdce_intr_no = ed->bEndpointAddress; 243 sc->cdce_intr_size = sizeof(sc->cdce_intr_buf); 244 } 245 } 246 247 id = usbd_get_interface_descriptor(sc->cdce_data_iface); 248 cd = usbd_get_config_descriptor(sc->cdce_udev); 249 numalts = usbd_get_no_alts(cd, id->bInterfaceNumber); 250 251 for (j = 0; j < numalts; j++) { 252 if (usbd_set_interface(sc->cdce_data_iface, j)) { 253 printf("%s: interface alternate setting %d failed\n", 254 sc->cdce_dev.dv_xname, j); 255 return; 256 } 257 /* Find endpoints. */ 258 id = usbd_get_interface_descriptor(sc->cdce_data_iface); 259 sc->cdce_bulkin_no = sc->cdce_bulkout_no = -1; 260 for (i = 0; i < id->bNumEndpoints; i++) { 261 ed = usbd_interface2endpoint_descriptor( 262 sc->cdce_data_iface, i); 263 if (!ed) { 264 printf("%s: no descriptor for bulk endpoint " 265 "%d\n", sc->cdce_dev.dv_xname, i); 266 return; 267 } 268 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 269 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 270 sc->cdce_bulkin_no = ed->bEndpointAddress; 271 } else if ( 272 UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && 273 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 274 sc->cdce_bulkout_no = ed->bEndpointAddress; 275 } 276 #ifdef CDCE_DEBUG 277 else if ( 278 UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_IN && 279 UE_GET_XFERTYPE(ed->bmAttributes) != UE_INTERRUPT) { 280 printf("%s: unexpected endpoint, ep=%x attr=%x" 281 "\n", sc->cdce_dev.dv_xname, 282 ed->bEndpointAddress, ed->bmAttributes); 283 } 284 #endif 285 } 286 if ((sc->cdce_bulkin_no != -1) && (sc->cdce_bulkout_no != -1)) { 287 DPRINTF(("cdce_attach: intr=0x%x, in=0x%x, out=0x%x\n", 288 sc->cdce_intr_no, sc->cdce_bulkin_no, 289 sc->cdce_bulkout_no)); 290 goto found; 291 } 292 } 293 294 if (sc->cdce_bulkin_no == -1) { 295 printf("%s: could not find data bulk in\n", 296 sc->cdce_dev.dv_xname); 297 return; 298 } 299 if (sc->cdce_bulkout_no == -1 ) { 300 printf("%s: could not find data bulk out\n", 301 sc->cdce_dev.dv_xname); 302 return; 303 } 304 305 found: 306 s = splnet(); 307 308 if (!ethd || usbd_get_string_desc(sc->cdce_udev, ethd->iMacAddress, 0, 309 &eaddr_str, &len)) { 310 ether_fakeaddr(ifp); 311 } else { 312 for (i = 0; i < ETHER_ADDR_LEN * 2; i++) { 313 int c = UGETW(eaddr_str.bString[i]); 314 315 if ('0' <= c && c <= '9') 316 c -= '0'; 317 else if ('A' <= c && c <= 'F') 318 c -= 'A' - 10; 319 else if ('a' <= c && c <= 'f') 320 c -= 'a' - 10; 321 c &= 0xf; 322 if (i % 2 == 0) 323 c <<= 4; 324 sc->cdce_arpcom.ac_enaddr[i / 2] |= c; 325 } 326 } 327 328 printf("%s: address %s\n", sc->cdce_dev.dv_xname, 329 ether_sprintf(sc->cdce_arpcom.ac_enaddr)); 330 331 ifp->if_softc = sc; 332 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 333 ifp->if_ioctl = cdce_ioctl; 334 ifp->if_start = cdce_start; 335 ifp->if_watchdog = cdce_watchdog; 336 strlcpy(ifp->if_xname, sc->cdce_dev.dv_xname, IFNAMSIZ); 337 338 if_attach(ifp); 339 ether_ifattach(ifp); 340 341 sc->cdce_attached = 1; 342 splx(s); 343 } 344 345 int 346 cdce_detach(struct device *self, int flags) 347 { 348 struct cdce_softc *sc = (struct cdce_softc *)self; 349 struct ifnet *ifp = GET_IFP(sc); 350 int s; 351 352 if (!sc->cdce_attached) 353 return (0); 354 355 s = splusb(); 356 357 if (ifp->if_flags & IFF_RUNNING) 358 cdce_stop(sc); 359 360 if (ifp->if_softc != NULL) { 361 ether_ifdetach(ifp); 362 if_detach(ifp); 363 } 364 365 sc->cdce_attached = 0; 366 splx(s); 367 368 return (0); 369 } 370 371 void 372 cdce_start(struct ifnet *ifp) 373 { 374 struct cdce_softc *sc = ifp->if_softc; 375 struct mbuf *m_head = NULL; 376 377 if (usbd_is_dying(sc->cdce_udev) || ifq_is_oactive(&ifp->if_snd)) 378 return; 379 380 m_head = ifq_deq_begin(&ifp->if_snd); 381 if (m_head == NULL) 382 return; 383 384 if (cdce_encap(sc, m_head, 0)) { 385 ifq_deq_rollback(&ifp->if_snd, m_head); 386 ifq_set_oactive(&ifp->if_snd); 387 return; 388 } 389 390 ifq_deq_commit(&ifp->if_snd, m_head); 391 392 #if NBPFILTER > 0 393 if (ifp->if_bpf) 394 bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT); 395 #endif 396 397 ifq_set_oactive(&ifp->if_snd); 398 399 ifp->if_timer = 6; 400 } 401 402 int 403 cdce_encap(struct cdce_softc *sc, struct mbuf *m, int idx) 404 { 405 struct cdce_chain *c; 406 usbd_status err; 407 int extra = 0; 408 409 c = &sc->cdce_cdata.cdce_tx_chain[idx]; 410 411 m_copydata(m, 0, m->m_pkthdr.len, c->cdce_buf); 412 if (sc->cdce_flags & CDCE_CRC32) { 413 /* Some devices want a 32-bit CRC appended to every frame */ 414 u_int32_t crc; 415 416 crc = cdce_crc32(c->cdce_buf, m->m_pkthdr.len); 417 bcopy(&crc, c->cdce_buf + m->m_pkthdr.len, 4); 418 extra = 4; 419 } 420 c->cdce_mbuf = m; 421 422 usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkout_pipe, c, c->cdce_buf, 423 m->m_pkthdr.len + extra, USBD_FORCE_SHORT_XFER | USBD_NO_COPY, 424 10000, cdce_txeof); 425 err = usbd_transfer(c->cdce_xfer); 426 if (err != USBD_IN_PROGRESS) { 427 cdce_stop(sc); 428 return (EIO); 429 } 430 431 sc->cdce_cdata.cdce_tx_cnt++; 432 433 return (0); 434 } 435 436 void 437 cdce_stop(struct cdce_softc *sc) 438 { 439 usbd_status err; 440 struct ifnet *ifp = GET_IFP(sc); 441 int i; 442 443 ifp->if_timer = 0; 444 ifp->if_flags &= ~IFF_RUNNING; 445 ifq_clr_oactive(&ifp->if_snd); 446 447 if (sc->cdce_bulkin_pipe != NULL) { 448 usbd_abort_pipe(sc->cdce_bulkin_pipe); 449 err = usbd_close_pipe(sc->cdce_bulkin_pipe); 450 if (err) 451 printf("%s: close rx pipe failed: %s\n", 452 sc->cdce_dev.dv_xname, usbd_errstr(err)); 453 sc->cdce_bulkin_pipe = NULL; 454 } 455 456 if (sc->cdce_bulkout_pipe != NULL) { 457 usbd_abort_pipe(sc->cdce_bulkout_pipe); 458 err = usbd_close_pipe(sc->cdce_bulkout_pipe); 459 if (err) 460 printf("%s: close tx pipe failed: %s\n", 461 sc->cdce_dev.dv_xname, usbd_errstr(err)); 462 sc->cdce_bulkout_pipe = NULL; 463 } 464 465 if (sc->cdce_intr_pipe != NULL) { 466 usbd_abort_pipe(sc->cdce_intr_pipe); 467 err = usbd_close_pipe(sc->cdce_intr_pipe); 468 if (err) 469 printf("%s: close interrupt pipe failed: %s\n", 470 sc->cdce_dev.dv_xname, usbd_errstr(err)); 471 sc->cdce_intr_pipe = NULL; 472 } 473 474 for (i = 0; i < CDCE_RX_LIST_CNT; i++) { 475 if (sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf != NULL) { 476 m_freem(sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf); 477 sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf = NULL; 478 } 479 if (sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer != NULL) { 480 usbd_free_xfer(sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer); 481 sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer = NULL; 482 } 483 } 484 485 for (i = 0; i < CDCE_TX_LIST_CNT; i++) { 486 if (sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf != NULL) { 487 m_freem(sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf); 488 sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf = NULL; 489 } 490 if (sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer != NULL) { 491 usbd_free_xfer( 492 sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer); 493 sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer = NULL; 494 } 495 } 496 } 497 498 int 499 cdce_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 500 { 501 struct cdce_softc *sc = ifp->if_softc; 502 int s, error = 0; 503 504 if (usbd_is_dying(sc->cdce_udev)) 505 return (EIO); 506 507 s = splnet(); 508 509 switch(command) { 510 case SIOCSIFADDR: 511 ifp->if_flags |= IFF_UP; 512 if (!(ifp->if_flags & IFF_RUNNING)) 513 cdce_init(sc); 514 break; 515 516 case SIOCSIFFLAGS: 517 if (ifp->if_flags & IFF_UP) { 518 if (ifp->if_flags & IFF_RUNNING) 519 error = ENETRESET; 520 else 521 cdce_init(sc); 522 } else { 523 if (ifp->if_flags & IFF_RUNNING) 524 cdce_stop(sc); 525 } 526 break; 527 528 default: 529 error = ether_ioctl(ifp, &sc->cdce_arpcom, command, data); 530 break; 531 } 532 533 if (error == ENETRESET) 534 error = 0; 535 536 splx(s); 537 return (error); 538 } 539 540 void 541 cdce_watchdog(struct ifnet *ifp) 542 { 543 struct cdce_softc *sc = ifp->if_softc; 544 545 if (usbd_is_dying(sc->cdce_udev)) 546 return; 547 548 ifp->if_oerrors++; 549 printf("%s: watchdog timeout\n", sc->cdce_dev.dv_xname); 550 } 551 552 void 553 cdce_init(void *xsc) 554 { 555 struct cdce_softc *sc = xsc; 556 struct ifnet *ifp = GET_IFP(sc); 557 struct cdce_chain *c; 558 usbd_status err; 559 int s, i; 560 561 s = splnet(); 562 563 if (sc->cdce_intr_no != -1 && sc->cdce_intr_pipe == NULL) { 564 DPRINTFN(1, ("cdce_init: establish interrupt pipe\n")); 565 err = usbd_open_pipe_intr(sc->cdce_ctl_iface, sc->cdce_intr_no, 566 USBD_SHORT_XFER_OK, &sc->cdce_intr_pipe, sc, 567 &sc->cdce_intr_buf, sc->cdce_intr_size, cdce_intr, 568 USBD_DEFAULT_INTERVAL); 569 if (err) { 570 printf("%s: open interrupt pipe failed: %s\n", 571 sc->cdce_dev.dv_xname, usbd_errstr(err)); 572 splx(s); 573 return; 574 } 575 } 576 577 if (cdce_tx_list_init(sc) == ENOBUFS) { 578 printf("%s: tx list init failed\n", sc->cdce_dev.dv_xname); 579 splx(s); 580 return; 581 } 582 583 if (cdce_rx_list_init(sc) == ENOBUFS) { 584 printf("%s: rx list init failed\n", sc->cdce_dev.dv_xname); 585 splx(s); 586 return; 587 } 588 589 /* Maybe set multicast / broadcast here??? */ 590 591 err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkin_no, 592 USBD_EXCLUSIVE_USE, &sc->cdce_bulkin_pipe); 593 if (err) { 594 printf("%s: open rx pipe failed: %s\n", sc->cdce_dev.dv_xname, 595 usbd_errstr(err)); 596 splx(s); 597 return; 598 } 599 600 err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkout_no, 601 USBD_EXCLUSIVE_USE, &sc->cdce_bulkout_pipe); 602 if (err) { 603 printf("%s: open tx pipe failed: %s\n", sc->cdce_dev.dv_xname, 604 usbd_errstr(err)); 605 splx(s); 606 return; 607 } 608 609 for (i = 0; i < CDCE_RX_LIST_CNT; i++) { 610 c = &sc->cdce_cdata.cdce_rx_chain[i]; 611 usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkin_pipe, c, 612 c->cdce_buf, CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, 613 USBD_NO_TIMEOUT, cdce_rxeof); 614 usbd_transfer(c->cdce_xfer); 615 } 616 617 ifp->if_flags |= IFF_RUNNING; 618 ifq_clr_oactive(&ifp->if_snd); 619 620 splx(s); 621 } 622 623 int 624 cdce_newbuf(struct cdce_softc *sc, struct cdce_chain *c, struct mbuf *m) 625 { 626 struct mbuf *m_new = NULL; 627 628 if (m == NULL) { 629 MGETHDR(m_new, M_DONTWAIT, MT_DATA); 630 if (m_new == NULL) { 631 printf("%s: no memory for rx list " 632 "-- packet dropped!\n", sc->cdce_dev.dv_xname); 633 return (ENOBUFS); 634 } 635 MCLGET(m_new, M_DONTWAIT); 636 if (!(m_new->m_flags & M_EXT)) { 637 printf("%s: no memory for rx list " 638 "-- packet dropped!\n", sc->cdce_dev.dv_xname); 639 m_freem(m_new); 640 return (ENOBUFS); 641 } 642 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; 643 } else { 644 m_new = m; 645 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; 646 m_new->m_data = m_new->m_ext.ext_buf; 647 } 648 649 m_adj(m_new, ETHER_ALIGN); 650 c->cdce_mbuf = m_new; 651 return (0); 652 } 653 654 int 655 cdce_rx_list_init(struct cdce_softc *sc) 656 { 657 struct cdce_cdata *cd; 658 struct cdce_chain *c; 659 int i; 660 661 cd = &sc->cdce_cdata; 662 for (i = 0; i < CDCE_RX_LIST_CNT; i++) { 663 c = &cd->cdce_rx_chain[i]; 664 c->cdce_sc = sc; 665 c->cdce_idx = i; 666 if (cdce_newbuf(sc, c, NULL) == ENOBUFS) 667 return (ENOBUFS); 668 if (c->cdce_xfer == NULL) { 669 c->cdce_xfer = usbd_alloc_xfer(sc->cdce_udev); 670 if (c->cdce_xfer == NULL) 671 return (ENOBUFS); 672 c->cdce_buf = usbd_alloc_buffer(c->cdce_xfer, 673 CDCE_BUFSZ); 674 if (c->cdce_buf == NULL) 675 return (ENOBUFS); 676 } 677 } 678 679 return (0); 680 } 681 682 int 683 cdce_tx_list_init(struct cdce_softc *sc) 684 { 685 struct cdce_cdata *cd; 686 struct cdce_chain *c; 687 int i; 688 689 cd = &sc->cdce_cdata; 690 for (i = 0; i < CDCE_TX_LIST_CNT; i++) { 691 c = &cd->cdce_tx_chain[i]; 692 c->cdce_sc = sc; 693 c->cdce_idx = i; 694 c->cdce_mbuf = NULL; 695 if (c->cdce_xfer == NULL) { 696 c->cdce_xfer = usbd_alloc_xfer(sc->cdce_udev); 697 if (c->cdce_xfer == NULL) 698 return (ENOBUFS); 699 c->cdce_buf = usbd_alloc_buffer(c->cdce_xfer, 700 CDCE_BUFSZ); 701 if (c->cdce_buf == NULL) 702 return (ENOBUFS); 703 } 704 } 705 706 return (0); 707 } 708 709 void 710 cdce_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status) 711 { 712 struct cdce_chain *c = priv; 713 struct cdce_softc *sc = c->cdce_sc; 714 struct ifnet *ifp = GET_IFP(sc); 715 struct mbuf *m; 716 struct mbuf_list ml = MBUF_LIST_INITIALIZER(); 717 int total_len = 0; 718 int s; 719 720 if (usbd_is_dying(sc->cdce_udev) || !(ifp->if_flags & IFF_RUNNING)) 721 return; 722 723 if (status != USBD_NORMAL_COMPLETION) { 724 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) 725 return; 726 if (sc->cdce_rxeof_errors == 0) 727 printf("%s: usb error on rx: %s\n", 728 sc->cdce_dev.dv_xname, usbd_errstr(status)); 729 if (status == USBD_STALLED) 730 usbd_clear_endpoint_stall_async(sc->cdce_bulkin_pipe); 731 DELAY(sc->cdce_rxeof_errors * 10000); 732 if (sc->cdce_rxeof_errors++ > 10) { 733 printf("%s: too many errors, disabling\n", 734 sc->cdce_dev.dv_xname); 735 usbd_deactivate(sc->cdce_udev); 736 return; 737 } 738 goto done; 739 } 740 741 sc->cdce_rxeof_errors = 0; 742 743 usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); 744 if (sc->cdce_flags & CDCE_CRC32) 745 total_len -= 4; /* Strip off added CRC */ 746 if (total_len <= 1) 747 goto done; 748 749 m = c->cdce_mbuf; 750 memcpy(mtod(m, char *), c->cdce_buf, total_len); 751 752 if (total_len < sizeof(struct ether_header)) { 753 ifp->if_ierrors++; 754 goto done; 755 } 756 757 m->m_pkthdr.len = m->m_len = total_len; 758 ml_enqueue(&ml, m); 759 760 if (cdce_newbuf(sc, c, NULL) == ENOBUFS) { 761 ifp->if_ierrors++; 762 goto done; 763 } 764 765 s = splnet(); 766 if_input(ifp, &ml); 767 splx(s); 768 769 done: 770 /* Setup new transfer. */ 771 usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkin_pipe, c, c->cdce_buf, 772 CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT, 773 cdce_rxeof); 774 usbd_transfer(c->cdce_xfer); 775 } 776 777 void 778 cdce_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status) 779 { 780 struct cdce_chain *c = priv; 781 struct cdce_softc *sc = c->cdce_sc; 782 struct ifnet *ifp = GET_IFP(sc); 783 usbd_status err; 784 int s; 785 786 if (usbd_is_dying(sc->cdce_udev)) 787 return; 788 789 s = splnet(); 790 791 ifp->if_timer = 0; 792 ifq_clr_oactive(&ifp->if_snd); 793 794 if (status != USBD_NORMAL_COMPLETION) { 795 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { 796 splx(s); 797 return; 798 } 799 ifp->if_oerrors++; 800 printf("%s: usb error on tx: %s\n", sc->cdce_dev.dv_xname, 801 usbd_errstr(status)); 802 if (status == USBD_STALLED) 803 usbd_clear_endpoint_stall_async(sc->cdce_bulkout_pipe); 804 splx(s); 805 return; 806 } 807 808 usbd_get_xfer_status(c->cdce_xfer, NULL, NULL, NULL, &err); 809 810 if (c->cdce_mbuf != NULL) { 811 m_freem(c->cdce_mbuf); 812 c->cdce_mbuf = NULL; 813 } 814 815 if (err) 816 ifp->if_oerrors++; 817 else 818 ifp->if_opackets++; 819 820 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) 821 cdce_start(ifp); 822 823 splx(s); 824 } 825 826 void 827 cdce_intr(struct usbd_xfer *xfer, void *addr, usbd_status status) 828 { 829 struct cdce_softc *sc = addr; 830 struct usb_cdc_notification *buf = &sc->cdce_intr_buf; 831 struct usb_cdc_connection_speed *speed; 832 u_int32_t count; 833 834 if (status == USBD_CANCELLED) 835 return; 836 837 if (status != USBD_NORMAL_COMPLETION) { 838 DPRINTFN(2, ("cdce_intr: status=%d\n", status)); 839 if (status == USBD_STALLED) 840 usbd_clear_endpoint_stall_async(sc->cdce_intr_pipe); 841 return; 842 } 843 844 usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL); 845 846 if (buf->bmRequestType == UCDC_NOTIFICATION) { 847 switch (buf->bNotification) { 848 case UCDC_N_NETWORK_CONNECTION: 849 DPRINTFN(1, ("cdce_intr: network %s\n", 850 UGETW(buf->wValue) ? "connected" : "disconnected")); 851 break; 852 case UCDC_N_CONNECTION_SPEED_CHANGE: 853 speed = (struct usb_cdc_connection_speed *)&buf->data; 854 DPRINTFN(1, ("cdce_intr: up=%d, down=%d\n", 855 UGETDW(speed->dwUSBitRate), 856 UGETDW(speed->dwDSBitRate))); 857 break; 858 default: 859 DPRINTF(("cdce_intr: bNotification 0x%x\n", 860 buf->bNotification)); 861 } 862 } 863 #ifdef CDCE_DEBUG 864 else { 865 printf("cdce_intr: bmRequestType=%d ", buf->bmRequestType); 866 printf("wValue=%d wIndex=%d wLength=%d\n", UGETW(buf->wValue), 867 UGETW(buf->wIndex), UGETW(buf->wLength)); 868 } 869 #endif 870 } 871 872 873 /* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or 874 * code or tables extracted from it, as desired without restriction. 875 */ 876 877 static uint32_t cdce_crc32_tab[] = { 878 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 879 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 880 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 881 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 882 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 883 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 884 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 885 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 886 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 887 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 888 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 889 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 890 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 891 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 892 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 893 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 894 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 895 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 896 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 897 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 898 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 899 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 900 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 901 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 902 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 903 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 904 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 905 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 906 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 907 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 908 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 909 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 910 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 911 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 912 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 913 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 914 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 915 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 916 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 917 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 918 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 919 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 920 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d 921 }; 922 923 uint32_t 924 cdce_crc32(const void *buf, size_t size) 925 { 926 const uint8_t *p; 927 uint32_t crc; 928 929 p = buf; 930 crc = ~0U; 931 932 while (size--) 933 crc = cdce_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); 934 935 return (htole32(crc) ^ ~0U); 936 } 937