This source file includes following definitions.
- cdcef_match
- cdcef_attach
- cdcef_do_request
- cdcef_start
- cdcef_txeof
- cdcef_start_timeout
- cdcef_rxeof
- cdcef_newbuf
- cdcef_ioctl
- cdcef_watchdog
- cdcef_init
- cdcef_encap
- cdcef_stop
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 #include <bpfilter.h>
25
26
27 #include <sys/param.h>
28 #include <sys/device.h>
29 #include <sys/socket.h>
30 #include <sys/systm.h>
31 #include <sys/mbuf.h>
32 #include <sys/timeout.h>
33
34 #include <net/if.h>
35
36 #include <dev/usb/usb.h>
37 #include <dev/usb/usbdi.h>
38 #include <dev/usb/usbf.h>
39 #include <dev/usb/usbcdc.h>
40
41 #if NBPFILTER > 0
42 #include <net/bpf.h>
43 #endif
44
45 #include <netinet/in.h>
46 #include <netinet/in_systm.h>
47 #include <netinet/in_var.h>
48 #include <netinet/ip.h>
49 #include <netinet/if_ether.h>
50
51
52 #define CDCEF_VENDOR_ID 0x0001
53 #define CDCEF_PRODUCT_ID 0x0001
54 #define CDCEF_DEVICE_CODE 0x0100
55 #define CDCEF_VENDOR_STRING "OpenBSD.org"
56 #define CDCEF_PRODUCT_STRING "CDC Ethernet Emulation"
57 #define CDCEF_SERIAL_STRING "1.00"
58
59 #define CDCEF_BUFSZ 1600
60
61
62 struct cdcef_softc {
63 struct usbf_function sc_dev;
64 usbf_config_handle sc_config;
65 usbf_interface_handle sc_iface;
66 usbf_endpoint_handle sc_ep_in;
67 usbf_endpoint_handle sc_ep_out;
68 usbf_pipe_handle sc_pipe_in;
69 usbf_pipe_handle sc_pipe_out;
70 usbf_xfer_handle sc_xfer_in;
71 usbf_xfer_handle sc_xfer_out;
72 void *sc_buffer_in;
73 void *sc_buffer_out;
74
75 struct timeout start_to;
76
77 struct mbuf *sc_xmit_mbuf;
78
79 struct arpcom sc_arpcom;
80 #define GET_IFP(sc) (&(sc)->sc_arpcom.ac_if)
81
82 int sc_rxeof_errors;
83 int sc_unit;
84 int sc_attached;
85 int sc_listening;
86 };
87
88 int cdcef_match(struct device *, void *, void *);
89 void cdcef_attach(struct device *, struct device *, void *);
90
91 usbf_status cdcef_do_request(usbf_function_handle,
92 usb_device_request_t *, void **);
93
94 void cdcef_start(struct ifnet *);
95
96 void cdcef_txeof(usbf_xfer_handle, usbf_private_handle,
97 usbf_status);
98 void cdcef_rxeof(usbf_xfer_handle, usbf_private_handle,
99 usbf_status);
100 int cdcef_ioctl(struct ifnet *ifp, u_long command, caddr_t data);
101 void cdcef_watchdog(struct ifnet *ifp);
102 void cdcef_init(struct cdcef_softc *);
103 void cdcef_stop(struct cdcef_softc *);
104 int cdcef_encap(struct cdcef_softc *sc, struct mbuf *m, int idx);
105 struct mbuf * cdcef_newbuf(void);
106 void cdcef_start_timeout (void *);
107
108 struct cfattach cdcef_ca = {
109 sizeof(struct cdcef_softc), cdcef_match, cdcef_attach
110 };
111
112 struct cfdriver cdcef_cd = {
113 NULL, "cdcef", DV_DULL
114 };
115
116 struct usbf_function_methods cdcef_methods = {
117 NULL,
118 cdcef_do_request
119 };
120
121 #ifndef CDCEF_DEBUG
122 #define DPRINTF(x) do {} while (0)
123 #else
124 #define DPRINTF(x) printf x
125 #endif
126
127 #define DEVNAME(sc) ((sc)->sc_dev.bdev.dv_xname)
128
129
130
131
132
133 int
134 cdcef_match(struct device *parent, void *match, void *aux)
135 {
136 return UMATCH_GENERIC;
137 }
138
139 void
140 cdcef_attach(struct device *parent, struct device *self, void *aux)
141 {
142 struct cdcef_softc *sc = (struct cdcef_softc *)self;
143 struct usbf_attach_arg *uaa = aux;
144 usbf_device_handle dev = uaa->device;
145 char *devinfop;
146 struct ifnet *ifp;
147 usbf_status err;
148 usb_cdc_union_descriptor_t udesc;
149 int s;
150 u_int16_t macaddr_hi;
151
152
153
154 usbf_devinfo_setup(dev, UDCLASS_IN_INTERFACE, 0, 0, CDCEF_VENDOR_ID,
155 CDCEF_PRODUCT_ID, CDCEF_DEVICE_CODE, CDCEF_VENDOR_STRING,
156 CDCEF_PRODUCT_STRING, CDCEF_SERIAL_STRING);
157
158 devinfop = usbf_devinfo_alloc(dev);
159 printf(": %s\n", devinfop);
160 usbf_devinfo_free(devinfop);
161
162
163 sc->sc_dev.methods = &cdcef_methods;
164
165
166 timeout_set(&sc->start_to, cdcef_start_timeout, sc);
167
168
169
170
171 err = usbf_add_config(dev, &sc->sc_config);
172 if (err) {
173 printf("%s: usbf_add_config failed\n", DEVNAME(sc));
174 return;
175 }
176 err = usbf_add_interface(sc->sc_config, UICLASS_CDC,
177 UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0, NULL,
178 &sc->sc_iface);
179 if (err) {
180 printf("%s: usbf_add_interface failed\n", DEVNAME(sc));
181 return;
182 }
183
184 err = usbf_add_endpoint(sc->sc_iface, UE_DIR_IN | 2, UE_BULK,
185 64, 16, &sc->sc_ep_in) ||
186 usbf_add_endpoint(sc->sc_iface, UE_DIR_OUT | 1, UE_BULK,
187 64, 16, &sc->sc_ep_out);
188 if (err) {
189 printf("%s: usbf_add_endpoint failed\n", DEVNAME(sc));
190 return;
191 }
192
193
194 bzero(&udesc, sizeof udesc);
195 udesc.bLength = sizeof udesc;
196 udesc.bDescriptorType = UDESC_CS_INTERFACE;
197 udesc.bDescriptorSubtype = UDESCSUB_CDC_UNION;
198 udesc.bSlaveInterface[0] = usbf_interface_number(sc->sc_iface);
199 err = usbf_add_config_desc(sc->sc_config,
200 (usb_descriptor_t *)&udesc, NULL);
201 if (err) {
202 printf("%s: usbf_add_config_desc failed\n", DEVNAME(sc));
203 return;
204 }
205
206
207
208
209 err = usbf_end_config(sc->sc_config);
210 if (err) {
211 printf("%s: usbf_end_config failed\n", DEVNAME(sc));
212 return;
213 }
214
215
216 sc->sc_xfer_in = usbf_alloc_xfer(dev);
217 sc->sc_xfer_out = usbf_alloc_xfer(dev);
218 sc->sc_buffer_in = usbf_alloc_buffer(sc->sc_xfer_in,
219 CDCEF_BUFSZ);
220 sc->sc_buffer_out = usbf_alloc_buffer(sc->sc_xfer_out,
221 CDCEF_BUFSZ);
222 if (sc->sc_buffer_in == NULL || sc->sc_buffer_out == NULL) {
223 printf("%s: usbf_alloc_buffer failed\n", DEVNAME(sc));
224 return;
225 }
226
227
228 err = usbf_open_pipe(sc->sc_iface,
229 usbf_endpoint_address(sc->sc_ep_out), &sc->sc_pipe_out) ||
230 usbf_open_pipe(sc->sc_iface,
231 usbf_endpoint_address(sc->sc_ep_in), &sc->sc_pipe_in);
232 if (err) {
233 printf("%s: usbf_open_pipe failed\n", DEVNAME(sc));
234 return;
235 }
236
237
238 usbf_setup_xfer(sc->sc_xfer_out, sc->sc_pipe_out, sc,
239 sc->sc_buffer_out, CDCEF_BUFSZ, USBD_SHORT_XFER_OK, 0, cdcef_rxeof);
240 err = usbf_transfer(sc->sc_xfer_out);
241 if (err && err != USBF_IN_PROGRESS) {
242 printf("%s: usbf_transfer failed\n", DEVNAME(sc));
243 return;
244 }
245
246 s = splnet();
247
248 macaddr_hi = htons(0x2acb);
249 bcopy(&macaddr_hi, &sc->sc_arpcom.ac_enaddr[0], sizeof(u_int16_t));
250 bcopy(&ticks, &sc->sc_arpcom.ac_enaddr[2], sizeof(u_int32_t));
251 sc->sc_arpcom.ac_enaddr[5] = (u_int8_t)(sc->sc_unit);
252
253 printf("%s: address %s\n", DEVNAME(sc),
254 ether_sprintf(sc->sc_arpcom.ac_enaddr));
255
256 ifp = GET_IFP(sc);
257 ifp->if_softc = sc;
258 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
259 ifp->if_ioctl = cdcef_ioctl;
260 ifp->if_start = cdcef_start;
261 ifp->if_watchdog = cdcef_watchdog;
262 strlcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ);
263
264 IFQ_SET_READY(&ifp->if_snd);
265
266 if_attach(ifp);
267 ether_ifattach(ifp);
268
269 sc->sc_attached = 1;
270 splx(s);
271 }
272
273 usbf_status
274 cdcef_do_request(usbf_function_handle fun, usb_device_request_t *req,
275 void **data)
276 {
277 printf("cdcef_do_request\n");
278 return USBF_STALLED;
279 }
280
281 void
282 cdcef_start(struct ifnet *ifp)
283 {
284 struct cdcef_softc *sc = ifp->if_softc;
285 struct mbuf *m_head = NULL;
286
287 if(ifp->if_flags & IFF_OACTIVE)
288 return;
289
290 IFQ_POLL(&ifp->if_snd, m_head);
291 if (m_head == NULL) {
292 return;
293 }
294
295 if (sc->sc_listening == 0 || m_head->m_pkthdr.len > CDCEF_BUFSZ) {
296
297
298
299
300 IFQ_DEQUEUE(&ifp->if_snd, m_head);
301 m_freem(m_head);
302 return;
303 }
304
305 if (cdcef_encap(sc, m_head, 0)) {
306 ifp->if_flags |= IFF_OACTIVE;
307 return;
308 }
309
310 IFQ_DEQUEUE(&ifp->if_snd, m_head);
311
312 #if NBPFILTER > 0
313 if (ifp->if_bpf)
314 bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT);
315 #endif
316
317 ifp->if_flags |= IFF_OACTIVE;
318
319 ifp->if_timer = 6;
320 }
321
322 void
323 cdcef_txeof(usbf_xfer_handle xfer, usbf_private_handle priv,
324 usbf_status err)
325 {
326 struct cdcef_softc *sc = priv;
327 struct ifnet *ifp = GET_IFP(sc);
328 int s;
329
330 s = splnet();
331 #if 0
332 printf("cdcef_txeof: xfer=%p, priv=%p, %s\n", xfer, priv,
333 usbf_errstr(err));
334 #endif
335
336 ifp->if_timer = 0;
337 ifp->if_flags &= ~IFF_OACTIVE;
338
339 if (sc->sc_xmit_mbuf != NULL) {
340 m_freem(sc->sc_xmit_mbuf);
341 sc->sc_xmit_mbuf = NULL;
342 }
343
344 if (err)
345 ifp->if_oerrors++;
346 else
347 ifp->if_opackets++;
348
349 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
350 timeout_add(&sc->start_to, 1);
351
352 splx(s);
353 }
354 void
355 cdcef_start_timeout (void *v)
356 {
357 struct cdcef_softc *sc = v;
358 struct ifnet *ifp = GET_IFP(sc);
359 int s;
360
361 s = splnet();
362 cdcef_start(ifp);
363 splx(s);
364 }
365
366
367 void
368 cdcef_rxeof(usbf_xfer_handle xfer, usbf_private_handle priv,
369 usbf_status status)
370 {
371 struct cdcef_softc *sc = priv;
372 int total_len = 0;
373 struct ifnet *ifp = GET_IFP(sc);
374 struct mbuf *m = NULL;
375
376
377 int s;
378
379 #if 0
380 printf("cdcef_rxeof: xfer=%p, priv=%p, %s\n", xfer, priv,
381 usbf_errstr(status));
382 #endif
383
384 if (status != USBF_NORMAL_COMPLETION) {
385 if (status == USBF_NOT_STARTED || status == USBF_CANCELLED)
386 return;
387 if (sc->sc_rxeof_errors == 0)
388 printf("%s: usb error on rx: %s\n",
389 DEVNAME(sc), usbf_errstr(status));
390
391 if (sc->sc_rxeof_errors++ > 10) {
392 printf("%s: too many errors, disabling\n",
393 DEVNAME(sc));
394
395
396 }
397 goto done;
398 }
399 sc->sc_rxeof_errors = 0;
400
401
402 if (sc->sc_listening == 0) {
403 sc->sc_listening = 1;
404 }
405
406
407 usbf_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
408
409
410 if (total_len <= 1)
411 goto done;
412
413 if (total_len < sizeof(struct ether_header)) {
414 ifp->if_ierrors++;
415 goto done;
416 }
417
418 s = splnet();
419 if (ifp->if_flags & IFF_RUNNING) {
420 m = cdcef_newbuf();
421 if (m == NULL) {
422
423 ifp->if_ierrors++;
424 goto done1;
425 }
426
427 m->m_pkthdr.len = m->m_len = total_len;
428 bcopy(sc->sc_buffer_out, mtod(m, char *), total_len);
429 m->m_pkthdr.rcvif = ifp;
430
431 ifp->if_ipackets++;
432
433 #if NBPFILTER > 0
434 if (ifp->if_bpf)
435 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
436 #endif
437
438 ether_input_mbuf(ifp, m);
439 }
440
441 done1:
442 splx(s);
443
444 done:
445
446 usbf_setup_xfer(xfer, sc->sc_pipe_out, sc, sc->sc_buffer_out,
447 CDCEF_BUFSZ, USBD_SHORT_XFER_OK, 0, cdcef_rxeof);
448
449 status = usbf_transfer(xfer);
450 if (status && status != USBF_IN_PROGRESS) {
451 printf("%s: usbf_transfer failed\n", DEVNAME(sc));
452 return;
453 }
454 }
455
456 struct mbuf *
457 cdcef_newbuf(void)
458 {
459 struct mbuf *m;
460
461 MGETHDR(m, M_DONTWAIT, MT_DATA);
462 if (m == NULL)
463 return (NULL);
464
465 MCLGET(m, M_DONTWAIT);
466 if (!(m->m_flags & M_EXT)) {
467 m_freem(m);
468 return (NULL);
469 }
470
471 m->m_len = m->m_pkthdr.len = MCLBYTES;
472 m_adj(m, ETHER_ALIGN);
473
474 return (m);
475 }
476
477 int
478 cdcef_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
479 {
480 struct cdcef_softc *sc = ifp->if_softc;
481 struct ifaddr *ifa = (struct ifaddr *)data;
482 struct ifreq *ifr = (struct ifreq *)data;
483 int s, error = 0;
484
485 s = splnet();
486
487 switch (command) {
488 case SIOCSIFADDR:
489 ifp->if_flags |= IFF_UP;
490 cdcef_init(sc);
491 switch (ifa->ifa_addr->sa_family) {
492 case AF_INET:
493 arp_ifinit(&sc->sc_arpcom, ifa);
494 break;
495 }
496 break;
497
498 case SIOCSIFMTU:
499 if (ifr->ifr_mtu > ETHERMTU)
500 error = EINVAL;
501 else
502 ifp->if_mtu = ifr->ifr_mtu;
503 break;
504
505 case SIOCSIFFLAGS:
506 if (ifp->if_flags & IFF_UP) {
507 if (!(ifp->if_flags & IFF_RUNNING))
508 cdcef_init(sc);
509 } else {
510 if (ifp->if_flags & IFF_RUNNING)
511 cdcef_stop(sc);
512 }
513 error = 0;
514 break;
515
516 case SIOCADDMULTI:
517 case SIOCDELMULTI:
518 error = (command == SIOCADDMULTI) ?
519 ether_addmulti(ifr, &sc->sc_arpcom) :
520 ether_delmulti(ifr, &sc->sc_arpcom);
521
522 if (error == ENETRESET)
523 error = 0;
524 break;
525
526 default:
527 error = EINVAL;
528 break;
529 }
530
531 splx(s);
532
533 return (error);
534 }
535
536 void
537 cdcef_watchdog(struct ifnet *ifp)
538 {
539 struct cdcef_softc *sc = ifp->if_softc;
540 int s;
541
542 #if 0
543 if (sc->sc_dying)
544 return;
545 #endif
546
547 ifp->if_oerrors++;
548 printf("%s: watchdog timeout\n", DEVNAME(sc));
549
550 s = splusb();
551 ifp->if_timer = 0;
552 ifp->if_flags &= ~IFF_OACTIVE;
553
554
555 usbf_abort_pipe(sc->sc_pipe_in);
556 splx(s);
557 }
558
559 void
560 cdcef_init(struct cdcef_softc *sc)
561 {
562 int s;
563 struct ifnet *ifp = GET_IFP(sc);
564 if (ifp->if_flags & IFF_RUNNING)
565 return;
566 s = splnet();
567
568 ifp->if_flags |= IFF_RUNNING;
569 ifp->if_flags &= ~IFF_OACTIVE;
570
571 splx(s);
572 }
573
574 int
575 cdcef_encap(struct cdcef_softc *sc, struct mbuf *m, int idx)
576 {
577 usbf_status err;
578
579 m_copydata(m, 0, m->m_pkthdr.len, sc->sc_buffer_in);
580
581
582 usbf_setup_xfer(sc->sc_xfer_in, sc->sc_pipe_in, sc, sc->sc_buffer_in,
583 m->m_pkthdr.len, USBD_FORCE_SHORT_XFER | USBD_NO_COPY,
584 10000, cdcef_txeof);
585
586 err = usbf_transfer(sc->sc_xfer_in);
587 if (err && err != USBD_IN_PROGRESS) {
588 printf("encap error\n");
589 cdcef_stop(sc);
590 return (EIO);
591 }
592 sc->sc_xmit_mbuf = m;
593
594 return (0);
595 }
596
597
598 void
599 cdcef_stop(struct cdcef_softc *sc)
600 {
601 struct ifnet *ifp = GET_IFP(sc);
602
603 ifp->if_timer = 0;
604 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
605
606
607
608 if (sc->sc_xmit_mbuf != NULL) {
609 m_freem(sc->sc_xmit_mbuf);
610 sc->sc_xmit_mbuf = NULL;
611 }
612 }