1 /* $OpenBSD: if_cdce.c,v 1.63 2015/03/14 03:38:49 jsg 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 #include <net/bpf.h> 56 #if NBPFILTER > 0 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_ZAURUS }, 97 {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_A300 }, CDCE_ZAURUS }, 98 {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5600 }, CDCE_ZAURUS }, 99 {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_C700 }, CDCE_ZAURUS }, 100 {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_C750 }, CDCE_ZAURUS }, 101 {{ USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_USBLAN }, CDCE_ZAURUS }, 102 {{ USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_USBLAN2 }, CDCE_ZAURUS }, 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; 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 struct timeval now; 166 u_int32_t macaddr_lo; 167 u_int16_t macaddr_hi; 168 int i, j, numalts, len; 169 int ctl_ifcno = -1; 170 int data_ifcno = -1; 171 172 sc->cdce_udev = uaa->device; 173 sc->cdce_ctl_iface = uaa->iface; 174 id = usbd_get_interface_descriptor(sc->cdce_ctl_iface); 175 ctl_ifcno = id->bInterfaceNumber; 176 177 t = cdce_lookup(uaa->vendor, uaa->product); 178 if (t) 179 sc->cdce_flags = t->cdce_flags; 180 181 /* Get the data interface no. and capabilities */ 182 ethd = NULL; 183 usbd_desc_iter_init(dev, &iter); 184 desc = usbd_desc_iter_next(&iter); 185 while (desc) { 186 if (desc->bDescriptorType != UDESC_CS_INTERFACE) { 187 desc = usbd_desc_iter_next(&iter); 188 continue; 189 } 190 switch(desc->bDescriptorSubtype) { 191 case UDESCSUB_CDC_UNION: 192 ud = (struct usb_cdc_union_descriptor *)desc; 193 if ((sc->cdce_flags & CDCE_SWAPUNION) == 0 && 194 ud->bMasterInterface == ctl_ifcno) 195 data_ifcno = ud->bSlaveInterface[0]; 196 if ((sc->cdce_flags & CDCE_SWAPUNION) && 197 ud->bSlaveInterface[0] == ctl_ifcno) 198 data_ifcno = ud->bMasterInterface; 199 break; 200 case UDESCSUB_CDC_ENF: 201 if (ethd) { 202 printf("%s: ", sc->cdce_dev.dv_xname); 203 printf("extra ethernet descriptor\n"); 204 return; 205 } 206 ethd = (struct usb_cdc_ethernet_descriptor *)desc; 207 break; 208 } 209 desc = usbd_desc_iter_next(&iter); 210 } 211 212 if (data_ifcno == -1) { 213 DPRINTF(("cdce_attach: no union interface\n")); 214 sc->cdce_data_iface = sc->cdce_ctl_iface; 215 } else { 216 DPRINTF(("cdce_attach: union interface: ctl=%d, data=%d\n", 217 ctl_ifcno, data_ifcno)); 218 for (i = 0; i < uaa->nifaces; i++) { 219 if (usbd_iface_claimed(sc->cdce_udev, i)) 220 continue; 221 id = usbd_get_interface_descriptor(uaa->ifaces[i]); 222 if (id != NULL && id->bInterfaceNumber == data_ifcno) { 223 sc->cdce_data_iface = uaa->ifaces[i]; 224 usbd_claim_iface(sc->cdce_udev, i); 225 } 226 } 227 } 228 229 if (sc->cdce_data_iface == NULL) { 230 printf("%s: no data interface\n", sc->cdce_dev.dv_xname); 231 return; 232 } 233 234 id = usbd_get_interface_descriptor(sc->cdce_ctl_iface); 235 sc->cdce_intr_no = -1; 236 for (i = 0; i < id->bNumEndpoints && sc->cdce_intr_no == -1; i++) { 237 ed = usbd_interface2endpoint_descriptor(sc->cdce_ctl_iface, i); 238 if (!ed) { 239 printf("%s: no descriptor for interrupt endpoint %d\n", 240 sc->cdce_dev.dv_xname, i); 241 return; 242 } 243 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 244 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { 245 sc->cdce_intr_no = ed->bEndpointAddress; 246 sc->cdce_intr_size = sizeof(sc->cdce_intr_buf); 247 } 248 } 249 250 id = usbd_get_interface_descriptor(sc->cdce_data_iface); 251 cd = usbd_get_config_descriptor(sc->cdce_udev); 252 numalts = usbd_get_no_alts(cd, id->bInterfaceNumber); 253 254 for (j = 0; j < numalts; j++) { 255 if (usbd_set_interface(sc->cdce_data_iface, j)) { 256 printf("%s: interface alternate setting %d failed\n", 257 sc->cdce_dev.dv_xname, j); 258 return; 259 } 260 /* Find endpoints. */ 261 id = usbd_get_interface_descriptor(sc->cdce_data_iface); 262 sc->cdce_bulkin_no = sc->cdce_bulkout_no = -1; 263 for (i = 0; i < id->bNumEndpoints; i++) { 264 ed = usbd_interface2endpoint_descriptor( 265 sc->cdce_data_iface, i); 266 if (!ed) { 267 printf("%s: no descriptor for bulk endpoint " 268 "%d\n", sc->cdce_dev.dv_xname, i); 269 return; 270 } 271 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 272 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 273 sc->cdce_bulkin_no = ed->bEndpointAddress; 274 } else if ( 275 UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && 276 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 277 sc->cdce_bulkout_no = ed->bEndpointAddress; 278 } 279 #ifdef CDCE_DEBUG 280 else if ( 281 UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_IN && 282 UE_GET_XFERTYPE(ed->bmAttributes) != UE_INTERRUPT) { 283 printf("%s: unexpected endpoint, ep=%x attr=%x" 284 "\n", sc->cdce_dev.dv_xname, 285 ed->bEndpointAddress, ed->bmAttributes); 286 } 287 #endif 288 } 289 if ((sc->cdce_bulkin_no != -1) && (sc->cdce_bulkout_no != -1)) { 290 DPRINTF(("cdce_attach: intr=0x%x, in=0x%x, out=0x%x\n", 291 sc->cdce_intr_no, sc->cdce_bulkin_no, 292 sc->cdce_bulkout_no)); 293 goto found; 294 } 295 } 296 297 if (sc->cdce_bulkin_no == -1) { 298 printf("%s: could not find data bulk in\n", 299 sc->cdce_dev.dv_xname); 300 return; 301 } 302 if (sc->cdce_bulkout_no == -1 ) { 303 printf("%s: could not find data bulk out\n", 304 sc->cdce_dev.dv_xname); 305 return; 306 } 307 308 found: 309 s = splnet(); 310 311 if (!ethd || usbd_get_string_desc(sc->cdce_udev, ethd->iMacAddress, 0, 312 &eaddr_str, &len)) { 313 macaddr_hi = htons(0x2acb); 314 bcopy(&macaddr_hi, &sc->cdce_arpcom.ac_enaddr[0], 315 sizeof(u_int16_t)); 316 getmicrotime(&now); 317 macaddr_lo = htonl(now.tv_usec << 8); 318 bcopy(&macaddr_lo, &sc->cdce_arpcom.ac_enaddr[2], sizeof(u_int32_t)); 319 sc->cdce_arpcom.ac_enaddr[5] = (u_int8_t)(sc->cdce_dev.dv_unit); 320 } else { 321 for (i = 0; i < ETHER_ADDR_LEN * 2; i++) { 322 int c = UGETW(eaddr_str.bString[i]); 323 324 if ('0' <= c && c <= '9') 325 c -= '0'; 326 else if ('A' <= c && c <= 'F') 327 c -= 'A' - 10; 328 else if ('a' <= c && c <= 'f') 329 c -= 'a' - 10; 330 c &= 0xf; 331 if (i % 2 == 0) 332 c <<= 4; 333 sc->cdce_arpcom.ac_enaddr[i / 2] |= c; 334 } 335 } 336 337 printf("%s: address %s\n", sc->cdce_dev.dv_xname, 338 ether_sprintf(sc->cdce_arpcom.ac_enaddr)); 339 340 ifp = GET_IFP(sc); 341 ifp->if_softc = sc; 342 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 343 ifp->if_ioctl = cdce_ioctl; 344 ifp->if_start = cdce_start; 345 ifp->if_watchdog = cdce_watchdog; 346 strlcpy(ifp->if_xname, sc->cdce_dev.dv_xname, IFNAMSIZ); 347 348 IFQ_SET_READY(&ifp->if_snd); 349 350 if_attach(ifp); 351 ether_ifattach(ifp); 352 353 sc->cdce_attached = 1; 354 splx(s); 355 } 356 357 int 358 cdce_detach(struct device *self, int flags) 359 { 360 struct cdce_softc *sc = (struct cdce_softc *)self; 361 struct ifnet *ifp = GET_IFP(sc); 362 int s; 363 364 if (!sc->cdce_attached) 365 return (0); 366 367 s = splusb(); 368 369 if (ifp->if_flags & IFF_RUNNING) 370 cdce_stop(sc); 371 372 if (ifp->if_softc != NULL) { 373 ether_ifdetach(ifp); 374 if_detach(ifp); 375 } 376 377 sc->cdce_attached = 0; 378 splx(s); 379 380 return (0); 381 } 382 383 void 384 cdce_start(struct ifnet *ifp) 385 { 386 struct cdce_softc *sc = ifp->if_softc; 387 struct mbuf *m_head = NULL; 388 389 if (usbd_is_dying(sc->cdce_udev) || (ifp->if_flags & IFF_OACTIVE)) 390 return; 391 392 IFQ_POLL(&ifp->if_snd, m_head); 393 if (m_head == NULL) 394 return; 395 396 if (cdce_encap(sc, m_head, 0)) { 397 ifp->if_flags |= IFF_OACTIVE; 398 return; 399 } 400 401 IFQ_DEQUEUE(&ifp->if_snd, m_head); 402 403 #if NBPFILTER > 0 404 if (ifp->if_bpf) 405 bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT); 406 #endif 407 408 ifp->if_flags |= IFF_OACTIVE; 409 410 ifp->if_timer = 6; 411 } 412 413 int 414 cdce_encap(struct cdce_softc *sc, struct mbuf *m, int idx) 415 { 416 struct cdce_chain *c; 417 usbd_status err; 418 int extra = 0; 419 420 c = &sc->cdce_cdata.cdce_tx_chain[idx]; 421 422 m_copydata(m, 0, m->m_pkthdr.len, c->cdce_buf); 423 if (sc->cdce_flags & CDCE_ZAURUS) { 424 /* Zaurus wants a 32-bit CRC appended to every frame */ 425 u_int32_t crc; 426 427 crc = cdce_crc32(c->cdce_buf, m->m_pkthdr.len); 428 bcopy(&crc, c->cdce_buf + m->m_pkthdr.len, 4); 429 extra = 4; 430 } 431 c->cdce_mbuf = m; 432 433 usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkout_pipe, c, c->cdce_buf, 434 m->m_pkthdr.len + extra, USBD_FORCE_SHORT_XFER | USBD_NO_COPY, 435 10000, cdce_txeof); 436 err = usbd_transfer(c->cdce_xfer); 437 if (err != USBD_IN_PROGRESS) { 438 cdce_stop(sc); 439 return (EIO); 440 } 441 442 sc->cdce_cdata.cdce_tx_cnt++; 443 444 return (0); 445 } 446 447 void 448 cdce_stop(struct cdce_softc *sc) 449 { 450 usbd_status err; 451 struct ifnet *ifp = GET_IFP(sc); 452 int i; 453 454 ifp->if_timer = 0; 455 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 456 457 if (sc->cdce_bulkin_pipe != NULL) { 458 usbd_abort_pipe(sc->cdce_bulkin_pipe); 459 err = usbd_close_pipe(sc->cdce_bulkin_pipe); 460 if (err) 461 printf("%s: close rx pipe failed: %s\n", 462 sc->cdce_dev.dv_xname, usbd_errstr(err)); 463 sc->cdce_bulkin_pipe = NULL; 464 } 465 466 if (sc->cdce_bulkout_pipe != NULL) { 467 usbd_abort_pipe(sc->cdce_bulkout_pipe); 468 err = usbd_close_pipe(sc->cdce_bulkout_pipe); 469 if (err) 470 printf("%s: close tx pipe failed: %s\n", 471 sc->cdce_dev.dv_xname, usbd_errstr(err)); 472 sc->cdce_bulkout_pipe = NULL; 473 } 474 475 if (sc->cdce_intr_pipe != NULL) { 476 usbd_abort_pipe(sc->cdce_intr_pipe); 477 err = usbd_close_pipe(sc->cdce_intr_pipe); 478 if (err) 479 printf("%s: close interrupt pipe failed: %s\n", 480 sc->cdce_dev.dv_xname, usbd_errstr(err)); 481 sc->cdce_intr_pipe = NULL; 482 } 483 484 for (i = 0; i < CDCE_RX_LIST_CNT; i++) { 485 if (sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf != NULL) { 486 m_freem(sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf); 487 sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf = NULL; 488 } 489 if (sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer != NULL) { 490 usbd_free_xfer(sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer); 491 sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer = NULL; 492 } 493 } 494 495 for (i = 0; i < CDCE_TX_LIST_CNT; i++) { 496 if (sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf != NULL) { 497 m_freem(sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf); 498 sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf = NULL; 499 } 500 if (sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer != NULL) { 501 usbd_free_xfer( 502 sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer); 503 sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer = NULL; 504 } 505 } 506 } 507 508 int 509 cdce_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 510 { 511 struct cdce_softc *sc = ifp->if_softc; 512 struct ifaddr *ifa = (struct ifaddr *)data; 513 int s, error = 0; 514 515 if (usbd_is_dying(sc->cdce_udev)) 516 return (EIO); 517 518 s = splnet(); 519 520 switch(command) { 521 case SIOCSIFADDR: 522 ifp->if_flags |= IFF_UP; 523 if (!(ifp->if_flags & IFF_RUNNING)) 524 cdce_init(sc); 525 if (ifa->ifa_addr->sa_family == AF_INET) 526 arp_ifinit(&sc->cdce_arpcom, ifa); 527 break; 528 529 case SIOCSIFFLAGS: 530 if (ifp->if_flags & IFF_UP) { 531 if (ifp->if_flags & IFF_RUNNING) 532 error = ENETRESET; 533 else 534 cdce_init(sc); 535 } else { 536 if (ifp->if_flags & IFF_RUNNING) 537 cdce_stop(sc); 538 } 539 break; 540 541 default: 542 error = ether_ioctl(ifp, &sc->cdce_arpcom, command, data); 543 break; 544 } 545 546 if (error == ENETRESET) 547 error = 0; 548 549 splx(s); 550 return (error); 551 } 552 553 void 554 cdce_watchdog(struct ifnet *ifp) 555 { 556 struct cdce_softc *sc = ifp->if_softc; 557 558 if (usbd_is_dying(sc->cdce_udev)) 559 return; 560 561 ifp->if_oerrors++; 562 printf("%s: watchdog timeout\n", sc->cdce_dev.dv_xname); 563 } 564 565 void 566 cdce_init(void *xsc) 567 { 568 struct cdce_softc *sc = xsc; 569 struct ifnet *ifp = GET_IFP(sc); 570 struct cdce_chain *c; 571 usbd_status err; 572 int s, i; 573 574 s = splnet(); 575 576 if (sc->cdce_intr_no != -1 && sc->cdce_intr_pipe == NULL) { 577 DPRINTFN(1, ("cdce_init: establish interrupt pipe\n")); 578 err = usbd_open_pipe_intr(sc->cdce_ctl_iface, sc->cdce_intr_no, 579 USBD_SHORT_XFER_OK, &sc->cdce_intr_pipe, sc, 580 &sc->cdce_intr_buf, sc->cdce_intr_size, cdce_intr, 581 USBD_DEFAULT_INTERVAL); 582 if (err) { 583 printf("%s: open interrupt pipe failed: %s\n", 584 sc->cdce_dev.dv_xname, usbd_errstr(err)); 585 splx(s); 586 return; 587 } 588 } 589 590 if (cdce_tx_list_init(sc) == ENOBUFS) { 591 printf("%s: tx list init failed\n", sc->cdce_dev.dv_xname); 592 splx(s); 593 return; 594 } 595 596 if (cdce_rx_list_init(sc) == ENOBUFS) { 597 printf("%s: rx list init failed\n", sc->cdce_dev.dv_xname); 598 splx(s); 599 return; 600 } 601 602 /* Maybe set multicast / broadcast here??? */ 603 604 err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkin_no, 605 USBD_EXCLUSIVE_USE, &sc->cdce_bulkin_pipe); 606 if (err) { 607 printf("%s: open rx pipe failed: %s\n", sc->cdce_dev.dv_xname, 608 usbd_errstr(err)); 609 splx(s); 610 return; 611 } 612 613 err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkout_no, 614 USBD_EXCLUSIVE_USE, &sc->cdce_bulkout_pipe); 615 if (err) { 616 printf("%s: open tx pipe failed: %s\n", sc->cdce_dev.dv_xname, 617 usbd_errstr(err)); 618 splx(s); 619 return; 620 } 621 622 for (i = 0; i < CDCE_RX_LIST_CNT; i++) { 623 c = &sc->cdce_cdata.cdce_rx_chain[i]; 624 usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkin_pipe, c, 625 c->cdce_buf, CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, 626 USBD_NO_TIMEOUT, cdce_rxeof); 627 usbd_transfer(c->cdce_xfer); 628 } 629 630 ifp->if_flags |= IFF_RUNNING; 631 ifp->if_flags &= ~IFF_OACTIVE; 632 633 splx(s); 634 } 635 636 int 637 cdce_newbuf(struct cdce_softc *sc, struct cdce_chain *c, struct mbuf *m) 638 { 639 struct mbuf *m_new = NULL; 640 641 if (m == NULL) { 642 MGETHDR(m_new, M_DONTWAIT, MT_DATA); 643 if (m_new == NULL) { 644 printf("%s: no memory for rx list " 645 "-- packet dropped!\n", sc->cdce_dev.dv_xname); 646 return (ENOBUFS); 647 } 648 MCLGET(m_new, M_DONTWAIT); 649 if (!(m_new->m_flags & M_EXT)) { 650 printf("%s: no memory for rx list " 651 "-- packet dropped!\n", sc->cdce_dev.dv_xname); 652 m_freem(m_new); 653 return (ENOBUFS); 654 } 655 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; 656 } else { 657 m_new = m; 658 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; 659 m_new->m_data = m_new->m_ext.ext_buf; 660 } 661 662 m_adj(m_new, ETHER_ALIGN); 663 c->cdce_mbuf = m_new; 664 return (0); 665 } 666 667 int 668 cdce_rx_list_init(struct cdce_softc *sc) 669 { 670 struct cdce_cdata *cd; 671 struct cdce_chain *c; 672 int i; 673 674 cd = &sc->cdce_cdata; 675 for (i = 0; i < CDCE_RX_LIST_CNT; i++) { 676 c = &cd->cdce_rx_chain[i]; 677 c->cdce_sc = sc; 678 c->cdce_idx = i; 679 if (cdce_newbuf(sc, c, NULL) == ENOBUFS) 680 return (ENOBUFS); 681 if (c->cdce_xfer == NULL) { 682 c->cdce_xfer = usbd_alloc_xfer(sc->cdce_udev); 683 if (c->cdce_xfer == NULL) 684 return (ENOBUFS); 685 c->cdce_buf = usbd_alloc_buffer(c->cdce_xfer, 686 CDCE_BUFSZ); 687 if (c->cdce_buf == NULL) 688 return (ENOBUFS); 689 } 690 } 691 692 return (0); 693 } 694 695 int 696 cdce_tx_list_init(struct cdce_softc *sc) 697 { 698 struct cdce_cdata *cd; 699 struct cdce_chain *c; 700 int i; 701 702 cd = &sc->cdce_cdata; 703 for (i = 0; i < CDCE_TX_LIST_CNT; i++) { 704 c = &cd->cdce_tx_chain[i]; 705 c->cdce_sc = sc; 706 c->cdce_idx = i; 707 c->cdce_mbuf = NULL; 708 if (c->cdce_xfer == NULL) { 709 c->cdce_xfer = usbd_alloc_xfer(sc->cdce_udev); 710 if (c->cdce_xfer == NULL) 711 return (ENOBUFS); 712 c->cdce_buf = usbd_alloc_buffer(c->cdce_xfer, 713 CDCE_BUFSZ); 714 if (c->cdce_buf == NULL) 715 return (ENOBUFS); 716 } 717 } 718 719 return (0); 720 } 721 722 void 723 cdce_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status) 724 { 725 struct cdce_chain *c = priv; 726 struct cdce_softc *sc = c->cdce_sc; 727 struct ifnet *ifp = GET_IFP(sc); 728 struct mbuf *m; 729 int total_len = 0; 730 int s; 731 732 if (usbd_is_dying(sc->cdce_udev) || !(ifp->if_flags & IFF_RUNNING)) 733 return; 734 735 if (status != USBD_NORMAL_COMPLETION) { 736 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) 737 return; 738 if (sc->cdce_rxeof_errors == 0) 739 printf("%s: usb error on rx: %s\n", 740 sc->cdce_dev.dv_xname, usbd_errstr(status)); 741 if (status == USBD_STALLED) 742 usbd_clear_endpoint_stall_async(sc->cdce_bulkin_pipe); 743 DELAY(sc->cdce_rxeof_errors * 10000); 744 if (sc->cdce_rxeof_errors++ > 10) { 745 printf("%s: too many errors, disabling\n", 746 sc->cdce_dev.dv_xname); 747 usbd_deactivate(sc->cdce_udev); 748 return; 749 } 750 goto done; 751 } 752 753 sc->cdce_rxeof_errors = 0; 754 755 usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); 756 if (sc->cdce_flags & CDCE_ZAURUS) 757 total_len -= 4; /* Strip off CRC added by Zaurus */ 758 if (total_len <= 1) 759 goto done; 760 761 m = c->cdce_mbuf; 762 memcpy(mtod(m, char *), c->cdce_buf, total_len); 763 764 if (total_len < sizeof(struct ether_header)) { 765 ifp->if_ierrors++; 766 goto done; 767 } 768 769 ifp->if_ipackets++; 770 771 m->m_pkthdr.len = m->m_len = total_len; 772 m->m_pkthdr.rcvif = ifp; 773 774 s = splnet(); 775 776 if (cdce_newbuf(sc, c, NULL) == ENOBUFS) { 777 ifp->if_ierrors++; 778 goto done1; 779 } 780 781 #if NBPFILTER > 0 782 if (ifp->if_bpf) 783 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN); 784 #endif 785 786 ether_input_mbuf(ifp, m); 787 788 done1: 789 splx(s); 790 791 done: 792 /* Setup new transfer. */ 793 usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkin_pipe, c, c->cdce_buf, 794 CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT, 795 cdce_rxeof); 796 usbd_transfer(c->cdce_xfer); 797 } 798 799 void 800 cdce_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status) 801 { 802 struct cdce_chain *c = priv; 803 struct cdce_softc *sc = c->cdce_sc; 804 struct ifnet *ifp = GET_IFP(sc); 805 usbd_status err; 806 int s; 807 808 if (usbd_is_dying(sc->cdce_udev)) 809 return; 810 811 s = splnet(); 812 813 ifp->if_timer = 0; 814 ifp->if_flags &= ~IFF_OACTIVE; 815 816 if (status != USBD_NORMAL_COMPLETION) { 817 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { 818 splx(s); 819 return; 820 } 821 ifp->if_oerrors++; 822 printf("%s: usb error on tx: %s\n", sc->cdce_dev.dv_xname, 823 usbd_errstr(status)); 824 if (status == USBD_STALLED) 825 usbd_clear_endpoint_stall_async(sc->cdce_bulkout_pipe); 826 splx(s); 827 return; 828 } 829 830 usbd_get_xfer_status(c->cdce_xfer, NULL, NULL, NULL, &err); 831 832 if (c->cdce_mbuf != NULL) { 833 m_freem(c->cdce_mbuf); 834 c->cdce_mbuf = NULL; 835 } 836 837 if (err) 838 ifp->if_oerrors++; 839 else 840 ifp->if_opackets++; 841 842 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) 843 cdce_start(ifp); 844 845 splx(s); 846 } 847 848 void 849 cdce_intr(struct usbd_xfer *xfer, void *addr, usbd_status status) 850 { 851 struct cdce_softc *sc = addr; 852 struct usb_cdc_notification *buf = &sc->cdce_intr_buf; 853 struct usb_cdc_connection_speed *speed; 854 u_int32_t count; 855 856 if (status == USBD_CANCELLED) 857 return; 858 859 if (status != USBD_NORMAL_COMPLETION) { 860 DPRINTFN(2, ("cdce_intr: status=%d\n", status)); 861 if (status == USBD_STALLED) 862 usbd_clear_endpoint_stall_async(sc->cdce_intr_pipe); 863 return; 864 } 865 866 usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL); 867 868 if (buf->bmRequestType == UCDC_NOTIFICATION) { 869 switch (buf->bNotification) { 870 case UCDC_N_NETWORK_CONNECTION: 871 DPRINTFN(1, ("cdce_intr: network %s\n", 872 UGETW(buf->wValue) ? "connected" : "disconnected")); 873 break; 874 case UCDC_N_CONNECTION_SPEED_CHANGE: 875 speed = (struct usb_cdc_connection_speed *)&buf->data; 876 DPRINTFN(1, ("cdce_intr: up=%d, down=%d\n", 877 UGETDW(speed->dwUSBitRate), 878 UGETDW(speed->dwDSBitRate))); 879 break; 880 default: 881 DPRINTF(("cdce_intr: bNotification 0x%x\n", 882 buf->bNotification)); 883 } 884 } 885 #ifdef CDCE_DEBUG 886 else { 887 printf("cdce_intr: bmRequestType=%d ", buf->bmRequestType); 888 printf("wValue=%d wIndex=%d wLength=%d\n", UGETW(buf->wValue), 889 UGETW(buf->wIndex), UGETW(buf->wLength)); 890 } 891 #endif 892 } 893 894 895 /* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or 896 * code or tables extracted from it, as desired without restriction. 897 */ 898 899 static uint32_t cdce_crc32_tab[] = { 900 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 901 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 902 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 903 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 904 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 905 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 906 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 907 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 908 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 909 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 910 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 911 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 912 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 913 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 914 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 915 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 916 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 917 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 918 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 919 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 920 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 921 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 922 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 923 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 924 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 925 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 926 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 927 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 928 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 929 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 930 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 931 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 932 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 933 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 934 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 935 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 936 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 937 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 938 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 939 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 940 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 941 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 942 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d 943 }; 944 945 uint32_t 946 cdce_crc32(const void *buf, size_t size) 947 { 948 const uint8_t *p; 949 uint32_t crc; 950 951 p = buf; 952 crc = ~0U; 953 954 while (size--) 955 crc = cdce_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); 956 957 return (htole32(crc) ^ ~0U); 958 } 959