53#include <sys/gsb_crc32.h>
54#include <sys/eventhandler.h>
55#include <sys/stdint.h>
56#include <sys/stddef.h>
59#include <sys/socket.h>
60#include <sys/kernel.h>
62#include <sys/module.h>
65#include <sys/condvar.h>
66#include <sys/sysctl.h>
68#include <sys/unistd.h>
69#include <sys/callout.h>
70#include <sys/malloc.h>
74#include <net/if_var.h>
82#define USB_DEBUG_VAR cdce_debug
115static int cdce_ioctl(
struct ifnet *, u_long, caddr_t);
119static uint32_t
cdce_m_crc32(
struct mbuf *, uint32_t, uint32_t);
124static int cdce_tx_interval = 0;
126static SYSCTL_NODE(_hw_usb, OID_AUTO, cdce, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
130SYSCTL_INT(_hw_usb_cdce, OID_AUTO, interval, CTLFLAG_RWTUN, &cdce_tx_interval, 0,
131 "NCM transmit interval in ms");
144 .
flags = {.
pipe_bof = 1,.short_frames_ok = 1,.short_xfer_ok = 1,.ext_buffer = 1,},
157 .
flags = {.
pipe_bof = 1,.force_short_xfer = 1,.ext_buffer = 1,},
169 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,.no_pipe_ok = 1,},
181 .flags = {.pipe_bof = 1,.force_short_xfer = 1,.no_pipe_ok = 1,},
197 .
flags = {.
pipe_bof = 1,.short_frames_ok = 1,.short_xfer_ok = 1,},
198 .callback = cdce_ncm_bulk_read_callback,
211 .callback = cdce_ncm_bulk_write_callback,
222 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,.no_pipe_ok = 1,},
234 .flags = {.pipe_bof = 1,.force_short_xfer = 1,.no_pipe_ok = 1,},
284 {
USB_VPI(USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8156, 0)},
348 if (ufd->
bLength <
sizeof(*ufd))
351 DPRINTFN(1,
"Found NCM functional descriptor.\n");
362 &temp, 0, NULL, 1000 );
388 DPRINTFN(1,
"Using default maximum receive length\n");
396 DPRINTFN(1,
"Using default maximum transmit length\n");
410 DPRINTFN(1,
"Using default other alignment: 4 bytes\n");
424 DPRINTFN(1,
"Using default transmit modulus: 4 bytes\n");
431 DPRINTFN(1,
"Using default transmit remainder: 0 bytes\n");
448 DPRINTFN(1,
"Using default max "
474 &value, 0, NULL, 1000 );
476 DPRINTFN(1,
"Setting input size "
488 NULL, 0, NULL, 1000 );
490 DPRINTFN(1,
"Setting CRC mode to off failed.\n");
501 NULL, 0, NULL, 1000 );
503 DPRINTFN(1,
"Setting NTB format to 16-bit failed.\n");
541 cdce_etag = EVENTHANDLER_REGISTER(usb_dev_configured,
545 EVENTHANDLER_DEREGISTER(usb_dev_configured,
cdce_etag);
578 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
582 IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
583 ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
584 IFQ_SET_READY(&ifp->if_snd);
587 if_setcapabilitiesbit(ifp, IFCAP_VLAN_MTU, 0);
589 if_setcapabilitiesbit(ifp, IFCAP_LINKSTATE, 0);
590 if_setcapenable(ifp, if_getcapabilities(ifp));
594 ifmedia_add(&sc->
sc_media, IFM_ETHER | IFM_AUTO, 0, NULL);
595 ifmedia_set(&sc->
sc_media, IFM_ETHER | IFM_AUTO);
618 uint8_t data_iface_no;
619 char eaddr_str[5 * ETHER_ADDR_LEN];
626 mtx_init(&sc->
sc_mtx, device_get_nameunit(
dev), NULL, MTX_DEF);
632 if ((ud == NULL) || (ud->
bLength <
sizeof(*ud)) ||
634 DPRINTFN(1,
"No union descriptor!\n");
637 goto alloc_transfers;
647 if (
id && (
id->bInterfaceNumber == data_iface_no)) {
654 device_printf(
dev,
"no data interface found\n");
686 for (i = 0; i != 32; i++) {
692 if ((i == 0) && (cdce_ncm_init(sc) == 0))
693 pcfg = cdce_ncm_config;
703 if (
error || (i == 32)) {
704 device_printf(
dev,
"No valid alternate "
713 if ((ued == NULL) || (ued->
bLength <
sizeof(*ued))) {
731 device_printf(
dev,
"faking MAC address\n");
740 for (i = 0; i != (ETHER_ADDR_LEN * 2); i++) {
741 char c = eaddr_str[i];
743 if (
'0' <= c && c <=
'9')
773 device_printf(
dev,
"could not attach interface\n");
816 struct ifreq *ifr = (
struct ifreq *)
data;
838 for (x = 0; x !=
n; x++) {
839 if (ppm[x] != NULL) {
857 if ((if_getflags(ifp) & IFF_UP) == 0)
860 ifmr->ifm_active = IFM_ETHER;
861 ifmr->ifm_status = IFM_AVALID;
863 ifp->if_link_state == LINK_STATE_UP ? IFM_ACTIVE : 0;
883 DPRINTFN(11,
"transfer complete: %u bytes in %u frames\n",
886 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
895 IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
909 if (!m_append(m, 4, (
void *)&crc)) {
911 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
915 if (m->m_len != m->m_pkthdr.len) {
916 mt = m_defrag(m, M_NOWAIT);
919 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
924 if (m->m_pkthdr.len > MCLBYTES) {
925 m->m_pkthdr.len = MCLBYTES;
944 DPRINTFN(11,
"transfer error, %s\n",
951 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
967 uint32_t *p_crc = arg;
969 *p_crc = crc32_raw(src,
count, *p_crc);
976 uint32_t crc = 0xFFFFFFFF;
979 return (crc ^ 0xFFFFFFFF);
990 ifp->if_drv_flags |= IFF_DRV_RUNNING;
1017 ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
1051 if (if_getflags(ifp) & IFF_PROMISC)
1053 if (if_getflags(ifp) & IFF_ALLMULTI)
1074 device_printf(
dev,
"Suspending\n");
1081 device_printf(
dev,
"Resuming\n");
1100 DPRINTF(
"received %u bytes in %u frames\n", actlen, aframes);
1102 for (x = 0; x != aframes; x++) {
1111 if (
len < (
int)
sizeof(
struct ether_header)) {
1125 for (x = 0; x != 1; x++) {
1174 uint32_t downrate, uprate;
1186 DPRINTF(
"Received %d bytes: %*D\n", actlen,
1187 (
int)MIN(actlen,
sizeof buf), buf,
"");
1199 DPRINTF(
"changing link state: %d\n",
1201 if_link_state_change(ifp,
1215 if (downrate != uprate)
1219 DPRINTF(
"changing baudrate: %u\n",
1221 if_setbaudrate(ifp, downrate);
1264 DPRINTF(
"Transferred %d bytes\n", actlen);
1309 speed = (13 * 512 * 8 * 1000 * 8);
1311 speed = (19 * 64 * 1 * 1000 * 8);
1338 const void *preq,
void **
pptr, uint16_t *
plen,
1343 uint8_t is_complete = *
pstate;
1351 if (is_complete == 1) {
1367 uint32_t start, uint32_t end)
1378cdce_ncm_fill_tx_frames(
struct usb_xfer *xfer, uint8_t index)
1386 uint32_t last_offset;
1403 cdce_ncm_tx_zero(pc, last_offset,
offset);
1418 IFQ_DRV_DEQUEUE(&(ifp->if_snd), m);
1426 if (m->m_pkthdr.len > (
int)rem) {
1429 DPRINTFN(1,
"Frame too big to be transmitted!\n");
1431 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
1436 IFQ_DRV_PREPEND(&(ifp->if_snd), m);
1445 offset += m->m_pkthdr.len;
1455 cdce_ncm_tx_zero(pc, last_offset,
offset);
1469 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
1475 rem = (
sizeof(sc->
sc_ncm.
dpt) + (4 *
n) + 4);
1497 cdce_ncm_tx_zero(pc, last_offset,
offset);
1544 DPRINTFN(10,
"transfer complete: "
1545 "%u bytes in %u frames\n", actlen, aframes);
1549 temp = cdce_ncm_fill_tx_frames(xfer, x);
1568 DPRINTFN(10,
"Transfer error: %s\n",
1572 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
1607 DPRINTFN(1,
"received %u bytes in %u frames\n",
1610 if (actlen < (
int)(
sizeof(sc->
sc_ncm.
hdr) +
1612 DPRINTFN(1,
"frame too short\n");
1622 DPRINTFN(1,
"invalid HDR signature: "
1623 "0x%02x:0x%02x:0x%02x:0x%02x\n",
1631 if (temp > sumlen) {
1632 DPRINTFN(1,
"unsupported block length %u/%u\n",
1637 if ((
int)(temp +
sizeof(sc->
sc_ncm.
dpt)) > actlen) {
1638 DPRINTFN(1,
"invalid DPT index: 0x%04x\n", temp);
1648 DPRINTFN(1,
"invalid DPT signature"
1649 "0x%02x:0x%02x:0x%02x:0x%02x\n",
1659 if (nframes >= (2 + 1))
1664 DPRINTFN(1,
"nframes = %u\n", nframes);
1668 if ((temp + (4 * nframes)) > actlen)
1672 DPRINTFN(1,
"Truncating number of frames from %u to %u\n",
1680 for (x = 0; x != nframes; x++) {
1685 (temp < (
int)
sizeof(
struct ether_header)) ||
1686 (temp > (MCLBYTES - ETHER_ALIGN))) {
1687 DPRINTFN(1,
"NULL frame detected at %d\n", x);
1691 }
else if ((
offset + temp) > actlen) {
1692 DPRINTFN(1,
"invalid frame "
1693 "detected at %d\n", x);
1697 }
else if (temp > (
int)(MHLEN - ETHER_ALIGN)) {
1698 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
1700 m = m_gethdr(M_NOWAIT, MT_DATA);
1703 DPRINTFN(16,
"frame %u, offset = %u, length = %u \n",
1708 m->m_len = m->m_pkthdr.len = temp + ETHER_ALIGN;
1709 m_adj(m, ETHER_ALIGN);
1718 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
1722 DPRINTFN(1,
"Efficiency: %u/%u bytes\n", sumdata, actlen);
1733 DPRINTFN(1,
"error = %s\n",
static SYSCTL_NODE(_hw_usb, OID_AUTO, dwc_otg, CTLFLAG_RW|CTLFLAG_MPSAFE, 0, "USB DWC OTG")
SYSCTL_INT(_hw_usb_dwc_otg, OID_AUTO, phy_type, CTLFLAG_RDTUN, &dwc_otg_phy_type, 0, "DWC OTG PHY TYPE - 0/1/2/3 - ULPI/HSIC/INTERNAL/UTMI+")
static device_method_t cdce_methods[]
static eventhandler_tag cdce_etag
static uether_fn_t cdce_setmulti
static int cdce_ioctl(struct ifnet *, u_long, caddr_t)
static const STRUCT_USB_DUAL_ID cdce_dual_devs[]
static usb_callback_t cdce_intr_write_callback
static uether_fn_t cdce_setpromisc
USB_PNP_DUAL_INFO(cdce_dual_devs)
USB_PNP_DEVICE_INFO(cdce_switch_devs)
static uether_fn_t cdce_start
static void cdce_test_autoinst(void *arg, struct usb_device *udev, struct usb_attach_arg *uaa)
static device_suspend_t cdce_suspend
static int cdce_media_change_cb(struct ifnet *)
static device_probe_t cdce_probe
static int cdce_driver_loaded(struct module *, int, void *)
MODULE_DEPEND(cdce, uether, 1, 1, 1)
static uether_fn_t cdce_stop
static device_resume_t cdce_resume
static devclass_t cdce_devclass
static usb_callback_t cdce_intr_read_callback
static driver_t cdce_driver
DRIVER_MODULE(cdce, uhub, cdce_driver, cdce_devclass, cdce_driver_loaded, 0)
static usb_handle_request_t cdce_handle_request
static uether_fn_t cdce_attach_post
static int cdce_attach_post_sub(struct usb_ether *)
static const struct usb_ether_methods cdce_ue_methods
static const STRUCT_USB_HOST_ID cdce_host_devs[]
static usb_callback_t cdce_bulk_read_callback
static uint32_t cdce_m_crc32(struct mbuf *, uint32_t, uint32_t)
static void cdce_set_filter(struct usb_ether *)
static uether_fn_t cdce_init
static usb_callback_t cdce_bulk_write_callback
static device_attach_t cdce_attach
static int32_t cdce_m_crc32_cb(void *arg, void *src, uint32_t count)
static device_detach_t cdce_detach
static void cdce_media_status_cb(struct ifnet *, struct ifmediareq *)
static const struct usb_config cdce_config[CDCE_N_TRANSFER]
USB_PNP_HOST_INFO(cdce_host_devs)
static void cdce_free_queue(struct mbuf **ppm, uint8_t n)
static const STRUCT_USB_HOST_ID cdce_switch_devs[]
#define CDCE_NCM_TX_MINLEN
#define CDCE_NCM_RX_MAXLEN
#define CDC_PACKET_TYPE_ALL_MULTICAST
#define CDCE_NOTIFY_SPEED_CHANGE
#define CDC_SET_ETHERNET_PACKET_FILTER
#define CDCE_NCM_RX_FRAMES_MAX
#define CDCE_LOCK_ASSERT(_sc, t)
#define CDCE_FLAG_NO_UNION
#define CDC_PACKET_TYPE_BROADCAST
#define CDCE_NCM_ALIGN(rem, off, mod)
#define CDCE_NCM_TX_FRAMES_MAX
#define CDC_PACKET_TYPE_DIRECTED
#define CDCE_NCM_TX_MAXLEN
#define CDCE_NCM_SUBFRAMES_MAX
#define CDCE_IND_SIZE_MAX
#define CDCE_NOTIFY_NETWORK_CONNECTION
#define CDC_PACKET_TYPE_PROMISC
struct usb_ncm16_dp dp[CDCE_NCM_SUBFRAMES_MAX]
struct mbuf * sc_tx_buf[CDCE_FRAMES_MAX]
struct mbuf * sc_rx_buf[CDCE_FRAMES_MAX]
uint8_t sc_ifaces_index[2]
struct usb_xfer * sc_xfer[CDCE_N_TRANSFER]
enum usb_hc_mode usb_mode
struct usbd_lookup_info info
struct usb_device * device
struct usb_xfer_flags flags
uether_fn_t * ue_attach_post
const struct usb_ether_methods * ue_methods
struct usb_device * ue_udev
uint8_t ue_eaddr[ETHER_ADDR_LEN]
struct usb_interface_descriptor * idesc
uByte bmNetworkCapabilities
#define UT_READ_CLASS_INTERFACE
#define UISUBCLASS_NETWORK_CONTROL_MODEL
#define UT_WRITE_CLASS_INTERFACE
#define UISUBCLASS_MOBILE_DIRECT_LINE_MODEL
#define UDESC_CS_INTERFACE
#define UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL
void usbd_frame_zero(struct usb_page_cache *cache, usb_frlength_t offset, usb_frlength_t len)
void usbd_copy_in(struct usb_page_cache *cache, usb_frlength_t offset, const void *ptr, usb_frlength_t len)
void usbd_copy_out(struct usb_page_cache *cache, usb_frlength_t offset, void *ptr, usb_frlength_t len)
#define UCDC_N_CONNECTION_SPEED_CHANGE
#define UCDC_NOTIFICATION_LENGTH
#define UCDC_NCM_SET_ETHERNET_PACKET_FILTER
#define UDESCSUB_CDC_UNION
#define UCDC_N_NETWORK_CONNECTION
#define UCDC_NCM_SET_NTB_INPUT_SIZE
#define UCDC_NCM_FUNC_DESC_SUBTYPE
#define UCDC_NCM_GET_NTB_PARAMETERS
#define UCDC_NCM_CAP_MAX_DGRAM
#define UCDC_NCM_SET_CRC_MODE
#define UCDC_NOTIFICATION
#define UCDC_NCM_SET_NTB_FORMAT
usb_error_t usbd_set_alt_interface_index(struct usb_device *udev, uint8_t iface_index, uint8_t alt_index)
struct usb_interface_descriptor * usbd_get_interface_descriptor(struct usb_interface *iface)
void usbd_set_parent_iface(struct usb_device *udev, uint8_t iface_index, uint8_t parent_index)
void * usbd_find_descriptor(struct usb_device *udev, void *id, uint8_t iface_index, uint8_t type, uint8_t type_mask, uint8_t subtype, uint8_t subtype_mask)
enum usb_dev_speed usbd_get_speed(struct usb_device *udev)
enum usb_hc_mode usbd_get_mode(struct usb_device *udev)
struct usb_interface * usbd_get_iface(struct usb_device *udev, uint8_t iface_index)
const char * usbd_errstr(usb_error_t err)
void uether_rxflush(struct usb_ether *ue)
struct mbuf * uether_newbuf(void)
void uether_ifdetach(struct usb_ether *ue)
void * uether_getsc(struct usb_ether *ue)
struct ifnet * uether_getifp(struct usb_ether *ue)
int uether_rxmbuf(struct usb_ether *ue, struct mbuf *m, unsigned int len)
void uether_init(void *arg)
int uether_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
int uether_ifattach(struct usb_ether *ue)
void uether_start(struct ifnet *ifp)
void() uether_fn_t(struct usb_ether *)
static usb_error_t usb_handle_request(struct usb_xfer *)
int usbd_lookup_id_by_uaa(const struct usb_device_id *id, usb_size_t sizeof_id, struct usb_attach_arg *uaa)
usb_error_t usb_msc_eject(struct usb_device *udev, uint8_t iface_index, int method)
usb_error_t usbd_req_get_string_any(struct usb_device *udev, struct mtx *mtx, char *buf, uint16_t len, uint8_t string_index)
usb_error_t usbd_do_request_flags(struct usb_device *udev, struct mtx *mtx, struct usb_device_request *req, void *data, uint16_t flags, uint16_t *actlen, usb_timeout_t timeout)
void usbd_transfer_submit(struct usb_xfer *xfer)
void usbd_xfer_set_frames(struct usb_xfer *xfer, usb_frcount_t n)
void usbd_transfer_unsetup(struct usb_xfer **pxfer, uint16_t n_setup)
void usbd_xfer_set_frame_data(struct usb_xfer *xfer, usb_frcount_t frindex, void *ptr, usb_frlength_t len)
void usbd_xfer_set_frame_len(struct usb_xfer *xfer, usb_frcount_t frindex, usb_frlength_t len)
usb_frlength_t usbd_xfer_frame_len(struct usb_xfer *xfer, usb_frcount_t frindex)
struct usb_page_cache * usbd_xfer_get_frame(struct usb_xfer *xfer, usb_frcount_t frindex)
usb_error_t usbd_transfer_setup(struct usb_device *udev, const uint8_t *ifaces, struct usb_xfer **ppxfer, const struct usb_config *setup_start, uint16_t n_setup, void *priv_sc, struct mtx *xfer_mtx)
void usbd_transfer_start(struct usb_xfer *xfer)
void usbd_xfer_set_frame_offset(struct usb_xfer *xfer, usb_frlength_t offset, usb_frcount_t frindex)
void * usbd_xfer_softc(struct usb_xfer *xfer)
void usbd_xfer_set_stall(struct usb_xfer *xfer)
void usbd_xfer_set_interval(struct usb_xfer *xfer, int i)
void usbd_transfer_stop(struct usb_xfer *xfer)
void usbd_xfer_status(struct usb_xfer *xfer, int *actlen, int *sumlen, int *aframes, int *nframes)
usb_frlength_t usbd_xfer_max_len(struct usb_xfer *xfer)
void device_set_usb_desc(device_t dev)
#define USB_IF_CSI(class, subclass, info)
#define USB_IFACE_SUBCLASS(isc)
#define USB_IFACE_CLASS(ic)
#define USB_ST_TRANSFERRED
void usbd_m_copy_in(struct usb_page_cache *cache, usb_frlength_t dst_offset, struct mbuf *m, usb_size_t src_offset, usb_frlength_t src_len)
#define USB_IFACE_PROTOCOL(ip)
void() usb_callback_t(struct usb_xfer *, usb_error_t)
#define USB_VPI(vend, prod, info)
#define STRUCT_USB_HOST_ID
#define USB_GET_DRIVER_INFO(did)
#define USB_GET_STATE(xfer)
#define usbd_do_request(u, m, r, d)
#define STRUCT_USB_DUAL_ID
#define USB_DRIVER_INFO(n)