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