1 /* $OpenBSD: if_cdce.c,v 1.76 2019/11/14 13:50:55 abieber 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 92 const struct cdce_type cdce_devs[] = { 93 {{ USB_VENDOR_ACERLABS, USB_PRODUCT_ACERLABS_M5632 }, 0 }, 94 {{ USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2501 }, 0 }, 95 {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5500 }, CDCE_CRC32 }, 96 {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_A300 }, CDCE_CRC32 }, 97 {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5600 }, CDCE_CRC32 }, 98 {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_C700 }, CDCE_CRC32 }, 99 {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_C750 }, CDCE_CRC32 }, 100 {{ USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_USBLAN }, CDCE_CRC32 }, 101 {{ USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_USBLAN2 }, CDCE_CRC32 }, 102 {{ USB_VENDOR_GMATE, USB_PRODUCT_GMATE_YP3X00 }, 0 }, 103 {{ USB_VENDOR_COMPAQ, USB_PRODUCT_COMPAQ_IPAQLINUX }, 0 }, 104 {{ USB_VENDOR_AMBIT, USB_PRODUCT_AMBIT_NTL_250 }, CDCE_SWAPUNION }, 105 }; 106 #define cdce_lookup(v, p) \ 107 ((const struct cdce_type *)usb_lookup(cdce_devs, v, p)) 108 109 int cdce_match(struct device *, void *, void *); 110 void cdce_attach(struct device *, struct device *, void *); 111 int cdce_detach(struct device *, int); 112 113 struct cfdriver cdce_cd = { 114 NULL, "cdce", DV_IFNET 115 }; 116 117 const struct cfattach cdce_ca = { 118 sizeof(struct cdce_softc), cdce_match, cdce_attach, cdce_detach 119 }; 120 121 int 122 cdce_match(struct device *parent, void *match, void *aux) 123 { 124 struct usb_attach_arg *uaa = aux; 125 usb_interface_descriptor_t *id; 126 127 if (uaa->iface == NULL) 128 return (UMATCH_NONE); 129 130 id = usbd_get_interface_descriptor(uaa->iface); 131 if (id == NULL) 132 return (UMATCH_NONE); 133 134 if (cdce_lookup(uaa->vendor, uaa->product) != NULL) 135 return (UMATCH_VENDOR_PRODUCT); 136 137 if (id->bInterfaceClass == UICLASS_CDC && 138 (id->bInterfaceSubClass == 139 UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL || 140 id->bInterfaceSubClass == UISUBCLASS_MOBILE_DIRECT_LINE_MODEL)) 141 return (UMATCH_IFACECLASS_GENERIC); 142 143 return (UMATCH_NONE); 144 } 145 146 void 147 cdce_attach(struct device *parent, struct device *self, void *aux) 148 { 149 struct cdce_softc *sc = (struct cdce_softc *)self; 150 struct usb_attach_arg *uaa = aux; 151 int s; 152 struct ifnet *ifp = GET_IFP(sc); 153 struct usbd_device *dev = uaa->device; 154 const struct cdce_type *t; 155 usb_interface_descriptor_t *id; 156 usb_endpoint_descriptor_t *ed; 157 struct usb_cdc_union_descriptor *ud; 158 struct usb_cdc_ethernet_descriptor *ethd; 159 usb_config_descriptor_t *cd; 160 const usb_descriptor_t *desc; 161 struct usbd_desc_iter iter; 162 usb_string_descriptor_t eaddr_str; 163 int i, j, numalts, len; 164 int ctl_ifcno = -1; 165 int data_ifcno = -1; 166 167 sc->cdce_udev = uaa->device; 168 sc->cdce_ctl_iface = uaa->iface; 169 id = usbd_get_interface_descriptor(sc->cdce_ctl_iface); 170 ctl_ifcno = id->bInterfaceNumber; 171 172 t = cdce_lookup(uaa->vendor, uaa->product); 173 if (t) 174 sc->cdce_flags = t->cdce_flags; 175 176 /* Get the data interface no. and capabilities */ 177 ethd = NULL; 178 usbd_desc_iter_init(dev, &iter); 179 desc = usbd_desc_iter_next(&iter); 180 while (desc) { 181 if (desc->bDescriptorType != UDESC_CS_INTERFACE) { 182 desc = usbd_desc_iter_next(&iter); 183 continue; 184 } 185 switch(desc->bDescriptorSubtype) { 186 case UDESCSUB_CDC_UNION: 187 ud = (struct usb_cdc_union_descriptor *)desc; 188 if ((sc->cdce_flags & CDCE_SWAPUNION) == 0 && 189 ud->bMasterInterface == ctl_ifcno) 190 data_ifcno = ud->bSlaveInterface[0]; 191 if ((sc->cdce_flags & CDCE_SWAPUNION) && 192 ud->bSlaveInterface[0] == ctl_ifcno) 193 data_ifcno = ud->bMasterInterface; 194 break; 195 case UDESCSUB_CDC_ENF: 196 if (ethd) { 197 printf("%s: ", sc->cdce_dev.dv_xname); 198 printf("extra ethernet descriptor\n"); 199 return; 200 } 201 ethd = (struct usb_cdc_ethernet_descriptor *)desc; 202 break; 203 } 204 desc = usbd_desc_iter_next(&iter); 205 } 206 207 if (data_ifcno == -1) { 208 DPRINTF(("cdce_attach: no union interface\n")); 209 sc->cdce_data_iface = sc->cdce_ctl_iface; 210 } else { 211 DPRINTF(("cdce_attach: union interface: ctl=%d, data=%d\n", 212 ctl_ifcno, data_ifcno)); 213 for (i = 0; i < uaa->nifaces; i++) { 214 if (usbd_iface_claimed(sc->cdce_udev, i)) 215 continue; 216 id = usbd_get_interface_descriptor(uaa->ifaces[i]); 217 if (id != NULL && id->bInterfaceNumber == data_ifcno) { 218 sc->cdce_data_iface = uaa->ifaces[i]; 219 usbd_claim_iface(sc->cdce_udev, i); 220 } 221 } 222 } 223 224 if (sc->cdce_data_iface == NULL) { 225 printf("%s: no data interface\n", sc->cdce_dev.dv_xname); 226 return; 227 } 228 229 id = usbd_get_interface_descriptor(sc->cdce_ctl_iface); 230 sc->cdce_intr_no = -1; 231 for (i = 0; i < id->bNumEndpoints && sc->cdce_intr_no == -1; i++) { 232 ed = usbd_interface2endpoint_descriptor(sc->cdce_ctl_iface, i); 233 if (!ed) { 234 printf("%s: no descriptor for interrupt endpoint %d\n", 235 sc->cdce_dev.dv_xname, i); 236 return; 237 } 238 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 239 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { 240 sc->cdce_intr_no = ed->bEndpointAddress; 241 sc->cdce_intr_size = sizeof(sc->cdce_intr_buf); 242 } 243 } 244 245 id = usbd_get_interface_descriptor(sc->cdce_data_iface); 246 cd = usbd_get_config_descriptor(sc->cdce_udev); 247 numalts = usbd_get_no_alts(cd, id->bInterfaceNumber); 248 249 for (j = 0; j < numalts; j++) { 250 if (usbd_set_interface(sc->cdce_data_iface, j)) { 251 printf("%s: interface alternate setting %d failed\n", 252 sc->cdce_dev.dv_xname, j); 253 return; 254 } 255 /* Find endpoints. */ 256 id = usbd_get_interface_descriptor(sc->cdce_data_iface); 257 sc->cdce_bulkin_no = sc->cdce_bulkout_no = -1; 258 for (i = 0; i < id->bNumEndpoints; i++) { 259 ed = usbd_interface2endpoint_descriptor( 260 sc->cdce_data_iface, i); 261 if (!ed) { 262 printf("%s: no descriptor for bulk endpoint " 263 "%d\n", sc->cdce_dev.dv_xname, i); 264 return; 265 } 266 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 267 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 268 sc->cdce_bulkin_no = ed->bEndpointAddress; 269 } else if ( 270 UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && 271 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 272 sc->cdce_bulkout_no = ed->bEndpointAddress; 273 } 274 #ifdef CDCE_DEBUG 275 else if ( 276 UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_IN && 277 UE_GET_XFERTYPE(ed->bmAttributes) != UE_INTERRUPT) { 278 printf("%s: unexpected endpoint, ep=%x attr=%x" 279 "\n", sc->cdce_dev.dv_xname, 280 ed->bEndpointAddress, ed->bmAttributes); 281 } 282 #endif 283 } 284 if ((sc->cdce_bulkin_no != -1) && (sc->cdce_bulkout_no != -1)) { 285 DPRINTF(("cdce_attach: intr=0x%x, in=0x%x, out=0x%x\n", 286 sc->cdce_intr_no, sc->cdce_bulkin_no, 287 sc->cdce_bulkout_no)); 288 goto found; 289 } 290 } 291 292 if (sc->cdce_bulkin_no == -1) { 293 printf("%s: could not find data bulk in\n", 294 sc->cdce_dev.dv_xname); 295 return; 296 } 297 if (sc->cdce_bulkout_no == -1 ) { 298 printf("%s: could not find data bulk out\n", 299 sc->cdce_dev.dv_xname); 300 return; 301 } 302 303 found: 304 s = splnet(); 305 306 if (!ethd || usbd_get_string_desc(sc->cdce_udev, ethd->iMacAddress, 0, 307 &eaddr_str, &len)) { 308 ether_fakeaddr(ifp); 309 } else { 310 for (i = 0; i < ETHER_ADDR_LEN * 2; i++) { 311 int c = UGETW(eaddr_str.bString[i]); 312 313 if ('0' <= c && c <= '9') 314 c -= '0'; 315 else if ('A' <= c && c <= 'F') 316 c -= 'A' - 10; 317 else if ('a' <= c && c <= 'f') 318 c -= 'a' - 10; 319 c &= 0xf; 320 if (i % 2 == 0) 321 c <<= 4; 322 sc->cdce_arpcom.ac_enaddr[i / 2] |= c; 323 } 324 } 325 326 printf("%s: address %s\n", sc->cdce_dev.dv_xname, 327 ether_sprintf(sc->cdce_arpcom.ac_enaddr)); 328 329 ifp->if_softc = sc; 330 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 331 ifp->if_ioctl = cdce_ioctl; 332 ifp->if_start = cdce_start; 333 ifp->if_watchdog = cdce_watchdog; 334 strlcpy(ifp->if_xname, sc->cdce_dev.dv_xname, IFNAMSIZ); 335 336 if_attach(ifp); 337 ether_ifattach(ifp); 338 339 sc->cdce_attached = 1; 340 splx(s); 341 } 342 343 int 344 cdce_detach(struct device *self, int flags) 345 { 346 struct cdce_softc *sc = (struct cdce_softc *)self; 347 struct ifnet *ifp = GET_IFP(sc); 348 int s; 349 350 if (!sc->cdce_attached) 351 return (0); 352 353 s = splusb(); 354 355 if (ifp->if_flags & IFF_RUNNING) 356 cdce_stop(sc); 357 358 if (ifp->if_softc != NULL) { 359 ether_ifdetach(ifp); 360 if_detach(ifp); 361 } 362 363 sc->cdce_attached = 0; 364 splx(s); 365 366 return (0); 367 } 368 369 void 370 cdce_start(struct ifnet *ifp) 371 { 372 struct cdce_softc *sc = ifp->if_softc; 373 struct mbuf *m_head = NULL; 374 375 if (usbd_is_dying(sc->cdce_udev) || ifq_is_oactive(&ifp->if_snd)) 376 return; 377 378 m_head = ifq_deq_begin(&ifp->if_snd); 379 if (m_head == NULL) 380 return; 381 382 if (cdce_encap(sc, m_head, 0)) { 383 ifq_deq_rollback(&ifp->if_snd, m_head); 384 ifq_set_oactive(&ifp->if_snd); 385 return; 386 } 387 388 ifq_deq_commit(&ifp->if_snd, m_head); 389 390 #if NBPFILTER > 0 391 if (ifp->if_bpf) 392 bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT); 393 #endif 394 395 ifq_set_oactive(&ifp->if_snd); 396 397 ifp->if_timer = 6; 398 } 399 400 int 401 cdce_encap(struct cdce_softc *sc, struct mbuf *m, int idx) 402 { 403 struct cdce_chain *c; 404 usbd_status err; 405 int extra = 0; 406 407 c = &sc->cdce_cdata.cdce_tx_chain[idx]; 408 409 m_copydata(m, 0, m->m_pkthdr.len, c->cdce_buf); 410 if (sc->cdce_flags & CDCE_CRC32) { 411 /* Some devices want a 32-bit CRC appended to every frame */ 412 u_int32_t crc; 413 414 crc = ether_crc32_le(c->cdce_buf, m->m_pkthdr.len) ^ ~0U; 415 bcopy(&crc, c->cdce_buf + m->m_pkthdr.len, 4); 416 extra = 4; 417 } 418 c->cdce_mbuf = m; 419 420 usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkout_pipe, c, c->cdce_buf, 421 m->m_pkthdr.len + extra, USBD_FORCE_SHORT_XFER | USBD_NO_COPY, 422 10000, cdce_txeof); 423 err = usbd_transfer(c->cdce_xfer); 424 if (err != USBD_IN_PROGRESS) { 425 cdce_stop(sc); 426 return (EIO); 427 } 428 429 sc->cdce_cdata.cdce_tx_cnt++; 430 431 return (0); 432 } 433 434 void 435 cdce_stop(struct cdce_softc *sc) 436 { 437 usbd_status err; 438 struct ifnet *ifp = GET_IFP(sc); 439 int i; 440 441 ifp->if_timer = 0; 442 ifp->if_flags &= ~IFF_RUNNING; 443 ifq_clr_oactive(&ifp->if_snd); 444 445 if (sc->cdce_bulkin_pipe != NULL) { 446 usbd_abort_pipe(sc->cdce_bulkin_pipe); 447 err = usbd_close_pipe(sc->cdce_bulkin_pipe); 448 if (err) 449 printf("%s: close rx pipe failed: %s\n", 450 sc->cdce_dev.dv_xname, usbd_errstr(err)); 451 sc->cdce_bulkin_pipe = NULL; 452 } 453 454 if (sc->cdce_bulkout_pipe != NULL) { 455 usbd_abort_pipe(sc->cdce_bulkout_pipe); 456 err = usbd_close_pipe(sc->cdce_bulkout_pipe); 457 if (err) 458 printf("%s: close tx pipe failed: %s\n", 459 sc->cdce_dev.dv_xname, usbd_errstr(err)); 460 sc->cdce_bulkout_pipe = NULL; 461 } 462 463 if (sc->cdce_intr_pipe != NULL) { 464 usbd_abort_pipe(sc->cdce_intr_pipe); 465 err = usbd_close_pipe(sc->cdce_intr_pipe); 466 if (err) 467 printf("%s: close interrupt pipe failed: %s\n", 468 sc->cdce_dev.dv_xname, usbd_errstr(err)); 469 sc->cdce_intr_pipe = NULL; 470 } 471 472 for (i = 0; i < CDCE_RX_LIST_CNT; i++) { 473 if (sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf != NULL) { 474 m_freem(sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf); 475 sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf = NULL; 476 } 477 if (sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer != NULL) { 478 usbd_free_xfer(sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer); 479 sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer = NULL; 480 } 481 } 482 483 for (i = 0; i < CDCE_TX_LIST_CNT; i++) { 484 if (sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf != NULL) { 485 m_freem(sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf); 486 sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf = NULL; 487 } 488 if (sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer != NULL) { 489 usbd_free_xfer( 490 sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer); 491 sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer = NULL; 492 } 493 } 494 } 495 496 int 497 cdce_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 498 { 499 struct cdce_softc *sc = ifp->if_softc; 500 int s, error = 0; 501 502 if (usbd_is_dying(sc->cdce_udev)) 503 return ENXIO; 504 505 s = splnet(); 506 507 switch(command) { 508 case SIOCSIFADDR: 509 ifp->if_flags |= IFF_UP; 510 if (!(ifp->if_flags & IFF_RUNNING)) 511 cdce_init(sc); 512 break; 513 514 case SIOCSIFFLAGS: 515 if (ifp->if_flags & IFF_UP) { 516 if (ifp->if_flags & IFF_RUNNING) 517 error = ENETRESET; 518 else 519 cdce_init(sc); 520 } else { 521 if (ifp->if_flags & IFF_RUNNING) 522 cdce_stop(sc); 523 } 524 break; 525 526 default: 527 error = ether_ioctl(ifp, &sc->cdce_arpcom, command, data); 528 break; 529 } 530 531 if (error == ENETRESET) 532 error = 0; 533 534 splx(s); 535 return (error); 536 } 537 538 void 539 cdce_watchdog(struct ifnet *ifp) 540 { 541 struct cdce_softc *sc = ifp->if_softc; 542 543 if (usbd_is_dying(sc->cdce_udev)) 544 return; 545 546 ifp->if_oerrors++; 547 printf("%s: watchdog timeout\n", sc->cdce_dev.dv_xname); 548 } 549 550 void 551 cdce_init(void *xsc) 552 { 553 struct cdce_softc *sc = xsc; 554 struct ifnet *ifp = GET_IFP(sc); 555 struct cdce_chain *c; 556 usbd_status err; 557 int s, i; 558 559 s = splnet(); 560 561 if (sc->cdce_intr_no != -1 && sc->cdce_intr_pipe == NULL) { 562 DPRINTFN(1, ("cdce_init: establish interrupt pipe\n")); 563 err = usbd_open_pipe_intr(sc->cdce_ctl_iface, sc->cdce_intr_no, 564 USBD_SHORT_XFER_OK, &sc->cdce_intr_pipe, sc, 565 &sc->cdce_intr_buf, sc->cdce_intr_size, cdce_intr, 566 USBD_DEFAULT_INTERVAL); 567 if (err) { 568 printf("%s: open interrupt pipe failed: %s\n", 569 sc->cdce_dev.dv_xname, usbd_errstr(err)); 570 splx(s); 571 return; 572 } 573 } 574 575 if (cdce_tx_list_init(sc) == ENOBUFS) { 576 printf("%s: tx list init failed\n", sc->cdce_dev.dv_xname); 577 splx(s); 578 return; 579 } 580 581 if (cdce_rx_list_init(sc) == ENOBUFS) { 582 printf("%s: rx list init failed\n", sc->cdce_dev.dv_xname); 583 splx(s); 584 return; 585 } 586 587 /* Maybe set multicast / broadcast here??? */ 588 589 err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkin_no, 590 USBD_EXCLUSIVE_USE, &sc->cdce_bulkin_pipe); 591 if (err) { 592 printf("%s: open rx pipe failed: %s\n", sc->cdce_dev.dv_xname, 593 usbd_errstr(err)); 594 splx(s); 595 return; 596 } 597 598 err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkout_no, 599 USBD_EXCLUSIVE_USE, &sc->cdce_bulkout_pipe); 600 if (err) { 601 printf("%s: open tx pipe failed: %s\n", sc->cdce_dev.dv_xname, 602 usbd_errstr(err)); 603 splx(s); 604 return; 605 } 606 607 for (i = 0; i < CDCE_RX_LIST_CNT; i++) { 608 c = &sc->cdce_cdata.cdce_rx_chain[i]; 609 usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkin_pipe, c, 610 c->cdce_buf, CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, 611 USBD_NO_TIMEOUT, cdce_rxeof); 612 usbd_transfer(c->cdce_xfer); 613 } 614 615 ifp->if_flags |= IFF_RUNNING; 616 ifq_clr_oactive(&ifp->if_snd); 617 618 splx(s); 619 } 620 621 int 622 cdce_newbuf(struct cdce_softc *sc, struct cdce_chain *c, struct mbuf *m) 623 { 624 struct mbuf *m_new = NULL; 625 626 if (m == NULL) { 627 MGETHDR(m_new, M_DONTWAIT, MT_DATA); 628 if (m_new == NULL) { 629 printf("%s: no memory for rx list " 630 "-- packet dropped!\n", sc->cdce_dev.dv_xname); 631 return (ENOBUFS); 632 } 633 MCLGET(m_new, M_DONTWAIT); 634 if (!(m_new->m_flags & M_EXT)) { 635 printf("%s: no memory for rx list " 636 "-- packet dropped!\n", sc->cdce_dev.dv_xname); 637 m_freem(m_new); 638 return (ENOBUFS); 639 } 640 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; 641 } else { 642 m_new = m; 643 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; 644 m_new->m_data = m_new->m_ext.ext_buf; 645 } 646 647 m_adj(m_new, ETHER_ALIGN); 648 c->cdce_mbuf = m_new; 649 return (0); 650 } 651 652 int 653 cdce_rx_list_init(struct cdce_softc *sc) 654 { 655 struct cdce_cdata *cd; 656 struct cdce_chain *c; 657 int i; 658 659 cd = &sc->cdce_cdata; 660 for (i = 0; i < CDCE_RX_LIST_CNT; i++) { 661 c = &cd->cdce_rx_chain[i]; 662 c->cdce_sc = sc; 663 c->cdce_idx = i; 664 if (cdce_newbuf(sc, c, NULL) == ENOBUFS) 665 return (ENOBUFS); 666 if (c->cdce_xfer == NULL) { 667 c->cdce_xfer = usbd_alloc_xfer(sc->cdce_udev); 668 if (c->cdce_xfer == NULL) 669 return (ENOBUFS); 670 c->cdce_buf = usbd_alloc_buffer(c->cdce_xfer, 671 CDCE_BUFSZ); 672 if (c->cdce_buf == NULL) 673 return (ENOBUFS); 674 } 675 } 676 677 return (0); 678 } 679 680 int 681 cdce_tx_list_init(struct cdce_softc *sc) 682 { 683 struct cdce_cdata *cd; 684 struct cdce_chain *c; 685 int i; 686 687 cd = &sc->cdce_cdata; 688 for (i = 0; i < CDCE_TX_LIST_CNT; i++) { 689 c = &cd->cdce_tx_chain[i]; 690 c->cdce_sc = sc; 691 c->cdce_idx = i; 692 c->cdce_mbuf = NULL; 693 if (c->cdce_xfer == NULL) { 694 c->cdce_xfer = usbd_alloc_xfer(sc->cdce_udev); 695 if (c->cdce_xfer == NULL) 696 return (ENOBUFS); 697 c->cdce_buf = usbd_alloc_buffer(c->cdce_xfer, 698 CDCE_BUFSZ); 699 if (c->cdce_buf == NULL) 700 return (ENOBUFS); 701 } 702 } 703 704 return (0); 705 } 706 707 void 708 cdce_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status) 709 { 710 struct cdce_chain *c = priv; 711 struct cdce_softc *sc = c->cdce_sc; 712 struct ifnet *ifp = GET_IFP(sc); 713 struct mbuf *m; 714 struct mbuf_list ml = MBUF_LIST_INITIALIZER(); 715 int total_len = 0; 716 int s; 717 718 if (usbd_is_dying(sc->cdce_udev) || !(ifp->if_flags & IFF_RUNNING)) 719 return; 720 721 if (status != USBD_NORMAL_COMPLETION) { 722 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) 723 return; 724 if (sc->cdce_rxeof_errors == 0) 725 printf("%s: usb error on rx: %s\n", 726 sc->cdce_dev.dv_xname, usbd_errstr(status)); 727 if (status == USBD_STALLED) 728 usbd_clear_endpoint_stall_async(sc->cdce_bulkin_pipe); 729 DELAY(sc->cdce_rxeof_errors * 10000); 730 if (sc->cdce_rxeof_errors++ > 10) { 731 printf("%s: too many errors, disabling\n", 732 sc->cdce_dev.dv_xname); 733 usbd_deactivate(sc->cdce_udev); 734 return; 735 } 736 goto done; 737 } 738 739 sc->cdce_rxeof_errors = 0; 740 741 usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); 742 if (sc->cdce_flags & CDCE_CRC32) 743 total_len -= 4; /* Strip off added CRC */ 744 if (total_len <= 1) 745 goto done; 746 747 m = c->cdce_mbuf; 748 memcpy(mtod(m, char *), c->cdce_buf, total_len); 749 750 if (total_len < sizeof(struct ether_header)) { 751 ifp->if_ierrors++; 752 goto done; 753 } 754 755 m->m_pkthdr.len = m->m_len = total_len; 756 ml_enqueue(&ml, m); 757 758 if (cdce_newbuf(sc, c, NULL) == ENOBUFS) { 759 ifp->if_ierrors++; 760 goto done; 761 } 762 763 s = splnet(); 764 if_input(ifp, &ml); 765 splx(s); 766 767 done: 768 /* Setup new transfer. */ 769 usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkin_pipe, c, c->cdce_buf, 770 CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT, 771 cdce_rxeof); 772 usbd_transfer(c->cdce_xfer); 773 } 774 775 void 776 cdce_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status) 777 { 778 struct cdce_chain *c = priv; 779 struct cdce_softc *sc = c->cdce_sc; 780 struct ifnet *ifp = GET_IFP(sc); 781 usbd_status err; 782 int s; 783 784 if (usbd_is_dying(sc->cdce_udev)) 785 return; 786 787 s = splnet(); 788 789 ifp->if_timer = 0; 790 ifq_clr_oactive(&ifp->if_snd); 791 792 if (status != USBD_NORMAL_COMPLETION) { 793 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { 794 splx(s); 795 return; 796 } 797 ifp->if_oerrors++; 798 printf("%s: usb error on tx: %s\n", sc->cdce_dev.dv_xname, 799 usbd_errstr(status)); 800 if (status == USBD_STALLED) 801 usbd_clear_endpoint_stall_async(sc->cdce_bulkout_pipe); 802 splx(s); 803 return; 804 } 805 806 usbd_get_xfer_status(c->cdce_xfer, NULL, NULL, NULL, &err); 807 808 if (c->cdce_mbuf != NULL) { 809 m_freem(c->cdce_mbuf); 810 c->cdce_mbuf = NULL; 811 } 812 813 if (err) 814 ifp->if_oerrors++; 815 816 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) 817 cdce_start(ifp); 818 819 splx(s); 820 } 821 822 void 823 cdce_intr(struct usbd_xfer *xfer, void *addr, usbd_status status) 824 { 825 struct cdce_softc *sc = addr; 826 struct usb_cdc_notification *buf = &sc->cdce_intr_buf; 827 struct usb_cdc_connection_speed *speed; 828 u_int32_t count; 829 830 if (status == USBD_CANCELLED) 831 return; 832 833 if (status != USBD_NORMAL_COMPLETION) { 834 DPRINTFN(2, ("cdce_intr: status=%d\n", status)); 835 if (status == USBD_STALLED) 836 usbd_clear_endpoint_stall_async(sc->cdce_intr_pipe); 837 return; 838 } 839 840 usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL); 841 842 if (buf->bmRequestType == UCDC_NOTIFICATION) { 843 switch (buf->bNotification) { 844 case UCDC_N_NETWORK_CONNECTION: 845 DPRINTFN(1, ("cdce_intr: network %s\n", 846 UGETW(buf->wValue) ? "connected" : "disconnected")); 847 break; 848 case UCDC_N_CONNECTION_SPEED_CHANGE: 849 speed = (struct usb_cdc_connection_speed *)&buf->data; 850 DPRINTFN(1, ("cdce_intr: up=%d, down=%d\n", 851 UGETDW(speed->dwUSBitRate), 852 UGETDW(speed->dwDSBitRate))); 853 break; 854 default: 855 DPRINTF(("cdce_intr: bNotification 0x%x\n", 856 buf->bNotification)); 857 } 858 } 859 #ifdef CDCE_DEBUG 860 else { 861 printf("cdce_intr: bmRequestType=%d ", buf->bmRequestType); 862 printf("wValue=%d wIndex=%d wLength=%d\n", UGETW(buf->wValue), 863 UGETW(buf->wIndex), UGETW(buf->wLength)); 864 } 865 #endif 866 } 867