34#include <sys/eventhandler.h>
38#include <sys/socket.h>
39#include <sys/kernel.h>
41#include <sys/module.h>
42#include <sys/sockio.h>
43#include <sys/socket.h>
46#include <sys/condvar.h>
47#include <sys/sysctl.h>
48#include <sys/malloc.h>
49#include <sys/taskqueue.h>
52#include <net/if_var.h>
54#include <machine/bus.h>
57#include <net/if_types.h>
58#include <net/netisr.h>
60#include <net/ethernet.h>
62#include <netinet/in.h>
63#include <netinet/ip.h>
64#include <netinet/ip6.h>
65#include <netinet/udp.h>
67#include <net80211/ieee80211_ioctl.h>
75#define USB_DEBUG_VAR usie_debug
85static int usie_debug = 0;
87static SYSCTL_NODE(_hw_usb, OID_AUTO, usie, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
95#define USIE_DEV(v, d) { \
96 USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##d) }
133 const struct sockaddr *,
struct route *);
151 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
159 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,.proxy_buffer = 1,},
167 .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
178 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
186 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
194 .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
270 NULL, 0, NULL, 250 );
297 struct usie_softc *sc = device_get_softc(self);
313 mtx_init(&sc->
sc_mtx,
"usie", MTX_NETWORK_LOCK, MTX_DEF);
347 DPRINTF(
"fwattr=%x\n", fwattr);
349 device_printf(self,
"DHCP is not supported. A firmware upgrade might be needed.\n");
364 if (
id->bInterfaceNumber >= 7 &&
id->bNumEndpoints == 3) {
368 DPRINTF(
"ifnum=%d, ifidx=%d\n",
379 "could not allocate USB transfers on "
380 "iface_index=%d, err=%s\n",
392 DPRINTF(
"NumEndpoints=%d bInterfaceNumber=%d\n",
393 id->bNumEndpoints,
id->bInterfaceNumber);
395 if (
id->bNumEndpoints == 2) {
422 device_printf(self,
"no comports found\n");
430 DPRINTF(
"ucom_attach failed\n");
436 sc->
sc_ifp = ifp = if_alloc(IFT_OTHER);
439 device_printf(self,
"Could not allocate a network interface\n");
442 if_initname(ifp,
"usie", device_get_unit(self));
446 ifp->if_flags |= IFF_NOARP;
451 IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
452 ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
453 IFQ_SET_READY(&ifp->if_snd);
456 bpfattach(ifp, DLT_RAW, 0);
460 DPRINTF(
"enabling automatic suspend and resume\n");
463 DPRINTF(
"USB power is always ON\n");
477 struct usie_softc *sc = device_get_softc(self);
499 device_claim_softc(self);
513 device_free_softc(sc);
636 DPRINTF(
"transferred=%u\n", actlen);
729 DPRINTFN(4,
"info received, actlen=%u\n", actlen);
731 if (actlen <
sizeof(st)) {
732 DPRINTF(
"data too short actlen=%u\n", actlen);
738 if (st.req.bmRequestType == 0xa1 && st.req.bRequest == 0x20) {
742 param = le16toh(st.param);
760 DPRINTF(
"USB transfer error, %s\n",
774 struct epoch_tracker et;
776 struct ifnet *ifp = sc->
sc_ifp;
778 struct mbuf *m = NULL;
793 DPRINTFN(15,
"rx done, actlen=%u\n", actlen);
795 if (actlen <
sizeof(
struct usie_hip)) {
796 DPRINTF(
"data too short %u\n", actlen);
807 sc->
sc_rxm = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR,
811 DPRINTF(
"could not allocate Rx mbuf\n");
812 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
834 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
849 m->m_pkthdr.len = m->m_len = actlen;
860 ipl = (
len -
pad - ETHER_HDR_LEN);
870 DPRINTF(
"received wrong type of packet\n");
872 m->m_pkthdr.len = (m->m_len -= diff);
874 if (m->m_pkthdr.len > 0)
879 switch (be16toh(rxd->
ethhdr.ether_type)) {
889 DPRINTF(
"unsupported ether type\n");
895 if (m->m_pkthdr.len <= diff) {
897 m->m_pkthdr.len = m->m_len = ipl;
898 m->m_pkthdr.rcvif = ifp;
900 netisr_dispatch(ipv, m);
904 m0 = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
905 if (__predict_false(m0 == NULL)) {
906 DPRINTF(
"could not allocate mbuf\n");
911 m_copydata(m,
sizeof(
struct usie_desc) +
pad, ipl, mtod(m0, caddr_t));
912 m0->m_pkthdr.rcvif = ifp;
913 m0->m_pkthdr.len = m0->m_len = ipl;
916 netisr_dispatch(ipv, m0);
919 m->m_pkthdr.len = (m->m_len -= diff);
925 if_inc_counter(ifp, IFCOUNTER_IERRORS, err);
926 if_inc_counter(ifp, IFCOUNTER_IPACKETS, pkt);
934 struct ifnet *ifp = sc->
sc_ifp;
940 DPRINTFN(11,
"transfer complete\n");
941 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
942 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
948 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
951 IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
955 if (m->m_pkthdr.len > (
int)(MCLBYTES - ETHER_HDR_LEN +
956 ETHER_CRC_LEN -
sizeof(sc->
sc_txd))) {
957 DPRINTF(
"packet len is too big: %d\n",
964 ETHER_HDR_LEN + ETHER_CRC_LEN);
970 size + ETHER_CRC_LEN);
980 DPRINTF(
"USB transfer error, %s\n",
982 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
986 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
1005 DPRINTFN(4,
"info received, actlen=%d\n", actlen);
1008 if (actlen < (
sizeof(cdc) - 16)) {
1009 DPRINTF(
"data too short %d\n", actlen);
1018 taskqueue_enqueue(taskqueue_thread,
1029 DPRINTF(
"USB transfer error, %s\n",
1068 struct ifnet *ifp = sc->
sc_ifp;
1082 USETW(
req.wLength,
sizeof(sc->sc_status_temp));
1084 for (ntries = 0; ntries != 10; ntries++) {
1094 DPRINTF(
"Control request failed: %s %d/10\n",
1106 hip = (
struct usie_hip *)sc->sc_status_temp;
1110 DPRINTF(
"hip.id=%x hip.len=%d actlen=%u pad=%d\n",
1111 hip->
id, be16toh(hip->
len), actlen,
pad);
1122 sc->sc_status_temp +
sizeof(
struct usie_hip) +
pad);
1132 device_printf(sc->
sc_dev,
"no service available\n");
1147 ifp->if_flags |= IFF_UP;
1148 ifp->if_drv_flags |= IFF_DRV_RUNNING;
1150 device_printf(sc->
sc_dev,
"IP Addr=%d.%d.%d.%d\n",
1153 device_printf(sc->
sc_dev,
"Gateway Addr=%d.%d.%d.%d\n",
1156 device_printf(sc->
sc_dev,
"Prim NS Addr=%d.%d.%d.%d\n",
1159 device_printf(sc->
sc_dev,
"Scnd NS Addr=%d.%d.%d.%d\n",
1170 DPRINTF(
"undefined msgid: %x\n", hip->
id);
1182 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
1190 DPRINTFN(3,
"interface started\n");
1199 DPRINTF(
"proto=%x\n", dst->sa_family);
1201 switch (dst->sa_family) {
1217 return (EAFNOSUPPORT);
1220 err = (ifp->if_transmit)(ifp, m);
1222 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
1225 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
1234 struct ifnet *ifp = sc->
sc_ifp;
1252 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
1257 DPRINTF(
"ifnet initialized\n");
1284 struct ieee80211req *ireq;
1285 struct ieee80211req_sta_info si;
1286 struct ifmediareq *ifmr;
1290 if (ifp->if_flags & IFF_UP) {
1291 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
1294 if (ifp->if_drv_flags & IFF_DRV_RUNNING)
1300 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
1301 device_printf(sc->
sc_dev,
1302 "Connect to the network first.\n");
1311 ireq = (
struct ieee80211req *)
data;
1313 if (ireq->i_type != IEEE80211_IOC_STA_INFO)
1316 memset(&si, 0,
sizeof(si));
1317 si.isi_len =
sizeof(si);
1322 si.isi_rssi = 2 * sc->
sc_rssi;
1323 if (copyout(&si, (uint8_t *)ireq->i_data + 8,
1324 sizeof(
struct ieee80211req_sta_info)))
1330 ifmr = (
struct ifmediareq *)
data;
1331 ifmr->ifm_count = 1;
1351 mtx_assert(&sc->
sc_mtx, MA_OWNED);
1353 for (ntries = 0; ntries != 10; ntries++) {
1359 DPRINTF(
"Control request failed: %s %d/10\n",
1391 struct ifnet *ifp = sc->
sc_ifp;
1400 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
1401 if (__predict_false(m == NULL)) {
1402 DPRINTF(
"could not allocate mbuf\n");
1403 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
1408 param = mtod(m, uint8_t *);
1411 cns = (
struct usie_cns *)(hip + 1);
1428 memcpy(tmp, &sc->
sc_net, 34);
1429 memset(tmp + 35, 0, 245 - 36);
1439 DPRINTF(
"unsupported CnS object type\n");
1444 hip->
len = htobe16(
sizeof(
struct usie_cns) + cns_len);
1449 cns->
id = htobe32(
id);
1453 param = (uint8_t *)(cns + 1);
1465 DPRINTF(
"Dropped CNS event\n");
1473 struct ifnet *ifp = sc->
sc_ifp;
1477 switch (be16toh(cns->
obj)) {
1482 ifp->if_flags &= ~IFF_UP;
1483 ifp->if_drv_flags &=
1484 ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
1486 DPRINTF(
"undefined link update\n");
1490 sc->
sc_rssi = be16toh(*(int16_t *)(cns + 1));
1492 device_printf(sc->
sc_dev,
"No signal\n");
1494 device_printf(sc->
sc_dev,
"RSSI=%ddBm\n",
1528 for (i = j = 0; ((i + off) <
len) &&
1534 if ((i + off + 1) >=
len)
1536 tmp[j++] = rsp[i++ + off + 1] ^ 0x20;
1538 tmp[j++] = rsp[i + off];
1554 memset(tmp + j, 0,
sizeof(tmp) - j);
1558 DPRINTF(
"hip: len=%d msgID=%02x, param=%02x\n",
1564 cns = (
struct usie_cns *)(((uint8_t *)(hip + 1)) +
pad);
1571 DPRINTF(
"cns: obj=%04x, op=%02x, rsv0=%02x, "
1572 "app=%08x, rsv1=%02x, len=%d\n",
1577 DPRINTF(
"CnS error response\n");
1585 j = be16toh(hip->
len);
1588 if (usie_debug == 0)
1591 while (i < USIE_HIPCNS_MAX && j > 0) {
1592 DPRINTF(
"param[0x%02x] = 0x%02x\n", i, tmp[i]);
1606 usie_etag = EVENTHANDLER_REGISTER(usb_dev_configured,
1610 EVENTHANDLER_DEREGISTER(usb_dev_configured,
usie_etag);
1613 return (EOPNOTSUPP);
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+")
struct ehci_hw_softc __aligned
static void usie_if_sync_cb(void *, int)
static int usie_if_output(struct ifnet *, struct mbuf *, const struct sockaddr *, struct route *)
static void usie_uc_cfg_set_rts(struct ucom_softc *, uint8_t)
static void usie_if_sync_to(void *)
static usb_callback_t usie_if_tx_callback
static void usie_uc_cfg_open(struct ucom_softc *)
static usb_callback_t usie_uc_rx_callback
DRIVER_MODULE(usie, uhub, usie_driver, usie_devclass, usie_driver_loaded, 0)
static const struct ucom_callback usie_uc_callback
static void usie_uc_start_write(struct ucom_softc *)
static void usie_if_stop(struct usie_softc *)
static int usie_if_ioctl(struct ifnet *, u_long, caddr_t)
static int usie_do_request(struct usie_softc *, struct usb_device_request *, void *)
static void usie_uc_cfg_close(struct ucom_softc *)
static device_attach_t usie_attach
static usb_callback_t usie_if_status_callback
static usb_callback_t usie_uc_status_callback
static device_probe_t usie_probe
static void usie_free(struct ucom_softc *)
static int usie_if_cmd(struct usie_softc *, uint8_t)
static void usie_if_start(struct ifnet *)
static const struct usb_config usie_if_config[USIE_IF_N_XFER]
static void usie_uc_update_line_state(struct ucom_softc *, uint8_t)
static void usie_cns_rsp(struct usie_softc *, struct usie_cns *)
static void usie_if_init(void *)
static eventhandler_tag usie_etag
static void usie_free_softc(struct usie_softc *)
static device_method_t usie_methods[]
static void usie_autoinst(void *arg, struct usb_device *udev, struct usb_attach_arg *uaa)
static const struct usb_config usie_uc_config[USIE_UC_N_XFER]
USB_PNP_HOST_INFO(usie_devs)
static void usie_uc_cfg_get_status(struct ucom_softc *, uint8_t *, uint8_t *)
static const STRUCT_USB_HOST_ID usie_devs[]
static void usie_uc_start_read(struct ucom_softc *)
static void usie_if_status_cb(void *, int)
static devclass_t usie_devclass
static void usie_cns_req(struct usie_softc *, uint32_t, uint16_t)
static driver_t usie_driver
static void usie_uc_cfg_set_dtr(struct ucom_softc *, uint8_t)
static usb_callback_t usie_uc_tx_callback
MODULE_DEPEND(usie, ucom, 1, 1, 1)
static device_detach_t usie_detach
static usb_callback_t usie_if_rx_callback
static void usie_uc_stop_read(struct ucom_softc *)
static int usie_driver_loaded(struct module *, int, void *)
static void usie_hip_rsp(struct usie_softc *, uint8_t *, uint32_t)
static void usie_uc_stop_write(struct ucom_softc *)
#define USIE_HIP_IP_LEN_MASK
#define USIE_CNS_OB_LINK_UPDATE
#define USIE_CNS_OB_PROF_WRITE
#define USIE_LSI_AREA_NODATA
#define USIE_LSI_STATE_IDLE
#define USIE_CNS_OB_PDP_READ
void(* ucom_cfg_get_status)(struct ucom_softc *, uint8_t *plsr, uint8_t *pmsr)
enum usb_hc_mode usb_mode
struct usbd_lookup_info info
struct usb_device * device
struct usb_interface_descriptor * idesc
struct ether_header ethhdr
struct task sc_if_status_task
struct task sc_if_sync_task
struct ucom_softc sc_ucom[USIE_UCOM_MAX]
struct usie_net_info sc_net
uint8_t sc_uc_ifnum[USIE_UCOM_MAX]
struct ucom_super_softc sc_super_ucom
struct usb_callout sc_if_sync_ch
struct usb_device * sc_udev
struct usb_xfer * sc_if_xfer[USIE_IF_N_XFER]
struct usb_xfer * sc_uc_xfer[USIE_UCOM_MAX][USIE_UC_N_XFER]
#define UT_READ_CLASS_INTERFACE
#define UF_DEVICE_REMOTE_WAKEUP
#define UT_WRITE_VENDOR_DEVICE
#define UT_READ_VENDOR_DEVICE
#define USB_POWER_MODE_SAVE
#define USB_POWER_MODE_ON
#define UT_WRITE_CLASS_INTERFACE
#define UHF_PORT_CONNECTION
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_SEND_ENCAPSULATED_COMMAND
#define UCDC_N_RESPONSE_AVAILABLE
#define UCDC_GET_ENCAPSULATED_RESPONSE
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)
const char * usb_get_product(struct usb_device *udev)
struct usb_interface * usbd_get_iface(struct usb_device *udev, uint8_t iface_index)
const char * usb_get_manufacturer(struct usb_device *udev)
const char * usbd_errstr(usb_error_t err)
void usbd_set_power_mode(struct usb_device *udev, uint8_t power_mode)
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 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)
uint8_t ucom_get_data(struct ucom_softc *sc, struct usb_page_cache *pc, uint32_t offset, uint32_t len, uint32_t *actlen)
int ucom_attach(struct ucom_super_softc *ssc, struct ucom_softc *sc, int subunits, void *parent, const struct ucom_callback *callback, struct mtx *mtx)
int ucom_unref(struct ucom_super_softc *ssc)
void ucom_ref(struct ucom_super_softc *ssc)
void ucom_detach(struct ucom_super_softc *ssc, struct ucom_softc *sc)
void ucom_put_data(struct ucom_softc *sc, struct usb_page_cache *pc, uint32_t offset, uint32_t len)
void usbd_transfer_submit(struct usb_xfer *xfer)
void usbd_xfer_set_frames(struct usb_xfer *xfer, usb_frcount_t n)
void * usbd_xfer_get_priv(struct usb_xfer *xfer)
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)
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_priv(struct usb_xfer *xfer, void *ptr)
void * usbd_xfer_softc(struct usb_xfer *xfer)
void usbd_xfer_set_stall(struct usb_xfer *xfer)
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)
void usb_pause_mtx(struct mtx *mtx, int timo)
#define USB_DEFAULT_TIMEOUT
#define usb_callout_init_mtx(c, m, f)
#define usb_callout_reset(c,...)
#define USB_SHORT_XFER_OK
#define usb_callout_drain(c)
#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_MS_TO_TICKS(ms)
void() usb_callback_t(struct usb_xfer *, usb_error_t)
#define STRUCT_USB_HOST_ID
#define usb_callout_stop(c)
#define USB_GET_STATE(xfer)
#define usbd_do_request(u, m, r, d)