if_cdce.c revision 1.1 1 /* $NetBSD: if_cdce.c,v 1.1 2004/10/22 13:08:23 augustss Exp $ */
2
3 /*
4 * Copyright (c) 1997, 1998, 1999, 2000-2003 Bill Paul <wpaul (at) windriver.com>
5 * Copyright (c) 2003 Craig Boston
6 * Copyright (c) 2004 Daniel Hartmeier
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by Bill Paul.
20 * 4. Neither the name of the author nor the names of any co-contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul, THE VOICES IN HIS HEAD OR
28 * THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
31 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
33 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
34 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 */
36
37 /*
38 * USB Communication Device Class (Ethernet Networking Control Model)
39 * http://www.usb.org/developers/devclass_docs/usbcdc11.pdf
40 *
41 */
42
43 #include <sys/cdefs.h>
44 __KERNEL_RCSID(0, "$NetBSD: if_cdce.c,v 1.1 2004/10/22 13:08:23 augustss Exp $");
45 #include "bpfilter.h"
46
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/sockio.h>
50 #include <sys/mbuf.h>
51 #include <sys/malloc.h>
52 #include <sys/kernel.h>
53 #include <sys/socket.h>
54 #include <sys/device.h>
55 #if defined(__OpenBSD__)
56 #include <sys/proc.h>
57 #endif
58
59 #if NRND > 0
60 #include <sys/rnd.h>
61 #endif
62
63 #include <net/if.h>
64 #if defined(__NetBSD__)
65 #include <net/if_arp.h>
66 #endif
67 #include <net/if_dl.h>
68 #include <net/if_media.h>
69
70 #define BPF_MTAP(ifp, m) bpf_mtap((ifp)->if_bpf, (m))
71
72 #if NBPFILTER > 0
73 #include <net/bpf.h>
74 #endif
75
76 #if defined(__NetBSD__)
77 #include <net/if_ether.h>
78 #ifdef INET
79 #include <netinet/in.h>
80 #include <netinet/if_inarp.h>
81 #endif
82 #endif /* defined(__NetBSD__) */
83
84 #if defined(__OpenBSD__)
85 #ifdef INET
86 #include <netinet/in.h>
87 #include <netinet/in_systm.h>
88 #include <netinet/in_var.h>
89 #include <netinet/ip.h>
90 #include <netinet/if_ether.h>
91 #endif
92 #endif /* defined(__OpenBSD__) */
93
94 #ifdef NS
95 #include <netns/ns.h>
96 #include <netns/ns_if.h>
97 #endif
98
99 #include <dev/usb/usb.h>
100 #include <dev/usb/usbdi.h>
101 #include <dev/usb/usbdi_util.h>
102 #include <dev/usb/usbdevs.h>
103 #include <dev/usb/usbcdc.h>
104
105 #include <dev/usb/if_cdcereg.h>
106
107 Static void *cdce_get_desc(usbd_device_handle dev, int type, int subtype);
108 Static int cdce_tx_list_init(struct cdce_softc *);
109 Static int cdce_rx_list_init(struct cdce_softc *);
110 Static int cdce_newbuf(struct cdce_softc *, struct cdce_chain *,
111 struct mbuf *);
112 Static int cdce_encap(struct cdce_softc *, struct mbuf *, int);
113 Static void cdce_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
114 Static void cdce_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
115 Static void cdce_start(struct ifnet *);
116 Static int cdce_ioctl(struct ifnet *, u_long, caddr_t);
117 Static void cdce_init(void *);
118 Static void cdce_watchdog(struct ifnet *);
119 Static void cdce_stop(struct cdce_softc *);
120 static uint32_t cdce_crc32(const void *, size_t);
121
122 Static const struct cdce_type cdce_devs[] = {
123 {{ USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2501 }, CDCE_NO_UNION },
124 {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5500 }, CDCE_ZAURUS },
125 {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_A300 }, CDCE_ZAURUS | CDCE_NO_UNION },
126 {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5600 }, CDCE_ZAURUS | CDCE_NO_UNION },
127 {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_C700 }, CDCE_ZAURUS | CDCE_NO_UNION },
128 {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_C750 }, CDCE_ZAURUS | CDCE_NO_UNION },
129 };
130 #define cdce_lookup(v, p) ((const struct cdce_type *)usb_lookup(cdce_devs, v, p))
131
132 USB_DECLARE_DRIVER(cdce);
133
134 USB_MATCH(cdce)
135 {
136 USB_MATCH_START(cdce, uaa);
137 usb_interface_descriptor_t *id;
138
139 if (uaa->iface == NULL)
140 return (UMATCH_NONE);
141
142 id = usbd_get_interface_descriptor(uaa->iface);
143 if (id == NULL)
144 return (UMATCH_NONE);
145
146 if (cdce_lookup(uaa->vendor, uaa->product) != NULL)
147 return (UMATCH_VENDOR_PRODUCT);
148
149 if (id->bInterfaceClass == UICLASS_CDC && id->bInterfaceSubClass ==
150 UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL)
151 return (UMATCH_IFACECLASS_GENERIC);
152
153 return (UMATCH_NONE);
154 }
155
156 USB_ATTACH(cdce)
157 {
158 USB_ATTACH_START(cdce, sc, uaa);
159 char devinfo[1024];
160 int s;
161 struct ifnet *ifp;
162 usbd_device_handle dev = uaa->device;
163 const struct cdce_type *t;
164 usb_interface_descriptor_t *id;
165 usb_endpoint_descriptor_t *ed;
166 usb_cdc_union_descriptor_t *ud;
167 int data_ifcno;
168 u_int16_t macaddr_hi;
169 int i;
170 u_char eaddr[ETHER_ADDR_LEN];
171
172 usbd_devinfo(dev, 0, devinfo, sizeof devinfo);
173 USB_ATTACH_SETUP;
174 printf("%s: %s\n", USBDEVNAME(sc->cdce_dev), devinfo);
175
176 sc->cdce_udev = uaa->device;
177 sc->cdce_ctl_iface = uaa->iface;
178
179 t = cdce_lookup(uaa->vendor, uaa->product);
180 if (t)
181 sc->cdce_flags = t->cdce_flags;
182
183 if (sc->cdce_flags & CDCE_NO_UNION)
184 sc->cdce_data_iface = sc->cdce_ctl_iface;
185 else {
186 ud = cdce_get_desc(sc->cdce_udev, UDESC_CS_INTERFACE,
187 UDESCSUB_CDC_UNION);
188 if (ud == NULL) {
189 printf("%s: no union descriptor\n",
190 USBDEVNAME(sc->cdce_dev));
191 USB_ATTACH_ERROR_RETURN;
192 }
193 data_ifcno = ud->bSlaveInterface[0];
194
195 for (i = 0; i < uaa->nifaces; i++) {
196 if (uaa->ifaces[i] != NULL) {
197 id = usbd_get_interface_descriptor(
198 uaa->ifaces[i]);
199 if (id != NULL && id->bInterfaceNumber ==
200 data_ifcno) {
201 sc->cdce_data_iface = uaa->ifaces[i];
202 uaa->ifaces[i] = NULL;
203 }
204 }
205 }
206 }
207
208 if (sc->cdce_data_iface == NULL) {
209 printf("%s: no data interface\n", USBDEVNAME(sc->cdce_dev));
210 USB_ATTACH_ERROR_RETURN;
211 }
212
213 /* Find endpoints. */
214 id = usbd_get_interface_descriptor(sc->cdce_data_iface);
215 sc->cdce_bulkin_no = sc->cdce_bulkout_no = -1;
216 for (i = 0; i < id->bNumEndpoints; i++) {
217 ed = usbd_interface2endpoint_descriptor(sc->cdce_data_iface, i);
218 if (!ed) {
219 printf("%s: could not read endpoint descriptor\n",
220 USBDEVNAME(sc->cdce_dev));
221 USB_ATTACH_ERROR_RETURN;
222 }
223 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
224 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
225 sc->cdce_bulkin_no = ed->bEndpointAddress;
226 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
227 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
228 sc->cdce_bulkout_no = ed->bEndpointAddress;
229 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
230 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
231 /* XXX: CDC spec defines an interrupt pipe, but it is not
232 * needed for simple host-to-host applications. */
233 } else {
234 printf("%s: unexpected endpoint\n",
235 USBDEVNAME(sc->cdce_dev));
236 }
237 }
238
239 if (sc->cdce_bulkin_no == -1) {
240 printf("%s: could not find data bulk in\n",
241 USBDEVNAME(sc->cdce_dev));
242 USB_ATTACH_ERROR_RETURN;
243 }
244 if (sc->cdce_bulkout_no == -1 ) {
245 printf("%s: could not find data bulk out\n",
246 USBDEVNAME(sc->cdce_dev));
247 USB_ATTACH_ERROR_RETURN;
248 }
249
250 s = splnet();
251
252 /*
253 * XXX This is totally broken for CDC.
254 * The address can be found as a string (weird, huh?).
255 */
256 macaddr_hi = htons(0x2acb);
257 memcpy(&eaddr[0], &macaddr_hi, sizeof(u_int16_t));
258 memcpy(&eaddr[2], &hardclock_ticks, sizeof(u_int32_t));
259 eaddr[5] = (u_int8_t)(sc->cdce_dev.dv_unit);
260
261 printf("%s: address %s\n", USBDEVNAME(sc->cdce_dev),
262 ether_sprintf(eaddr));
263
264 ifp = GET_IFP(sc);
265 ifp->if_softc = sc;
266 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
267 ifp->if_ioctl = cdce_ioctl;
268 ifp->if_start = cdce_start;
269 ifp->if_watchdog = cdce_watchdog;
270 strncpy(ifp->if_xname, USBDEVNAME(sc->cdce_dev), IFNAMSIZ);
271
272 IFQ_SET_READY(&ifp->if_snd);
273
274 if_attach(ifp);
275 Ether_ifattach(ifp, eaddr);
276
277 sc->cdce_attached = 1;
278 splx(s);
279
280 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->cdce_udev,
281 USBDEV(sc->cdce_dev));
282
283 USB_ATTACH_SUCCESS_RETURN;
284 }
285
286 USB_DETACH(cdce)
287 {
288 USB_DETACH_START(cdce, sc);
289 struct ifnet *ifp = GET_IFP(sc);
290 int s;
291
292 s = splusb();
293
294 if (!sc->cdce_attached) {
295 splx(s);
296 return (0);
297 }
298
299 if (ifp->if_flags & IFF_RUNNING)
300 cdce_stop(sc);
301
302 ether_ifdetach(ifp);
303
304 if_detach(ifp);
305
306 sc->cdce_attached = 0;
307 splx(s);
308
309 return (0);
310 }
311
312 Static void
313 cdce_start(struct ifnet *ifp)
314 {
315 struct cdce_softc *sc = ifp->if_softc;
316 struct mbuf *m_head = NULL;
317
318 if (sc->cdce_dying || (ifp->if_flags & IFF_OACTIVE))
319 return;
320
321 IFQ_POLL(&ifp->if_snd, m_head);
322 if (m_head == NULL)
323 return;
324
325 if (cdce_encap(sc, m_head, 0)) {
326 ifp->if_flags |= IFF_OACTIVE;
327 return;
328 }
329
330 IFQ_DEQUEUE(&ifp->if_snd, m_head);
331
332 #if NBPFILTER > 0
333 if (ifp->if_bpf)
334 BPF_MTAP(ifp, m_head);
335 #endif
336
337 ifp->if_flags |= IFF_OACTIVE;
338
339 ifp->if_timer = 6;
340 }
341
342 Static int
343 cdce_encap(struct cdce_softc *sc, struct mbuf *m, int idx)
344 {
345 struct cdce_chain *c;
346 usbd_status err;
347 int extra = 0;
348
349 c = &sc->cdce_cdata.cdce_tx_chain[idx];
350
351 m_copydata(m, 0, m->m_pkthdr.len, c->cdce_buf);
352 if (sc->cdce_flags & CDCE_ZAURUS) {
353 /* Zaurus wants a 32-bit CRC appended to every frame */
354 u_int32_t crc;
355
356 crc = cdce_crc32(c->cdce_buf, m->m_pkthdr.len);
357 bcopy(&crc, c->cdce_buf + m->m_pkthdr.len, 4);
358 extra = 4;
359 }
360 c->cdce_mbuf = m;
361
362 usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkout_pipe, c, c->cdce_buf,
363 m->m_pkthdr.len + extra, USBD_NO_COPY, 10000, cdce_txeof);
364 err = usbd_transfer(c->cdce_xfer);
365 if (err != USBD_IN_PROGRESS) {
366 cdce_stop(sc);
367 return (EIO);
368 }
369
370 sc->cdce_cdata.cdce_tx_cnt++;
371
372 return (0);
373 }
374
375 Static void
376 cdce_stop(struct cdce_softc *sc)
377 {
378 usbd_status err;
379 struct ifnet *ifp = GET_IFP(sc);
380 int i;
381
382 ifp->if_timer = 0;
383
384 if (sc->cdce_bulkin_pipe != NULL) {
385 err = usbd_abort_pipe(sc->cdce_bulkin_pipe);
386 if (err)
387 printf("%s: abort rx pipe failed: %s\n",
388 USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
389 err = usbd_close_pipe(sc->cdce_bulkin_pipe);
390 if (err)
391 printf("%s: close rx pipe failed: %s\n",
392 USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
393 sc->cdce_bulkin_pipe = NULL;
394 }
395
396 if (sc->cdce_bulkout_pipe != NULL) {
397 err = usbd_abort_pipe(sc->cdce_bulkout_pipe);
398 if (err)
399 printf("%s: abort tx pipe failed: %s\n",
400 USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
401 err = usbd_close_pipe(sc->cdce_bulkout_pipe);
402 if (err)
403 printf("%s: close tx pipe failed: %s\n",
404 USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
405 sc->cdce_bulkout_pipe = NULL;
406 }
407
408 for (i = 0; i < CDCE_RX_LIST_CNT; i++) {
409 if (sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf != NULL) {
410 m_freem(sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf);
411 sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf = NULL;
412 }
413 if (sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer != NULL) {
414 usbd_free_xfer(sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer);
415 sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer = NULL;
416 }
417 }
418
419 for (i = 0; i < CDCE_TX_LIST_CNT; i++) {
420 if (sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf != NULL) {
421 m_freem(sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf);
422 sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf = NULL;
423 }
424 if (sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer != NULL) {
425 usbd_free_xfer(sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer);
426 sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer = NULL;
427 }
428 }
429
430 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
431 }
432
433 Static int
434 cdce_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
435 {
436 struct cdce_softc *sc = ifp->if_softc;
437 struct ifaddr *ifa = (struct ifaddr *)data;
438 struct ifreq *ifr = (struct ifreq *)data;
439 int s, error = 0;
440
441 if (sc->cdce_dying)
442 return (EIO);
443
444 s = splnet();
445
446 switch(command) {
447 case SIOCSIFADDR:
448 ifp->if_flags |= IFF_UP;
449 cdce_init(sc);
450 switch (ifa->ifa_addr->sa_family) {
451 #ifdef INET
452 case AF_INET:
453 #if defined(__NetBSD__)
454 arp_ifinit(ifp, ifa);
455 #else
456 arp_ifinit(&sc->arpcom, ifa);
457 #endif
458 break;
459 #endif /* INET */
460 #ifdef NS
461 case AF_NS:
462 {
463 struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
464
465 if (ns_nullhost(*ina))
466 ina->x_host = *(union ns_host *)
467 LLADDR(ifp->if_sadl);
468 else
469 memcpy(LLADDR(ifp->if_sadl),
470 ina->x_host.c_host,
471 ifp->if_addrlen);
472 break;
473 }
474 #endif /* NS */
475 }
476 break;
477
478 case SIOCSIFMTU:
479 if (ifr->ifr_mtu > ETHERMTU)
480 error = EINVAL;
481 else
482 ifp->if_mtu = ifr->ifr_mtu;
483 break;
484
485 case SIOCSIFFLAGS:
486 if (ifp->if_flags & IFF_UP) {
487 if (!(ifp->if_flags & IFF_RUNNING))
488 cdce_init(sc);
489 } else {
490 if (ifp->if_flags & IFF_RUNNING)
491 cdce_stop(sc);
492 }
493 error = 0;
494 break;
495
496 default:
497 error = EINVAL;
498 break;
499 }
500
501 splx(s);
502
503 return (error);
504 }
505
506 Static void
507 cdce_watchdog(struct ifnet *ifp)
508 {
509 struct cdce_softc *sc = ifp->if_softc;
510
511 if (sc->cdce_dying)
512 return;
513
514 ifp->if_oerrors++;
515 printf("%s: watchdog timeout\n", USBDEVNAME(sc->cdce_dev));
516 }
517
518 Static void
519 cdce_init(void *xsc)
520 {
521 struct cdce_softc *sc = xsc;
522 struct ifnet *ifp = GET_IFP(sc);
523 struct cdce_chain *c;
524 usbd_status err;
525 int s, i;
526
527 if (ifp->if_flags & IFF_RUNNING)
528 return;
529
530 s = splnet();
531
532 if (cdce_tx_list_init(sc) == ENOBUFS) {
533 printf("%s: tx list init failed\n", USBDEVNAME(sc->cdce_dev));
534 splx(s);
535 return;
536 }
537
538 if (cdce_rx_list_init(sc) == ENOBUFS) {
539 printf("%s: rx list init failed\n", USBDEVNAME(sc->cdce_dev));
540 splx(s);
541 return;
542 }
543
544 /* Maybe set multicast / broadcast here??? */
545
546 err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkin_no,
547 USBD_EXCLUSIVE_USE, &sc->cdce_bulkin_pipe);
548 if (err) {
549 printf("%s: open rx pipe failed: %s\n", USBDEVNAME(sc->cdce_dev),
550 usbd_errstr(err));
551 splx(s);
552 return;
553 }
554
555 err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkout_no,
556 USBD_EXCLUSIVE_USE, &sc->cdce_bulkout_pipe);
557 if (err) {
558 printf("%s: open tx pipe failed: %s\n", USBDEVNAME(sc->cdce_dev),
559 usbd_errstr(err));
560 splx(s);
561 return;
562 }
563
564 for (i = 0; i < CDCE_RX_LIST_CNT; i++) {
565 c = &sc->cdce_cdata.cdce_rx_chain[i];
566 usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkin_pipe, c,
567 c->cdce_buf, CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
568 USBD_NO_TIMEOUT, cdce_rxeof);
569 usbd_transfer(c->cdce_xfer);
570 }
571
572 ifp->if_flags |= IFF_RUNNING;
573 ifp->if_flags &= ~IFF_OACTIVE;
574
575 splx(s);
576 }
577
578 Static int
579 cdce_newbuf(struct cdce_softc *sc, struct cdce_chain *c, struct mbuf *m)
580 {
581 struct mbuf *m_new = NULL;
582
583 if (m == NULL) {
584 MGETHDR(m_new, M_DONTWAIT, MT_DATA);
585 if (m_new == NULL) {
586 printf("%s: no memory for rx list "
587 "-- packet dropped!\n", USBDEVNAME(sc->cdce_dev));
588 return (ENOBUFS);
589 }
590 MCLGET(m_new, M_DONTWAIT);
591 if (!(m_new->m_flags & M_EXT)) {
592 printf("%s: no memory for rx list "
593 "-- packet dropped!\n", USBDEVNAME(sc->cdce_dev));
594 m_freem(m_new);
595 return (ENOBUFS);
596 }
597 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
598 } else {
599 m_new = m;
600 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
601 m_new->m_data = m_new->m_ext.ext_buf;
602 }
603 c->cdce_mbuf = m_new;
604 return (0);
605 }
606
607 Static int
608 cdce_rx_list_init(struct cdce_softc *sc)
609 {
610 struct cdce_cdata *cd;
611 struct cdce_chain *c;
612 int i;
613
614 cd = &sc->cdce_cdata;
615 for (i = 0; i < CDCE_RX_LIST_CNT; i++) {
616 c = &cd->cdce_rx_chain[i];
617 c->cdce_sc = sc;
618 c->cdce_idx = i;
619 if (cdce_newbuf(sc, c, NULL) == ENOBUFS)
620 return (ENOBUFS);
621 if (c->cdce_xfer == NULL) {
622 c->cdce_xfer = usbd_alloc_xfer(sc->cdce_udev);
623 if (c->cdce_xfer == NULL)
624 return (ENOBUFS);
625 c->cdce_buf = usbd_alloc_buffer(c->cdce_xfer, CDCE_BUFSZ);
626 if (c->cdce_buf == NULL)
627 return (ENOBUFS);
628 }
629 }
630
631 return (0);
632 }
633
634 Static int
635 cdce_tx_list_init(struct cdce_softc *sc)
636 {
637 struct cdce_cdata *cd;
638 struct cdce_chain *c;
639 int i;
640
641 cd = &sc->cdce_cdata;
642 for (i = 0; i < CDCE_TX_LIST_CNT; i++) {
643 c = &cd->cdce_tx_chain[i];
644 c->cdce_sc = sc;
645 c->cdce_idx = i;
646 c->cdce_mbuf = NULL;
647 if (c->cdce_xfer == NULL) {
648 c->cdce_xfer = usbd_alloc_xfer(sc->cdce_udev);
649 if (c->cdce_xfer == NULL)
650 return (ENOBUFS);
651 c->cdce_buf = usbd_alloc_buffer(c->cdce_xfer, CDCE_BUFSZ);
652 if (c->cdce_buf == NULL)
653 return (ENOBUFS);
654 }
655 }
656
657 return (0);
658 }
659
660 Static void
661 cdce_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
662 {
663 struct cdce_chain *c = priv;
664 struct cdce_softc *sc = c->cdce_sc;
665 struct ifnet *ifp = GET_IFP(sc);
666 struct mbuf *m;
667 int total_len = 0;
668 int s;
669
670 if (sc->cdce_dying || !(ifp->if_flags & IFF_RUNNING))
671 return;
672
673 if (status != USBD_NORMAL_COMPLETION) {
674 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
675 return;
676 if (sc->cdce_rxeof_errors == 0)
677 printf("%s: usb error on rx: %s\n",
678 USBDEVNAME(sc->cdce_dev), usbd_errstr(status));
679 if (status == USBD_STALLED)
680 usbd_clear_endpoint_stall(sc->cdce_bulkin_pipe);
681 DELAY(sc->cdce_rxeof_errors * 10000);
682 sc->cdce_rxeof_errors++;
683 goto done;
684 }
685
686 sc->cdce_rxeof_errors = 0;
687
688 usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
689 if (sc->cdce_flags & CDCE_ZAURUS)
690 total_len -= 4; /* Strip off CRC added by Zaurus */
691 if (total_len <= 1)
692 goto done;
693
694 m = c->cdce_mbuf;
695 memcpy(mtod(m, char *), c->cdce_buf, total_len);
696
697 if (total_len < sizeof(struct ether_header)) {
698 ifp->if_ierrors++;
699 goto done;
700 }
701
702 ifp->if_ipackets++;
703 m->m_pkthdr.len = m->m_len = total_len;
704 m->m_pkthdr.rcvif = ifp;
705
706 s = splnet();
707
708 if (cdce_newbuf(sc, c, NULL) == ENOBUFS) {
709 ifp->if_ierrors++;
710 goto done1;
711 }
712
713 #if NBPFILTER > 0
714 if (ifp->if_bpf)
715 BPF_MTAP(ifp, m);
716 #endif
717
718 IF_INPUT(ifp, m);
719
720 done1:
721 splx(s);
722
723 done:
724 /* Setup new transfer. */
725 usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkin_pipe, c, c->cdce_buf,
726 CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
727 cdce_rxeof);
728 usbd_transfer(c->cdce_xfer);
729 }
730
731 Static void
732 cdce_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
733 {
734 struct cdce_chain *c = priv;
735 struct cdce_softc *sc = c->cdce_sc;
736 struct ifnet *ifp = GET_IFP(sc);
737 usbd_status err;
738 int s;
739
740 if (sc->cdce_dying)
741 return;
742
743 s = splnet();
744
745 ifp->if_timer = 0;
746 ifp->if_flags &= ~IFF_OACTIVE;
747
748 if (status != USBD_NORMAL_COMPLETION) {
749 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
750 splx(s);
751 return;
752 }
753 ifp->if_oerrors++;
754 printf("%s: usb error on tx: %s\n", USBDEVNAME(sc->cdce_dev),
755 usbd_errstr(status));
756 if (status == USBD_STALLED)
757 usbd_clear_endpoint_stall(sc->cdce_bulkout_pipe);
758 splx(s);
759 return;
760 }
761
762 usbd_get_xfer_status(c->cdce_xfer, NULL, NULL, NULL, &err);
763
764 if (c->cdce_mbuf != NULL) {
765 m_freem(c->cdce_mbuf);
766 c->cdce_mbuf = NULL;
767 }
768
769 if (err)
770 ifp->if_oerrors++;
771 else
772 ifp->if_opackets++;
773
774 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
775 cdce_start(ifp);
776
777 splx(s);
778 }
779
780 void *
781 cdce_get_desc(usbd_device_handle dev, int type, int subtype)
782 {
783 usb_descriptor_t *desc;
784 usb_config_descriptor_t *cd = usbd_get_config_descriptor(dev);
785 uByte *p = (uByte *)cd;
786 uByte *end = p + UGETW(cd->wTotalLength);
787
788 while (p < end) {
789 desc = (usb_descriptor_t *)p;
790 if (desc->bDescriptorType == type &&
791 desc->bDescriptorSubtype == subtype)
792 return (desc);
793 p += desc->bLength;
794 }
795
796 return (NULL);
797 }
798
799 int
800 cdce_activate(device_ptr_t self, enum devact act)
801 {
802 struct cdce_softc *sc = (struct cdce_softc *)self;
803
804 switch (act) {
805 case DVACT_ACTIVATE:
806 return (EOPNOTSUPP);
807 break;
808
809 case DVACT_DEACTIVATE:
810 if_deactivate(GET_IFP(sc));
811 sc->cdce_dying = 1;
812 break;
813 }
814 return (0);
815 }
816
817
818 /* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
819 * code or tables extracted from it, as desired without restriction.
820 */
821
822 static uint32_t cdce_crc32_tab[] = {
823 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
824 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
825 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
826 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
827 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
828 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
829 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
830 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
831 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
832 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
833 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
834 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
835 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
836 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
837 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
838 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
839 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
840 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
841 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
842 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
843 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
844 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
845 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
846 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
847 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
848 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
849 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
850 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
851 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
852 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
853 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
854 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
855 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
856 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
857 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
858 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
859 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
860 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
861 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
862 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
863 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
864 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
865 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
866 };
867
868 uint32_t
869 cdce_crc32(const void *buf, size_t size)
870 {
871 const uint8_t *p;
872 uint32_t crc;
873
874 p = buf;
875 crc = ~0U;
876
877 while (size--)
878 crc = cdce_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
879
880 return (crc ^ ~0U);
881 }
882