xref: /plan9-contrib/sys/src/cmd/usb/ether/cdc.c (revision d4df0e25729142c8872e87f57ac688cf887aee08)
1906943f9SDavid du Colombier /*
2906943f9SDavid du Colombier  * Standard usb ethernet communications device.
3906943f9SDavid du Colombier  */
4906943f9SDavid du Colombier #include <u.h>
5906943f9SDavid du Colombier #include <libc.h>
6906943f9SDavid du Colombier #include <fcall.h>
7906943f9SDavid du Colombier #include <thread.h>
8906943f9SDavid du Colombier #include "usb.h"
9906943f9SDavid du Colombier #include "usbfs.h"
10906943f9SDavid du Colombier #include "ether.h"
11906943f9SDavid du Colombier 
12906943f9SDavid du Colombier static int
okclass(Iface * iface)13906943f9SDavid du Colombier okclass(Iface *iface)
14906943f9SDavid du Colombier {
15906943f9SDavid du Colombier 	return Class(iface->csp) == Clcomms && Subclass(iface->csp) == Scether;
16906943f9SDavid du Colombier }
17906943f9SDavid du Colombier 
18906943f9SDavid du Colombier static int
getmac(Ether * ether)19906943f9SDavid du Colombier getmac(Ether *ether)
20906943f9SDavid du Colombier {
21906943f9SDavid du Colombier 	int i;
22906943f9SDavid du Colombier 	Usbdev *ud;
23906943f9SDavid du Colombier 	uchar *b;
24906943f9SDavid du Colombier 	Desc *dd;
25906943f9SDavid du Colombier 	char *mac;
26906943f9SDavid du Colombier 
27906943f9SDavid du Colombier 	ud = ether->dev->usb;
28906943f9SDavid du Colombier 
29906943f9SDavid du Colombier 	for(i = 0; i < nelem(ud->ddesc); i++)
30906943f9SDavid du Colombier 		if((dd = ud->ddesc[i]) != nil && okclass(dd->iface)){
31906943f9SDavid du Colombier 			b = (uchar*)&dd->data;
32906943f9SDavid du Colombier 			if(b[1] == Dfunction && b[2] == Fnether){
33906943f9SDavid du Colombier 				mac = loaddevstr(ether->dev, b[3]);
34906943f9SDavid du Colombier 				if(mac != nil && strlen(mac) != 12){
35906943f9SDavid du Colombier 					free(mac);
36906943f9SDavid du Colombier 					mac = nil;
37906943f9SDavid du Colombier 				}
38906943f9SDavid du Colombier 				if(mac != nil){
39906943f9SDavid du Colombier 					parseaddr(ether->addr, mac);
40906943f9SDavid du Colombier 					free(mac);
41906943f9SDavid du Colombier 					return 0;
42906943f9SDavid du Colombier 				}
43906943f9SDavid du Colombier 			}
44906943f9SDavid du Colombier 		}
45906943f9SDavid du Colombier 	return -1;
46906943f9SDavid du Colombier }
47906943f9SDavid du Colombier 
48906943f9SDavid du Colombier int
cdcreset(Ether * ether)49906943f9SDavid du Colombier cdcreset(Ether *ether)
50906943f9SDavid du Colombier {
51*d4df0e25SDavid du Colombier 	Usbdev *ud;
52*d4df0e25SDavid du Colombier 	Ep *ep;
53*d4df0e25SDavid du Colombier 	int i;
54*d4df0e25SDavid du Colombier 
55906943f9SDavid du Colombier 	/*
56906943f9SDavid du Colombier 	 * Assume that all communication devices are going to
57906943f9SDavid du Colombier 	 * be std. ethernet communication devices. Specific controllers
58906943f9SDavid du Colombier 	 * must have been probed first.
59906943f9SDavid du Colombier 	 */
60*d4df0e25SDavid du Colombier 	ud = ether->dev->usb;
61*d4df0e25SDavid du Colombier 	if(ud->class == Clcomms)
62906943f9SDavid du Colombier 		return getmac(ether);
63*d4df0e25SDavid du Colombier 	if(getmac(ether) == 0){
64*d4df0e25SDavid du Colombier 		for(i = 0; i < Nep; i++){
65*d4df0e25SDavid du Colombier 			ep = ud->ep[i];
66*d4df0e25SDavid du Colombier 			if(ep == nil)
67*d4df0e25SDavid du Colombier 				continue;
68*d4df0e25SDavid du Colombier 			if(ep->iface == nil || !okclass(ep->iface))
69*d4df0e25SDavid du Colombier 				continue;
70*d4df0e25SDavid du Colombier 			if(ep->conf->cval != 1)
71*d4df0e25SDavid du Colombier 				usbcmd(ether->dev, Rh2d|Rstd|Rdev, Rsetconf, ep->conf->cval, 0, nil, 0);
72*d4df0e25SDavid du Colombier 			return 0;
73*d4df0e25SDavid du Colombier 		}
74*d4df0e25SDavid du Colombier 	}
75906943f9SDavid du Colombier 	return -1;
76906943f9SDavid du Colombier }
77