1 /* $OpenBSD: if_cdce.c,v 1.64 2015/04/10 08:41:43 mpi 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 struct mbuf_list ml = MBUF_LIST_INITIALIZER(); 730 int total_len = 0; 731 int s; 732 733 if (usbd_is_dying(sc->cdce_udev) || !(ifp->if_flags & IFF_RUNNING)) 734 return; 735 736 if (status != USBD_NORMAL_COMPLETION) { 737 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) 738 return; 739 if (sc->cdce_rxeof_errors == 0) 740 printf("%s: usb error on rx: %s\n", 741 sc->cdce_dev.dv_xname, usbd_errstr(status)); 742 if (status == USBD_STALLED) 743 usbd_clear_endpoint_stall_async(sc->cdce_bulkin_pipe); 744 DELAY(sc->cdce_rxeof_errors * 10000); 745 if (sc->cdce_rxeof_errors++ > 10) { 746 printf("%s: too many errors, disabling\n", 747 sc->cdce_dev.dv_xname); 748 usbd_deactivate(sc->cdce_udev); 749 return; 750 } 751 goto done; 752 } 753 754 sc->cdce_rxeof_errors = 0; 755 756 usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); 757 if (sc->cdce_flags & CDCE_ZAURUS) 758 total_len -= 4; /* Strip off CRC added by Zaurus */ 759 if (total_len <= 1) 760 goto done; 761 762 m = c->cdce_mbuf; 763 memcpy(mtod(m, char *), c->cdce_buf, total_len); 764 765 if (total_len < sizeof(struct ether_header)) { 766 ifp->if_ierrors++; 767 goto done; 768 } 769 770 ifp->if_ipackets++; 771 m->m_pkthdr.len = m->m_len = total_len; 772 ml_enqueue(&ml, m); 773 774 if (cdce_newbuf(sc, c, NULL) == ENOBUFS) { 775 ifp->if_ierrors++; 776 goto done; 777 } 778 779 s = splnet(); 780 if_input(ifp, &ml); 781 splx(s); 782 783 done: 784 /* Setup new transfer. */ 785 usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkin_pipe, c, c->cdce_buf, 786 CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT, 787 cdce_rxeof); 788 usbd_transfer(c->cdce_xfer); 789 } 790 791 void 792 cdce_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status) 793 { 794 struct cdce_chain *c = priv; 795 struct cdce_softc *sc = c->cdce_sc; 796 struct ifnet *ifp = GET_IFP(sc); 797 usbd_status err; 798 int s; 799 800 if (usbd_is_dying(sc->cdce_udev)) 801 return; 802 803 s = splnet(); 804 805 ifp->if_timer = 0; 806 ifp->if_flags &= ~IFF_OACTIVE; 807 808 if (status != USBD_NORMAL_COMPLETION) { 809 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { 810 splx(s); 811 return; 812 } 813 ifp->if_oerrors++; 814 printf("%s: usb error on tx: %s\n", sc->cdce_dev.dv_xname, 815 usbd_errstr(status)); 816 if (status == USBD_STALLED) 817 usbd_clear_endpoint_stall_async(sc->cdce_bulkout_pipe); 818 splx(s); 819 return; 820 } 821 822 usbd_get_xfer_status(c->cdce_xfer, NULL, NULL, NULL, &err); 823 824 if (c->cdce_mbuf != NULL) { 825 m_freem(c->cdce_mbuf); 826 c->cdce_mbuf = NULL; 827 } 828 829 if (err) 830 ifp->if_oerrors++; 831 else 832 ifp->if_opackets++; 833 834 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) 835 cdce_start(ifp); 836 837 splx(s); 838 } 839 840 void 841 cdce_intr(struct usbd_xfer *xfer, void *addr, usbd_status status) 842 { 843 struct cdce_softc *sc = addr; 844 struct usb_cdc_notification *buf = &sc->cdce_intr_buf; 845 struct usb_cdc_connection_speed *speed; 846 u_int32_t count; 847 848 if (status == USBD_CANCELLED) 849 return; 850 851 if (status != USBD_NORMAL_COMPLETION) { 852 DPRINTFN(2, ("cdce_intr: status=%d\n", status)); 853 if (status == USBD_STALLED) 854 usbd_clear_endpoint_stall_async(sc->cdce_intr_pipe); 855 return; 856 } 857 858 usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL); 859 860 if (buf->bmRequestType == UCDC_NOTIFICATION) { 861 switch (buf->bNotification) { 862 case UCDC_N_NETWORK_CONNECTION: 863 DPRINTFN(1, ("cdce_intr: network %s\n", 864 UGETW(buf->wValue) ? "connected" : "disconnected")); 865 break; 866 case UCDC_N_CONNECTION_SPEED_CHANGE: 867 speed = (struct usb_cdc_connection_speed *)&buf->data; 868 DPRINTFN(1, ("cdce_intr: up=%d, down=%d\n", 869 UGETDW(speed->dwUSBitRate), 870 UGETDW(speed->dwDSBitRate))); 871 break; 872 default: 873 DPRINTF(("cdce_intr: bNotification 0x%x\n", 874 buf->bNotification)); 875 } 876 } 877 #ifdef CDCE_DEBUG 878 else { 879 printf("cdce_intr: bmRequestType=%d ", buf->bmRequestType); 880 printf("wValue=%d wIndex=%d wLength=%d\n", UGETW(buf->wValue), 881 UGETW(buf->wIndex), UGETW(buf->wLength)); 882 } 883 #endif 884 } 885 886 887 /* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or 888 * code or tables extracted from it, as desired without restriction. 889 */ 890 891 static uint32_t cdce_crc32_tab[] = { 892 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 893 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 894 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 895 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 896 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 897 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 898 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 899 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 900 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 901 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 902 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 903 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 904 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 905 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 906 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 907 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 908 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 909 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 910 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 911 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 912 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 913 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 914 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 915 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 916 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 917 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 918 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 919 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 920 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 921 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 922 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 923 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 924 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 925 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 926 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 927 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 928 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 929 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 930 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 931 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 932 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 933 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 934 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d 935 }; 936 937 uint32_t 938 cdce_crc32(const void *buf, size_t size) 939 { 940 const uint8_t *p; 941 uint32_t crc; 942 943 p = buf; 944 crc = ~0U; 945 946 while (size--) 947 crc = cdce_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); 948 949 return (htole32(crc) ^ ~0U); 950 } 951