1 /* $NetBSD: if_cdce.c,v 1.25 2009/09/23 19:07:19 plunky Exp $ */
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
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
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.
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.
38 * USB Communication Device Class (Ethernet Networking Control Model)
39 * http://www.usb.org/developers/devclass_docs/usbcdc11.pdf
43 #include <sys/cdefs.h>
44 __KERNEL_RCSID(0, "$NetBSD: if_cdce.c,v 1.25 2009/09/23 19:07:19 plunky Exp $");
50 #include <sys/param.h>
51 #include <sys/systm.h>
52 #include <sys/sockio.h>
54 #include <sys/malloc.h>
55 #include <sys/kernel.h>
56 #include <sys/socket.h>
57 #include <sys/device.h>
64 #include <net/if_arp.h>
65 #include <net/if_dl.h>
66 #include <net/if_media.h>
68 #define BPF_MTAP(ifp, m) bpf_mtap((ifp)->if_bpf, (m))
74 #include <net/if_ether.h>
76 #include <netinet/in.h>
77 #include <netinet/if_inarp.h>
82 #include <dev/usb/usb.h>
83 #include <dev/usb/usbdi.h>
84 #include <dev/usb/usbdi_util.h>
85 #include <dev/usb/usbdevs.h>
86 #include <dev/usb/usbcdc.h>
88 #include <dev/usb/if_cdcereg.h>
90 Static
int cdce_tx_list_init(struct cdce_softc
*);
91 Static
int cdce_rx_list_init(struct cdce_softc
*);
92 Static
int cdce_newbuf(struct cdce_softc
*, struct cdce_chain
*,
94 Static
int cdce_encap(struct cdce_softc
*, struct mbuf
*, int);
95 Static
void cdce_rxeof(usbd_xfer_handle
, usbd_private_handle
, usbd_status
);
96 Static
void cdce_txeof(usbd_xfer_handle
, usbd_private_handle
, usbd_status
);
97 Static
void cdce_start(struct ifnet
*);
98 Static
int cdce_ioctl(struct ifnet
*, u_long
, void *);
99 Static
void cdce_init(void *);
100 Static
void cdce_watchdog(struct ifnet
*);
101 Static
void cdce_stop(struct cdce_softc
*);
102 Static
uint32_t cdce_crc32(const void *, size_t);
104 Static
const struct cdce_type cdce_devs
[] = {
105 {{ USB_VENDOR_PROLIFIC
, USB_PRODUCT_PROLIFIC_PL2501
}, CDCE_NO_UNION
},
106 {{ USB_VENDOR_SHARP
, USB_PRODUCT_SHARP_SL5500
}, CDCE_ZAURUS
},
107 {{ USB_VENDOR_SHARP
, USB_PRODUCT_SHARP_A300
}, CDCE_ZAURUS
| CDCE_NO_UNION
},
108 {{ USB_VENDOR_SHARP
, USB_PRODUCT_SHARP_SL5600
}, CDCE_ZAURUS
| CDCE_NO_UNION
},
109 {{ USB_VENDOR_SHARP
, USB_PRODUCT_SHARP_C700
}, CDCE_ZAURUS
| CDCE_NO_UNION
},
110 {{ USB_VENDOR_SHARP
, USB_PRODUCT_SHARP_C750
}, CDCE_ZAURUS
| CDCE_NO_UNION
},
112 #define cdce_lookup(v, p) ((const struct cdce_type *)usb_lookup(cdce_devs, v, p))
114 int cdce_match(device_t
, cfdata_t
, void *);
115 void cdce_attach(device_t
, device_t
, void *);
116 int cdce_detach(device_t
, int);
117 int cdce_activate(device_t
, enum devact
);
118 extern struct cfdriver cdce_cd
;
119 CFATTACH_DECL_NEW(cdce
, sizeof(struct cdce_softc
), cdce_match
, cdce_attach
,
120 cdce_detach
, cdce_activate
);
123 cdce_match(device_t parent
, cfdata_t match
, void *aux
)
125 struct usbif_attach_arg
*uaa
= aux
;
127 if (cdce_lookup(uaa
->vendor
, uaa
->product
) != NULL
)
128 return (UMATCH_VENDOR_PRODUCT
);
130 if (uaa
->class == UICLASS_CDC
&& uaa
->subclass
==
131 UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL
)
132 return (UMATCH_IFACECLASS_GENERIC
);
134 return (UMATCH_NONE
);
138 cdce_attach(device_t parent
, device_t self
, void *aux
)
140 struct cdce_softc
*sc
= device_private(self
);
141 struct usbif_attach_arg
*uaa
= aux
;
145 usbd_device_handle dev
= uaa
->device
;
146 const struct cdce_type
*t
;
147 usb_interface_descriptor_t
*id
;
148 usb_endpoint_descriptor_t
*ed
;
149 const usb_cdc_union_descriptor_t
*ud
;
150 usb_config_descriptor_t
*cd
;
153 u_char eaddr
[ETHER_ADDR_LEN
];
154 const usb_cdc_ethernet_descriptor_t
*ue
;
155 char eaddr_str
[USB_MAX_ENCODED_STRING_LEN
];
162 devinfop
= usbd_devinfo_alloc(dev
, 0);
163 aprint_normal_dev(self
, "%s\n", devinfop
);
164 usbd_devinfo_free(devinfop
);
166 sc
->cdce_udev
= uaa
->device
;
167 sc
->cdce_ctl_iface
= uaa
->iface
;
169 t
= cdce_lookup(uaa
->vendor
, uaa
->product
);
171 sc
->cdce_flags
= t
->cdce_flags
;
173 if (sc
->cdce_flags
& CDCE_NO_UNION
)
174 sc
->cdce_data_iface
= sc
->cdce_ctl_iface
;
176 ud
= (const usb_cdc_union_descriptor_t
*)usb_find_desc(sc
->cdce_udev
,
177 UDESC_CS_INTERFACE
, UDESCSUB_CDC_UNION
);
179 aprint_error_dev(self
, "no union descriptor\n");
182 data_ifcno
= ud
->bSlaveInterface
[0];
184 for (i
= 0; i
< uaa
->nifaces
; i
++) {
185 if (uaa
->ifaces
[i
] != NULL
) {
186 id
= usbd_get_interface_descriptor(
188 if (id
!= NULL
&& id
->bInterfaceNumber
==
190 sc
->cdce_data_iface
= uaa
->ifaces
[i
];
191 uaa
->ifaces
[i
] = NULL
;
197 if (sc
->cdce_data_iface
== NULL
) {
198 aprint_error_dev(self
, "no data interface\n");
204 * The Data Class interface of a networking device shall have a minimum
205 * of two interface settings. The first setting (the default interface
206 * setting) includes no endpoints and therefore no networking traffic is
207 * exchanged whenever the default interface setting is selected. One or
208 * more additional interface settings are used for normal operation, and
209 * therefore each includes a pair of endpoints (one IN, and one OUT) to
210 * exchange network traffic. Select an alternate interface setting to
211 * initialize the network aspects of the device and to enable the
212 * exchange of network traffic.
215 * Some devices, most notably cable modems, include interface settings
216 * that have no IN or OUT endpoint, therefore loop through the list of all
217 * available interface settings looking for one with both IN and OUT
220 id
= usbd_get_interface_descriptor(sc
->cdce_data_iface
);
221 cd
= usbd_get_config_descriptor(sc
->cdce_udev
);
222 numalts
= usbd_get_no_alts(cd
, id
->bInterfaceNumber
);
224 for (j
= 0; j
< numalts
; j
++) {
225 if (usbd_set_interface(sc
->cdce_data_iface
, j
)) {
226 aprint_error_dev(sc
->cdce_dev
,
227 "setting alternate interface failed\n");
230 /* Find endpoints. */
231 id
= usbd_get_interface_descriptor(sc
->cdce_data_iface
);
232 sc
->cdce_bulkin_no
= sc
->cdce_bulkout_no
= -1;
233 for (i
= 0; i
< id
->bNumEndpoints
; i
++) {
234 ed
= usbd_interface2endpoint_descriptor(sc
->cdce_data_iface
, i
);
236 aprint_error_dev(self
,
237 "could not read endpoint descriptor\n");
240 if (UE_GET_DIR(ed
->bEndpointAddress
) == UE_DIR_IN
&&
241 UE_GET_XFERTYPE(ed
->bmAttributes
) == UE_BULK
) {
242 sc
->cdce_bulkin_no
= ed
->bEndpointAddress
;
243 } else if (UE_GET_DIR(ed
->bEndpointAddress
) == UE_DIR_OUT
&&
244 UE_GET_XFERTYPE(ed
->bmAttributes
) == UE_BULK
) {
245 sc
->cdce_bulkout_no
= ed
->bEndpointAddress
;
246 } else if (UE_GET_DIR(ed
->bEndpointAddress
) == UE_DIR_IN
&&
247 UE_GET_XFERTYPE(ed
->bmAttributes
) == UE_INTERRUPT
) {
248 /* XXX: CDC spec defines an interrupt pipe, but it is not
249 * needed for simple host-to-host applications. */
251 aprint_error_dev(self
, "unexpected endpoint\n");
254 /* If we found something, try and use it... */
255 if ((sc
->cdce_bulkin_no
!= -1) && (sc
->cdce_bulkout_no
!= -1))
259 if (sc
->cdce_bulkin_no
== -1) {
260 aprint_error_dev(self
, "could not find data bulk in\n");
263 if (sc
->cdce_bulkout_no
== -1 ) {
264 aprint_error_dev(self
, "could not find data bulk out\n");
268 ue
= (const usb_cdc_ethernet_descriptor_t
*)usb_find_desc(dev
,
269 UDESC_INTERFACE
, UDESCSUB_CDC_ENF
);
270 if (!ue
|| usbd_get_string(dev
, ue
->iMacAddress
, eaddr_str
)) {
271 aprint_normal_dev(self
, "faking address\n");
273 memcpy(&eaddr
[1], &hardclock_ticks
, sizeof(u_int32_t
));
274 eaddr
[5] = (u_int8_t
)(device_unit(sc
->cdce_dev
));
276 (void)ether_nonstatic_aton(eaddr
, eaddr_str
);
281 aprint_normal_dev(self
, "address %s\n", ether_sprintf(eaddr
));
285 ifp
->if_flags
= IFF_BROADCAST
| IFF_SIMPLEX
| IFF_MULTICAST
;
286 ifp
->if_ioctl
= cdce_ioctl
;
287 ifp
->if_start
= cdce_start
;
288 ifp
->if_watchdog
= cdce_watchdog
;
289 strncpy(ifp
->if_xname
, device_xname(sc
->cdce_dev
), IFNAMSIZ
);
291 IFQ_SET_READY(&ifp
->if_snd
);
294 ether_ifattach(ifp
, eaddr
);
296 sc
->cdce_attached
= 1;
299 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH
, sc
->cdce_udev
,
306 cdce_detach(device_t self
, int flags
)
308 struct cdce_softc
*sc
= device_private(self
);
309 struct ifnet
*ifp
= GET_IFP(sc
);
314 if (!sc
->cdce_attached
) {
319 if (ifp
->if_flags
& IFF_RUNNING
)
326 sc
->cdce_attached
= 0;
333 cdce_start(struct ifnet
*ifp
)
335 struct cdce_softc
*sc
= ifp
->if_softc
;
336 struct mbuf
*m_head
= NULL
;
338 if (sc
->cdce_dying
|| (ifp
->if_flags
& IFF_OACTIVE
))
341 IFQ_POLL(&ifp
->if_snd
, m_head
);
345 if (cdce_encap(sc
, m_head
, 0)) {
346 ifp
->if_flags
|= IFF_OACTIVE
;
350 IFQ_DEQUEUE(&ifp
->if_snd
, m_head
);
354 BPF_MTAP(ifp
, m_head
);
357 ifp
->if_flags
|= IFF_OACTIVE
;
363 cdce_encap(struct cdce_softc
*sc
, struct mbuf
*m
, int idx
)
365 struct cdce_chain
*c
;
369 c
= &sc
->cdce_cdata
.cdce_tx_chain
[idx
];
371 m_copydata(m
, 0, m
->m_pkthdr
.len
, c
->cdce_buf
);
372 if (sc
->cdce_flags
& CDCE_ZAURUS
) {
373 /* Zaurus wants a 32-bit CRC appended to every frame */
376 crc
= cdce_crc32(c
->cdce_buf
, m
->m_pkthdr
.len
);
377 memcpy(c
->cdce_buf
+ m
->m_pkthdr
.len
, &crc
, 4);
382 usbd_setup_xfer(c
->cdce_xfer
, sc
->cdce_bulkout_pipe
, c
, c
->cdce_buf
,
383 m
->m_pkthdr
.len
+ extra
, USBD_NO_COPY
, 10000, cdce_txeof
);
384 err
= usbd_transfer(c
->cdce_xfer
);
385 if (err
!= USBD_IN_PROGRESS
) {
390 sc
->cdce_cdata
.cdce_tx_cnt
++;
396 cdce_stop(struct cdce_softc
*sc
)
399 struct ifnet
*ifp
= GET_IFP(sc
);
404 if (sc
->cdce_bulkin_pipe
!= NULL
) {
405 err
= usbd_abort_pipe(sc
->cdce_bulkin_pipe
);
407 printf("%s: abort rx pipe failed: %s\n",
408 device_xname(sc
->cdce_dev
), usbd_errstr(err
));
409 err
= usbd_close_pipe(sc
->cdce_bulkin_pipe
);
411 printf("%s: close rx pipe failed: %s\n",
412 device_xname(sc
->cdce_dev
), usbd_errstr(err
));
413 sc
->cdce_bulkin_pipe
= NULL
;
416 if (sc
->cdce_bulkout_pipe
!= NULL
) {
417 err
= usbd_abort_pipe(sc
->cdce_bulkout_pipe
);
419 printf("%s: abort tx pipe failed: %s\n",
420 device_xname(sc
->cdce_dev
), usbd_errstr(err
));
421 err
= usbd_close_pipe(sc
->cdce_bulkout_pipe
);
423 printf("%s: close tx pipe failed: %s\n",
424 device_xname(sc
->cdce_dev
), usbd_errstr(err
));
425 sc
->cdce_bulkout_pipe
= NULL
;
428 for (i
= 0; i
< CDCE_RX_LIST_CNT
; i
++) {
429 if (sc
->cdce_cdata
.cdce_rx_chain
[i
].cdce_mbuf
!= NULL
) {
430 m_freem(sc
->cdce_cdata
.cdce_rx_chain
[i
].cdce_mbuf
);
431 sc
->cdce_cdata
.cdce_rx_chain
[i
].cdce_mbuf
= NULL
;
433 if (sc
->cdce_cdata
.cdce_rx_chain
[i
].cdce_xfer
!= NULL
) {
434 usbd_free_xfer(sc
->cdce_cdata
.cdce_rx_chain
[i
].cdce_xfer
);
435 sc
->cdce_cdata
.cdce_rx_chain
[i
].cdce_xfer
= NULL
;
439 for (i
= 0; i
< CDCE_TX_LIST_CNT
; i
++) {
440 if (sc
->cdce_cdata
.cdce_tx_chain
[i
].cdce_mbuf
!= NULL
) {
441 m_freem(sc
->cdce_cdata
.cdce_tx_chain
[i
].cdce_mbuf
);
442 sc
->cdce_cdata
.cdce_tx_chain
[i
].cdce_mbuf
= NULL
;
444 if (sc
->cdce_cdata
.cdce_tx_chain
[i
].cdce_xfer
!= NULL
) {
445 usbd_free_xfer(sc
->cdce_cdata
.cdce_tx_chain
[i
].cdce_xfer
);
446 sc
->cdce_cdata
.cdce_tx_chain
[i
].cdce_xfer
= NULL
;
450 ifp
->if_flags
&= ~(IFF_RUNNING
| IFF_OACTIVE
);
454 cdce_ioctl(struct ifnet
*ifp
, u_long command
, void *data
)
456 struct cdce_softc
*sc
= ifp
->if_softc
;
457 struct ifaddr
*ifa
= (struct ifaddr
*)data
;
458 struct ifreq
*ifr
= (struct ifreq
*)data
;
468 ifp
->if_flags
|= IFF_UP
;
470 switch (ifa
->ifa_addr
->sa_family
) {
473 arp_ifinit(ifp
, ifa
);
480 if (ifr
->ifr_mtu
< ETHERMIN
|| ifr
->ifr_mtu
> ETHERMTU
)
482 else if ((error
= ifioctl_common(ifp
, command
, data
)) == ENETRESET
)
487 if ((error
= ifioctl_common(ifp
, command
, data
)) != 0)
489 /* XXX re-use ether_ioctl() */
490 switch (ifp
->if_flags
& (IFF_UP
|IFF_RUNNING
)) {
503 error
= ether_ioctl(ifp
, command
, data
);
513 cdce_watchdog(struct ifnet
*ifp
)
515 struct cdce_softc
*sc
= ifp
->if_softc
;
521 printf("%s: watchdog timeout\n", device_xname(sc
->cdce_dev
));
527 struct cdce_softc
*sc
= xsc
;
528 struct ifnet
*ifp
= GET_IFP(sc
);
529 struct cdce_chain
*c
;
533 if (ifp
->if_flags
& IFF_RUNNING
)
538 if (cdce_tx_list_init(sc
) == ENOBUFS
) {
539 printf("%s: tx list init failed\n", device_xname(sc
->cdce_dev
));
544 if (cdce_rx_list_init(sc
) == ENOBUFS
) {
545 printf("%s: rx list init failed\n", device_xname(sc
->cdce_dev
));
550 /* Maybe set multicast / broadcast here??? */
552 err
= usbd_open_pipe(sc
->cdce_data_iface
, sc
->cdce_bulkin_no
,
553 USBD_EXCLUSIVE_USE
, &sc
->cdce_bulkin_pipe
);
555 printf("%s: open rx pipe failed: %s\n", device_xname(sc
->cdce_dev
),
561 err
= usbd_open_pipe(sc
->cdce_data_iface
, sc
->cdce_bulkout_no
,
562 USBD_EXCLUSIVE_USE
, &sc
->cdce_bulkout_pipe
);
564 printf("%s: open tx pipe failed: %s\n",
565 device_xname(sc
->cdce_dev
), usbd_errstr(err
));
570 for (i
= 0; i
< CDCE_RX_LIST_CNT
; i
++) {
571 c
= &sc
->cdce_cdata
.cdce_rx_chain
[i
];
572 usbd_setup_xfer(c
->cdce_xfer
, sc
->cdce_bulkin_pipe
, c
,
573 c
->cdce_buf
, CDCE_BUFSZ
, USBD_SHORT_XFER_OK
| USBD_NO_COPY
,
574 USBD_NO_TIMEOUT
, cdce_rxeof
);
575 usbd_transfer(c
->cdce_xfer
);
578 ifp
->if_flags
|= IFF_RUNNING
;
579 ifp
->if_flags
&= ~IFF_OACTIVE
;
585 cdce_newbuf(struct cdce_softc
*sc
, struct cdce_chain
*c
, struct mbuf
*m
)
587 struct mbuf
*m_new
= NULL
;
590 MGETHDR(m_new
, M_DONTWAIT
, MT_DATA
);
592 printf("%s: no memory for rx list "
593 "-- packet dropped!\n", device_xname(sc
->cdce_dev
));
596 MCLGET(m_new
, M_DONTWAIT
);
597 if (!(m_new
->m_flags
& M_EXT
)) {
598 printf("%s: no memory for rx list "
599 "-- packet dropped!\n", device_xname(sc
->cdce_dev
));
603 m_new
->m_len
= m_new
->m_pkthdr
.len
= MCLBYTES
;
606 m_new
->m_len
= m_new
->m_pkthdr
.len
= MCLBYTES
;
607 m_new
->m_data
= m_new
->m_ext
.ext_buf
;
609 c
->cdce_mbuf
= m_new
;
614 cdce_rx_list_init(struct cdce_softc
*sc
)
616 struct cdce_cdata
*cd
;
617 struct cdce_chain
*c
;
620 cd
= &sc
->cdce_cdata
;
621 for (i
= 0; i
< CDCE_RX_LIST_CNT
; i
++) {
622 c
= &cd
->cdce_rx_chain
[i
];
625 if (cdce_newbuf(sc
, c
, NULL
) == ENOBUFS
)
627 if (c
->cdce_xfer
== NULL
) {
628 c
->cdce_xfer
= usbd_alloc_xfer(sc
->cdce_udev
);
629 if (c
->cdce_xfer
== NULL
)
631 c
->cdce_buf
= usbd_alloc_buffer(c
->cdce_xfer
, CDCE_BUFSZ
);
632 if (c
->cdce_buf
== NULL
)
641 cdce_tx_list_init(struct cdce_softc
*sc
)
643 struct cdce_cdata
*cd
;
644 struct cdce_chain
*c
;
647 cd
= &sc
->cdce_cdata
;
648 for (i
= 0; i
< CDCE_TX_LIST_CNT
; i
++) {
649 c
= &cd
->cdce_tx_chain
[i
];
653 if (c
->cdce_xfer
== NULL
) {
654 c
->cdce_xfer
= usbd_alloc_xfer(sc
->cdce_udev
);
655 if (c
->cdce_xfer
== NULL
)
657 c
->cdce_buf
= usbd_alloc_buffer(c
->cdce_xfer
, CDCE_BUFSZ
);
658 if (c
->cdce_buf
== NULL
)
667 cdce_rxeof(usbd_xfer_handle xfer
, usbd_private_handle priv
, usbd_status status
)
669 struct cdce_chain
*c
= priv
;
670 struct cdce_softc
*sc
= c
->cdce_sc
;
671 struct ifnet
*ifp
= GET_IFP(sc
);
676 if (sc
->cdce_dying
|| !(ifp
->if_flags
& IFF_RUNNING
))
679 if (status
!= USBD_NORMAL_COMPLETION
) {
680 if (status
== USBD_NOT_STARTED
|| status
== USBD_CANCELLED
)
682 if (sc
->cdce_rxeof_errors
== 0)
683 printf("%s: usb error on rx: %s\n",
684 device_xname(sc
->cdce_dev
), usbd_errstr(status
));
685 if (status
== USBD_STALLED
)
686 usbd_clear_endpoint_stall_async(sc
->cdce_bulkin_pipe
);
687 DELAY(sc
->cdce_rxeof_errors
* 10000);
688 sc
->cdce_rxeof_errors
++;
692 sc
->cdce_rxeof_errors
= 0;
694 usbd_get_xfer_status(xfer
, NULL
, NULL
, &total_len
, NULL
);
695 if (sc
->cdce_flags
& CDCE_ZAURUS
)
696 total_len
-= 4; /* Strip off CRC added by Zaurus */
701 memcpy(mtod(m
, char *), c
->cdce_buf
, total_len
);
703 if (total_len
< sizeof(struct ether_header
)) {
709 m
->m_pkthdr
.len
= m
->m_len
= total_len
;
710 m
->m_pkthdr
.rcvif
= ifp
;
714 if (cdce_newbuf(sc
, c
, NULL
) == ENOBUFS
) {
724 (*(ifp
)->if_input
)((ifp
), (m
));
730 /* Setup new transfer. */
731 usbd_setup_xfer(c
->cdce_xfer
, sc
->cdce_bulkin_pipe
, c
, c
->cdce_buf
,
732 CDCE_BUFSZ
, USBD_SHORT_XFER_OK
| USBD_NO_COPY
, USBD_NO_TIMEOUT
,
734 usbd_transfer(c
->cdce_xfer
);
738 cdce_txeof(usbd_xfer_handle xfer
, usbd_private_handle priv
,
741 struct cdce_chain
*c
= priv
;
742 struct cdce_softc
*sc
= c
->cdce_sc
;
743 struct ifnet
*ifp
= GET_IFP(sc
);
753 ifp
->if_flags
&= ~IFF_OACTIVE
;
755 if (status
!= USBD_NORMAL_COMPLETION
) {
756 if (status
== USBD_NOT_STARTED
|| status
== USBD_CANCELLED
) {
761 printf("%s: usb error on tx: %s\n", device_xname(sc
->cdce_dev
),
762 usbd_errstr(status
));
763 if (status
== USBD_STALLED
)
764 usbd_clear_endpoint_stall_async(sc
->cdce_bulkout_pipe
);
769 usbd_get_xfer_status(c
->cdce_xfer
, NULL
, NULL
, NULL
, &err
);
771 if (c
->cdce_mbuf
!= NULL
) {
772 m_freem(c
->cdce_mbuf
);
781 if (IFQ_IS_EMPTY(&ifp
->if_snd
) == 0)
788 cdce_activate(device_t self
, enum devact act
)
790 struct cdce_softc
*sc
= device_private(self
);
793 case DVACT_DEACTIVATE
:
794 if_deactivate(GET_IFP(sc
));
803 /* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
804 * code or tables extracted from it, as desired without restriction.
807 static uint32_t cdce_crc32_tab
[] = {
808 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
809 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
810 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
811 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
812 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
813 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
814 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
815 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
816 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
817 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
818 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
819 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
820 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
821 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
822 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
823 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
824 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
825 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
826 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
827 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
828 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
829 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
830 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
831 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
832 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
833 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
834 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
835 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
836 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
837 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
838 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
839 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
840 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
841 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
842 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
843 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
844 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
845 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
846 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
847 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
848 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
849 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
850 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
854 cdce_crc32(const void *buf
, size_t size
)
863 crc
= cdce_crc32_tab
[(crc
^ *p
++) & 0xFF] ^ (crc
>> 8);