1 /* $OpenBSD: if_cdce.c,v 1.77 2020/06/09 07:43:39 gerhard 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_dequeue(&ifp->if_snd); 379 if (m_head == NULL) 380 return; 381 382 if (cdce_encap(sc, m_head, 0)) { 383 m_freem(m_head); 384 ifq_set_oactive(&ifp->if_snd); 385 return; 386 } 387 388 #if NBPFILTER > 0 389 if (ifp->if_bpf) 390 bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT); 391 #endif 392 393 ifq_set_oactive(&ifp->if_snd); 394 395 ifp->if_timer = 6; 396 } 397 398 int 399 cdce_encap(struct cdce_softc *sc, struct mbuf *m, int idx) 400 { 401 struct cdce_chain *c; 402 usbd_status err; 403 int extra = 0; 404 405 c = &sc->cdce_cdata.cdce_tx_chain[idx]; 406 407 m_copydata(m, 0, m->m_pkthdr.len, c->cdce_buf); 408 if (sc->cdce_flags & CDCE_CRC32) { 409 /* Some devices want a 32-bit CRC appended to every frame */ 410 u_int32_t crc; 411 412 crc = ether_crc32_le(c->cdce_buf, m->m_pkthdr.len) ^ ~0U; 413 bcopy(&crc, c->cdce_buf + m->m_pkthdr.len, 4); 414 extra = 4; 415 } 416 c->cdce_mbuf = m; 417 418 usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkout_pipe, c, c->cdce_buf, 419 m->m_pkthdr.len + extra, USBD_FORCE_SHORT_XFER | USBD_NO_COPY, 420 10000, cdce_txeof); 421 err = usbd_transfer(c->cdce_xfer); 422 if (err != USBD_IN_PROGRESS) { 423 c->cdce_mbuf = NULL; 424 cdce_stop(sc); 425 return (EIO); 426 } 427 428 sc->cdce_cdata.cdce_tx_cnt++; 429 430 return (0); 431 } 432 433 void 434 cdce_stop(struct cdce_softc *sc) 435 { 436 usbd_status err; 437 struct ifnet *ifp = GET_IFP(sc); 438 int i; 439 440 ifp->if_timer = 0; 441 ifp->if_flags &= ~IFF_RUNNING; 442 ifq_clr_oactive(&ifp->if_snd); 443 444 if (sc->cdce_bulkin_pipe != NULL) { 445 usbd_abort_pipe(sc->cdce_bulkin_pipe); 446 err = usbd_close_pipe(sc->cdce_bulkin_pipe); 447 if (err) 448 printf("%s: close rx pipe failed: %s\n", 449 sc->cdce_dev.dv_xname, usbd_errstr(err)); 450 sc->cdce_bulkin_pipe = NULL; 451 } 452 453 if (sc->cdce_bulkout_pipe != NULL) { 454 usbd_abort_pipe(sc->cdce_bulkout_pipe); 455 err = usbd_close_pipe(sc->cdce_bulkout_pipe); 456 if (err) 457 printf("%s: close tx pipe failed: %s\n", 458 sc->cdce_dev.dv_xname, usbd_errstr(err)); 459 sc->cdce_bulkout_pipe = NULL; 460 } 461 462 if (sc->cdce_intr_pipe != NULL) { 463 usbd_abort_pipe(sc->cdce_intr_pipe); 464 err = usbd_close_pipe(sc->cdce_intr_pipe); 465 if (err) 466 printf("%s: close interrupt pipe failed: %s\n", 467 sc->cdce_dev.dv_xname, usbd_errstr(err)); 468 sc->cdce_intr_pipe = NULL; 469 } 470 471 for (i = 0; i < CDCE_RX_LIST_CNT; i++) { 472 if (sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf != NULL) { 473 m_freem(sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf); 474 sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf = NULL; 475 } 476 if (sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer != NULL) { 477 usbd_free_xfer(sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer); 478 sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer = NULL; 479 } 480 } 481 482 for (i = 0; i < CDCE_TX_LIST_CNT; i++) { 483 if (sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf != NULL) { 484 m_freem(sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf); 485 sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf = NULL; 486 } 487 if (sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer != NULL) { 488 usbd_free_xfer( 489 sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer); 490 sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer = NULL; 491 } 492 } 493 } 494 495 int 496 cdce_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 497 { 498 struct cdce_softc *sc = ifp->if_softc; 499 int s, error = 0; 500 501 if (usbd_is_dying(sc->cdce_udev)) 502 return ENXIO; 503 504 s = splnet(); 505 506 switch(command) { 507 case SIOCSIFADDR: 508 ifp->if_flags |= IFF_UP; 509 if (!(ifp->if_flags & IFF_RUNNING)) 510 cdce_init(sc); 511 break; 512 513 case SIOCSIFFLAGS: 514 if (ifp->if_flags & IFF_UP) { 515 if (ifp->if_flags & IFF_RUNNING) 516 error = ENETRESET; 517 else 518 cdce_init(sc); 519 } else { 520 if (ifp->if_flags & IFF_RUNNING) 521 cdce_stop(sc); 522 } 523 break; 524 525 default: 526 error = ether_ioctl(ifp, &sc->cdce_arpcom, command, data); 527 break; 528 } 529 530 if (error == ENETRESET) 531 error = 0; 532 533 splx(s); 534 return (error); 535 } 536 537 void 538 cdce_watchdog(struct ifnet *ifp) 539 { 540 struct cdce_softc *sc = ifp->if_softc; 541 542 if (usbd_is_dying(sc->cdce_udev)) 543 return; 544 545 ifp->if_oerrors++; 546 printf("%s: watchdog timeout\n", sc->cdce_dev.dv_xname); 547 } 548 549 void 550 cdce_init(void *xsc) 551 { 552 struct cdce_softc *sc = xsc; 553 struct ifnet *ifp = GET_IFP(sc); 554 struct cdce_chain *c; 555 usbd_status err; 556 int s, i; 557 558 s = splnet(); 559 560 if (sc->cdce_intr_no != -1 && sc->cdce_intr_pipe == NULL) { 561 DPRINTFN(1, ("cdce_init: establish interrupt pipe\n")); 562 err = usbd_open_pipe_intr(sc->cdce_ctl_iface, sc->cdce_intr_no, 563 USBD_SHORT_XFER_OK, &sc->cdce_intr_pipe, sc, 564 &sc->cdce_intr_buf, sc->cdce_intr_size, cdce_intr, 565 USBD_DEFAULT_INTERVAL); 566 if (err) { 567 printf("%s: open interrupt pipe failed: %s\n", 568 sc->cdce_dev.dv_xname, usbd_errstr(err)); 569 splx(s); 570 return; 571 } 572 } 573 574 if (cdce_tx_list_init(sc) == ENOBUFS) { 575 printf("%s: tx list init failed\n", sc->cdce_dev.dv_xname); 576 splx(s); 577 return; 578 } 579 580 if (cdce_rx_list_init(sc) == ENOBUFS) { 581 printf("%s: rx list init failed\n", sc->cdce_dev.dv_xname); 582 splx(s); 583 return; 584 } 585 586 /* Maybe set multicast / broadcast here??? */ 587 588 err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkin_no, 589 USBD_EXCLUSIVE_USE, &sc->cdce_bulkin_pipe); 590 if (err) { 591 printf("%s: open rx pipe failed: %s\n", sc->cdce_dev.dv_xname, 592 usbd_errstr(err)); 593 splx(s); 594 return; 595 } 596 597 err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkout_no, 598 USBD_EXCLUSIVE_USE, &sc->cdce_bulkout_pipe); 599 if (err) { 600 printf("%s: open tx pipe failed: %s\n", sc->cdce_dev.dv_xname, 601 usbd_errstr(err)); 602 splx(s); 603 return; 604 } 605 606 for (i = 0; i < CDCE_RX_LIST_CNT; i++) { 607 c = &sc->cdce_cdata.cdce_rx_chain[i]; 608 usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkin_pipe, c, 609 c->cdce_buf, CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, 610 USBD_NO_TIMEOUT, cdce_rxeof); 611 usbd_transfer(c->cdce_xfer); 612 } 613 614 ifp->if_flags |= IFF_RUNNING; 615 ifq_clr_oactive(&ifp->if_snd); 616 617 splx(s); 618 } 619 620 int 621 cdce_newbuf(struct cdce_softc *sc, struct cdce_chain *c, struct mbuf *m) 622 { 623 struct mbuf *m_new = NULL; 624 625 if (m == NULL) { 626 MGETHDR(m_new, M_DONTWAIT, MT_DATA); 627 if (m_new == NULL) { 628 printf("%s: no memory for rx list " 629 "-- packet dropped!\n", sc->cdce_dev.dv_xname); 630 return (ENOBUFS); 631 } 632 MCLGET(m_new, M_DONTWAIT); 633 if (!(m_new->m_flags & M_EXT)) { 634 printf("%s: no memory for rx list " 635 "-- packet dropped!\n", sc->cdce_dev.dv_xname); 636 m_freem(m_new); 637 return (ENOBUFS); 638 } 639 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; 640 } else { 641 m_new = m; 642 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; 643 m_new->m_data = m_new->m_ext.ext_buf; 644 } 645 646 m_adj(m_new, ETHER_ALIGN); 647 c->cdce_mbuf = m_new; 648 return (0); 649 } 650 651 int 652 cdce_rx_list_init(struct cdce_softc *sc) 653 { 654 struct cdce_cdata *cd; 655 struct cdce_chain *c; 656 int i; 657 658 cd = &sc->cdce_cdata; 659 for (i = 0; i < CDCE_RX_LIST_CNT; i++) { 660 c = &cd->cdce_rx_chain[i]; 661 c->cdce_sc = sc; 662 c->cdce_idx = i; 663 if (cdce_newbuf(sc, c, NULL) == ENOBUFS) 664 return (ENOBUFS); 665 if (c->cdce_xfer == NULL) { 666 c->cdce_xfer = usbd_alloc_xfer(sc->cdce_udev); 667 if (c->cdce_xfer == NULL) 668 return (ENOBUFS); 669 c->cdce_buf = usbd_alloc_buffer(c->cdce_xfer, 670 CDCE_BUFSZ); 671 if (c->cdce_buf == NULL) 672 return (ENOBUFS); 673 } 674 } 675 676 return (0); 677 } 678 679 int 680 cdce_tx_list_init(struct cdce_softc *sc) 681 { 682 struct cdce_cdata *cd; 683 struct cdce_chain *c; 684 int i; 685 686 cd = &sc->cdce_cdata; 687 for (i = 0; i < CDCE_TX_LIST_CNT; i++) { 688 c = &cd->cdce_tx_chain[i]; 689 c->cdce_sc = sc; 690 c->cdce_idx = i; 691 c->cdce_mbuf = NULL; 692 if (c->cdce_xfer == NULL) { 693 c->cdce_xfer = usbd_alloc_xfer(sc->cdce_udev); 694 if (c->cdce_xfer == NULL) 695 return (ENOBUFS); 696 c->cdce_buf = usbd_alloc_buffer(c->cdce_xfer, 697 CDCE_BUFSZ); 698 if (c->cdce_buf == NULL) 699 return (ENOBUFS); 700 } 701 } 702 703 return (0); 704 } 705 706 void 707 cdce_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status) 708 { 709 struct cdce_chain *c = priv; 710 struct cdce_softc *sc = c->cdce_sc; 711 struct ifnet *ifp = GET_IFP(sc); 712 struct mbuf *m; 713 struct mbuf_list ml = MBUF_LIST_INITIALIZER(); 714 int total_len = 0; 715 int s; 716 717 if (usbd_is_dying(sc->cdce_udev) || !(ifp->if_flags & IFF_RUNNING)) 718 return; 719 720 if (status != USBD_NORMAL_COMPLETION) { 721 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) 722 return; 723 if (sc->cdce_rxeof_errors == 0) 724 printf("%s: usb error on rx: %s\n", 725 sc->cdce_dev.dv_xname, usbd_errstr(status)); 726 if (status == USBD_STALLED) 727 usbd_clear_endpoint_stall_async(sc->cdce_bulkin_pipe); 728 DELAY(sc->cdce_rxeof_errors * 10000); 729 if (sc->cdce_rxeof_errors++ > 10) { 730 printf("%s: too many errors, disabling\n", 731 sc->cdce_dev.dv_xname); 732 usbd_deactivate(sc->cdce_udev); 733 return; 734 } 735 goto done; 736 } 737 738 sc->cdce_rxeof_errors = 0; 739 740 usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); 741 if (sc->cdce_flags & CDCE_CRC32) 742 total_len -= 4; /* Strip off added CRC */ 743 if (total_len <= 1) 744 goto done; 745 746 m = c->cdce_mbuf; 747 memcpy(mtod(m, char *), c->cdce_buf, total_len); 748 749 if (total_len < sizeof(struct ether_header)) { 750 ifp->if_ierrors++; 751 goto done; 752 } 753 754 m->m_pkthdr.len = m->m_len = total_len; 755 ml_enqueue(&ml, m); 756 757 if (cdce_newbuf(sc, c, NULL) == ENOBUFS) { 758 ifp->if_ierrors++; 759 goto done; 760 } 761 762 s = splnet(); 763 if_input(ifp, &ml); 764 splx(s); 765 766 done: 767 /* Setup new transfer. */ 768 usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkin_pipe, c, c->cdce_buf, 769 CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT, 770 cdce_rxeof); 771 usbd_transfer(c->cdce_xfer); 772 } 773 774 void 775 cdce_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status) 776 { 777 struct cdce_chain *c = priv; 778 struct cdce_softc *sc = c->cdce_sc; 779 struct ifnet *ifp = GET_IFP(sc); 780 usbd_status err; 781 int s; 782 783 if (usbd_is_dying(sc->cdce_udev)) 784 return; 785 786 s = splnet(); 787 788 ifp->if_timer = 0; 789 ifq_clr_oactive(&ifp->if_snd); 790 791 if (status != USBD_NORMAL_COMPLETION) { 792 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { 793 splx(s); 794 return; 795 } 796 ifp->if_oerrors++; 797 printf("%s: usb error on tx: %s\n", sc->cdce_dev.dv_xname, 798 usbd_errstr(status)); 799 if (status == USBD_STALLED) 800 usbd_clear_endpoint_stall_async(sc->cdce_bulkout_pipe); 801 splx(s); 802 return; 803 } 804 805 usbd_get_xfer_status(c->cdce_xfer, NULL, NULL, NULL, &err); 806 807 if (c->cdce_mbuf != NULL) { 808 m_freem(c->cdce_mbuf); 809 c->cdce_mbuf = NULL; 810 } 811 812 if (err) 813 ifp->if_oerrors++; 814 815 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) 816 cdce_start(ifp); 817 818 splx(s); 819 } 820 821 void 822 cdce_intr(struct usbd_xfer *xfer, void *addr, usbd_status status) 823 { 824 struct cdce_softc *sc = addr; 825 struct usb_cdc_notification *buf = &sc->cdce_intr_buf; 826 struct usb_cdc_connection_speed *speed; 827 u_int32_t count; 828 829 if (status == USBD_CANCELLED) 830 return; 831 832 if (status != USBD_NORMAL_COMPLETION) { 833 DPRINTFN(2, ("cdce_intr: status=%d\n", status)); 834 if (status == USBD_STALLED) 835 usbd_clear_endpoint_stall_async(sc->cdce_intr_pipe); 836 return; 837 } 838 839 usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL); 840 841 if (buf->bmRequestType == UCDC_NOTIFICATION) { 842 switch (buf->bNotification) { 843 case UCDC_N_NETWORK_CONNECTION: 844 DPRINTFN(1, ("cdce_intr: network %s\n", 845 UGETW(buf->wValue) ? "connected" : "disconnected")); 846 break; 847 case UCDC_N_CONNECTION_SPEED_CHANGE: 848 speed = (struct usb_cdc_connection_speed *)&buf->data; 849 DPRINTFN(1, ("cdce_intr: up=%d, down=%d\n", 850 UGETDW(speed->dwUSBitRate), 851 UGETDW(speed->dwDSBitRate))); 852 break; 853 default: 854 DPRINTF(("cdce_intr: bNotification 0x%x\n", 855 buf->bNotification)); 856 } 857 } 858 #ifdef CDCE_DEBUG 859 else { 860 printf("cdce_intr: bmRequestType=%d ", buf->bmRequestType); 861 printf("wValue=%d wIndex=%d wLength=%d\n", UGETW(buf->wValue), 862 UGETW(buf->wIndex), UGETW(buf->wLength)); 863 } 864 #endif 865 } 866