1 /* $NetBSD: if_cdce.c,v 1.4 2004/10/24 12:50:54 augustss Exp $ */
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
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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.
39 * USB Communication Device Class (Ethernet Networking Control Model)
40 * http://www.usb.org/developers/devclass_docs/usbcdc11.pdf
44 * USB Network Control Model (NCM)
45 * http://www.usb.org/developers/devclass_docs/NCM10.zip
48 #include <sys/cdefs.h>
50 #include <sys/stdint.h>
51 #include <sys/param.h>
52 #include <sys/queue.h>
53 #include <sys/types.h>
54 #include <sys/systm.h>
55 #include <sys/kernel.h>
57 #include <sys/module.h>
59 #include <sys/condvar.h>
60 #include <sys/sysctl.h>
61 #include <sys/unistd.h>
62 #include <sys/callout.h>
63 #include <sys/malloc.h>
67 #include <net/if_var.h>
68 #include <net/ifq_var.h>
70 #include <bus/u4b/usb.h>
71 #include <bus/u4b/usbdi.h>
72 #include <bus/u4b/usbdi_util.h>
73 #include <bus/u4b/usb_cdc.h>
76 #define USB_DEBUG_VAR cdce_debug
77 #include <bus/u4b/usb_debug.h>
78 #include <bus/u4b/usb_process.h>
79 #include <bus/u4b/usb_msctest.h>
82 #include <bus/u4b/net/usb_ethernet.h>
83 #include <bus/u4b/net/if_cdcereg.h>
85 static device_probe_t cdce_probe
;
86 static device_attach_t cdce_attach
;
87 static device_detach_t cdce_detach
;
88 static device_suspend_t cdce_suspend
;
89 static device_resume_t cdce_resume
;
90 static usb_handle_request_t cdce_handle_request
;
92 static usb_callback_t cdce_bulk_write_callback
;
93 static usb_callback_t cdce_bulk_read_callback
;
94 static usb_callback_t cdce_intr_read_callback
;
95 static usb_callback_t cdce_intr_write_callback
;
98 static usb_callback_t cdce_ncm_bulk_write_callback
;
99 static usb_callback_t cdce_ncm_bulk_read_callback
;
102 static uether_fn_t cdce_attach_post
;
103 static uether_fn_t cdce_init
;
104 static uether_fn_t cdce_stop
;
105 static uether_fn_t cdce_start
;
106 static uether_fn_t cdce_setmulti
;
107 static uether_fn_t cdce_setpromisc
;
109 static uint32_t cdce_m_crc32(struct mbuf
*, uint32_t, uint32_t);
112 static int cdce_debug
= 0;
113 static int cdce_tx_interval
= 0;
115 static SYSCTL_NODE(_hw_usb
, OID_AUTO
, cdce
, CTLFLAG_RW
, 0, "USB CDC-Ethernet");
116 SYSCTL_INT(_hw_usb_cdce
, OID_AUTO
, debug
, CTLFLAG_RW
, &cdce_debug
, 0,
118 SYSCTL_INT(_hw_usb_cdce
, OID_AUTO
, interval
, CTLFLAG_RW
, &cdce_tx_interval
, 0,
119 "NCM transmit interval in ms");
122 static const struct usb_config cdce_config
[CDCE_N_TRANSFER
] = {
126 .endpoint
= UE_ADDR_ANY
,
127 .direction
= UE_DIR_RX
,
129 .frames
= CDCE_FRAMES_MAX
,
130 .bufsize
= (CDCE_FRAMES_MAX
* MCLBYTES
),
131 .flags
= {.pipe_bof
= 1,.short_frames_ok
= 1,.short_xfer_ok
= 1,.ext_buffer
= 1,},
132 .callback
= cdce_bulk_read_callback
,
133 .timeout
= 0, /* no timeout */
134 .usb_mode
= USB_MODE_DUAL
, /* both modes */
139 .endpoint
= UE_ADDR_ANY
,
140 .direction
= UE_DIR_TX
,
142 .frames
= CDCE_FRAMES_MAX
,
143 .bufsize
= (CDCE_FRAMES_MAX
* MCLBYTES
),
144 .flags
= {.pipe_bof
= 1,.force_short_xfer
= 1,.ext_buffer
= 1,},
145 .callback
= cdce_bulk_write_callback
,
146 .timeout
= 10000, /* 10 seconds */
147 .usb_mode
= USB_MODE_DUAL
, /* both modes */
151 .type
= UE_INTERRUPT
,
152 .endpoint
= UE_ADDR_ANY
,
153 .direction
= UE_DIR_RX
,
155 .bufsize
= CDCE_IND_SIZE_MAX
,
156 .flags
= {.pipe_bof
= 1,.short_xfer_ok
= 1,.no_pipe_ok
= 1,},
157 .callback
= cdce_intr_read_callback
,
159 .usb_mode
= USB_MODE_HOST
,
163 .type
= UE_INTERRUPT
,
164 .endpoint
= UE_ADDR_ANY
,
165 .direction
= UE_DIR_TX
,
167 .bufsize
= CDCE_IND_SIZE_MAX
,
168 .flags
= {.pipe_bof
= 1,.force_short_xfer
= 1,.no_pipe_ok
= 1,},
169 .callback
= cdce_intr_write_callback
,
170 .timeout
= 10000, /* 10 seconds */
171 .usb_mode
= USB_MODE_DEVICE
,
176 static const struct usb_config cdce_ncm_config
[CDCE_N_TRANSFER
] = {
180 .endpoint
= UE_ADDR_ANY
,
181 .direction
= UE_DIR_RX
,
183 .frames
= CDCE_NCM_RX_FRAMES_MAX
,
184 .bufsize
= (CDCE_NCM_RX_FRAMES_MAX
* CDCE_NCM_RX_MAXLEN
),
185 .flags
= {.pipe_bof
= 1,.short_frames_ok
= 1,.short_xfer_ok
= 1,},
186 .callback
= cdce_ncm_bulk_read_callback
,
187 .timeout
= 0, /* no timeout */
188 .usb_mode
= USB_MODE_DUAL
, /* both modes */
193 .endpoint
= UE_ADDR_ANY
,
194 .direction
= UE_DIR_TX
,
196 .frames
= CDCE_NCM_TX_FRAMES_MAX
,
197 .bufsize
= (CDCE_NCM_TX_FRAMES_MAX
* CDCE_NCM_TX_MAXLEN
),
198 .flags
= {.pipe_bof
= 1,},
199 .callback
= cdce_ncm_bulk_write_callback
,
200 .timeout
= 10000, /* 10 seconds */
201 .usb_mode
= USB_MODE_DUAL
, /* both modes */
205 .type
= UE_INTERRUPT
,
206 .endpoint
= UE_ADDR_ANY
,
207 .direction
= UE_DIR_RX
,
209 .bufsize
= CDCE_IND_SIZE_MAX
,
210 .flags
= {.pipe_bof
= 1,.short_xfer_ok
= 1,.no_pipe_ok
= 1,},
211 .callback
= cdce_intr_read_callback
,
213 .usb_mode
= USB_MODE_HOST
,
217 .type
= UE_INTERRUPT
,
218 .endpoint
= UE_ADDR_ANY
,
219 .direction
= UE_DIR_TX
,
221 .bufsize
= CDCE_IND_SIZE_MAX
,
222 .flags
= {.pipe_bof
= 1,.force_short_xfer
= 1,.no_pipe_ok
= 1,},
223 .callback
= cdce_intr_write_callback
,
224 .timeout
= 10000, /* 10 seconds */
225 .usb_mode
= USB_MODE_DEVICE
,
230 static device_method_t cdce_methods
[] = {
232 DEVMETHOD(usb_handle_request
, cdce_handle_request
),
234 /* Device interface */
235 DEVMETHOD(device_probe
, cdce_probe
),
236 DEVMETHOD(device_attach
, cdce_attach
),
237 DEVMETHOD(device_detach
, cdce_detach
),
238 DEVMETHOD(device_suspend
, cdce_suspend
),
239 DEVMETHOD(device_resume
, cdce_resume
),
244 static driver_t cdce_driver
= {
246 .methods
= cdce_methods
,
247 .size
= sizeof(struct cdce_softc
),
250 static devclass_t cdce_devclass
;
251 static eventhandler_tag cdce_etag
;
253 static int cdce_driver_loaded(struct module
*, int, void *);
255 DRIVER_MODULE(cdce
, uhub
, cdce_driver
, cdce_devclass
, cdce_driver_loaded
, NULL
);
256 MODULE_VERSION(cdce
, 1);
257 MODULE_DEPEND(cdce
, uether
, 1, 1, 1);
258 MODULE_DEPEND(cdce
, usb
, 1, 1, 1);
259 MODULE_DEPEND(cdce
, ether
, 1, 1, 1);
261 static const struct usb_ether_methods cdce_ue_methods
= {
262 .ue_attach_post
= cdce_attach_post
,
263 .ue_start
= cdce_start
,
264 .ue_init
= cdce_init
,
265 .ue_stop
= cdce_stop
,
266 .ue_setmulti
= cdce_setmulti
,
267 .ue_setpromisc
= cdce_setpromisc
,
271 static const STRUCT_USB_HOST_ID cdce_switch_devs
[] = {
272 {USB_VPI(USB_VENDOR_HUAWEI
, USB_PRODUCT_HUAWEI_E3272_INIT
, MSC_EJECT_HUAWEI2
)},
275 static const STRUCT_USB_HOST_ID cdce_host_devs
[] = {
276 {USB_VPI(USB_VENDOR_ACERLABS
, USB_PRODUCT_ACERLABS_M5632
, CDCE_FLAG_NO_UNION
)},
277 {USB_VPI(USB_VENDOR_AMBIT
, USB_PRODUCT_AMBIT_NTL_250
, CDCE_FLAG_NO_UNION
)},
278 {USB_VPI(USB_VENDOR_COMPAQ
, USB_PRODUCT_COMPAQ_IPAQLINUX
, CDCE_FLAG_NO_UNION
)},
279 {USB_VPI(USB_VENDOR_GMATE
, USB_PRODUCT_GMATE_YP3X00
, CDCE_FLAG_NO_UNION
)},
280 {USB_VPI(USB_VENDOR_MOTOROLA2
, USB_PRODUCT_MOTOROLA2_USBLAN
, CDCE_FLAG_ZAURUS
| CDCE_FLAG_NO_UNION
)},
281 {USB_VPI(USB_VENDOR_MOTOROLA2
, USB_PRODUCT_MOTOROLA2_USBLAN2
, CDCE_FLAG_ZAURUS
| CDCE_FLAG_NO_UNION
)},
282 {USB_VPI(USB_VENDOR_NETCHIP
, USB_PRODUCT_NETCHIP_ETHERNETGADGET
, CDCE_FLAG_NO_UNION
)},
283 {USB_VPI(USB_VENDOR_PROLIFIC
, USB_PRODUCT_PROLIFIC_PL2501
, CDCE_FLAG_NO_UNION
)},
284 {USB_VPI(USB_VENDOR_SHARP
, USB_PRODUCT_SHARP_SL5500
, CDCE_FLAG_ZAURUS
)},
285 {USB_VPI(USB_VENDOR_SHARP
, USB_PRODUCT_SHARP_SL5600
, CDCE_FLAG_ZAURUS
| CDCE_FLAG_NO_UNION
)},
286 {USB_VPI(USB_VENDOR_SHARP
, USB_PRODUCT_SHARP_SLA300
, CDCE_FLAG_ZAURUS
| CDCE_FLAG_NO_UNION
)},
287 {USB_VPI(USB_VENDOR_SHARP
, USB_PRODUCT_SHARP_SLC700
, CDCE_FLAG_ZAURUS
| CDCE_FLAG_NO_UNION
)},
288 {USB_VPI(USB_VENDOR_SHARP
, USB_PRODUCT_SHARP_SLC750
, CDCE_FLAG_ZAURUS
| CDCE_FLAG_NO_UNION
)},
290 {USB_VENDOR(USB_VENDOR_HUAWEI
), USB_IFACE_CLASS(UICLASS_VENDOR
),
291 USB_IFACE_SUBCLASS(0x02), USB_IFACE_PROTOCOL(0x16),
293 {USB_VENDOR(USB_VENDOR_HUAWEI
), USB_IFACE_CLASS(UICLASS_VENDOR
),
294 USB_IFACE_SUBCLASS(0x02), USB_IFACE_PROTOCOL(0x46),
296 {USB_VENDOR(USB_VENDOR_HUAWEI
), USB_IFACE_CLASS(UICLASS_VENDOR
),
297 USB_IFACE_SUBCLASS(0x02), USB_IFACE_PROTOCOL(0x76),
299 {USB_VENDOR(USB_VENDOR_HUAWEI
), USB_IFACE_CLASS(UICLASS_VENDOR
),
300 USB_IFACE_SUBCLASS(0x03), USB_IFACE_PROTOCOL(0x16),
305 static const STRUCT_USB_DUAL_ID cdce_dual_devs
[] = {
306 {USB_IF_CSI(UICLASS_CDC
, UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL
, 0)},
307 {USB_IF_CSI(UICLASS_CDC
, UISUBCLASS_MOBILE_DIRECT_LINE_MODEL
, 0)},
308 {USB_IF_CSI(UICLASS_CDC
, UISUBCLASS_NETWORK_CONTROL_MODEL
, 0)},
312 /*------------------------------------------------------------------------*
318 *------------------------------------------------------------------------*/
320 cdce_ncm_init(struct cdce_softc
*sc
)
322 struct usb_ncm_parameters temp
;
323 struct usb_device_request req
;
324 struct usb_ncm_func_descriptor
*ufd
;
328 ufd
= usbd_find_descriptor(sc
->sc_ue
.ue_udev
, NULL
,
329 sc
->sc_ifaces_index
[1], UDESC_CS_INTERFACE
, 0 - 1,
330 UCDC_NCM_FUNC_DESC_SUBTYPE
, 0 - 1);
332 /* verify length of NCM functional descriptor */
334 if (ufd
->bLength
< sizeof(*ufd
))
337 DPRINTFN(1, "Found NCM functional descriptor.\n");
340 req
.bmRequestType
= UT_READ_CLASS_INTERFACE
;
341 req
.bRequest
= UCDC_NCM_GET_NTB_PARAMETERS
;
342 USETW(req
.wValue
, 0);
343 req
.wIndex
[0] = sc
->sc_ifaces_index
[1];
345 USETW(req
.wLength
, sizeof(temp
));
347 err
= usbd_do_request_flags(sc
->sc_ue
.ue_udev
, NULL
, &req
,
348 &temp
, 0, NULL
, 1000 /* ms */);
352 /* Read correct set of parameters according to device mode */
354 if (usbd_get_mode(sc
->sc_ue
.ue_udev
) == USB_MODE_HOST
) {
355 sc
->sc_ncm
.rx_max
= UGETDW(temp
.dwNtbInMaxSize
);
356 sc
->sc_ncm
.tx_max
= UGETDW(temp
.dwNtbOutMaxSize
);
357 sc
->sc_ncm
.tx_remainder
= UGETW(temp
.wNdpOutPayloadRemainder
);
358 sc
->sc_ncm
.tx_modulus
= UGETW(temp
.wNdpOutDivisor
);
359 sc
->sc_ncm
.tx_struct_align
= UGETW(temp
.wNdpOutAlignment
);
360 sc
->sc_ncm
.tx_nframe
= UGETW(temp
.wNtbOutMaxDatagrams
);
362 sc
->sc_ncm
.rx_max
= UGETDW(temp
.dwNtbOutMaxSize
);
363 sc
->sc_ncm
.tx_max
= UGETDW(temp
.dwNtbInMaxSize
);
364 sc
->sc_ncm
.tx_remainder
= UGETW(temp
.wNdpInPayloadRemainder
);
365 sc
->sc_ncm
.tx_modulus
= UGETW(temp
.wNdpInDivisor
);
366 sc
->sc_ncm
.tx_struct_align
= UGETW(temp
.wNdpInAlignment
);
367 sc
->sc_ncm
.tx_nframe
= UGETW(temp
.wNtbOutMaxDatagrams
);
370 /* Verify maximum receive length */
372 if ((sc
->sc_ncm
.rx_max
< 32) ||
373 (sc
->sc_ncm
.rx_max
> CDCE_NCM_RX_MAXLEN
)) {
374 DPRINTFN(1, "Using default maximum receive length\n");
375 sc
->sc_ncm
.rx_max
= CDCE_NCM_RX_MAXLEN
;
378 /* Verify maximum transmit length */
380 if ((sc
->sc_ncm
.tx_max
< 32) ||
381 (sc
->sc_ncm
.tx_max
> CDCE_NCM_TX_MAXLEN
)) {
382 DPRINTFN(1, "Using default maximum transmit length\n");
383 sc
->sc_ncm
.tx_max
= CDCE_NCM_TX_MAXLEN
;
387 * Verify that the structure alignment is:
389 * - not greater than the maximum transmit length
390 * - not less than four bytes
392 if ((sc
->sc_ncm
.tx_struct_align
< 4) ||
393 (sc
->sc_ncm
.tx_struct_align
!=
394 ((-sc
->sc_ncm
.tx_struct_align
) & sc
->sc_ncm
.tx_struct_align
)) ||
395 (sc
->sc_ncm
.tx_struct_align
>= sc
->sc_ncm
.tx_max
)) {
396 DPRINTFN(1, "Using default other alignment: 4 bytes\n");
397 sc
->sc_ncm
.tx_struct_align
= 4;
401 * Verify that the payload alignment is:
403 * - not greater than the maximum transmit length
404 * - not less than four bytes
406 if ((sc
->sc_ncm
.tx_modulus
< 4) ||
407 (sc
->sc_ncm
.tx_modulus
!=
408 ((-sc
->sc_ncm
.tx_modulus
) & sc
->sc_ncm
.tx_modulus
)) ||
409 (sc
->sc_ncm
.tx_modulus
>= sc
->sc_ncm
.tx_max
)) {
410 DPRINTFN(1, "Using default transmit modulus: 4 bytes\n");
411 sc
->sc_ncm
.tx_modulus
= 4;
414 /* Verify that the payload remainder */
416 if ((sc
->sc_ncm
.tx_remainder
>= sc
->sc_ncm
.tx_modulus
)) {
417 DPRINTFN(1, "Using default transmit remainder: 0 bytes\n");
418 sc
->sc_ncm
.tx_remainder
= 0;
422 * Offset the TX remainder so that IP packet payload starts at
423 * the tx_modulus. This is not too clear in the specification.
426 sc
->sc_ncm
.tx_remainder
=
427 (sc
->sc_ncm
.tx_remainder
- ETHER_HDR_LEN
) &
428 (sc
->sc_ncm
.tx_modulus
- 1);
430 /* Verify max datagrams */
432 if (sc
->sc_ncm
.tx_nframe
== 0 ||
433 sc
->sc_ncm
.tx_nframe
> (CDCE_NCM_SUBFRAMES_MAX
- 1)) {
434 DPRINTFN(1, "Using default max "
435 "subframes: %u units\n", CDCE_NCM_SUBFRAMES_MAX
- 1);
436 /* need to reserve one entry for zero padding */
437 sc
->sc_ncm
.tx_nframe
= (CDCE_NCM_SUBFRAMES_MAX
- 1);
440 /* Additional configuration, will fail in device side mode, which is OK. */
442 req
.bmRequestType
= UT_WRITE_CLASS_INTERFACE
;
443 req
.bRequest
= UCDC_NCM_SET_NTB_INPUT_SIZE
;
444 USETW(req
.wValue
, 0);
445 req
.wIndex
[0] = sc
->sc_ifaces_index
[1];
449 (ufd
->bmNetworkCapabilities
& UCDC_NCM_CAP_MAX_DGRAM
)) {
450 USETW(req
.wLength
, 8);
451 USETDW(value
, sc
->sc_ncm
.rx_max
);
452 USETW(value
+ 4, (CDCE_NCM_SUBFRAMES_MAX
- 1));
455 USETW(req
.wLength
, 4);
456 USETDW(value
, sc
->sc_ncm
.rx_max
);
459 err
= usbd_do_request_flags(sc
->sc_ue
.ue_udev
, NULL
, &req
,
460 &value
, 0, NULL
, 1000 /* ms */);
462 DPRINTFN(1, "Setting input size "
463 "to %u failed.\n", sc
->sc_ncm
.rx_max
);
466 req
.bmRequestType
= UT_WRITE_CLASS_INTERFACE
;
467 req
.bRequest
= UCDC_NCM_SET_CRC_MODE
;
468 USETW(req
.wValue
, 0); /* no CRC */
469 req
.wIndex
[0] = sc
->sc_ifaces_index
[1];
471 USETW(req
.wLength
, 0);
473 err
= usbd_do_request_flags(sc
->sc_ue
.ue_udev
, NULL
, &req
,
474 NULL
, 0, NULL
, 1000 /* ms */);
476 DPRINTFN(1, "Setting CRC mode to off failed.\n");
479 req
.bmRequestType
= UT_WRITE_CLASS_INTERFACE
;
480 req
.bRequest
= UCDC_NCM_SET_NTB_FORMAT
;
481 USETW(req
.wValue
, 0); /* NTB-16 */
482 req
.wIndex
[0] = sc
->sc_ifaces_index
[1];
484 USETW(req
.wLength
, 0);
486 err
= usbd_do_request_flags(sc
->sc_ue
.ue_udev
, NULL
, &req
,
487 NULL
, 0, NULL
, 1000 /* ms */);
489 DPRINTFN(1, "Setting NTB format to 16-bit failed.\n");
492 return (0); /* success */
497 cdce_test_autoinst(void *arg
, struct usb_device
*udev
,
498 struct usb_attach_arg
*uaa
)
500 struct usb_interface
*iface
;
501 struct usb_interface_descriptor
*id
;
503 if (uaa
->dev_state
!= UAA_DEV_READY
)
506 iface
= usbd_get_iface(udev
, 0);
510 if (id
== NULL
|| id
->bInterfaceClass
!= UICLASS_MASS
)
512 if (usbd_lookup_id_by_uaa(cdce_switch_devs
, sizeof(cdce_switch_devs
), uaa
))
513 return; /* no device match */
515 if (usb_msc_eject(udev
, 0, USB_GET_DRIVER_INFO(uaa
)) == 0) {
516 /* success, mark the udev as disappearing */
517 uaa
->dev_state
= UAA_DEV_EJECTING
;
522 cdce_driver_loaded(struct module
*mod
, int what
, void *arg
)
526 /* register our autoinstall handler */
527 cdce_etag
= EVENTHANDLER_REGISTER(usb_dev_configured
,
528 cdce_test_autoinst
, NULL
, EVENTHANDLER_PRI_ANY
);
531 EVENTHANDLER_DEREGISTER(usb_dev_configured
, cdce_etag
);
539 cdce_probe(device_t dev
)
541 struct usb_attach_arg
*uaa
= device_get_ivars(dev
);
544 error
= usbd_lookup_id_by_uaa(cdce_host_devs
, sizeof(cdce_host_devs
), uaa
);
546 error
= usbd_lookup_id_by_uaa(cdce_dual_devs
, sizeof(cdce_dual_devs
), uaa
);
551 cdce_attach_post(struct usb_ether
*ue
)
553 struct ifnet
*ifp
= uether_getifp(ue
);
554 ifq_set_maxlen(&ifp
->if_snd
, ifqmaxlen
);
555 ifq_set_ready(&ifp
->if_snd
);
559 cdce_attach(device_t dev
)
561 struct cdce_softc
*sc
= device_get_softc(dev
);
562 struct usb_ether
*ue
= &sc
->sc_ue
;
563 struct usb_attach_arg
*uaa
= device_get_ivars(dev
);
564 struct usb_interface
*iface
;
565 const struct usb_cdc_union_descriptor
*ud
;
566 const struct usb_interface_descriptor
*id
;
567 const struct usb_cdc_ethernet_descriptor
*ued
;
568 const struct usb_config
*pcfg
;
572 uint8_t data_iface_no
;
573 char eaddr_str
[5 * ETHER_ADDR_LEN
]; /* approx */
575 sc
->sc_flags
= USB_GET_DRIVER_INFO(uaa
);
576 sc
->sc_ue
.ue_udev
= uaa
->device
;
578 device_set_usb_desc(dev
);
580 lockinit(&sc
->sc_lock
, device_get_nameunit(dev
), 0, 0);
582 ud
= usbd_find_descriptor
583 (uaa
->device
, NULL
, uaa
->info
.bIfaceIndex
,
584 UDESC_CS_INTERFACE
, 0 - 1, UDESCSUB_CDC_UNION
, 0 - 1);
586 if ((ud
== NULL
) || (ud
->bLength
< sizeof(*ud
)) ||
587 (sc
->sc_flags
& CDCE_FLAG_NO_UNION
)) {
588 DPRINTFN(1, "No union descriptor!\n");
589 sc
->sc_ifaces_index
[0] = uaa
->info
.bIfaceIndex
;
590 sc
->sc_ifaces_index
[1] = uaa
->info
.bIfaceIndex
;
591 goto alloc_transfers
;
593 data_iface_no
= ud
->bSlaveInterface
[0];
597 iface
= usbd_get_iface(uaa
->device
, i
);
601 id
= usbd_get_interface_descriptor(iface
);
603 if (id
&& (id
->bInterfaceNumber
== data_iface_no
)) {
604 sc
->sc_ifaces_index
[0] = i
;
605 sc
->sc_ifaces_index
[1] = uaa
->info
.bIfaceIndex
;
606 usbd_set_parent_iface(uaa
->device
, i
, uaa
->info
.bIfaceIndex
);
610 device_printf(dev
, "no data interface found\n");
618 * The Data Class interface of a networking device shall have
619 * a minimum of two interface settings. The first setting
620 * (the default interface setting) includes no endpoints and
621 * therefore no networking traffic is exchanged whenever the
622 * default interface setting is selected. One or more
623 * additional interface settings are used for normal
624 * operation, and therefore each includes a pair of endpoints
625 * (one IN, and one OUT) to exchange network traffic. Select
626 * an alternate interface setting to initialize the network
627 * aspects of the device and to enable the exchange of
632 * Some devices, most notably cable modems, include interface
633 * settings that have no IN or OUT endpoint, therefore loop
634 * through the list of all available interface settings
635 * looking for one with both IN and OUT endpoints.
640 pcfg
= cdce_config
; /* Default Configuration */
642 for (i
= 0; i
!= 32; i
++) {
644 error
= usbd_set_alt_interface_index(uaa
->device
,
645 sc
->sc_ifaces_index
[0], i
);
649 if ((i
== 0) && (cdce_ncm_init(sc
) == 0))
650 pcfg
= cdce_ncm_config
;
652 error
= usbd_transfer_setup(uaa
->device
,
653 sc
->sc_ifaces_index
, sc
->sc_xfer
,
654 pcfg
, CDCE_N_TRANSFER
, sc
, &sc
->sc_lock
);
660 if (error
|| (i
== 32)) {
661 device_printf(dev
, "No valid alternate "
666 ued
= usbd_find_descriptor
667 (uaa
->device
, NULL
, uaa
->info
.bIfaceIndex
,
668 UDESC_CS_INTERFACE
, 0 - 1, UDESCSUB_CDC_ENF
, 0 - 1);
670 if ((ued
== NULL
) || (ued
->bLength
< sizeof(*ued
))) {
671 error
= USB_ERR_INVAL
;
673 error
= usbd_req_get_string_any(uaa
->device
, NULL
,
674 eaddr_str
, sizeof(eaddr_str
), ued
->iMacAddress
);
679 /* fake MAC address */
681 device_printf(dev
, "faking MAC address\n");
683 sc
->sc_ue
.ue_eaddr
[0] = 0x2a;
684 memcpy(&sc
->sc_ue
.ue_eaddr
[1], &seed
, sizeof(uint32_t));
685 sc
->sc_ue
.ue_eaddr
[5] = device_get_unit(dev
);
689 memset(sc
->sc_ue
.ue_eaddr
, 0, sizeof(sc
->sc_ue
.ue_eaddr
));
691 for (i
= 0; i
!= (ETHER_ADDR_LEN
* 2); i
++) {
693 char c
= eaddr_str
[i
];
695 if ('0' <= c
&& c
<= '9')
706 sc
->sc_ue
.ue_eaddr
[i
/ 2] |= c
;
709 if (uaa
->usb_mode
== USB_MODE_DEVICE
) {
711 * Do not use the same MAC address like the peer !
713 sc
->sc_ue
.ue_eaddr
[5] ^= 0xFF;
719 ue
->ue_udev
= uaa
->device
;
720 ue
->ue_lock
= &sc
->sc_lock
;
721 ue
->ue_methods
= &cdce_ue_methods
;
723 error
= uether_ifattach(ue
);
725 device_printf(dev
, "could not attach interface\n");
728 return (0); /* success */
732 return (ENXIO
); /* failure */
736 cdce_detach(device_t dev
)
738 struct cdce_softc
*sc
= device_get_softc(dev
);
739 struct usb_ether
*ue
= &sc
->sc_ue
;
741 /* stop all USB transfers first */
742 usbd_transfer_unsetup(sc
->sc_xfer
, CDCE_N_TRANSFER
);
744 lockuninit(&sc
->sc_lock
);
750 cdce_start(struct usb_ether
*ue
)
752 struct cdce_softc
*sc
= uether_getsc(ue
);
755 * Start the USB transfers, if not already started:
757 usbd_transfer_start(sc
->sc_xfer
[CDCE_BULK_TX
]);
758 usbd_transfer_start(sc
->sc_xfer
[CDCE_BULK_RX
]);
762 cdce_free_queue(struct mbuf
**ppm
, uint8_t n
)
765 for (x
= 0; x
!= n
; x
++) {
766 if (ppm
[x
] != NULL
) {
774 cdce_bulk_write_callback(struct usb_xfer
*xfer
, usb_error_t error
)
776 struct cdce_softc
*sc
= usbd_xfer_softc(xfer
);
777 struct ifnet
*ifp
= uether_getifp(&sc
->sc_ue
);
784 usbd_xfer_status(xfer
, &actlen
, NULL
, &aframes
, NULL
);
788 switch (USB_GET_STATE(xfer
)) {
789 case USB_ST_TRANSFERRED
:
790 DPRINTFN(11, "transfer complete: %u bytes in %u frames\n",
792 ifq_clr_oactive(&ifp
->if_snd
);
793 IFNET_STAT_INC(ifp
, opackets
, 1);
795 /* free all previous TX buffers */
796 cdce_free_queue(sc
->sc_tx_buf
, CDCE_FRAMES_MAX
);
801 DPRINTFN(11, "transfer setup\n");
802 if(ifq_is_oactive(&ifp
->if_snd
))
805 for (x
= 0; x
!= CDCE_FRAMES_MAX
; x
++) {
807 m
= ifq_dequeue(&ifp
->if_snd
);
812 if (sc
->sc_flags
& CDCE_FLAG_ZAURUS
) {
814 * Zaurus wants a 32-bit CRC appended
818 crc
= cdce_m_crc32(m
, 0, m
->m_pkthdr
.len
);
821 if (!m_append(m
, 4, (void *)&crc
)) {
823 IFNET_STAT_INC(ifp
, oerrors
, 1);
827 if (m
->m_len
!= m
->m_pkthdr
.len
) {
828 mt
= m_defrag(m
, M_NOWAIT
);
836 if (m
->m_pkthdr
.len
> MCLBYTES
) {
837 m
->m_pkthdr
.len
= MCLBYTES
;
839 sc
->sc_tx_buf
[x
] = m
;
840 usbd_xfer_set_frame_data(xfer
, x
, m
->m_data
, m
->m_len
);
843 * If there's a BPF listener, bounce a copy of
849 usbd_xfer_set_frames(xfer
, x
);
850 usbd_transfer_submit(xfer
);
851 ifq_set_oactive(&ifp
->if_snd
);
856 DPRINTFN(11, "transfer error, %s\n",
859 /* free all previous TX buffers */
860 cdce_free_queue(sc
->sc_tx_buf
, CDCE_FRAMES_MAX
);
862 /* count output errors */
863 IFNET_STAT_INC(ifp
, oerrors
, 1);
864 ifq_clr_oactive(&ifp
->if_snd
);
865 if (error
!= USB_ERR_CANCELLED
) {
866 if (usbd_get_mode(sc
->sc_ue
.ue_udev
) == USB_MODE_HOST
) {
867 /* try to clear stall first */
868 usbd_xfer_set_stall(xfer
);
877 cdce_m_crc32_cb(void *arg
, void *src
, uint32_t count
)
879 uint32_t *p_crc
= arg
;
881 *p_crc
= crc32_ext(src
, count
, *p_crc
);
887 cdce_m_crc32(struct mbuf
*m
, uint32_t src_offset
, uint32_t src_len
)
889 uint32_t crc
= 0xFFFFFFFF;
892 error
= m_apply(m
, src_offset
, src_len
, cdce_m_crc32_cb
, &crc
);
893 return (crc
^ 0xFFFFFFFF);
897 cdce_init(struct usb_ether
*ue
)
899 struct cdce_softc
*sc
= uether_getsc(ue
);
900 struct ifnet
*ifp
= uether_getifp(ue
);
902 CDCE_LOCK_ASSERT(sc
, MA_OWNED
);
904 ifp
->if_flags
|= IFF_RUNNING
;
906 /* start interrupt transfer */
907 usbd_transfer_start(sc
->sc_xfer
[CDCE_INTR_RX
]);
908 usbd_transfer_start(sc
->sc_xfer
[CDCE_INTR_TX
]);
911 * Stall data write direction, which depends on USB mode.
913 * Some USB host stacks (e.g. Mac OS X) don't clears stall
914 * bit as it should, so set it in our host mode only.
916 if (usbd_get_mode(sc
->sc_ue
.ue_udev
) == USB_MODE_HOST
)
917 usbd_xfer_set_stall(sc
->sc_xfer
[CDCE_BULK_TX
]);
919 /* start data transfers */
924 cdce_stop(struct usb_ether
*ue
)
926 struct cdce_softc
*sc
= uether_getsc(ue
);
927 struct ifnet
*ifp
= uether_getifp(ue
);
929 CDCE_LOCK_ASSERT(sc
, MA_OWNED
);
931 ifp
->if_flags
&= ~IFF_RUNNING
;
932 ifq_clr_oactive(&ifp
->if_snd
);
935 * stop all the transfers, if not already stopped:
937 usbd_transfer_stop(sc
->sc_xfer
[CDCE_BULK_RX
]);
938 usbd_transfer_stop(sc
->sc_xfer
[CDCE_BULK_TX
]);
939 usbd_transfer_stop(sc
->sc_xfer
[CDCE_INTR_RX
]);
940 usbd_transfer_stop(sc
->sc_xfer
[CDCE_INTR_TX
]);
944 cdce_setmulti(struct usb_ether
*ue
)
951 cdce_setpromisc(struct usb_ether
*ue
)
958 cdce_suspend(device_t dev
)
960 device_printf(dev
, "Suspending\n");
965 cdce_resume(device_t dev
)
967 device_printf(dev
, "Resuming\n");
972 cdce_bulk_read_callback(struct usb_xfer
*xfer
, usb_error_t error
)
974 struct cdce_softc
*sc
= usbd_xfer_softc(xfer
);
977 int actlen
, aframes
, len
;
979 usbd_xfer_status(xfer
, &actlen
, NULL
, &aframes
, NULL
);
981 switch (USB_GET_STATE(xfer
)) {
982 case USB_ST_TRANSFERRED
:
984 DPRINTF("received %u bytes in %u frames\n", actlen
, aframes
);
986 for (x
= 0; x
!= aframes
; x
++) {
988 m
= sc
->sc_rx_buf
[x
];
989 sc
->sc_rx_buf
[x
] = NULL
;
990 len
= usbd_xfer_frame_len(xfer
, x
);
992 /* Strip off CRC added by Zaurus, if any */
993 if ((sc
->sc_flags
& CDCE_FLAG_ZAURUS
) && len
>= 14)
996 if (len
< (int)sizeof(struct ether_header
)) {
1001 uether_rxmbuf(&sc
->sc_ue
, m
, len
);
1007 * TODO: Implement support for multi frame transfers,
1008 * when the USB hardware supports it.
1010 for (x
= 0; x
!= 1; x
++) {
1011 if (sc
->sc_rx_buf
[x
] == NULL
) {
1012 m
= uether_newbuf();
1015 sc
->sc_rx_buf
[x
] = m
;
1017 m
= sc
->sc_rx_buf
[x
];
1020 usbd_xfer_set_frame_data(xfer
, x
, m
->m_data
, m
->m_len
);
1022 /* set number of frames and start hardware */
1023 usbd_xfer_set_frames(xfer
, x
);
1024 usbd_transfer_submit(xfer
);
1025 /* flush any received frames */
1026 uether_rxflush(&sc
->sc_ue
);
1029 default: /* Error */
1030 DPRINTF("error = %s\n",
1031 usbd_errstr(error
));
1033 if (error
!= USB_ERR_CANCELLED
) {
1035 if (usbd_get_mode(sc
->sc_ue
.ue_udev
) == USB_MODE_HOST
) {
1036 /* try to clear stall first */
1037 usbd_xfer_set_stall(xfer
);
1038 usbd_xfer_set_frames(xfer
, 0);
1039 usbd_transfer_submit(xfer
);
1044 /* need to free the RX-mbufs when we are cancelled */
1045 cdce_free_queue(sc
->sc_rx_buf
, CDCE_FRAMES_MAX
);
1051 cdce_intr_read_callback(struct usb_xfer
*xfer
, usb_error_t error
)
1053 struct cdce_softc
*sc
= usbd_xfer_softc(xfer
);
1056 usbd_xfer_status(xfer
, &actlen
, NULL
, NULL
, NULL
);
1058 switch (USB_GET_STATE(xfer
)) {
1059 case USB_ST_TRANSFERRED
:
1061 DPRINTF("Received %d bytes\n", actlen
);
1063 /* TODO: decode some indications */
1068 usbd_xfer_set_frame_len(xfer
, 0, usbd_xfer_max_len(xfer
));
1069 usbd_transfer_submit(xfer
);
1072 default: /* Error */
1073 if (error
!= USB_ERR_CANCELLED
) {
1074 /* start clear stall */
1075 if (usbd_get_mode(sc
->sc_ue
.ue_udev
) == USB_MODE_HOST
)
1076 usbd_xfer_set_stall(xfer
);
1084 cdce_intr_write_callback(struct usb_xfer
*xfer
, usb_error_t error
)
1086 struct cdce_softc
*sc
= usbd_xfer_softc(xfer
);
1087 struct usb_cdc_notification req
;
1088 struct usb_page_cache
*pc
;
1092 usbd_xfer_status(xfer
, &actlen
, NULL
, NULL
, NULL
);
1094 switch (USB_GET_STATE(xfer
)) {
1095 case USB_ST_TRANSFERRED
:
1097 DPRINTF("Transferred %d bytes\n", actlen
);
1099 switch (sc
->sc_notify_state
) {
1100 case CDCE_NOTIFY_NETWORK_CONNECTION
:
1101 sc
->sc_notify_state
= CDCE_NOTIFY_SPEED_CHANGE
;
1103 case CDCE_NOTIFY_SPEED_CHANGE
:
1104 sc
->sc_notify_state
= CDCE_NOTIFY_DONE
;
1114 * Inform host about connection. Required according to USB CDC
1115 * specification and communicating to Mac OS X USB host stack.
1116 * Some of the values seems ignored by Mac OS X though.
1118 if (sc
->sc_notify_state
== CDCE_NOTIFY_NETWORK_CONNECTION
) {
1119 req
.bmRequestType
= UCDC_NOTIFICATION
;
1120 req
.bNotification
= UCDC_N_NETWORK_CONNECTION
;
1121 req
.wIndex
[0] = sc
->sc_ifaces_index
[1];
1123 USETW(req
.wValue
, 1); /* Connected */
1124 USETW(req
.wLength
, 0);
1126 pc
= usbd_xfer_get_frame(xfer
, 0);
1127 usbd_copy_in(pc
, 0, &req
, sizeof(req
));
1128 usbd_xfer_set_frame_len(xfer
, 0, sizeof(req
));
1129 usbd_xfer_set_frames(xfer
, 1);
1130 usbd_transfer_submit(xfer
);
1132 } else if (sc
->sc_notify_state
== CDCE_NOTIFY_SPEED_CHANGE
) {
1133 req
.bmRequestType
= UCDC_NOTIFICATION
;
1134 req
.bNotification
= UCDC_N_CONNECTION_SPEED_CHANGE
;
1135 req
.wIndex
[0] = sc
->sc_ifaces_index
[1];
1137 USETW(req
.wValue
, 0);
1138 USETW(req
.wLength
, 8);
1140 /* Peak theoretical bulk trasfer rate in bits/s */
1141 if (usbd_get_speed(sc
->sc_ue
.ue_udev
) != USB_SPEED_FULL
)
1142 speed
= (13 * 512 * 8 * 1000 * 8);
1144 speed
= (19 * 64 * 1 * 1000 * 8);
1146 USETDW(req
.data
+ 0, speed
); /* Upstream bit rate */
1147 USETDW(req
.data
+ 4, speed
); /* Downstream bit rate */
1149 pc
= usbd_xfer_get_frame(xfer
, 0);
1150 usbd_copy_in(pc
, 0, &req
, sizeof(req
));
1151 usbd_xfer_set_frame_len(xfer
, 0, sizeof(req
));
1152 usbd_xfer_set_frames(xfer
, 1);
1153 usbd_transfer_submit(xfer
);
1157 default: /* Error */
1158 if (error
!= USB_ERR_CANCELLED
) {
1159 if (usbd_get_mode(sc
->sc_ue
.ue_udev
) == USB_MODE_HOST
) {
1160 /* start clear stall */
1161 usbd_xfer_set_stall(xfer
);
1170 cdce_handle_request(device_t dev
,
1171 const void *preq
, void **pptr
, uint16_t *plen
,
1172 uint16_t offset
, uint8_t *pstate
)
1174 struct cdce_softc
*sc
= device_get_softc(dev
);
1175 const struct usb_device_request
*req
= preq
;
1176 uint8_t is_complete
= *pstate
;
1179 * When Mac OS X resumes after suspending it expects
1180 * to be notified again after this request.
1182 if (req
->bmRequestType
== UT_WRITE_CLASS_INTERFACE
&& \
1183 req
->bRequest
== UCDC_NCM_SET_ETHERNET_PACKET_FILTER
) {
1185 if (is_complete
== 1) {
1187 sc
->sc_notify_state
= CDCE_NOTIFY_SPEED_CHANGE
;
1188 usbd_transfer_start(sc
->sc_xfer
[CDCE_INTR_TX
]);
1195 return (ENXIO
); /* use builtin handler */
1200 cdce_ncm_tx_zero(struct usb_page_cache
*pc
,
1201 uint32_t start
, uint32_t end
)
1203 if (start
>= CDCE_NCM_TX_MAXLEN
)
1205 if (end
> CDCE_NCM_TX_MAXLEN
)
1206 end
= CDCE_NCM_TX_MAXLEN
;
1208 usbd_frame_zero(pc
, start
, end
- start
);
1212 cdce_ncm_fill_tx_frames(struct usb_xfer
*xfer
, uint8_t index
)
1214 struct cdce_softc
*sc
= usbd_xfer_softc(xfer
);
1215 struct ifnet
*ifp
= uether_getifp(&sc
->sc_ue
);
1216 struct usb_page_cache
*pc
= usbd_xfer_get_frame(xfer
, index
);
1220 uint32_t last_offset
;
1224 usbd_xfer_set_frame_offset(xfer
, index
* CDCE_NCM_TX_MAXLEN
, index
);
1226 offset
= sizeof(sc
->sc_ncm
.hdr
) +
1227 sizeof(sc
->sc_ncm
.dpt
) + sizeof(sc
->sc_ncm
.dp
);
1229 /* Store last valid offset before alignment */
1230 last_offset
= offset
;
1233 offset
= CDCE_NCM_ALIGN(sc
->sc_ncm
.tx_remainder
,
1234 offset
, sc
->sc_ncm
.tx_modulus
);
1237 cdce_ncm_tx_zero(pc
, last_offset
, offset
);
1242 for (n
= 0; n
!= sc
->sc_ncm
.tx_nframe
; n
++) {
1244 /* check if end of transmit buffer is reached */
1246 if (offset
>= sc
->sc_ncm
.tx_max
)
1249 /* compute maximum buffer size */
1251 rem
= sc
->sc_ncm
.tx_max
- offset
;
1253 m
= ifq_dequeue(&ifp
->if_snd
);
1256 /* buffer not full */
1261 if (m
->m_pkthdr
.len
> (int)rem
) {
1263 /* The frame won't fit in our buffer */
1264 DPRINTFN(1, "Frame too big to be transmitted!\n");
1270 /* Wait till next buffer becomes ready */
1271 ifq_prepend(&ifp
->if_snd
, m
);
1274 usbd_m_copy_in(pc
, offset
, m
, 0, m
->m_pkthdr
.len
);
1276 USETW(sc
->sc_ncm
.dp
[n
].wFrameLength
, m
->m_pkthdr
.len
);
1277 USETW(sc
->sc_ncm
.dp
[n
].wFrameIndex
, offset
);
1280 offset
+= m
->m_pkthdr
.len
;
1282 /* Store last valid offset before alignment */
1283 last_offset
= offset
;
1286 offset
= CDCE_NCM_ALIGN(sc
->sc_ncm
.tx_remainder
,
1287 offset
, sc
->sc_ncm
.tx_modulus
);
1290 cdce_ncm_tx_zero(pc
, last_offset
, offset
);
1293 * If there's a BPF listener, bounce a copy
1294 * of this frame to him:
1302 /* Pre-increment interface counter */
1304 IFNET_STAT_INC(ifp
, opackets
, 1);
1310 rem
= (sizeof(sc
->sc_ncm
.dpt
) + (4 * n
) + 4);
1312 USETW(sc
->sc_ncm
.dpt
.wLength
, rem
);
1314 /* zero the rest of the data pointer entries */
1315 for (; n
!= CDCE_NCM_SUBFRAMES_MAX
; n
++) {
1316 USETW(sc
->sc_ncm
.dp
[n
].wFrameLength
, 0);
1317 USETW(sc
->sc_ncm
.dp
[n
].wFrameIndex
, 0);
1320 offset
= last_offset
;
1323 offset
= CDCE_NCM_ALIGN(0, offset
, CDCE_NCM_TX_MINLEN
);
1325 /* Optimise, save bandwidth and force short termination */
1326 if (offset
>= sc
->sc_ncm
.tx_max
)
1327 offset
= sc
->sc_ncm
.tx_max
;
1332 cdce_ncm_tx_zero(pc
, last_offset
, offset
);
1334 /* set frame length */
1335 usbd_xfer_set_frame_len(xfer
, index
, offset
);
1337 /* Fill out 16-bit header */
1338 sc
->sc_ncm
.hdr
.dwSignature
[0] = 'N';
1339 sc
->sc_ncm
.hdr
.dwSignature
[1] = 'C';
1340 sc
->sc_ncm
.hdr
.dwSignature
[2] = 'M';
1341 sc
->sc_ncm
.hdr
.dwSignature
[3] = 'H';
1342 USETW(sc
->sc_ncm
.hdr
.wHeaderLength
, sizeof(sc
->sc_ncm
.hdr
));
1343 USETW(sc
->sc_ncm
.hdr
.wBlockLength
, offset
);
1344 USETW(sc
->sc_ncm
.hdr
.wSequence
, sc
->sc_ncm
.tx_seq
);
1345 USETW(sc
->sc_ncm
.hdr
.wDptIndex
, sizeof(sc
->sc_ncm
.hdr
));
1347 sc
->sc_ncm
.tx_seq
++;
1349 /* Fill out 16-bit frame table header */
1350 sc
->sc_ncm
.dpt
.dwSignature
[0] = 'N';
1351 sc
->sc_ncm
.dpt
.dwSignature
[1] = 'C';
1352 sc
->sc_ncm
.dpt
.dwSignature
[2] = 'M';
1353 sc
->sc_ncm
.dpt
.dwSignature
[3] = '0';
1354 USETW(sc
->sc_ncm
.dpt
.wNextNdpIndex
, 0); /* reserved */
1356 usbd_copy_in(pc
, 0, &(sc
->sc_ncm
.hdr
), sizeof(sc
->sc_ncm
.hdr
));
1357 usbd_copy_in(pc
, sizeof(sc
->sc_ncm
.hdr
), &(sc
->sc_ncm
.dpt
),
1358 sizeof(sc
->sc_ncm
.dpt
));
1359 usbd_copy_in(pc
, sizeof(sc
->sc_ncm
.hdr
) + sizeof(sc
->sc_ncm
.dpt
),
1360 &(sc
->sc_ncm
.dp
), sizeof(sc
->sc_ncm
.dp
));
1365 cdce_ncm_bulk_write_callback(struct usb_xfer
*xfer
, usb_error_t error
)
1367 struct cdce_softc
*sc
= usbd_xfer_softc(xfer
);
1368 struct ifnet
*ifp
= uether_getifp(&sc
->sc_ue
);
1374 switch (USB_GET_STATE(xfer
)) {
1375 case USB_ST_TRANSFERRED
:
1377 usbd_xfer_status(xfer
, &actlen
, NULL
, &aframes
, NULL
);
1379 DPRINTFN(10, "transfer complete: "
1380 "%u bytes in %u frames\n", actlen
, aframes
);
1383 for (x
= 0; x
!= CDCE_NCM_TX_FRAMES_MAX
; x
++) {
1384 temp
= cdce_ncm_fill_tx_frames(xfer
, x
);
1395 usbd_xfer_set_interval(xfer
, cdce_tx_interval
);
1397 usbd_xfer_set_frames(xfer
, x
);
1398 usbd_transfer_submit(xfer
);
1402 default: /* Error */
1403 DPRINTFN(10, "Transfer error: %s\n",
1404 usbd_errstr(error
));
1406 /* update error counter */
1407 ifp
->if_oerrors
+= 1;
1409 if (error
!= USB_ERR_CANCELLED
) {
1410 if (usbd_get_mode(sc
->sc_ue
.ue_udev
) == USB_MODE_HOST
) {
1411 /* try to clear stall first */
1412 usbd_xfer_set_stall(xfer
);
1413 usbd_xfer_set_frames(xfer
, 0);
1414 usbd_transfer_submit(xfer
);
1422 cdce_ncm_bulk_read_callback(struct usb_xfer
*xfer
, usb_error_t error
)
1424 struct cdce_softc
*sc
= usbd_xfer_softc(xfer
);
1425 struct usb_page_cache
*pc
= usbd_xfer_get_frame(xfer
, 0);
1426 struct ifnet
*ifp
= uether_getifp(&sc
->sc_ue
);
1437 switch (USB_GET_STATE(xfer
)) {
1438 case USB_ST_TRANSFERRED
:
1440 usbd_xfer_status(xfer
, &actlen
, &sumlen
, &aframes
, NULL
);
1442 DPRINTFN(1, "received %u bytes in %u frames\n",
1445 if (actlen
< (int)(sizeof(sc
->sc_ncm
.hdr
) +
1446 sizeof(sc
->sc_ncm
.dpt
))) {
1447 DPRINTFN(1, "frame too short\n");
1450 usbd_copy_out(pc
, 0, &(sc
->sc_ncm
.hdr
),
1451 sizeof(sc
->sc_ncm
.hdr
));
1453 if ((sc
->sc_ncm
.hdr
.dwSignature
[0] != 'N') ||
1454 (sc
->sc_ncm
.hdr
.dwSignature
[1] != 'C') ||
1455 (sc
->sc_ncm
.hdr
.dwSignature
[2] != 'M') ||
1456 (sc
->sc_ncm
.hdr
.dwSignature
[3] != 'H')) {
1457 DPRINTFN(1, "invalid HDR signature: "
1458 "0x%02x:0x%02x:0x%02x:0x%02x\n",
1459 sc
->sc_ncm
.hdr
.dwSignature
[0],
1460 sc
->sc_ncm
.hdr
.dwSignature
[1],
1461 sc
->sc_ncm
.hdr
.dwSignature
[2],
1462 sc
->sc_ncm
.hdr
.dwSignature
[3]);
1465 temp
= UGETW(sc
->sc_ncm
.hdr
.wBlockLength
);
1466 if (temp
> sumlen
) {
1467 DPRINTFN(1, "unsupported block length %u/%u\n",
1471 temp
= UGETW(sc
->sc_ncm
.hdr
.wDptIndex
);
1472 if ((int)(temp
+ sizeof(sc
->sc_ncm
.dpt
)) > actlen
) {
1473 DPRINTFN(1, "invalid DPT index: 0x%04x\n", temp
);
1476 usbd_copy_out(pc
, temp
, &(sc
->sc_ncm
.dpt
),
1477 sizeof(sc
->sc_ncm
.dpt
));
1479 if ((sc
->sc_ncm
.dpt
.dwSignature
[0] != 'N') ||
1480 (sc
->sc_ncm
.dpt
.dwSignature
[1] != 'C') ||
1481 (sc
->sc_ncm
.dpt
.dwSignature
[2] != 'M') ||
1482 (sc
->sc_ncm
.dpt
.dwSignature
[3] != '0')) {
1483 DPRINTFN(1, "invalid DPT signature"
1484 "0x%02x:0x%02x:0x%02x:0x%02x\n",
1485 sc
->sc_ncm
.dpt
.dwSignature
[0],
1486 sc
->sc_ncm
.dpt
.dwSignature
[1],
1487 sc
->sc_ncm
.dpt
.dwSignature
[2],
1488 sc
->sc_ncm
.dpt
.dwSignature
[3]);
1491 nframes
= UGETW(sc
->sc_ncm
.dpt
.wLength
) / 4;
1493 /* Subtract size of header and last zero padded entry */
1494 if (nframes
>= (2 + 1))
1499 DPRINTFN(1, "nframes = %u\n", nframes
);
1501 temp
+= sizeof(sc
->sc_ncm
.dpt
);
1503 if ((temp
+ (4 * nframes
)) > actlen
)
1506 if (nframes
> CDCE_NCM_SUBFRAMES_MAX
) {
1507 DPRINTFN(1, "Truncating number of frames from %u to %u\n",
1508 nframes
, CDCE_NCM_SUBFRAMES_MAX
);
1509 nframes
= CDCE_NCM_SUBFRAMES_MAX
;
1511 usbd_copy_out(pc
, temp
, &(sc
->sc_ncm
.dp
), (4 * nframes
));
1515 for (x
= 0; x
!= nframes
; x
++) {
1517 offset
= UGETW(sc
->sc_ncm
.dp
[x
].wFrameIndex
);
1518 temp
= UGETW(sc
->sc_ncm
.dp
[x
].wFrameLength
);
1520 if ((offset
== 0) ||
1521 (temp
< (int)sizeof(struct ether_header
)) ||
1522 (temp
> (MCLBYTES
- ETHER_ALIGN
))) {
1523 DPRINTFN(1, "NULL frame detected at %d\n", x
);
1525 /* silently ignore this frame */
1527 } else if ((offset
+ temp
) > actlen
) {
1528 DPRINTFN(1, "invalid frame "
1529 "detected at %d\n", x
);
1531 /* silently ignore this frame */
1533 } else if (temp
> (int)(MHLEN
- ETHER_ALIGN
)) {
1534 m
= m_getcl(M_NOWAIT
, MT_DATA
, M_PKTHDR
);
1536 m
= m_gethdr(M_NOWAIT
, MT_DATA
);
1539 DPRINTFN(16, "frame %u, offset = %u, length = %u \n",
1542 /* check if we have a buffer */
1544 m
->m_len
= m
->m_pkthdr
.len
= temp
+ ETHER_ALIGN
;
1545 m_adj(m
, ETHER_ALIGN
);
1547 usbd_copy_out(pc
, offset
, m
->m_data
, temp
);
1550 uether_rxmbuf(&sc
->sc_ue
, m
, temp
);
1558 DPRINTFN(1, "Efficiency: %u/%u bytes\n", sumdata
, actlen
);
1562 usbd_xfer_set_frame_len(xfer
, 0, sc
->sc_ncm
.rx_max
);
1563 usbd_xfer_set_frames(xfer
, 1);
1564 usbd_transfer_submit(xfer
);
1565 uether_rxflush(&sc
->sc_ue
); /* must be last */
1568 default: /* Error */
1569 DPRINTFN(1, "error = %s\n",
1570 usbd_errstr(error
));
1572 if (error
!= USB_ERR_CANCELLED
) {
1574 if (usbd_get_mode(sc
->sc_ue
.ue_udev
) == USB_MODE_HOST
) {
1575 /* try to clear stall first */
1576 usbd_xfer_set_stall(xfer
);
1577 usbd_xfer_set_frames(xfer
, 0);
1578 usbd_transfer_submit(xfer
);