1 /*
2 * LG-P500 Smartphone
3 * Written by Yellow Rabbit <yrabbit@sdf.lonestar.org>
4 */
5
6 /*
7 * XXX
8 * USB:
9 * Takes two interfaces.
10 * IN and OUT endpoints on the data interface (altsetting).
11 * Interrupt endpoint on the control interface.
12 *
13 * NET:
14 * Transfer frames without modification (AS IS).
15 */
16
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>
22 #include <sys/bus.h>
23
24 #include <net/if.h>
25 #include <net/ifq_var.h>
26 #include <net/if_arp.h>
27 #include <net/ethernet.h>
28 #include <net/bpf.h>
29
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>
36
37 #include "if_lgue.h"
38
39 /*
40 * Supported device vendors/products
41 */
42 static struct usb_devno lgue_devs[] = {
43 { USB_DEVICE(0x1004, 0x61a2) } /* LG P500 */
44 };
45
46 static int lgue_match(device_t);
47 static int lgue_attach(device_t);
48 static int lgue_detach(device_t);
49
50 static void lgue_start(struct ifnet *, struct ifaltq_subque *);
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 *);
55
56 static int lgue_encap(struct lgue_softc *, struct mbuf *);
57 static int lgue_start_transfer(struct lgue_softc *);
58
59 static void lgue_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
60
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);
64
65 static void lgue_intrstart(struct ifnet *);
66 static void lgue_intreof(usbd_xfer_handle, usbd_private_handle, usbd_status);
67
68 static int lgue_get_data_iface_no(usbd_device_handle,
69 usb_interface_descriptor_t *);
70
71 static int lgue_getmac(struct lgue_softc *, void *);
72 static int lgue_getmtu(struct lgue_softc *);
73
74 static int hex(char);
75
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),
80
81 DEVMETHOD_END
82 };
83
84 static driver_t lgue_driver = {
85 "lgue",
86 lgue_methods,
87 sizeof(struct lgue_softc)
88 };
89
90 static devclass_t lgue_devclass;
91
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);
95
96 /*
97 * Probe chip
98 */
99 static int
100 lgue_match(device_t dev)
101 {
102 struct usb_attach_arg *uaa;
103 usb_interface_descriptor_t *id;
104
105 uaa = device_get_ivars(dev);
106 if (uaa->iface == NULL)
107 return(UMATCH_NONE);
108
109 if (usb_lookup(lgue_devs, uaa->vendor, uaa->product) != NULL) {
110 id = usbd_get_interface_descriptor(uaa->iface);
111 if (id != NULL &&
112 id->bInterfaceClass == UICLASS_CDC &&
113 id->bInterfaceSubClass == UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL)
114 return(UMATCH_VENDOR_PRODUCT);
115 }
116 return(UMATCH_NONE);
117 }
118
119 /*
120 * Attach the interface.
121 */
122 static int
123 lgue_attach(device_t dev)
124 {
125 struct lgue_softc *sc;
126 struct usb_attach_arg *uaa;
127 struct ifnet *ifp;
128 usb_interface_descriptor_t *id;
129 usb_endpoint_descriptor_t *ed;
130 int i;
131 u_char eaddr[ETHER_ADDR_LEN];
132 usbd_status err;
133
134 sc = device_get_softc(dev);
135 uaa = device_get_ivars(dev);
136
137 sc->lgue_ctl_iface = uaa->iface;
138 sc->lgue_udev = uaa->device;
139
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",
143 LGUE_CONFIG_NO);
144 return(ENXIO);
145 }
146
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);
151
152 if (sc->lgue_data_iface_no == -1) {
153 device_printf(dev, "no data interface number\n");
154 goto bad;
155 }
156
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]);
161 if (id != NULL &&
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) {
166 device_printf(dev,
167 "no alternate data interface. err:%s\n",
168 usbd_errstr(err));
169 goto bad;
170 }
171 sc->lgue_data_iface = uaa->ifaces[i];
172 uaa->ifaces[i] = NULL;
173 }
174 }
175 }
176 if (sc->lgue_data_iface == NULL) {
177 device_printf(dev, "no data interface\n");
178 goto bad;
179 }
180
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);
186 if (!ed) {
187 device_printf(dev,
188 "couldn't get endpoint descriptor %d\n", i);
189 goto bad;
190 }
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;
197 }
198 }
199
200 if (sc->lgue_ed[LGUE_ENDPT_RX] == -1) {
201 device_printf(dev, "couldn't find data bilk in\n");
202 goto bad;
203 }
204 if (sc->lgue_ed[LGUE_ENDPT_TX] == -1) {
205 device_printf(dev, "couldn't find data bilk out\n");
206 goto bad;
207 }
208
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);
214 if (!ed) {
215 device_printf(dev,
216 "couldn't get endpoint descriptor %d\n", i);
217 goto bad;
218 }
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;
222 }
223 }
224
225 if (sc->lgue_ed[LGUE_ENDPT_INTR] == -1) {
226 device_printf(dev, "couldn't find interrupt bilk in\n");
227 goto bad;
228 }
229
230 /* Create interface */
231 ifp = &sc->lgue_arpcom.ac_if;
232 ifp->if_softc = sc;
233 if_initname(ifp, device_get_name(dev), device_get_unit(dev));
234 lgue_getmac(sc, eaddr);
235
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);
246
247 /* Call attach routine */
248 ether_ifattach(ifp, eaddr, NULL);
249 usb_register_netisr();
250 sc->lgue_dying = 0;
251 return(0);
252
253 bad:
254 return(ENXIO);
255 }
256
257 /*
258 * Device detached.
259 */
260 static int
261 lgue_detach(device_t dev)
262 {
263 struct lgue_softc *sc;
264 struct ifnet *ifp;
265
266 sc = device_get_softc(dev);
267 ifp = &sc->lgue_arpcom.ac_if;
268 ether_ifdetach(ifp);
269
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]);
276 return(0);
277 }
278
279 /*
280 * Find data interface.
281 */
282 int
283 lgue_get_data_iface_no(usbd_device_handle dev, usb_interface_descriptor_t *id)
284 {
285 const usb_cdc_union_descriptor_t *cud;
286
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);
290 }
291
292 /*
293 * Get hard max mtu
294 */
295 static int
296 lgue_getmtu(struct lgue_softc *sc)
297 {
298 const usb_cdc_ethernet_descriptor_t *ced;
299 usb_interface_descriptor_t *id;
300
301 id = usbd_get_interface_descriptor(sc->lgue_ctl_iface);
302 if (id == NULL) {
303 kprintf("usbd_get_interface_descriptor() returned NULL\n");
304 return(ETHERMTU);
305 }
306
307 ced = (const usb_cdc_ethernet_descriptor_t *)usb_find_desc_if(sc->lgue_udev,
308 UDESC_CS_INTERFACE, UDESCSUB_CDC_ETHERNET, id);
309 if (ced == NULL) {
310 kprintf("usb_find_desc_if() returned NULL\n");
311 return(ETHERMTU);
312 }
313 return(UGETW(ced->wMaxSegmentSize));
314 }
315
316 /*
317 * Get mac address
318 */
319 static int
320 lgue_getmac(struct lgue_softc *sc, void *buf)
321 {
322 const usb_cdc_ethernet_descriptor_t *ced;
323 usb_interface_descriptor_t *id;
324 char sbuf[ETHER_ADDR_LEN * 2 + 1];
325 usbd_status err;
326 int i;
327
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;
333
334 err = usbd_get_string(sc->lgue_udev, ced->iMACAddress, sbuf);
335 if(err) {
336 kprintf("Read MAC address failed\n");
337 goto bad;
338 }
339
340 for (i = 0; i < ETHER_ADDR_LEN; ++i) {
341 ((uByte *)buf)[i] = (hex(sbuf[i * 2]) << 4) + hex(sbuf[(i * 2) + 1]);
342 }
343 return(0);
344 bad:
345 return(-1);
346 }
347
348 /*
349 * Listen INTR pipe
350 */
351 static void
352 lgue_intrstart(struct ifnet *ifp)
353 {
354 struct lgue_softc *sc;
355
356 sc = ifp->if_softc;
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);
361 }
362
363 /*
364 * INTR arrived
365 */
366 static void
367 lgue_intreof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
368 {
369 struct ifnet *ifp;
370 struct lgue_softc *sc;
371
372 sc = priv;
373 if (sc->lgue_dying)
374 return;
375
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);
381 return;
382 }
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);
387 return;
388 }
389 lgue_intrstart(ifp);
390 lwkt_serialize_exit(ifp->if_serializer);
391 }
392
393 /*
394 * Encap packet & send
395 */
396 static int
397 lgue_encap(struct lgue_softc *sc, struct mbuf *m)
398 {
399 struct ifnet *ifp;
400 struct lgue_queue_entry *entry;
401
402 ifp = &sc->lgue_arpcom.ac_if;
403 entry = kmalloc(sizeof(struct lgue_queue_entry), M_USBDEV , M_NOWAIT);
404 if (entry == NULL) {
405 if_printf(ifp, "no memory for internal queue entry\n");
406 return(ENOBUFS);
407 }
408 entry->entry_mbuf = m;
409
410 /* Put packet into internal queue tail */
411 STAILQ_INSERT_TAIL(&sc->lgue_tx_queue, entry, entry_next);
412 return(0);
413 }
414
415 /*
416 * Start transfer from internal queue
417 */
418 static int
419 lgue_start_transfer(struct lgue_softc *sc) {
420 usbd_status err;
421 struct lgue_queue_entry *entry;
422 struct ifnet *ifp;
423
424 if (STAILQ_EMPTY(&sc->lgue_tx_queue))
425 return(0);
426
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);
430
431 m_copydata(entry->entry_mbuf, 0, entry->entry_mbuf->m_pkthdr.len,
432 sc->lgue_tx_buf);
433
434 /* Transmit */
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);
442 lgue_stop(sc);
443 ifq_clr_oactive(&ifp->if_snd);
444 return(EIO);
445 }
446
447 m_freem(entry->entry_mbuf);
448 kfree(entry, M_USBDEV);
449
450 sc->lgue_tx_cnt++;
451 ifq_set_oactive(&ifp->if_snd);
452 ifp->if_timer = 5;
453 return(0);
454 }
455
456 /*
457 * End of sending
458 */
459 static void
460 lgue_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
461 {
462 struct ifnet *ifp;
463 struct lgue_softc *sc;
464 usbd_status err;
465
466 sc = priv;
467 if (sc->lgue_dying)
468 return;
469
470 ifp = &sc->lgue_arpcom.ac_if;
471
472 if (status != USBD_NORMAL_COMPLETION) {
473 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
474 return;
475 if (status == USBD_STALLED)
476 usbd_clear_endpoint_stall(sc->lgue_ep[LGUE_ENDPT_TX]);
477 return;
478 }
479 usbd_get_xfer_status(sc->lgue_tx_xfer, NULL, NULL, NULL,&err);
480 if (err)
481 IFNET_STAT_INC(ifp, oerrors, 1);
482 else
483 IFNET_STAT_INC(ifp, opackets, 1);
484
485 if (!STAILQ_EMPTY(&sc->lgue_tx_queue)) {
486 if_devstart_sched(ifp);
487 }
488
489 ifp->if_timer = 0;
490 ifq_clr_oactive(&ifp->if_snd);
491 }
492
493 /*
494 * Start transfer
495 */
496 static void
497 lgue_start(struct ifnet *ifp, struct ifaltq_subque *ifsq)
498 {
499 struct lgue_softc *sc;
500 struct mbuf *m_head;
501
502 ASSERT_ALTQ_SQ_DEFAULT(ifp, ifsq);
503
504 sc = ifp->if_softc;
505 if (sc->lgue_dying)
506 return;
507
508 if (ifq_is_oactive(&ifp->if_snd)) {
509 return;
510 }
511
512 /* To internal queue */
513 while ((m_head = ifq_dequeue(&ifp->if_snd)) != NULL) {
514 if (lgue_encap(sc, m_head)) {
515 m_freem(m_head);
516 break;
517 }
518 /* Filter */
519 BPF_MTAP(ifp, m_head);
520 }
521
522 lgue_start_transfer(sc);
523 }
524
525 /*
526 * Stop
527 */
528 static void
529 lgue_stop(struct lgue_softc *sc)
530 {
531 struct ifnet *ifp;
532 usbd_status err;
533 struct lgue_queue_entry *entry;
534
535 if (sc->lgue_dying)
536 return;
537 sc->lgue_dying = 1;
538
539 ifp = &sc->lgue_arpcom.ac_if;
540
541 /* Stop transfers */
542 if (sc->lgue_ep[LGUE_ENDPT_TX] != NULL) {
543 err = usbd_abort_pipe(sc->lgue_ep[LGUE_ENDPT_TX]);
544 if (err) {
545 if_printf(ifp, "abort tx pipe failed:%s\n",
546 usbd_errstr(err));
547 }
548 err = usbd_close_pipe(sc->lgue_ep[LGUE_ENDPT_TX]);
549 if (err) {
550 if_printf(ifp, "close tx pipe failed:%s\n",
551 usbd_errstr(err));
552 }
553 }
554 if (sc->lgue_ep[LGUE_ENDPT_RX] != NULL) {
555 err = usbd_abort_pipe(sc->lgue_ep[LGUE_ENDPT_RX]);
556 if (err) {
557 if_printf(ifp, "abort rx pipe failed:%s\n",
558 usbd_errstr(err));
559 }
560 err = usbd_close_pipe(sc->lgue_ep[LGUE_ENDPT_RX]);
561 if (err) {
562 if_printf(ifp, "close rx pipe failed:%s\n",
563 usbd_errstr(err));
564 }
565 }
566 if (sc->lgue_ep[LGUE_ENDPT_INTR] != NULL) {
567 err = usbd_abort_pipe(sc->lgue_ep[LGUE_ENDPT_INTR]);
568 if (err) {
569 if_printf(ifp, "abort intr pipe failed:%s\n",
570 usbd_errstr(err));
571 }
572 err = usbd_close_pipe(sc->lgue_ep[LGUE_ENDPT_INTR]);
573 if (err) {
574 if_printf(ifp, "close intr pipe failed:%s\n",
575 usbd_errstr(err));
576 }
577 }
578
579 /* Free tx buffers */
580 if (sc->lgue_tx_buf != NULL) {
581 kfree(sc->lgue_tx_buf, M_USBDEV);
582 sc->lgue_tx_buf = NULL;
583 }
584 if (sc->lgue_tx_xfer != NULL) {
585 usbd_free_xfer(sc->lgue_tx_xfer);
586 sc->lgue_tx_xfer = NULL;
587 }
588
589 /* Free rx buffers */
590 if (sc->lgue_rx_buf != NULL) {
591 kfree(sc->lgue_rx_buf, M_USBDEV);
592 sc->lgue_rx_buf = NULL;
593 }
594 if (sc->lgue_rx_xfer != NULL) {
595 usbd_free_xfer(sc->lgue_rx_xfer);
596 sc->lgue_rx_xfer = NULL;
597 }
598
599 /* Free intr buffer */
600 if (sc->lgue_intr_buf != NULL) {
601 kfree(sc->lgue_intr_buf, M_USBDEV);
602 sc->lgue_intr_buf = NULL;
603 }
604 if (sc->lgue_intr_xfer != NULL) {
605 usbd_free_xfer(sc->lgue_intr_xfer);
606 sc->lgue_intr_xfer = NULL;
607 }
608
609 /* Clear internal queue */
610 while (!STAILQ_EMPTY(&sc->lgue_tx_queue)) {
611 entry = STAILQ_FIRST(&sc->lgue_tx_queue);
612 STAILQ_REMOVE_HEAD(&sc->lgue_tx_queue, entry_next);
613 m_freem(entry->entry_mbuf);
614 kfree(entry, M_USBDEV);
615 }
616
617 ifp->if_flags &= ~IFF_RUNNING;
618 ifq_clr_oactive(&ifp->if_snd);
619 }
620
621 /*
622 * Init
623 */
624 static void
625 lgue_init(void *xsc)
626 {
627 struct lgue_softc *sc;
628 struct ifnet *ifp;
629 usbd_status err;
630
631 sc = xsc;
632 ifp = &sc->lgue_arpcom.ac_if;
633
634 if (ifp->if_flags & IFF_RUNNING)
635 return;
636
637 /* Create RX and TX bufs */
638 if (sc->lgue_tx_xfer == NULL) {
639 sc->lgue_tx_xfer = usbd_alloc_xfer(sc->lgue_udev);
640 if (sc->lgue_tx_xfer == NULL) {
641 if_printf(ifp, "tx buffer allocate failed\n");
642 return;
643 }
644 }
645 sc->lgue_tx_buf = kmalloc(LGUE_BUFSZ, M_USBDEV, M_WAITOK);
646
647 if (sc->lgue_rx_xfer == NULL) {
648 sc->lgue_rx_xfer = usbd_alloc_xfer(sc->lgue_udev);
649 if (sc->lgue_rx_xfer == NULL) {
650 if_printf(ifp, "rx buffer allocate failed\n");
651 return;
652 }
653 }
654 sc->lgue_rx_buf = kmalloc(LGUE_BUFSZ, M_USBDEV, M_WAITOK);
655
656 /* Create INTR buf */
657 if (sc->lgue_intr_xfer == NULL) {
658 sc->lgue_intr_xfer = usbd_alloc_xfer(sc->lgue_udev);
659 if (sc->lgue_intr_xfer == NULL) {
660 if_printf(ifp, "intr buffer allocate failed\n");
661 return;
662 }
663 }
664 sc->lgue_intr_buf = kmalloc(LGUE_BUFSZ, M_USBDEV, M_WAITOK);
665
666 /* Open RX and TX pipes. */
667 err = usbd_open_pipe(sc->lgue_data_iface, sc->lgue_ed[LGUE_ENDPT_RX],
668 USBD_EXCLUSIVE_USE, &sc->lgue_ep[LGUE_ENDPT_RX]);
669 if (err) {
670 if_printf(ifp, "open RX pipe failed: %s\n", usbd_errstr(err));
671 return;
672 }
673 err = usbd_open_pipe(sc->lgue_data_iface, sc->lgue_ed[LGUE_ENDPT_TX],
674 USBD_EXCLUSIVE_USE, &sc->lgue_ep[LGUE_ENDPT_TX]);
675 if (err) {
676 if_printf(ifp, "open TX pipe failed: %s\n", usbd_errstr(err));
677 return;
678 }
679 /* Open INTR pipe. */
680 err = usbd_open_pipe(sc->lgue_ctl_iface, sc->lgue_ed[LGUE_ENDPT_INTR],
681 USBD_EXCLUSIVE_USE, &sc->lgue_ep[LGUE_ENDPT_INTR]);
682 if (err) {
683 if_printf(ifp, "open INTR pipe failed: %s\n", usbd_errstr(err));
684 return;
685 }
686
687 /* Create internal queue */
688 STAILQ_INIT(&sc->lgue_tx_queue);
689
690 ifp->if_flags |= IFF_RUNNING;
691 ifq_clr_oactive(&ifp->if_snd);
692
693 sc->lgue_dying = 0;
694
695 lgue_rxstart(ifp);
696 lgue_intrstart(ifp);
697 }
698
699 /*
700 * New mbuf
701 */
702 static int
703 lgue_newbuf(struct lgue_softc *sc, int len, struct mbuf **m_buf)
704 {
705 struct ifnet *ifp;
706
707 ifp = &sc->lgue_arpcom.ac_if;
708 *m_buf = NULL;
709
710 /* Allocate mbuf */
711 *m_buf = m_getcl(MB_DONTWAIT, MT_DATA, MT_HEADER);
712 if (*m_buf == NULL) {
713 if_printf(ifp, " no memory for rx buffer --- packet dropped!\n");
714 return(ENOBUFS);
715 }
716 (*m_buf)->m_len = (*m_buf)->m_pkthdr.len = MCLBYTES;
717 m_adj(*m_buf, ETHER_ALIGN);
718 return(0);
719 }
720
721 /*
722 * Start read
723 */
724 static void
725 lgue_rxstart(struct ifnet *ifp)
726 {
727 struct lgue_softc *sc;
728
729 sc = ifp->if_softc;
730 if (sc->lgue_dying)
731 return;
732
733 usbd_setup_xfer(sc->lgue_rx_xfer, sc->lgue_ep[LGUE_ENDPT_RX], sc,
734 sc->lgue_rx_buf, LGUE_BUFSZ,
735 USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, lgue_rxeof);
736 usbd_transfer(sc->lgue_rx_xfer);
737 }
738
739 /*
740 * A frame has been uploaded: pass the resulting mbuf up to
741 * the higher level protocols.
742 */
743 static void
744 lgue_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
745 {
746 struct lgue_softc *sc;
747 struct mbuf *m;
748 struct ifnet *ifp;
749 int total_len;
750
751 sc = priv;
752 if (sc->lgue_dying)
753 return;
754
755 ifp = &sc->lgue_arpcom.ac_if;
756
757 total_len = 0;
758
759 if (!(ifp->if_flags & IFF_RUNNING))
760 return;
761
762 if (status != USBD_NORMAL_COMPLETION) {
763 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
764 return;
765 if (usbd_ratecheck(&sc->lgue_rx_notice)) {
766 if_printf(ifp, "usb error on rx:%s\n",
767 usbd_errstr(status));
768 }
769 if (status == USBD_STALLED)
770 usbd_clear_endpoint_stall(sc->lgue_ep[LGUE_ENDPT_RX]);
771 goto done;
772 }
773
774 usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
775
776 if (total_len < sizeof(struct ether_header)) {
777 IFNET_STAT_INC(ifp, ierrors, 1);
778 goto done;
779 }
780
781 if (lgue_newbuf(sc, total_len, &m) == ENOBUFS) {
782 IFNET_STAT_INC(ifp, ierrors, 1);
783 return;
784 }
785
786 IFNET_STAT_INC(ifp, ipackets, 1);
787 m_copyback(m, 0, total_len, sc->lgue_rx_buf);
788 m->m_pkthdr.rcvif = ifp;
789 m->m_pkthdr.len = m->m_len = total_len;
790
791 usb_ether_input(m);
792 lgue_rxstart(ifp);
793 return;
794 done:
795 usbd_setup_xfer(sc->lgue_rx_xfer, sc->lgue_ep[LGUE_ENDPT_RX], sc,
796 sc->lgue_rx_buf, LGUE_BUFSZ,
797 USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, lgue_rxeof);
798 usbd_transfer(sc->lgue_rx_xfer);
799 }
800
801 /*
802 * Control
803 */
804 static int
805 lgue_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr)
806 {
807 struct lgue_softc *sc;
808 struct ifreq *ifr;
809 int err;
810
811 err = 0;
812 ifr = (struct ifreq *)data;
813 sc = ifp->if_softc;
814
815 switch(command) {
816 case SIOCSIFFLAGS:
817 if (ifp->if_flags & IFF_UP) {
818 if (!(ifp->if_flags & IFF_RUNNING))
819 lgue_init(sc);
820 } else if (ifp->if_flags & IFF_RUNNING) {
821 lgue_stop(sc);
822 }
823 sc->lgue_if_flags = ifp->if_flags;
824 err = 0;
825 break;
826 #if 0
827 case SIOCADDMULTI:
828 case SIOCDELMULTI:
829 err = 0;
830 break;
831 #endif
832 case SIOCSIFMTU:
833 ifp->if_mtu = ifr->ifr_mtu;
834 break;
835 default:
836 err = ether_ioctl(ifp, command, data);
837 break;
838 }
839 return(err);
840 }
841
842 /*
843 * Watchdog
844 */
845 static void
846 lgue_watchdog(struct ifnet *ifp)
847 {
848 IFNET_STAT_INC(ifp, oerrors, 1);
849
850 if (!ifq_is_empty(&ifp->if_snd))
851 if_devstart_sched(ifp);
852 }
853
854 /*
855 * Hex -> bin
856 */
857 static int
858 hex(char ch)
859 {
860 if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10);
861 if ((ch >= '') && (ch <= '9')) return (ch-'');
862 if ((ch >= 'A') && (ch <= 'F')) return (ch-'A'+10);
863 return (-1);
864 }
Cache object: 3fa64d747fb5034b7c3bc03873763b2c
|