3 * Written by Yellow Rabbit <yrabbit@sdf.lonestar.org>
9 * Takes two interfaces.
10 * IN and OUT endpoints on the data interface (altsetting).
11 * Interrupt endpoint on the control interface.
14 * Transfer frames without modification (AS IS).
17 #include <sys/param.h>
18 #include <sys/systm.h>
19 #include <sys/kernel.h>
20 #include <sys/socket.h>
21 #include <sys/sockio.h>
25 #include <net/ifq_var.h>
26 #include <net/if_arp.h>
27 #include <net/ethernet.h>
30 #include <bus/usb/usb.h>
31 #include <bus/usb/usbcdc.h>
32 #include <bus/usb/usbdi.h>
33 #include <bus/usb/usbdi_util.h>
34 #include <bus/usb/usbdivar.h>
35 #include <bus/usb/usb_ethersubr.h>
40 * Supported device vendors/products
42 static struct usb_devno lgue_devs[] = {
43 { USB_DEVICE(0x1004, 0x61a2) } /* LG P500 */
46 static int lgue_match(device_t);
47 static int lgue_attach(device_t);
48 static int lgue_detach(device_t);
50 static void lgue_start(struct ifnet *);
51 static void lgue_stop(struct lgue_softc *);
52 static void lgue_init(void *);
53 static void lgue_watchdog(struct ifnet *);
54 static int lgue_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *);
56 static int lgue_encap(struct lgue_softc *, struct mbuf *);
57 static int lgue_start_transfer(struct lgue_softc *);
59 static void lgue_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
61 static int lgue_newbuf(struct lgue_softc *, int, struct mbuf **);
62 static void lgue_rxstart(struct ifnet *);
63 static void lgue_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
65 static void lgue_intrstart(struct ifnet *);
66 static void lgue_intreof(usbd_xfer_handle, usbd_private_handle, usbd_status);
68 static int lgue_get_data_iface_no(usbd_device_handle,
69 usb_interface_descriptor_t *);
71 static int lgue_getmac(struct lgue_softc *, void *);
72 static int lgue_getmtu(struct lgue_softc *);
76 static device_method_t lgue_methods[] = {
77 DEVMETHOD(device_probe, lgue_match),
78 DEVMETHOD(device_attach, lgue_attach),
79 DEVMETHOD(device_detach, lgue_detach),
84 static driver_t lgue_driver = {
87 sizeof(struct lgue_softc)
90 static devclass_t lgue_devclass;
92 DECLARE_DUMMY_MODULE(if_lgue);
93 DRIVER_MODULE(lgue, uhub, lgue_driver, lgue_devclass, usbd_driver_load, NULL);
94 MODULE_DEPEND(lgue, usb, 1, 1, 1);
100 lgue_match(device_t dev)
102 struct usb_attach_arg *uaa;
103 usb_interface_descriptor_t *id;
105 uaa = device_get_ivars(dev);
106 if (uaa->iface == NULL)
109 if (usb_lookup(lgue_devs, uaa->vendor, uaa->product) != NULL) {
110 id = usbd_get_interface_descriptor(uaa->iface);
112 id->bInterfaceClass == UICLASS_CDC &&
113 id->bInterfaceSubClass == UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL)
114 return(UMATCH_VENDOR_PRODUCT);
120 * Attach the interface.
123 lgue_attach(device_t dev)
125 struct lgue_softc *sc;
126 struct usb_attach_arg *uaa;
128 usb_interface_descriptor_t *id;
129 usb_endpoint_descriptor_t *ed;
131 u_char eaddr[ETHER_ADDR_LEN];
134 sc = device_get_softc(dev);
135 uaa = device_get_ivars(dev);
137 sc->lgue_ctl_iface = uaa->iface;
138 sc->lgue_udev = uaa->device;
140 /* It has only config but in case... */
141 if (usbd_set_config_no(sc->lgue_udev, LGUE_CONFIG_NO, 0)) {
142 device_printf(dev, "setting config no %d failed\n",
147 /* Get control and data intefaces */
148 id = usbd_get_interface_descriptor(uaa->iface);
149 sc->lgue_ctl_iface_no = id->bInterfaceNumber;
150 sc->lgue_data_iface_no = lgue_get_data_iface_no(sc->lgue_udev, id);
152 if (sc->lgue_data_iface_no == -1) {
153 device_printf(dev, "no data interface number\n");
157 /* Claim data interface */
158 for (i = 0; i < uaa->nifaces; ++i) {
159 if (uaa->ifaces[i] != NULL) {
160 id = usbd_get_interface_descriptor(uaa->ifaces[i]);
162 id->bInterfaceNumber == sc->lgue_data_iface_no) {
163 err = usbd_set_interface(uaa->ifaces[i],
164 LGUE_ALTERNATE_SETTING);
165 if ( err != USBD_NORMAL_COMPLETION) {
167 "no alternate data interface. err:%s\n",
171 sc->lgue_data_iface = uaa->ifaces[i];
172 uaa->ifaces[i] = NULL;
176 if (sc->lgue_data_iface == NULL) {
177 device_printf(dev, "no data interface\n");
181 /* Find data interface endpoints */
182 id = usbd_get_interface_descriptor(sc->lgue_data_iface);
183 sc->lgue_ed[LGUE_ENDPT_RX] = sc->lgue_ed[LGUE_ENDPT_TX] = -1;
184 for (i = 0; i < id->bNumEndpoints; ++i) {
185 ed = usbd_interface2endpoint_descriptor(sc->lgue_data_iface, i);
188 "couldn't get endpoint descriptor %d\n", i);
191 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
192 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
193 sc->lgue_ed[LGUE_ENDPT_RX] = ed->bEndpointAddress;
194 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
195 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
196 sc->lgue_ed[LGUE_ENDPT_TX] = ed->bEndpointAddress;
200 if (sc->lgue_ed[LGUE_ENDPT_RX] == -1) {
201 device_printf(dev, "couldn't find data bilk in\n");
204 if (sc->lgue_ed[LGUE_ENDPT_TX] == -1) {
205 device_printf(dev, "couldn't find data bilk out\n");
209 /* Find control interface endpoint */
210 id = usbd_get_interface_descriptor(sc->lgue_ctl_iface);
211 sc->lgue_ed[LGUE_ENDPT_INTR] = -1;
212 for (i = 0; i < id->bNumEndpoints; ++i) {
213 ed = usbd_interface2endpoint_descriptor(sc->lgue_ctl_iface, i);
216 "couldn't get endpoint descriptor %d\n", i);
219 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
220 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
221 sc->lgue_ed[LGUE_ENDPT_INTR] = ed->bEndpointAddress;
225 if (sc->lgue_ed[LGUE_ENDPT_INTR] == -1) {
226 device_printf(dev, "couldn't find interrupt bilk in\n");
230 /* Create interface */
231 ifp = &sc->lgue_arpcom.ac_if;
233 if_initname(ifp, device_get_name(dev), device_get_unit(dev));
234 lgue_getmac(sc, eaddr);
236 ifp->if_mtu = lgue_getmtu(sc);
237 ifp->if_data.ifi_mtu = ifp->if_mtu;
238 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
239 ifp->if_baudrate = 10000000;
240 ifp->if_ioctl = lgue_ioctl;
241 ifp->if_start = lgue_start;
242 ifp->if_watchdog = lgue_watchdog;
243 ifp->if_init = lgue_init;
244 ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN);
245 ifq_set_ready(&ifp->if_snd);
247 /* Call attach routine */
248 ether_ifattach(ifp, eaddr, NULL);
249 usb_register_netisr();
261 lgue_detach(device_t dev)
263 struct lgue_softc *sc;
266 sc = device_get_softc(dev);
267 ifp = &sc->lgue_arpcom.ac_if;
270 if (sc->lgue_ep[LGUE_ENDPT_TX] != NULL)
271 usbd_abort_pipe(sc->lgue_ep[LGUE_ENDPT_TX]);
272 if (sc->lgue_ep[LGUE_ENDPT_RX] != NULL)
273 usbd_abort_pipe(sc->lgue_ep[LGUE_ENDPT_RX]);
274 if (sc->lgue_ep[LGUE_ENDPT_INTR] != NULL)
275 usbd_abort_pipe(sc->lgue_ep[LGUE_ENDPT_INTR]);
280 * Find data interface.
283 lgue_get_data_iface_no(usbd_device_handle dev, usb_interface_descriptor_t *id)
285 const usb_cdc_union_descriptor_t *cud;
287 cud = (const usb_cdc_union_descriptor_t *)usb_find_desc_if(dev,
288 UDESC_CS_INTERFACE, UDESCSUB_CDC_UNION, id);
289 return(cud ? cud->bSlaveInterface[0] : -1);
296 lgue_getmtu(struct lgue_softc *sc)
298 const usb_cdc_ethernet_descriptor_t *ced;
299 usb_interface_descriptor_t *id;
301 id = usbd_get_interface_descriptor(sc->lgue_ctl_iface);
303 kprintf("usbd_get_interface_descriptor() returned NULL\n");
307 ced = (const usb_cdc_ethernet_descriptor_t *)usb_find_desc_if(sc->lgue_udev,
308 UDESC_CS_INTERFACE, UDESCSUB_CDC_ETHERNET, id);
310 kprintf("usb_find_desc_if() returned NULL\n");
313 return(UGETW(ced->wMaxSegmentSize));
320 lgue_getmac(struct lgue_softc *sc, void *buf)
322 const usb_cdc_ethernet_descriptor_t *ced;
323 usb_interface_descriptor_t *id;
324 char sbuf[ETHER_ADDR_LEN * 2 + 1];
328 id = usbd_get_interface_descriptor(sc->lgue_ctl_iface);
329 if (id == NULL) goto bad;
330 ced = (const usb_cdc_ethernet_descriptor_t *)usb_find_desc_if(sc->lgue_udev,
331 UDESC_CS_INTERFACE, UDESCSUB_CDC_ETHERNET, id);
332 if (ced == NULL) goto bad;
334 err = usbd_get_string(sc->lgue_udev, ced->iMACAddress, sbuf);
336 kprintf("Read MAC address failed\n");
340 for (i = 0; i < ETHER_ADDR_LEN; ++i) {
341 ((uByte *)buf)[i] = (hex(sbuf[i * 2]) << 4) + hex(sbuf[(i * 2) + 1]);
352 lgue_intrstart(struct ifnet *ifp)
354 struct lgue_softc *sc;
357 usbd_setup_xfer(sc->lgue_intr_xfer, sc->lgue_ep[LGUE_ENDPT_INTR], sc,
358 sc->lgue_intr_buf, LGUE_BUFSZ,
359 USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, lgue_intreof);
360 usbd_transfer(sc->lgue_intr_xfer);
367 lgue_intreof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
370 struct lgue_softc *sc;
376 ifp = &sc->lgue_arpcom.ac_if;
377 lwkt_serialize_enter(ifp->if_serializer);
378 if (status != USBD_NORMAL_COMPLETION) {
379 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
380 lwkt_serialize_exit(ifp->if_serializer);
383 if_printf(ifp, "usb error on intr: %s\n", usbd_errstr(status));
384 if (status == USBD_STALLED)
385 usbd_clear_endpoint_stall(sc->lgue_ep[LGUE_ENDPT_INTR]);
386 lwkt_serialize_exit(ifp->if_serializer);
390 lwkt_serialize_exit(ifp->if_serializer);
394 * Encap packet & send
397 lgue_encap(struct lgue_softc *sc, struct mbuf *m)
400 struct lgue_queue_entry *entry;
402 ifp = &sc->lgue_arpcom.ac_if;
403 entry = kmalloc(sizeof(struct lgue_queue_entry), M_USBDEV , M_NOWAIT);
405 if_printf(ifp, "no memory for internal queue entry\n");
408 entry->entry_mbuf = m;
410 /* Put packet into internal queue tail */
411 STAILQ_INSERT_TAIL(&sc->lgue_tx_queue, entry, entry_next);
416 * Start transfer from internal queue
419 lgue_start_transfer(struct lgue_softc *sc) {
421 struct lgue_queue_entry *entry;
424 if (STAILQ_EMPTY(&sc->lgue_tx_queue))
427 ifp = &sc->lgue_arpcom.ac_if;
428 entry = STAILQ_FIRST(&sc->lgue_tx_queue);
429 STAILQ_REMOVE_HEAD(&sc->lgue_tx_queue, entry_next);
431 m_copydata(entry->entry_mbuf, 0, entry->entry_mbuf->m_pkthdr.len,
435 usbd_setup_xfer(sc->lgue_tx_xfer, sc->lgue_ep[LGUE_ENDPT_TX], sc,
436 sc->lgue_tx_buf, entry->entry_mbuf->m_pkthdr.len,
437 USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, lgue_txeof);
438 err = usbd_transfer(sc->lgue_tx_xfer);
439 if (err != USBD_IN_PROGRESS) {
440 m_freem(entry->entry_mbuf);
441 kfree(entry, M_USBDEV);
443 ifq_clr_oactive(&ifp->if_snd);
447 m_freem(entry->entry_mbuf);
448 kfree(entry, M_USBDEV);
451 ifq_set_oactive(&ifp->if_snd);
460 lgue_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
463 struct lgue_softc *sc;
470 ifp = &sc->lgue_arpcom.ac_if;
472 if (status != USBD_NORMAL_COMPLETION) {
473 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
475 if (status == USBD_STALLED)
476 usbd_clear_endpoint_stall(sc->lgue_ep[LGUE_ENDPT_TX]);
479 usbd_get_xfer_status(sc->lgue_tx_xfer, NULL, NULL, NULL,&err);
485 if (!STAILQ_EMPTY(&sc->lgue_tx_queue)) {
486 if_devstart_sched(ifp);
490 ifq_clr_oactive(&ifp->if_snd);
497 lgue_start(struct ifnet *ifp)
499 struct lgue_softc *sc;
506 if (ifq_is_oactive(&ifp->if_snd)) {
510 /* To internal queue */
511 while ((m_head = ifq_dequeue(&ifp->if_snd, NULL)) != NULL) {
512 if (lgue_encap(sc, m_head)) {
517 BPF_MTAP(ifp, m_head);
520 lgue_start_transfer(sc);
527 lgue_stop(struct lgue_softc *sc)
531 struct lgue_queue_entry *entry;
537 ifp = &sc->lgue_arpcom.ac_if;
540 if (sc->lgue_ep[LGUE_ENDPT_TX] != NULL) {
541 err = usbd_abort_pipe(sc->lgue_ep[LGUE_ENDPT_TX]);
543 if_printf(ifp, "abort tx pipe failed:%s\n",
546 err = usbd_close_pipe(sc->lgue_ep[LGUE_ENDPT_TX]);
548 if_printf(ifp, "close tx pipe failed:%s\n",
552 if (sc->lgue_ep[LGUE_ENDPT_RX] != NULL) {
553 err = usbd_abort_pipe(sc->lgue_ep[LGUE_ENDPT_RX]);
555 if_printf(ifp, "abort rx pipe failed:%s\n",
558 err = usbd_close_pipe(sc->lgue_ep[LGUE_ENDPT_RX]);
560 if_printf(ifp, "close rx pipe failed:%s\n",
564 if (sc->lgue_ep[LGUE_ENDPT_INTR] != NULL) {
565 err = usbd_abort_pipe(sc->lgue_ep[LGUE_ENDPT_INTR]);
567 if_printf(ifp, "abort intr pipe failed:%s\n",
570 err = usbd_close_pipe(sc->lgue_ep[LGUE_ENDPT_INTR]);
572 if_printf(ifp, "close intr pipe failed:%s\n",
577 /* Free tx buffers */
578 if (sc->lgue_tx_buf != NULL) {
579 kfree(sc->lgue_tx_buf, M_USBDEV);
580 sc->lgue_tx_buf = NULL;
582 if (sc->lgue_tx_xfer != NULL) {
583 usbd_free_xfer(sc->lgue_tx_xfer);
584 sc->lgue_tx_xfer = NULL;
587 /* Free rx buffers */
588 if (sc->lgue_rx_buf != NULL) {
589 kfree(sc->lgue_rx_buf, M_USBDEV);
590 sc->lgue_rx_buf = NULL;
592 if (sc->lgue_rx_xfer != NULL) {
593 usbd_free_xfer(sc->lgue_rx_xfer);
594 sc->lgue_rx_xfer = NULL;
597 /* Free intr buffer */
598 if (sc->lgue_intr_buf != NULL) {
599 kfree(sc->lgue_intr_buf, M_USBDEV);
600 sc->lgue_intr_buf = NULL;
602 if (sc->lgue_intr_xfer != NULL) {
603 usbd_free_xfer(sc->lgue_intr_xfer);
604 sc->lgue_intr_xfer = NULL;
607 /* Clear internal queue */
608 while (!STAILQ_EMPTY(&sc->lgue_tx_queue)) {
609 entry = STAILQ_FIRST(&sc->lgue_tx_queue);
610 STAILQ_REMOVE_HEAD(&sc->lgue_tx_queue, entry_next);
611 m_freem(entry->entry_mbuf);
612 kfree(entry, M_USBDEV);
615 ifp->if_flags &= ~IFF_RUNNING;
616 ifq_clr_oactive(&ifp->if_snd);
625 struct lgue_softc *sc;
630 ifp = &sc->lgue_arpcom.ac_if;
632 if (ifp->if_flags & IFF_RUNNING)
635 /* Create RX and TX bufs */
636 if (sc->lgue_tx_xfer == NULL) {
637 sc->lgue_tx_xfer = usbd_alloc_xfer(sc->lgue_udev);
638 if (sc->lgue_tx_xfer == NULL) {
639 if_printf(ifp, "tx buffer allocate failed\n");
643 sc->lgue_tx_buf = kmalloc(LGUE_BUFSZ, M_USBDEV, M_WAITOK);
645 if (sc->lgue_rx_xfer == NULL) {
646 sc->lgue_rx_xfer = usbd_alloc_xfer(sc->lgue_udev);
647 if (sc->lgue_rx_xfer == NULL) {
648 if_printf(ifp, "rx buffer allocate failed\n");
652 sc->lgue_rx_buf = kmalloc(LGUE_BUFSZ, M_USBDEV, M_WAITOK);
654 /* Create INTR buf */
655 if (sc->lgue_intr_xfer == NULL) {
656 sc->lgue_intr_xfer = usbd_alloc_xfer(sc->lgue_udev);
657 if (sc->lgue_intr_xfer == NULL) {
658 if_printf(ifp, "intr buffer allocate failed\n");
662 sc->lgue_intr_buf = kmalloc(LGUE_BUFSZ, M_USBDEV, M_WAITOK);
664 /* Open RX and TX pipes. */
665 err = usbd_open_pipe(sc->lgue_data_iface, sc->lgue_ed[LGUE_ENDPT_RX],
666 USBD_EXCLUSIVE_USE, &sc->lgue_ep[LGUE_ENDPT_RX]);
668 if_printf(ifp, "open RX pipe failed: %s\n", usbd_errstr(err));
671 err = usbd_open_pipe(sc->lgue_data_iface, sc->lgue_ed[LGUE_ENDPT_TX],
672 USBD_EXCLUSIVE_USE, &sc->lgue_ep[LGUE_ENDPT_TX]);
674 if_printf(ifp, "open TX pipe failed: %s\n", usbd_errstr(err));
677 /* Open INTR pipe. */
678 err = usbd_open_pipe(sc->lgue_ctl_iface, sc->lgue_ed[LGUE_ENDPT_INTR],
679 USBD_EXCLUSIVE_USE, &sc->lgue_ep[LGUE_ENDPT_INTR]);
681 if_printf(ifp, "open INTR pipe failed: %s\n", usbd_errstr(err));
685 /* Create internal queue */
686 STAILQ_INIT(&sc->lgue_tx_queue);
688 ifp->if_flags |= IFF_RUNNING;
689 ifq_clr_oactive(&ifp->if_snd);
701 lgue_newbuf(struct lgue_softc *sc, int len, struct mbuf **m_buf)
705 ifp = &sc->lgue_arpcom.ac_if;
709 *m_buf = m_getcl(MB_DONTWAIT, MT_DATA, MT_HEADER);
710 if (*m_buf == NULL) {
711 if_printf(ifp, " no memory for rx buffer --- packet dropped!\n");
714 (*m_buf)->m_len = (*m_buf)->m_pkthdr.len = MCLBYTES;
715 m_adj(*m_buf, ETHER_ALIGN);
723 lgue_rxstart(struct ifnet *ifp)
725 struct lgue_softc *sc;
731 usbd_setup_xfer(sc->lgue_rx_xfer, sc->lgue_ep[LGUE_ENDPT_RX], sc,
732 sc->lgue_rx_buf, LGUE_BUFSZ,
733 USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, lgue_rxeof);
734 usbd_transfer(sc->lgue_rx_xfer);
738 * A frame has been uploaded: pass the resulting mbuf up to
739 * the higher level protocols.
742 lgue_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
744 struct lgue_softc *sc;
753 ifp = &sc->lgue_arpcom.ac_if;
757 if (!(ifp->if_flags & IFF_RUNNING))
760 if (status != USBD_NORMAL_COMPLETION) {
761 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
763 if (usbd_ratecheck(&sc->lgue_rx_notice)) {
764 if_printf(ifp, "usb error on rx:%s\n",
765 usbd_errstr(status));
767 if (status == USBD_STALLED)
768 usbd_clear_endpoint_stall(sc->lgue_ep[LGUE_ENDPT_RX]);
772 usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
774 if (total_len < sizeof(struct ether_header)) {
779 if (lgue_newbuf(sc, total_len, &m) == ENOBUFS) {
785 m_copyback(m, 0, total_len, sc->lgue_rx_buf);
786 m->m_pkthdr.rcvif = ifp;
787 m->m_pkthdr.len = m->m_len = total_len;
793 usbd_setup_xfer(sc->lgue_rx_xfer, sc->lgue_ep[LGUE_ENDPT_RX], sc,
794 sc->lgue_rx_buf, LGUE_BUFSZ,
795 USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, lgue_rxeof);
796 usbd_transfer(sc->lgue_rx_xfer);
803 lgue_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr)
805 struct lgue_softc *sc;
810 ifr = (struct ifreq *)data;
815 if (ifp->if_flags & IFF_UP) {
816 if (!(ifp->if_flags & IFF_RUNNING))
818 } else if (ifp->if_flags & IFF_RUNNING) {
821 sc->lgue_if_flags = ifp->if_flags;
831 ifp->if_mtu = ifr->ifr_mtu;
834 err = ether_ioctl(ifp, command, data);
844 lgue_watchdog(struct ifnet *ifp)
848 if (!ifq_is_empty(&ifp->if_snd))
849 if_devstart_sched(ifp);
858 if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10);
859 if ((ch >= '0') && (ch <= '9')) return (ch-'0');
860 if ((ch >= 'A') && (ch <= 'F')) return (ch-'A'+10);