xref: /plan9-contrib/sys/src/cmd/usb/ether/cdc.c (revision d4df0e25729142c8872e87f57ac688cf887aee08)
1 /*
2  * Standard usb ethernet communications device.
3  */
4 #include <u.h>
5 #include <libc.h>
6 #include <fcall.h>
7 #include <thread.h>
8 #include "usb.h"
9 #include "usbfs.h"
10 #include "ether.h"
11 
12 static int
okclass(Iface * iface)13 okclass(Iface *iface)
14 {
15 	return Class(iface->csp) == Clcomms && Subclass(iface->csp) == Scether;
16 }
17 
18 static int
getmac(Ether * ether)19 getmac(Ether *ether)
20 {
21 	int i;
22 	Usbdev *ud;
23 	uchar *b;
24 	Desc *dd;
25 	char *mac;
26 
27 	ud = ether->dev->usb;
28 
29 	for(i = 0; i < nelem(ud->ddesc); i++)
30 		if((dd = ud->ddesc[i]) != nil && okclass(dd->iface)){
31 			b = (uchar*)&dd->data;
32 			if(b[1] == Dfunction && b[2] == Fnether){
33 				mac = loaddevstr(ether->dev, b[3]);
34 				if(mac != nil && strlen(mac) != 12){
35 					free(mac);
36 					mac = nil;
37 				}
38 				if(mac != nil){
39 					parseaddr(ether->addr, mac);
40 					free(mac);
41 					return 0;
42 				}
43 			}
44 		}
45 	return -1;
46 }
47 
48 int
cdcreset(Ether * ether)49 cdcreset(Ether *ether)
50 {
51 	Usbdev *ud;
52 	Ep *ep;
53 	int i;
54 
55 	/*
56 	 * Assume that all communication devices are going to
57 	 * be std. ethernet communication devices. Specific controllers
58 	 * must have been probed first.
59 	 */
60 	ud = ether->dev->usb;
61 	if(ud->class == Clcomms)
62 		return getmac(ether);
63 	if(getmac(ether) == 0){
64 		for(i = 0; i < Nep; i++){
65 			ep = ud->ep[i];
66 			if(ep == nil)
67 				continue;
68 			if(ep->iface == nil || !okclass(ep->iface))
69 				continue;
70 			if(ep->conf->cval != 1)
71 				usbcmd(ether->dev, Rh2d|Rstd|Rdev, Rsetconf, ep->conf->cval, 0, nil, 0);
72 			return 0;
73 		}
74 	}
75 	return -1;
76 }
77