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