Home | History | Annotate | Line # | Download | only in usb
if_cdce.c revision 1.1
      1 /*	$NetBSD: if_cdce.c,v 1.1 2004/10/22 13:08:23 augustss Exp $ */
      2 
      3 /*
      4  * Copyright (c) 1997, 1998, 1999, 2000-2003 Bill Paul <wpaul (at) 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 <sys/cdefs.h>
     44 __KERNEL_RCSID(0, "$NetBSD: if_cdce.c,v 1.1 2004/10/22 13:08:23 augustss Exp $");
     45 #include "bpfilter.h"
     46 
     47 #include <sys/param.h>
     48 #include <sys/systm.h>
     49 #include <sys/sockio.h>
     50 #include <sys/mbuf.h>
     51 #include <sys/malloc.h>
     52 #include <sys/kernel.h>
     53 #include <sys/socket.h>
     54 #include <sys/device.h>
     55 #if defined(__OpenBSD__)
     56 #include <sys/proc.h>
     57 #endif
     58 
     59 #if NRND > 0
     60 #include <sys/rnd.h>
     61 #endif
     62 
     63 #include <net/if.h>
     64 #if defined(__NetBSD__)
     65 #include <net/if_arp.h>
     66 #endif
     67 #include <net/if_dl.h>
     68 #include <net/if_media.h>
     69 
     70 #define BPF_MTAP(ifp, m) bpf_mtap((ifp)->if_bpf, (m))
     71 
     72 #if NBPFILTER > 0
     73 #include <net/bpf.h>
     74 #endif
     75 
     76 #if defined(__NetBSD__)
     77 #include <net/if_ether.h>
     78 #ifdef INET
     79 #include <netinet/in.h>
     80 #include <netinet/if_inarp.h>
     81 #endif
     82 #endif /* defined(__NetBSD__) */
     83 
     84 #if defined(__OpenBSD__)
     85 #ifdef INET
     86 #include <netinet/in.h>
     87 #include <netinet/in_systm.h>
     88 #include <netinet/in_var.h>
     89 #include <netinet/ip.h>
     90 #include <netinet/if_ether.h>
     91 #endif
     92 #endif /* defined(__OpenBSD__) */
     93 
     94 #ifdef NS
     95 #include <netns/ns.h>
     96 #include <netns/ns_if.h>
     97 #endif
     98 
     99 #include <dev/usb/usb.h>
    100 #include <dev/usb/usbdi.h>
    101 #include <dev/usb/usbdi_util.h>
    102 #include <dev/usb/usbdevs.h>
    103 #include <dev/usb/usbcdc.h>
    104 
    105 #include <dev/usb/if_cdcereg.h>
    106 
    107 Static void	*cdce_get_desc(usbd_device_handle dev, int type, int subtype);
    108 Static int	 cdce_tx_list_init(struct cdce_softc *);
    109 Static int	 cdce_rx_list_init(struct cdce_softc *);
    110 Static int	 cdce_newbuf(struct cdce_softc *, struct cdce_chain *,
    111 		    struct mbuf *);
    112 Static int	 cdce_encap(struct cdce_softc *, struct mbuf *, int);
    113 Static void	 cdce_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
    114 Static void	 cdce_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
    115 Static void	 cdce_start(struct ifnet *);
    116 Static int	 cdce_ioctl(struct ifnet *, u_long, caddr_t);
    117 Static void	 cdce_init(void *);
    118 Static void	 cdce_watchdog(struct ifnet *);
    119 Static void	 cdce_stop(struct cdce_softc *);
    120 static uint32_t	 cdce_crc32(const void *, size_t);
    121 
    122 Static const struct cdce_type cdce_devs[] = {
    123   {{ USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2501 }, CDCE_NO_UNION },
    124   {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5500 }, CDCE_ZAURUS },
    125   {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_A300 }, CDCE_ZAURUS | CDCE_NO_UNION },
    126   {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5600 }, CDCE_ZAURUS | CDCE_NO_UNION },
    127   {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_C700 }, CDCE_ZAURUS | CDCE_NO_UNION },
    128   {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_C750 }, CDCE_ZAURUS | CDCE_NO_UNION },
    129 };
    130 #define cdce_lookup(v, p) ((const struct cdce_type *)usb_lookup(cdce_devs, v, p))
    131 
    132 USB_DECLARE_DRIVER(cdce);
    133 
    134 USB_MATCH(cdce)
    135 {
    136 	USB_MATCH_START(cdce, uaa);
    137 	usb_interface_descriptor_t *id;
    138 
    139 	if (uaa->iface == NULL)
    140 		return (UMATCH_NONE);
    141 
    142 	id = usbd_get_interface_descriptor(uaa->iface);
    143 	if (id == NULL)
    144 		return (UMATCH_NONE);
    145 
    146 	if (cdce_lookup(uaa->vendor, uaa->product) != NULL)
    147 		return (UMATCH_VENDOR_PRODUCT);
    148 
    149 	if (id->bInterfaceClass == UICLASS_CDC && id->bInterfaceSubClass ==
    150 	    UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL)
    151 		return (UMATCH_IFACECLASS_GENERIC);
    152 
    153 	return (UMATCH_NONE);
    154 }
    155 
    156 USB_ATTACH(cdce)
    157 {
    158 	USB_ATTACH_START(cdce, sc, uaa);
    159 	char				 devinfo[1024];
    160 	int				 s;
    161 	struct ifnet			*ifp;
    162 	usbd_device_handle		 dev = uaa->device;
    163 	const struct cdce_type		*t;
    164 	usb_interface_descriptor_t	*id;
    165 	usb_endpoint_descriptor_t	*ed;
    166 	usb_cdc_union_descriptor_t	*ud;
    167 	int				 data_ifcno;
    168 	u_int16_t			 macaddr_hi;
    169 	int				 i;
    170 	u_char				 eaddr[ETHER_ADDR_LEN];
    171 
    172 	usbd_devinfo(dev, 0, devinfo, sizeof devinfo);
    173 	USB_ATTACH_SETUP;
    174 	printf("%s: %s\n", USBDEVNAME(sc->cdce_dev), devinfo);
    175 
    176 	sc->cdce_udev = uaa->device;
    177 	sc->cdce_ctl_iface = uaa->iface;
    178 
    179 	t = cdce_lookup(uaa->vendor, uaa->product);
    180 	if (t)
    181 		sc->cdce_flags = t->cdce_flags;
    182 
    183 	if (sc->cdce_flags & CDCE_NO_UNION)
    184 		sc->cdce_data_iface = sc->cdce_ctl_iface;
    185 	else {
    186 		ud = cdce_get_desc(sc->cdce_udev, UDESC_CS_INTERFACE,
    187 		    UDESCSUB_CDC_UNION);
    188 		if (ud == NULL) {
    189 			printf("%s: no union descriptor\n",
    190 			    USBDEVNAME(sc->cdce_dev));
    191 			USB_ATTACH_ERROR_RETURN;
    192 		}
    193 		data_ifcno = ud->bSlaveInterface[0];
    194 
    195 		for (i = 0; i < uaa->nifaces; i++) {
    196 			if (uaa->ifaces[i] != NULL) {
    197 				id = usbd_get_interface_descriptor(
    198 				    uaa->ifaces[i]);
    199 				if (id != NULL && id->bInterfaceNumber ==
    200 				    data_ifcno) {
    201 					sc->cdce_data_iface = uaa->ifaces[i];
    202 					uaa->ifaces[i] = NULL;
    203 				}
    204 			}
    205 		}
    206 	}
    207 
    208 	if (sc->cdce_data_iface == NULL) {
    209 		printf("%s: no data interface\n", USBDEVNAME(sc->cdce_dev));
    210 		USB_ATTACH_ERROR_RETURN;
    211 	}
    212 
    213 	/* Find endpoints. */
    214 	id = usbd_get_interface_descriptor(sc->cdce_data_iface);
    215 	sc->cdce_bulkin_no = sc->cdce_bulkout_no = -1;
    216 	for (i = 0; i < id->bNumEndpoints; i++) {
    217 		ed = usbd_interface2endpoint_descriptor(sc->cdce_data_iface, i);
    218 		if (!ed) {
    219 			printf("%s: could not read endpoint descriptor\n",
    220 			    USBDEVNAME(sc->cdce_dev));
    221 			USB_ATTACH_ERROR_RETURN;
    222 		}
    223 		if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
    224 		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
    225 			sc->cdce_bulkin_no = ed->bEndpointAddress;
    226 		} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
    227 		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
    228 			sc->cdce_bulkout_no = ed->bEndpointAddress;
    229 		} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
    230 		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
    231 			/* XXX: CDC spec defines an interrupt pipe, but it is not
    232 			 * needed for simple host-to-host applications. */
    233 		} else {
    234 			printf("%s: unexpected endpoint\n",
    235 			    USBDEVNAME(sc->cdce_dev));
    236 		}
    237 	}
    238 
    239 	if (sc->cdce_bulkin_no == -1) {
    240 		printf("%s: could not find data bulk in\n",
    241 		    USBDEVNAME(sc->cdce_dev));
    242 		USB_ATTACH_ERROR_RETURN;
    243 	}
    244 	if (sc->cdce_bulkout_no == -1 ) {
    245 		printf("%s: could not find data bulk out\n",
    246 		    USBDEVNAME(sc->cdce_dev));
    247 		USB_ATTACH_ERROR_RETURN;
    248 	}
    249 
    250 	s = splnet();
    251 
    252 	/*
    253 	 * XXX This is totally broken for CDC.
    254 	 * The address can be found as a string (weird, huh?).
    255 	 */
    256 	macaddr_hi = htons(0x2acb);
    257 	memcpy(&eaddr[0], &macaddr_hi, sizeof(u_int16_t));
    258 	memcpy(&eaddr[2], &hardclock_ticks, sizeof(u_int32_t));
    259 	eaddr[5] = (u_int8_t)(sc->cdce_dev.dv_unit);
    260 
    261 	printf("%s: address %s\n", USBDEVNAME(sc->cdce_dev),
    262 	    ether_sprintf(eaddr));
    263 
    264 	ifp = GET_IFP(sc);
    265 	ifp->if_softc = sc;
    266 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
    267 	ifp->if_ioctl = cdce_ioctl;
    268 	ifp->if_start = cdce_start;
    269 	ifp->if_watchdog = cdce_watchdog;
    270 	strncpy(ifp->if_xname, USBDEVNAME(sc->cdce_dev), IFNAMSIZ);
    271 
    272 	IFQ_SET_READY(&ifp->if_snd);
    273 
    274 	if_attach(ifp);
    275 	Ether_ifattach(ifp, eaddr);
    276 
    277 	sc->cdce_attached = 1;
    278 	splx(s);
    279 
    280 	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->cdce_udev,
    281 	    USBDEV(sc->cdce_dev));
    282 
    283 	USB_ATTACH_SUCCESS_RETURN;
    284 }
    285 
    286 USB_DETACH(cdce)
    287 {
    288 	USB_DETACH_START(cdce, sc);
    289 	struct ifnet	*ifp = GET_IFP(sc);
    290 	int		 s;
    291 
    292 	s = splusb();
    293 
    294 	if (!sc->cdce_attached) {
    295 		splx(s);
    296 		return (0);
    297 	}
    298 
    299 	if (ifp->if_flags & IFF_RUNNING)
    300 		cdce_stop(sc);
    301 
    302 	ether_ifdetach(ifp);
    303 
    304 	if_detach(ifp);
    305 
    306 	sc->cdce_attached = 0;
    307 	splx(s);
    308 
    309 	return (0);
    310 }
    311 
    312 Static void
    313 cdce_start(struct ifnet *ifp)
    314 {
    315 	struct cdce_softc	*sc = ifp->if_softc;
    316 	struct mbuf		*m_head = NULL;
    317 
    318 	if (sc->cdce_dying || (ifp->if_flags & IFF_OACTIVE))
    319 		return;
    320 
    321 	IFQ_POLL(&ifp->if_snd, m_head);
    322 	if (m_head == NULL)
    323 		return;
    324 
    325 	if (cdce_encap(sc, m_head, 0)) {
    326 		ifp->if_flags |= IFF_OACTIVE;
    327 		return;
    328 	}
    329 
    330 	IFQ_DEQUEUE(&ifp->if_snd, m_head);
    331 
    332 #if NBPFILTER > 0
    333 	if (ifp->if_bpf)
    334 		BPF_MTAP(ifp, m_head);
    335 #endif
    336 
    337 	ifp->if_flags |= IFF_OACTIVE;
    338 
    339 	ifp->if_timer = 6;
    340 }
    341 
    342 Static int
    343 cdce_encap(struct cdce_softc *sc, struct mbuf *m, int idx)
    344 {
    345 	struct cdce_chain	*c;
    346 	usbd_status		 err;
    347 	int			 extra = 0;
    348 
    349 	c = &sc->cdce_cdata.cdce_tx_chain[idx];
    350 
    351 	m_copydata(m, 0, m->m_pkthdr.len, c->cdce_buf);
    352 	if (sc->cdce_flags & CDCE_ZAURUS) {
    353 		/* Zaurus wants a 32-bit CRC appended to every frame */
    354 		u_int32_t crc;
    355 
    356 		crc = cdce_crc32(c->cdce_buf, m->m_pkthdr.len);
    357 		bcopy(&crc, c->cdce_buf + m->m_pkthdr.len, 4);
    358 		extra = 4;
    359 	}
    360 	c->cdce_mbuf = m;
    361 
    362 	usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkout_pipe, c, c->cdce_buf,
    363 	    m->m_pkthdr.len + extra, USBD_NO_COPY, 10000, cdce_txeof);
    364 	err = usbd_transfer(c->cdce_xfer);
    365 	if (err != USBD_IN_PROGRESS) {
    366 		cdce_stop(sc);
    367 		return (EIO);
    368 	}
    369 
    370 	sc->cdce_cdata.cdce_tx_cnt++;
    371 
    372 	return (0);
    373 }
    374 
    375 Static void
    376 cdce_stop(struct cdce_softc *sc)
    377 {
    378 	usbd_status	 err;
    379 	struct ifnet	*ifp = GET_IFP(sc);
    380 	int		 i;
    381 
    382 	ifp->if_timer = 0;
    383 
    384 	if (sc->cdce_bulkin_pipe != NULL) {
    385 		err = usbd_abort_pipe(sc->cdce_bulkin_pipe);
    386 		if (err)
    387 			printf("%s: abort rx pipe failed: %s\n",
    388 			    USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
    389 		err = usbd_close_pipe(sc->cdce_bulkin_pipe);
    390 		if (err)
    391 			printf("%s: close rx pipe failed: %s\n",
    392 			    USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
    393 		sc->cdce_bulkin_pipe = NULL;
    394 	}
    395 
    396 	if (sc->cdce_bulkout_pipe != NULL) {
    397 		err = usbd_abort_pipe(sc->cdce_bulkout_pipe);
    398 		if (err)
    399 			printf("%s: abort tx pipe failed: %s\n",
    400 			    USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
    401 		err = usbd_close_pipe(sc->cdce_bulkout_pipe);
    402 		if (err)
    403 			printf("%s: close tx pipe failed: %s\n",
    404 			    USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
    405 		sc->cdce_bulkout_pipe = NULL;
    406 	}
    407 
    408 	for (i = 0; i < CDCE_RX_LIST_CNT; i++) {
    409 		if (sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf != NULL) {
    410 			m_freem(sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf);
    411 			sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf = NULL;
    412 		}
    413 		if (sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer != NULL) {
    414 			usbd_free_xfer(sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer);
    415 			sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer = NULL;
    416 		}
    417 	}
    418 
    419 	for (i = 0; i < CDCE_TX_LIST_CNT; i++) {
    420 		if (sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf != NULL) {
    421 			m_freem(sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf);
    422 			sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf = NULL;
    423 		}
    424 		if (sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer != NULL) {
    425 			usbd_free_xfer(sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer);
    426 			sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer = NULL;
    427 		}
    428 	}
    429 
    430 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
    431 }
    432 
    433 Static int
    434 cdce_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
    435 {
    436 	struct cdce_softc	*sc = ifp->if_softc;
    437 	struct ifaddr		*ifa = (struct ifaddr *)data;
    438 	struct ifreq		*ifr = (struct ifreq *)data;
    439 	int			 s, error = 0;
    440 
    441 	if (sc->cdce_dying)
    442 		return (EIO);
    443 
    444 	s = splnet();
    445 
    446 	switch(command) {
    447 	case SIOCSIFADDR:
    448 		ifp->if_flags |= IFF_UP;
    449 		cdce_init(sc);
    450 		switch (ifa->ifa_addr->sa_family) {
    451 #ifdef INET
    452 		case AF_INET:
    453 #if defined(__NetBSD__)
    454 			arp_ifinit(ifp, ifa);
    455 #else
    456 			arp_ifinit(&sc->arpcom, ifa);
    457 #endif
    458 			break;
    459 #endif /* INET */
    460 #ifdef NS
    461 		case AF_NS:
    462 		    {
    463 			struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
    464 
    465 			if (ns_nullhost(*ina))
    466 				ina->x_host = *(union ns_host *)
    467 					LLADDR(ifp->if_sadl);
    468 			else
    469 				memcpy(LLADDR(ifp->if_sadl),
    470 				       ina->x_host.c_host,
    471 				       ifp->if_addrlen);
    472 			break;
    473 		    }
    474 #endif /* NS */
    475 		}
    476 		break;
    477 
    478 	case SIOCSIFMTU:
    479 		if (ifr->ifr_mtu > ETHERMTU)
    480 			error = EINVAL;
    481 		else
    482 			ifp->if_mtu = ifr->ifr_mtu;
    483 		break;
    484 
    485 	case SIOCSIFFLAGS:
    486 		if (ifp->if_flags & IFF_UP) {
    487 			if (!(ifp->if_flags & IFF_RUNNING))
    488 				cdce_init(sc);
    489 		} else {
    490 			if (ifp->if_flags & IFF_RUNNING)
    491 				cdce_stop(sc);
    492 		}
    493 		error = 0;
    494 		break;
    495 
    496 	default:
    497 		error = EINVAL;
    498 		break;
    499 	}
    500 
    501 	splx(s);
    502 
    503 	return (error);
    504 }
    505 
    506 Static void
    507 cdce_watchdog(struct ifnet *ifp)
    508 {
    509 	struct cdce_softc	*sc = ifp->if_softc;
    510 
    511 	if (sc->cdce_dying)
    512 		return;
    513 
    514 	ifp->if_oerrors++;
    515 	printf("%s: watchdog timeout\n", USBDEVNAME(sc->cdce_dev));
    516 }
    517 
    518 Static void
    519 cdce_init(void *xsc)
    520 {
    521 	struct cdce_softc	*sc = xsc;
    522 	struct ifnet		*ifp = GET_IFP(sc);
    523 	struct cdce_chain	*c;
    524 	usbd_status		 err;
    525 	int			 s, i;
    526 
    527 	if (ifp->if_flags & IFF_RUNNING)
    528 		return;
    529 
    530 	s = splnet();
    531 
    532 	if (cdce_tx_list_init(sc) == ENOBUFS) {
    533 		printf("%s: tx list init failed\n", USBDEVNAME(sc->cdce_dev));
    534 		splx(s);
    535 		return;
    536 	}
    537 
    538 	if (cdce_rx_list_init(sc) == ENOBUFS) {
    539 		printf("%s: rx list init failed\n", USBDEVNAME(sc->cdce_dev));
    540 		splx(s);
    541 		return;
    542 	}
    543 
    544 	/* Maybe set multicast / broadcast here??? */
    545 
    546 	err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkin_no,
    547 	    USBD_EXCLUSIVE_USE, &sc->cdce_bulkin_pipe);
    548 	if (err) {
    549 		printf("%s: open rx pipe failed: %s\n", USBDEVNAME(sc->cdce_dev),
    550 		    usbd_errstr(err));
    551 		splx(s);
    552 		return;
    553 	}
    554 
    555 	err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkout_no,
    556 	    USBD_EXCLUSIVE_USE, &sc->cdce_bulkout_pipe);
    557 	if (err) {
    558 		printf("%s: open tx pipe failed: %s\n", USBDEVNAME(sc->cdce_dev),
    559 		    usbd_errstr(err));
    560 		splx(s);
    561 		return;
    562 	}
    563 
    564 	for (i = 0; i < CDCE_RX_LIST_CNT; i++) {
    565 		c = &sc->cdce_cdata.cdce_rx_chain[i];
    566 		usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkin_pipe, c,
    567 		    c->cdce_buf, CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
    568 		    USBD_NO_TIMEOUT, cdce_rxeof);
    569 		usbd_transfer(c->cdce_xfer);
    570 	}
    571 
    572 	ifp->if_flags |= IFF_RUNNING;
    573 	ifp->if_flags &= ~IFF_OACTIVE;
    574 
    575 	splx(s);
    576 }
    577 
    578 Static int
    579 cdce_newbuf(struct cdce_softc *sc, struct cdce_chain *c, struct mbuf *m)
    580 {
    581 	struct mbuf	*m_new = NULL;
    582 
    583 	if (m == NULL) {
    584 		MGETHDR(m_new, M_DONTWAIT, MT_DATA);
    585 		if (m_new == NULL) {
    586 			printf("%s: no memory for rx list "
    587 			    "-- packet dropped!\n", USBDEVNAME(sc->cdce_dev));
    588 			return (ENOBUFS);
    589 		}
    590 		MCLGET(m_new, M_DONTWAIT);
    591 		if (!(m_new->m_flags & M_EXT)) {
    592 			printf("%s: no memory for rx list "
    593 			    "-- packet dropped!\n", USBDEVNAME(sc->cdce_dev));
    594 			m_freem(m_new);
    595 			return (ENOBUFS);
    596 		}
    597 		m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
    598 	} else {
    599 		m_new = m;
    600 		m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
    601 		m_new->m_data = m_new->m_ext.ext_buf;
    602 	}
    603 	c->cdce_mbuf = m_new;
    604 	return (0);
    605 }
    606 
    607 Static int
    608 cdce_rx_list_init(struct cdce_softc *sc)
    609 {
    610 	struct cdce_cdata	*cd;
    611 	struct cdce_chain	*c;
    612 	int			 i;
    613 
    614 	cd = &sc->cdce_cdata;
    615 	for (i = 0; i < CDCE_RX_LIST_CNT; i++) {
    616 		c = &cd->cdce_rx_chain[i];
    617 		c->cdce_sc = sc;
    618 		c->cdce_idx = i;
    619 		if (cdce_newbuf(sc, c, NULL) == ENOBUFS)
    620 			return (ENOBUFS);
    621 		if (c->cdce_xfer == NULL) {
    622 			c->cdce_xfer = usbd_alloc_xfer(sc->cdce_udev);
    623 			if (c->cdce_xfer == NULL)
    624 				return (ENOBUFS);
    625 			c->cdce_buf = usbd_alloc_buffer(c->cdce_xfer, CDCE_BUFSZ);
    626 			if (c->cdce_buf == NULL)
    627 				return (ENOBUFS);
    628 		}
    629 	}
    630 
    631 	return (0);
    632 }
    633 
    634 Static int
    635 cdce_tx_list_init(struct cdce_softc *sc)
    636 {
    637 	struct cdce_cdata	*cd;
    638 	struct cdce_chain	*c;
    639 	int			 i;
    640 
    641 	cd = &sc->cdce_cdata;
    642 	for (i = 0; i < CDCE_TX_LIST_CNT; i++) {
    643 		c = &cd->cdce_tx_chain[i];
    644 		c->cdce_sc = sc;
    645 		c->cdce_idx = i;
    646 		c->cdce_mbuf = NULL;
    647 		if (c->cdce_xfer == NULL) {
    648 			c->cdce_xfer = usbd_alloc_xfer(sc->cdce_udev);
    649 			if (c->cdce_xfer == NULL)
    650 				return (ENOBUFS);
    651 			c->cdce_buf = usbd_alloc_buffer(c->cdce_xfer, CDCE_BUFSZ);
    652 			if (c->cdce_buf == NULL)
    653 				return (ENOBUFS);
    654 		}
    655 	}
    656 
    657 	return (0);
    658 }
    659 
    660 Static void
    661 cdce_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
    662 {
    663 	struct cdce_chain	*c = priv;
    664 	struct cdce_softc	*sc = c->cdce_sc;
    665 	struct ifnet		*ifp = GET_IFP(sc);
    666 	struct mbuf		*m;
    667 	int			 total_len = 0;
    668 	int			 s;
    669 
    670 	if (sc->cdce_dying || !(ifp->if_flags & IFF_RUNNING))
    671 		return;
    672 
    673 	if (status != USBD_NORMAL_COMPLETION) {
    674 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
    675 			return;
    676 		if (sc->cdce_rxeof_errors == 0)
    677 			printf("%s: usb error on rx: %s\n",
    678 			    USBDEVNAME(sc->cdce_dev), usbd_errstr(status));
    679 		if (status == USBD_STALLED)
    680 			usbd_clear_endpoint_stall(sc->cdce_bulkin_pipe);
    681 		DELAY(sc->cdce_rxeof_errors * 10000);
    682 		sc->cdce_rxeof_errors++;
    683 		goto done;
    684 	}
    685 
    686 	sc->cdce_rxeof_errors = 0;
    687 
    688 	usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
    689 	if (sc->cdce_flags & CDCE_ZAURUS)
    690 		total_len -= 4;	/* Strip off CRC added by Zaurus */
    691 	if (total_len <= 1)
    692 		goto done;
    693 
    694 	m = c->cdce_mbuf;
    695 	memcpy(mtod(m, char *), c->cdce_buf, total_len);
    696 
    697 	if (total_len < sizeof(struct ether_header)) {
    698 		ifp->if_ierrors++;
    699 		goto done;
    700 	}
    701 
    702 	ifp->if_ipackets++;
    703 	m->m_pkthdr.len = m->m_len = total_len;
    704 	m->m_pkthdr.rcvif = ifp;
    705 
    706 	s = splnet();
    707 
    708 	if (cdce_newbuf(sc, c, NULL) == ENOBUFS) {
    709 		ifp->if_ierrors++;
    710 		goto done1;
    711 	}
    712 
    713 #if NBPFILTER > 0
    714 	if (ifp->if_bpf)
    715 		BPF_MTAP(ifp, m);
    716 #endif
    717 
    718 	IF_INPUT(ifp, m);
    719 
    720 done1:
    721 	splx(s);
    722 
    723 done:
    724 	/* Setup new transfer. */
    725 	usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkin_pipe, c, c->cdce_buf,
    726 	    CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
    727 	    cdce_rxeof);
    728 	usbd_transfer(c->cdce_xfer);
    729 }
    730 
    731 Static void
    732 cdce_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
    733 {
    734 	struct cdce_chain	*c = priv;
    735 	struct cdce_softc	*sc = c->cdce_sc;
    736 	struct ifnet		*ifp = GET_IFP(sc);
    737 	usbd_status		 err;
    738 	int			 s;
    739 
    740 	if (sc->cdce_dying)
    741 		return;
    742 
    743 	s = splnet();
    744 
    745 	ifp->if_timer = 0;
    746 	ifp->if_flags &= ~IFF_OACTIVE;
    747 
    748 	if (status != USBD_NORMAL_COMPLETION) {
    749 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
    750 			splx(s);
    751 			return;
    752 		}
    753 		ifp->if_oerrors++;
    754 		printf("%s: usb error on tx: %s\n", USBDEVNAME(sc->cdce_dev),
    755 		    usbd_errstr(status));
    756 		if (status == USBD_STALLED)
    757 			usbd_clear_endpoint_stall(sc->cdce_bulkout_pipe);
    758 		splx(s);
    759 		return;
    760 	}
    761 
    762 	usbd_get_xfer_status(c->cdce_xfer, NULL, NULL, NULL, &err);
    763 
    764 	if (c->cdce_mbuf != NULL) {
    765 		m_freem(c->cdce_mbuf);
    766 		c->cdce_mbuf = NULL;
    767 	}
    768 
    769 	if (err)
    770 		ifp->if_oerrors++;
    771 	else
    772 		ifp->if_opackets++;
    773 
    774 	if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
    775 		cdce_start(ifp);
    776 
    777 	splx(s);
    778 }
    779 
    780 void *
    781 cdce_get_desc(usbd_device_handle dev, int type, int subtype)
    782 {
    783 	usb_descriptor_t	*desc;
    784 	usb_config_descriptor_t	*cd = usbd_get_config_descriptor(dev);
    785 	uByte			*p = (uByte *)cd;
    786 	uByte			*end = p + UGETW(cd->wTotalLength);
    787 
    788 	while (p < end) {
    789 		desc = (usb_descriptor_t *)p;
    790 		if (desc->bDescriptorType == type &&
    791 		    desc->bDescriptorSubtype == subtype)
    792 			return (desc);
    793 		p += desc->bLength;
    794 	}
    795 
    796 	return (NULL);
    797 }
    798 
    799 int
    800 cdce_activate(device_ptr_t self, enum devact act)
    801 {
    802 	struct cdce_softc *sc = (struct cdce_softc *)self;
    803 
    804 	switch (act) {
    805 	case DVACT_ACTIVATE:
    806 		return (EOPNOTSUPP);
    807 		break;
    808 
    809 	case DVACT_DEACTIVATE:
    810 		if_deactivate(GET_IFP(sc));
    811 		sc->cdce_dying = 1;
    812 		break;
    813 	}
    814 	return (0);
    815 }
    816 
    817 
    818 /*  COPYRIGHT (C) 1986 Gary S. Brown.  You may use this program, or
    819  *  code or tables extracted from it, as desired without restriction.
    820  */
    821 
    822 static uint32_t cdce_crc32_tab[] = {
    823 	0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
    824 	0xe963a535, 0x9e6495a3,	0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
    825 	0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
    826 	0xf3b97148, 0x84be41de,	0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
    827 	0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,	0x14015c4f, 0x63066cd9,
    828 	0xfa0f3d63, 0x8d080df5,	0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
    829 	0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,	0x35b5a8fa, 0x42b2986c,
    830 	0xdbbbc9d6, 0xacbcf940,	0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
    831 	0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
    832 	0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
    833 	0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,	0x76dc4190, 0x01db7106,
    834 	0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
    835 	0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
    836 	0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
    837 	0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
    838 	0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
    839 	0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
    840 	0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
    841 	0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
    842 	0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
    843 	0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
    844 	0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
    845 	0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
    846 	0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
    847 	0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
    848 	0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
    849 	0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
    850 	0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
    851 	0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
    852 	0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
    853 	0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
    854 	0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
    855 	0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
    856 	0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
    857 	0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
    858 	0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
    859 	0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
    860 	0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
    861 	0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
    862 	0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
    863 	0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
    864 	0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
    865 	0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
    866 };
    867 
    868 uint32_t
    869 cdce_crc32(const void *buf, size_t size)
    870 {
    871 	const uint8_t *p;
    872 	uint32_t crc;
    873 
    874 	p = buf;
    875 	crc = ~0U;
    876 
    877 	while (size--)
    878 		crc = cdce_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
    879 
    880 	return (crc ^ ~0U);
    881 }
    882