xref: /freebsd/sys/dev/usb/net/if_cdce.c (revision eb6219e337483cb80eccb6f2b4ad649bc1d751ec)
1 /*	$NetBSD: if_cdce.c,v 1.4 2004/10/24 12:50:54 augustss Exp $ */
2 
3 /*-
4  * Copyright (c) 1997, 1998, 1999, 2000-2003 Bill Paul <wpaul@windriver.com>
5  * Copyright (c) 2003-2005 Craig Boston
6  * Copyright (c) 2004 Daniel Hartmeier
7  * Copyright (c) 2009 Hans Petter Selasky
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by Bill Paul.
21  * 4. Neither the name of the author nor the names of any co-contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul, THE VOICES IN HIS HEAD OR
29  * THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
32  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
33  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
34  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
35  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36  */
37 
38 /*
39  * USB Communication Device Class (Ethernet Networking Control Model)
40  * http://www.usb.org/developers/devclass_docs/usbcdc11.pdf
41  */
42 
43 #include <sys/cdefs.h>
44 __FBSDID("$FreeBSD$");
45 
46 #include <sys/stdint.h>
47 #include <sys/stddef.h>
48 #include <sys/param.h>
49 #include <sys/queue.h>
50 #include <sys/types.h>
51 #include <sys/systm.h>
52 #include <sys/kernel.h>
53 #include <sys/bus.h>
54 #include <sys/linker_set.h>
55 #include <sys/module.h>
56 #include <sys/lock.h>
57 #include <sys/mutex.h>
58 #include <sys/condvar.h>
59 #include <sys/sysctl.h>
60 #include <sys/sx.h>
61 #include <sys/unistd.h>
62 #include <sys/callout.h>
63 #include <sys/malloc.h>
64 #include <sys/priv.h>
65 
66 #include <dev/usb/usb.h>
67 #include <dev/usb/usbdi.h>
68 #include <dev/usb/usbdi_util.h>
69 #include <dev/usb/usb_cdc.h>
70 #include "usbdevs.h"
71 
72 #define	USB_DEBUG_VAR cdce_debug
73 #include <dev/usb/usb_debug.h>
74 #include <dev/usb/usb_process.h>
75 #include "usb_if.h"
76 
77 #include <dev/usb/net/usb_ethernet.h>
78 #include <dev/usb/net/if_cdcereg.h>
79 
80 static device_probe_t cdce_probe;
81 static device_attach_t cdce_attach;
82 static device_detach_t cdce_detach;
83 static device_suspend_t cdce_suspend;
84 static device_resume_t cdce_resume;
85 static usb_handle_request_t cdce_handle_request;
86 
87 static usb_callback_t cdce_bulk_write_callback;
88 static usb_callback_t cdce_bulk_read_callback;
89 static usb_callback_t cdce_intr_read_callback;
90 static usb_callback_t cdce_intr_write_callback;
91 
92 static uether_fn_t cdce_attach_post;
93 static uether_fn_t cdce_init;
94 static uether_fn_t cdce_stop;
95 static uether_fn_t cdce_start;
96 static uether_fn_t cdce_setmulti;
97 static uether_fn_t cdce_setpromisc;
98 
99 static uint32_t	cdce_m_crc32(struct mbuf *, uint32_t, uint32_t);
100 
101 #if USB_DEBUG
102 static int cdce_debug = 0;
103 
104 SYSCTL_NODE(_hw_usb, OID_AUTO, cdce, CTLFLAG_RW, 0, "USB CDC-Ethernet");
105 SYSCTL_INT(_hw_usb_cdce, OID_AUTO, debug, CTLFLAG_RW, &cdce_debug, 0,
106     "Debug level");
107 #endif
108 
109 static const struct usb_config cdce_config[CDCE_N_TRANSFER] = {
110 
111 	[CDCE_BULK_RX] = {
112 		.type = UE_BULK,
113 		.endpoint = UE_ADDR_ANY,
114 		.direction = UE_DIR_RX,
115 		.if_index = 0,
116 		.frames = CDCE_FRAMES_MAX,
117 		.bufsize = (CDCE_FRAMES_MAX * MCLBYTES),
118 		.flags = {.pipe_bof = 1,.short_frames_ok = 1,.short_xfer_ok = 1,.ext_buffer = 1,},
119 		.callback = cdce_bulk_read_callback,
120 		.timeout = 0,	/* no timeout */
121 		.usb_mode = USB_MODE_DUAL,	/* both modes */
122 	},
123 
124 	[CDCE_BULK_TX] = {
125 		.type = UE_BULK,
126 		.endpoint = UE_ADDR_ANY,
127 		.direction = UE_DIR_TX,
128 		.if_index = 0,
129 		.frames = CDCE_FRAMES_MAX,
130 		.bufsize = (CDCE_FRAMES_MAX * MCLBYTES),
131 		.flags = {.pipe_bof = 1,.force_short_xfer = 1,.ext_buffer = 1,},
132 		.callback = cdce_bulk_write_callback,
133 		.timeout = 10000,	/* 10 seconds */
134 		.usb_mode = USB_MODE_DUAL,	/* both modes */
135 	},
136 
137 	[CDCE_INTR_RX] = {
138 		.type = UE_INTERRUPT,
139 		.endpoint = UE_ADDR_ANY,
140 		.direction = UE_DIR_RX,
141 		.if_index = 1,
142 		.bufsize = CDCE_IND_SIZE_MAX,
143 		.flags = {.pipe_bof = 1,.short_xfer_ok = 1,.no_pipe_ok = 1,},
144 		.callback = cdce_intr_read_callback,
145 		.timeout = 0,
146 		.usb_mode = USB_MODE_HOST,
147 	},
148 
149 	[CDCE_INTR_TX] = {
150 		.type = UE_INTERRUPT,
151 		.endpoint = UE_ADDR_ANY,
152 		.direction = UE_DIR_TX,
153 		.if_index = 1,
154 		.bufsize = CDCE_IND_SIZE_MAX,
155 		.flags = {.pipe_bof = 1,.force_short_xfer = 1,.no_pipe_ok = 1,},
156 		.callback = cdce_intr_write_callback,
157 		.timeout = 10000,	/* 10 seconds */
158 		.usb_mode = USB_MODE_DEVICE,
159 	},
160 };
161 
162 static device_method_t cdce_methods[] = {
163 	/* USB interface */
164 	DEVMETHOD(usb_handle_request, cdce_handle_request),
165 
166 	/* Device interface */
167 	DEVMETHOD(device_probe, cdce_probe),
168 	DEVMETHOD(device_attach, cdce_attach),
169 	DEVMETHOD(device_detach, cdce_detach),
170 	DEVMETHOD(device_suspend, cdce_suspend),
171 	DEVMETHOD(device_resume, cdce_resume),
172 
173 	{0, 0}
174 };
175 
176 static driver_t cdce_driver = {
177 	.name = "cdce",
178 	.methods = cdce_methods,
179 	.size = sizeof(struct cdce_softc),
180 };
181 
182 static devclass_t cdce_devclass;
183 
184 DRIVER_MODULE(cdce, uhub, cdce_driver, cdce_devclass, NULL, 0);
185 MODULE_VERSION(cdce, 1);
186 MODULE_DEPEND(cdce, uether, 1, 1, 1);
187 MODULE_DEPEND(cdce, usb, 1, 1, 1);
188 MODULE_DEPEND(cdce, ether, 1, 1, 1);
189 
190 static const struct usb_ether_methods cdce_ue_methods = {
191 	.ue_attach_post = cdce_attach_post,
192 	.ue_start = cdce_start,
193 	.ue_init = cdce_init,
194 	.ue_stop = cdce_stop,
195 	.ue_setmulti = cdce_setmulti,
196 	.ue_setpromisc = cdce_setpromisc,
197 };
198 
199 static const struct usb_device_id cdce_devs[] = {
200 	{USB_IF_CSI(UICLASS_CDC, UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0)},
201 	{USB_IF_CSI(UICLASS_CDC, UISUBCLASS_MOBILE_DIRECT_LINE_MODEL, 0)},
202 
203 	{USB_VPI(USB_VENDOR_ACERLABS, USB_PRODUCT_ACERLABS_M5632, CDCE_FLAG_NO_UNION)},
204 	{USB_VPI(USB_VENDOR_AMBIT, USB_PRODUCT_AMBIT_NTL_250, CDCE_FLAG_NO_UNION)},
205 	{USB_VPI(USB_VENDOR_COMPAQ, USB_PRODUCT_COMPAQ_IPAQLINUX, CDCE_FLAG_NO_UNION)},
206 	{USB_VPI(USB_VENDOR_GMATE, USB_PRODUCT_GMATE_YP3X00, CDCE_FLAG_NO_UNION)},
207 	{USB_VPI(USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_USBLAN, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)},
208 	{USB_VPI(USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_USBLAN2, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)},
209 	{USB_VPI(USB_VENDOR_NETCHIP, USB_PRODUCT_NETCHIP_ETHERNETGADGET, CDCE_FLAG_NO_UNION)},
210 	{USB_VPI(USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2501, CDCE_FLAG_NO_UNION)},
211 	{USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5500, CDCE_FLAG_ZAURUS)},
212 	{USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5600, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)},
213 	{USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLA300, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)},
214 	{USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLC700, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)},
215 	{USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLC750, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)},
216 };
217 
218 static int
219 cdce_probe(device_t dev)
220 {
221 	struct usb_attach_arg *uaa = device_get_ivars(dev);
222 
223 	return (usbd_lookup_id_by_uaa(cdce_devs, sizeof(cdce_devs), uaa));
224 }
225 
226 static void
227 cdce_attach_post(struct usb_ether *ue)
228 {
229 	/* no-op */
230 	return;
231 }
232 
233 static int
234 cdce_attach(device_t dev)
235 {
236 	struct cdce_softc *sc = device_get_softc(dev);
237 	struct usb_ether *ue = &sc->sc_ue;
238 	struct usb_attach_arg *uaa = device_get_ivars(dev);
239 	struct usb_interface *iface;
240 	const struct usb_cdc_union_descriptor *ud;
241 	const struct usb_interface_descriptor *id;
242 	const struct usb_cdc_ethernet_descriptor *ued;
243 	int error;
244 	uint8_t i;
245 	char eaddr_str[5 * ETHER_ADDR_LEN];	/* approx */
246 
247 	sc->sc_flags = USB_GET_DRIVER_INFO(uaa);
248 
249 	device_set_usb_desc(dev);
250 
251 	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
252 
253 	if (sc->sc_flags & CDCE_FLAG_NO_UNION) {
254 		sc->sc_ifaces_index[0] = uaa->info.bIfaceIndex;
255 		sc->sc_ifaces_index[1] = uaa->info.bIfaceIndex;
256 		sc->sc_data_iface_no = 0;	/* not used */
257 		goto alloc_transfers;
258 	}
259 	ud = usbd_find_descriptor
260 	    (uaa->device, NULL, uaa->info.bIfaceIndex,
261 	    UDESC_CS_INTERFACE, 0 - 1, UDESCSUB_CDC_UNION, 0 - 1);
262 
263 	if ((ud == NULL) || (ud->bLength < sizeof(*ud))) {
264 		device_printf(dev, "no union descriptor!\n");
265 		goto detach;
266 	}
267 	sc->sc_data_iface_no = ud->bSlaveInterface[0];
268 
269 	for (i = 0;; i++) {
270 
271 		iface = usbd_get_iface(uaa->device, i);
272 
273 		if (iface) {
274 
275 			id = usbd_get_interface_descriptor(iface);
276 
277 			if (id && (id->bInterfaceNumber ==
278 			    sc->sc_data_iface_no)) {
279 				sc->sc_ifaces_index[0] = i;
280 				sc->sc_ifaces_index[1] = uaa->info.bIfaceIndex;
281 				usbd_set_parent_iface(uaa->device, i, uaa->info.bIfaceIndex);
282 				break;
283 			}
284 		} else {
285 			device_printf(dev, "no data interface found!\n");
286 			goto detach;
287 		}
288 	}
289 
290 	/*
291 	 * <quote>
292 	 *
293 	 *  The Data Class interface of a networking device shall have
294 	 *  a minimum of two interface settings. The first setting
295 	 *  (the default interface setting) includes no endpoints and
296 	 *  therefore no networking traffic is exchanged whenever the
297 	 *  default interface setting is selected. One or more
298 	 *  additional interface settings are used for normal
299 	 *  operation, and therefore each includes a pair of endpoints
300 	 *  (one IN, and one OUT) to exchange network traffic. Select
301 	 *  an alternate interface setting to initialize the network
302 	 *  aspects of the device and to enable the exchange of
303 	 *  network traffic.
304 	 *
305 	 * </quote>
306 	 *
307 	 * Some devices, most notably cable modems, include interface
308 	 * settings that have no IN or OUT endpoint, therefore loop
309 	 * through the list of all available interface settings
310 	 * looking for one with both IN and OUT endpoints.
311 	 */
312 
313 alloc_transfers:
314 
315 	for (i = 0; i != 32; i++) {
316 
317 		error = usbd_set_alt_interface_index
318 		    (uaa->device, sc->sc_ifaces_index[0], i);
319 
320 		if (error) {
321 			device_printf(dev, "no valid alternate "
322 			    "setting found!\n");
323 			goto detach;
324 		}
325 		error = usbd_transfer_setup
326 		    (uaa->device, sc->sc_ifaces_index,
327 		    sc->sc_xfer, cdce_config, CDCE_N_TRANSFER,
328 		    sc, &sc->sc_mtx);
329 
330 		if (error == 0) {
331 			break;
332 		}
333 	}
334 
335 	ued = usbd_find_descriptor
336 	    (uaa->device, NULL, uaa->info.bIfaceIndex,
337 	    UDESC_CS_INTERFACE, 0 - 1, UDESCSUB_CDC_ENF, 0 - 1);
338 
339 	if ((ued == NULL) || (ued->bLength < sizeof(*ued))) {
340 		error = USB_ERR_INVAL;
341 	} else {
342 		error = usbd_req_get_string_any(uaa->device, NULL,
343 		    eaddr_str, sizeof(eaddr_str), ued->iMacAddress);
344 	}
345 
346 	if (error) {
347 
348 		/* fake MAC address */
349 
350 		device_printf(dev, "faking MAC address\n");
351 		sc->sc_ue.ue_eaddr[0] = 0x2a;
352 		memcpy(&sc->sc_ue.ue_eaddr[1], &ticks, sizeof(uint32_t));
353 		sc->sc_ue.ue_eaddr[5] = device_get_unit(dev);
354 
355 	} else {
356 
357 		bzero(sc->sc_ue.ue_eaddr, sizeof(sc->sc_ue.ue_eaddr));
358 
359 		for (i = 0; i != (ETHER_ADDR_LEN * 2); i++) {
360 
361 			char c = eaddr_str[i];
362 
363 			if ('0' <= c && c <= '9')
364 				c -= '0';
365 			else if (c != 0)
366 				c -= 'A' - 10;
367 			else
368 				break;
369 
370 			c &= 0xf;
371 
372 			if ((i & 1) == 0)
373 				c <<= 4;
374 			sc->sc_ue.ue_eaddr[i / 2] |= c;
375 		}
376 
377 		if (uaa->usb_mode == USB_MODE_DEVICE) {
378 			/*
379 			 * Do not use the same MAC address like the peer !
380 			 */
381 			sc->sc_ue.ue_eaddr[5] ^= 0xFF;
382 		}
383 	}
384 
385 	ue->ue_sc = sc;
386 	ue->ue_dev = dev;
387 	ue->ue_udev = uaa->device;
388 	ue->ue_mtx = &sc->sc_mtx;
389 	ue->ue_methods = &cdce_ue_methods;
390 
391 	error = uether_ifattach(ue);
392 	if (error) {
393 		device_printf(dev, "could not attach interface\n");
394 		goto detach;
395 	}
396 	return (0);			/* success */
397 
398 detach:
399 	cdce_detach(dev);
400 	return (ENXIO);			/* failure */
401 }
402 
403 static int
404 cdce_detach(device_t dev)
405 {
406 	struct cdce_softc *sc = device_get_softc(dev);
407 	struct usb_ether *ue = &sc->sc_ue;
408 
409 	/* stop all USB transfers first */
410 	usbd_transfer_unsetup(sc->sc_xfer, CDCE_N_TRANSFER);
411 	uether_ifdetach(ue);
412 	mtx_destroy(&sc->sc_mtx);
413 
414 	return (0);
415 }
416 
417 static void
418 cdce_start(struct usb_ether *ue)
419 {
420 	struct cdce_softc *sc = uether_getsc(ue);
421 
422 	/*
423 	 * Start the USB transfers, if not already started:
424 	 */
425 	usbd_transfer_start(sc->sc_xfer[CDCE_BULK_TX]);
426 	usbd_transfer_start(sc->sc_xfer[CDCE_BULK_RX]);
427 }
428 
429 static void
430 cdce_free_queue(struct mbuf **ppm, uint8_t n)
431 {
432 	uint8_t x;
433 	for (x = 0; x != n; x++) {
434 		if (ppm[x] != NULL) {
435 			m_freem(ppm[x]);
436 			ppm[x] = NULL;
437 		}
438 	}
439 }
440 
441 static void
442 cdce_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
443 {
444 	struct cdce_softc *sc = usbd_xfer_softc(xfer);
445 	struct ifnet *ifp = uether_getifp(&sc->sc_ue);
446 	struct mbuf *m;
447 	struct mbuf *mt;
448 	uint32_t crc;
449 	uint8_t x;
450 	int actlen, aframes;
451 
452 	usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL);
453 
454 	DPRINTFN(1, "\n");
455 
456 	switch (USB_GET_STATE(xfer)) {
457 	case USB_ST_TRANSFERRED:
458 		DPRINTFN(11, "transfer complete: %u bytes in %u frames\n",
459 		    actlen, aframes);
460 
461 		ifp->if_opackets++;
462 
463 		/* free all previous TX buffers */
464 		cdce_free_queue(sc->sc_tx_buf, CDCE_FRAMES_MAX);
465 
466 		/* FALLTHROUGH */
467 	case USB_ST_SETUP:
468 tr_setup:
469 		for (x = 0; x != CDCE_FRAMES_MAX; x++) {
470 
471 			IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
472 
473 			if (m == NULL)
474 				break;
475 
476 			if (sc->sc_flags & CDCE_FLAG_ZAURUS) {
477 				/*
478 				 * Zaurus wants a 32-bit CRC appended
479 				 * to every frame
480 				 */
481 
482 				crc = cdce_m_crc32(m, 0, m->m_pkthdr.len);
483 				crc = htole32(crc);
484 
485 				if (!m_append(m, 4, (void *)&crc)) {
486 					m_freem(m);
487 					ifp->if_oerrors++;
488 					continue;
489 				}
490 			}
491 			if (m->m_len != m->m_pkthdr.len) {
492 				mt = m_defrag(m, M_DONTWAIT);
493 				if (mt == NULL) {
494 					m_freem(m);
495 					ifp->if_oerrors++;
496 					continue;
497 				}
498 				m = mt;
499 			}
500 			if (m->m_pkthdr.len > MCLBYTES) {
501 				m->m_pkthdr.len = MCLBYTES;
502 			}
503 			sc->sc_tx_buf[x] = m;
504 			usbd_xfer_set_frame_data(xfer, x, m->m_data, m->m_len);
505 
506 			/*
507 			 * If there's a BPF listener, bounce a copy of
508 			 * this frame to him:
509 			 */
510 			BPF_MTAP(ifp, m);
511 		}
512 		if (x != 0) {
513 			usbd_xfer_set_frames(xfer, x);
514 
515 			usbd_transfer_submit(xfer);
516 		}
517 		break;
518 
519 	default:			/* Error */
520 		DPRINTFN(11, "transfer error, %s\n",
521 		    usbd_errstr(error));
522 
523 		/* free all previous TX buffers */
524 		cdce_free_queue(sc->sc_tx_buf, CDCE_FRAMES_MAX);
525 
526 		/* count output errors */
527 		ifp->if_oerrors++;
528 
529 		if (error != USB_ERR_CANCELLED) {
530 			/* try to clear stall first */
531 			usbd_xfer_set_stall(xfer);
532 			goto tr_setup;
533 		}
534 		break;
535 	}
536 }
537 
538 static int32_t
539 cdce_m_crc32_cb(void *arg, void *src, uint32_t count)
540 {
541 	uint32_t *p_crc = arg;
542 
543 	*p_crc = crc32_raw(src, count, *p_crc);
544 	return (0);
545 }
546 
547 static uint32_t
548 cdce_m_crc32(struct mbuf *m, uint32_t src_offset, uint32_t src_len)
549 {
550 	uint32_t crc = 0xFFFFFFFF;
551 	int error;
552 
553 	error = m_apply(m, src_offset, src_len, cdce_m_crc32_cb, &crc);
554 	return (crc ^ 0xFFFFFFFF);
555 }
556 
557 static void
558 cdce_init(struct usb_ether *ue)
559 {
560 	struct cdce_softc *sc = uether_getsc(ue);
561 	struct ifnet *ifp = uether_getifp(ue);
562 
563 	CDCE_LOCK_ASSERT(sc, MA_OWNED);
564 
565 	ifp->if_drv_flags |= IFF_DRV_RUNNING;
566 
567 	/* start interrupt transfer */
568 	usbd_transfer_start(sc->sc_xfer[CDCE_INTR_RX]);
569 	usbd_transfer_start(sc->sc_xfer[CDCE_INTR_TX]);
570 
571 	/* stall data write direction, which depends on USB mode */
572 	usbd_xfer_set_stall(sc->sc_xfer[CDCE_BULK_TX]);
573 
574 	/* start data transfers */
575 	cdce_start(ue);
576 }
577 
578 static void
579 cdce_stop(struct usb_ether *ue)
580 {
581 	struct cdce_softc *sc = uether_getsc(ue);
582 	struct ifnet *ifp = uether_getifp(ue);
583 
584 	CDCE_LOCK_ASSERT(sc, MA_OWNED);
585 
586 	ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
587 
588 	/*
589 	 * stop all the transfers, if not already stopped:
590 	 */
591 	usbd_transfer_stop(sc->sc_xfer[CDCE_BULK_RX]);
592 	usbd_transfer_stop(sc->sc_xfer[CDCE_BULK_TX]);
593 	usbd_transfer_stop(sc->sc_xfer[CDCE_INTR_RX]);
594 	usbd_transfer_stop(sc->sc_xfer[CDCE_INTR_TX]);
595 }
596 
597 static void
598 cdce_setmulti(struct usb_ether *ue)
599 {
600 	/* no-op */
601 	return;
602 }
603 
604 static void
605 cdce_setpromisc(struct usb_ether *ue)
606 {
607 	/* no-op */
608 	return;
609 }
610 
611 static int
612 cdce_suspend(device_t dev)
613 {
614 	device_printf(dev, "Suspending\n");
615 	return (0);
616 }
617 
618 static int
619 cdce_resume(device_t dev)
620 {
621 	device_printf(dev, "Resuming\n");
622 	return (0);
623 }
624 
625 static void
626 cdce_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
627 {
628 	struct cdce_softc *sc = usbd_xfer_softc(xfer);
629 	struct mbuf *m;
630 	uint8_t x;
631 	int actlen, aframes, len;
632 
633 	usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL);
634 
635 	switch (USB_GET_STATE(xfer)) {
636 	case USB_ST_TRANSFERRED:
637 
638 		DPRINTF("received %u bytes in %u frames\n", actlen, aframes);
639 
640 		for (x = 0; x != aframes; x++) {
641 
642 			m = sc->sc_rx_buf[x];
643 			sc->sc_rx_buf[x] = NULL;
644 			len = usbd_xfer_frame_len(xfer, x);
645 
646 			/* Strip off CRC added by Zaurus, if any */
647 			if ((sc->sc_flags & CDCE_FLAG_ZAURUS) && len >= 14)
648 				len -= 4;
649 
650 			if (len < sizeof(struct ether_header)) {
651 				m_freem(m);
652 				continue;
653 			}
654 			/* queue up mbuf */
655 			uether_rxmbuf(&sc->sc_ue, m, len);
656 		}
657 
658 		/* FALLTHROUGH */
659 	case USB_ST_SETUP:
660 		/*
661 		 * TODO: Implement support for multi frame transfers,
662 		 * when the USB hardware supports it.
663 		 */
664 		for (x = 0; x != 1; x++) {
665 			if (sc->sc_rx_buf[x] == NULL) {
666 				m = uether_newbuf();
667 				if (m == NULL)
668 					goto tr_stall;
669 				sc->sc_rx_buf[x] = m;
670 			} else {
671 				m = sc->sc_rx_buf[x];
672 			}
673 
674 			usbd_xfer_set_frame_data(xfer, x, m->m_data, m->m_len);
675 		}
676 		/* set number of frames and start hardware */
677 		usbd_xfer_set_frames(xfer, x);
678 		usbd_transfer_submit(xfer);
679 		/* flush any received frames */
680 		uether_rxflush(&sc->sc_ue);
681 		break;
682 
683 	default:			/* Error */
684 		DPRINTF("error = %s\n",
685 		    usbd_errstr(error));
686 
687 		if (error != USB_ERR_CANCELLED) {
688 tr_stall:
689 			/* try to clear stall first */
690 			usbd_xfer_set_stall(xfer);
691 			usbd_xfer_set_frames(xfer, 0);
692 			usbd_transfer_submit(xfer);
693 			break;
694 		}
695 
696 		/* need to free the RX-mbufs when we are cancelled */
697 		cdce_free_queue(sc->sc_rx_buf, CDCE_FRAMES_MAX);
698 		break;
699 	}
700 }
701 
702 static void
703 cdce_intr_read_callback(struct usb_xfer *xfer, usb_error_t error)
704 {
705 	int actlen;
706 
707 	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
708 
709 	switch (USB_GET_STATE(xfer)) {
710 	case USB_ST_TRANSFERRED:
711 
712 		DPRINTF("Received %d bytes\n", actlen);
713 
714 		/* TODO: decode some indications */
715 
716 		/* FALLTHROUGH */
717 	case USB_ST_SETUP:
718 tr_setup:
719 		usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
720 		usbd_transfer_submit(xfer);
721 		break;
722 
723 	default:			/* Error */
724 		if (error != USB_ERR_CANCELLED) {
725 			/* start clear stall */
726 			usbd_xfer_set_stall(xfer);
727 			goto tr_setup;
728 		}
729 		break;
730 	}
731 }
732 
733 static void
734 cdce_intr_write_callback(struct usb_xfer *xfer, usb_error_t error)
735 {
736 	int actlen;
737 
738 	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
739 
740 	switch (USB_GET_STATE(xfer)) {
741 	case USB_ST_TRANSFERRED:
742 
743 		DPRINTF("Transferred %d bytes\n", actlen);
744 
745 		/* FALLTHROUGH */
746 	case USB_ST_SETUP:
747 tr_setup:
748 #if 0
749 		usbd_xfer_set_frame_len(xfer, 0, XXX);
750 		usbd_transfer_submit(xfer);
751 #endif
752 		break;
753 
754 	default:			/* Error */
755 		if (error != USB_ERR_CANCELLED) {
756 			/* start clear stall */
757 			usbd_xfer_set_stall(xfer);
758 			goto tr_setup;
759 		}
760 		break;
761 	}
762 }
763 
764 static int
765 cdce_handle_request(device_t dev,
766     const void *req, void **pptr, uint16_t *plen,
767     uint16_t offset, uint8_t is_complete)
768 {
769 	return (ENXIO);			/* use builtin handler */
770 }
771