Page MenuHomeFreeBSD

D30625.id.diff
No OneTemporary

D30625.id.diff

diff --git a/sys/dev/usb/net/if_cdce.c b/sys/dev/usb/net/if_cdce.c
--- a/sys/dev/usb/net/if_cdce.c
+++ b/sys/dev/usb/net/if_cdce.c
@@ -111,6 +111,10 @@
static uether_fn_t cdce_start;
static uether_fn_t cdce_setmulti;
static uether_fn_t cdce_setpromisc;
+static int cdce_attach_post_sub(struct usb_ether *);
+static int cdce_ioctl(struct ifnet *, u_long, caddr_t);
+static int cdce_media_change_cb(struct ifnet *);
+static void cdce_media_status_cb(struct ifnet *, struct ifmediareq *);
static uint32_t cdce_m_crc32(struct mbuf *, uint32_t, uint32_t);
@@ -124,6 +128,8 @@
"Debug level");
SYSCTL_INT(_hw_usb_cdce, OID_AUTO, interval, CTLFLAG_RWTUN, &cdce_tx_interval, 0,
"NCM transmit interval in ms");
+#else
+#define cdce_debug 0
#endif
static const struct usb_config cdce_config[CDCE_N_TRANSFER] = {
@@ -307,6 +313,7 @@
static const struct usb_ether_methods cdce_ue_methods = {
.ue_attach_post = cdce_attach_post,
+ .ue_attach_post_sub = cdce_attach_post_sub,
.ue_start = cdce_start,
.ue_init = cdce_init,
.ue_stop = cdce_stop,
@@ -560,6 +567,36 @@
return;
}
+static int
+cdce_attach_post_sub(struct usb_ether *ue)
+{
+ struct cdce_softc *sc = uether_getsc(ue);
+ struct ifnet *ifp = uether_getifp(ue);
+
+ /* mostly copied from usb_ethernet.c */
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_start = uether_start;
+ ifp->if_ioctl = cdce_ioctl;
+ ifp->if_init = uether_init;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
+ IFQ_SET_READY(&ifp->if_snd);
+
+ if ((sc->sc_flags & CDCE_FLAG_VLAN) == CDCE_FLAG_VLAN)
+ if_setcapabilitiesbit(ifp, IFCAP_VLAN_MTU, 0);
+
+ if_setcapabilitiesbit(ifp, IFCAP_LINKSTATE, 0);
+ if_setcapenable(ifp, if_getcapabilities(ifp));
+
+ ifmedia_init(&sc->sc_media, IFM_IMASK, cdce_media_change_cb,
+ cdce_media_status_cb);
+ ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL);
+ ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO);
+ sc->sc_media.ifm_media = sc->sc_media.ifm_cur->ifm_media;
+
+ return 0;
+}
+
static int
cdce_attach(device_t dev)
{
@@ -676,6 +713,14 @@
eaddr_str, sizeof(eaddr_str), ued->iMacAddress);
}
+ /*
+ * ECM 1.2 doesn't say it excludes the CRC, but states that it's
+ * normally 1514, which excludes the CRC.
+ */
+ DPRINTF("max segsize: %d\n", UGETW(ued->wMaxSegmentSize));
+ if (UGETW(ued->wMaxSegmentSize) >= (ETHER_MAX_LEN - ETHER_CRC_LEN + ETHER_VLAN_ENCAP_LEN))
+ sc->sc_flags |= CDCE_FLAG_VLAN;
+
if (error) {
/* fake MAC address */
@@ -742,6 +787,8 @@
uether_ifdetach(ue);
mtx_destroy(&sc->sc_mtx);
+ ifmedia_removeall(&sc->sc_media);
+
return (0);
}
@@ -757,6 +804,29 @@
usbd_transfer_start(sc->sc_xfer[CDCE_BULK_RX]);
}
+static int
+cdce_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
+{
+ struct usb_ether *ue = ifp->if_softc;
+ struct cdce_softc *sc = uether_getsc(ue);
+ struct ifreq *ifr = (struct ifreq *)data;
+ int error;
+
+ error = 0;
+
+ switch(command) {
+ case SIOCGIFMEDIA:
+ case SIOCSIFMEDIA:
+ error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, command);
+ break;
+ default:
+ error = uether_ioctl(ifp, command, data);
+ break;
+ }
+
+ return (error);
+}
+
static void
cdce_free_queue(struct mbuf **ppm, uint8_t n)
{
@@ -769,6 +839,26 @@
}
}
+static int
+cdce_media_change_cb(struct ifnet *ifp)
+{
+
+ return (EOPNOTSUPP);
+}
+
+static void
+cdce_media_status_cb(struct ifnet *ifp, struct ifmediareq *ifmr)
+{
+
+ if ((if_getflags(ifp) & IFF_UP) == 0)
+ return;
+
+ ifmr->ifm_active = IFM_ETHER;
+ ifmr->ifm_status = IFM_AVALID;
+ ifmr->ifm_status |=
+ ifp->if_link_state == LINK_STATE_UP ? IFM_ACTIVE : 0;
+}
+
static void
cdce_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
{
@@ -1043,17 +1133,69 @@
static void
cdce_intr_read_callback(struct usb_xfer *xfer, usb_error_t error)
{
- struct cdce_softc *sc = usbd_xfer_softc(xfer);
- int actlen;
+ u_char buf[CDCE_IND_SIZE_MAX];
+ struct usb_cdc_notification ucn;
+ struct cdce_softc *sc;
+ struct ifnet *ifp;
+ struct usb_page_cache *pc;
+ int off, actlen;
+ uint32_t downrate, uprate;
+
+ sc = usbd_xfer_softc(xfer);
+ ifp = uether_getifp(&sc->sc_ue);
+ pc = usbd_xfer_get_frame(xfer, 0);
usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
switch (USB_GET_STATE(xfer)) {
case USB_ST_TRANSFERRED:
+ if (USB_DEBUG_VAR)
+ usbd_copy_out(pc, 0, buf, MIN(actlen, sizeof buf));
+ DPRINTF("Received %d bytes: %*D\n", actlen,
+ (int)MIN(actlen, sizeof buf), buf, "");
+
+ off = 0;
+ while (actlen - off >= UCDC_NOTIFICATION_LENGTH) {
+ usbd_copy_out(pc, off, &ucn, UCDC_NOTIFICATION_LENGTH);
+
+ do {
+ if (ucn.bmRequestType != 0xa1)
+ break;
+
+ switch (ucn.bNotification) {
+ case UCDC_N_NETWORK_CONNECTION:
+ DPRINTF("changing link state: %d\n",
+ UGETW(ucn.wValue));
+ if_link_state_change(ifp,
+ UGETW(ucn.wValue) ? LINK_STATE_UP :
+ LINK_STATE_DOWN);
+ break;
+
+ case UCDC_N_CONNECTION_SPEED_CHANGE:
+ if (UGETW(ucn.wLength) != 8)
+ break;
+
+ usbd_copy_out(pc, off +
+ UCDC_NOTIFICATION_LENGTH,
+ &ucn.data, UGETW(ucn.wLength));
+ downrate = UGETDW(ucn.data);
+ uprate = UGETDW(ucn.data);
+ if (downrate != uprate)
+ break;
+
+ /* set rate */
+ DPRINTF("changing baudrate: %u\n",
+ downrate);
+ if_setbaudrate(ifp, downrate);
+ break;
+
+ default:
+ break;
+ }
+ } while (0);
- DPRINTF("Received %d bytes\n", actlen);
-
- /* TODO: decode some indications */
+ off += UCDC_NOTIFICATION_LENGTH + UGETW(ucn.wLength);
+ }
/* FALLTHROUGH */
case USB_ST_SETUP:
diff --git a/sys/dev/usb/net/if_cdcereg.h b/sys/dev/usb/net/if_cdcereg.h
--- a/sys/dev/usb/net/if_cdcereg.h
+++ b/sys/dev/usb/net/if_cdcereg.h
@@ -88,10 +88,13 @@
struct mbuf *sc_rx_buf[CDCE_FRAMES_MAX];
struct mbuf *sc_tx_buf[CDCE_FRAMES_MAX];
+ struct ifmedia sc_media;
+
int sc_flags;
#define CDCE_FLAG_ZAURUS 0x0001
#define CDCE_FLAG_NO_UNION 0x0002
#define CDCE_FLAG_RX_DATA 0x0010
+#define CDCE_FLAG_VLAN 0x0020
uint8_t sc_eaddr_str_index;
uint8_t sc_ifaces_index[2];

File Metadata

Mime Type
text/plain
Expires
Tue, Nov 19, 10:52 PM (13 h, 20 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14724877
Default Alt Text
D30625.id.diff (6 KB)

Event Timeline