Page MenuHomeFreeBSD

D30625.id90350.diff
No OneTemporary

D30625.id90350.diff

Index: sys/dev/usb/net/if_cdce.c
===================================================================
--- sys/dev/usb/net/if_cdce.c
+++ 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);
@@ -308,6 +312,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,
@@ -561,6 +566,32 @@
return;
}
+static int
+cdce_attach_post_sub(struct usb_ether *ue)
+{
+ struct cdce_softc *sc = uether_getsc(ue);
+ struct ifnet *ifp = uether_getifp(ue);
+
+ 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_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)
{
@@ -743,6 +774,8 @@
uether_ifdetach(ue);
mtx_destroy(&sc->sc_mtx);
+ ifmedia_removeall(&sc->sc_media);
+
return (0);
}
@@ -758,6 +791,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)
{
@@ -770,6 +826,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)
{
@@ -1044,17 +1120,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[128];
+ 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:
Index: sys/dev/usb/net/if_cdcereg.h
===================================================================
--- sys/dev/usb/net/if_cdcereg.h
+++ sys/dev/usb/net/if_cdcereg.h
@@ -88,6 +88,8 @@
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

File Metadata

Mime Type
text/plain
Expires
Mon, Apr 20, 11:10 PM (21 h, 17 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31870534
Default Alt Text
D30625.id90350.diff (5 KB)

Event Timeline