xref: /plan9/sys/src/cmd/usb/serial/silabs.c (revision 9b7bf7df4595c26f1e9b67beb0c6e44c9876fb05)
1*9b7bf7dfSDavid du Colombier #include <u.h>
2*9b7bf7dfSDavid du Colombier #include <libc.h>
3*9b7bf7dfSDavid du Colombier #include <thread.h>
4*9b7bf7dfSDavid du Colombier #include "usb.h"
5*9b7bf7dfSDavid du Colombier #include "usbfs.h"
6*9b7bf7dfSDavid du Colombier #include "serial.h"
7*9b7bf7dfSDavid du Colombier #include "silabs.h"
8*9b7bf7dfSDavid du Colombier 
9*9b7bf7dfSDavid du Colombier static Cinfo slinfo[] = {
10*9b7bf7dfSDavid du Colombier 	{ 0x10c4, 0xea60, },		/* CP210x */
11*9b7bf7dfSDavid du Colombier 	{ 0x10c4, 0xea61, },		/* CP210x */
12*9b7bf7dfSDavid du Colombier 	{ 0,	0, },
13*9b7bf7dfSDavid du Colombier };
14*9b7bf7dfSDavid du Colombier 
15*9b7bf7dfSDavid du Colombier enum {
16*9b7bf7dfSDavid du Colombier 	Enable		= 0x00,
17*9b7bf7dfSDavid du Colombier 
18*9b7bf7dfSDavid du Colombier 	Getbaud		= 0x1D,
19*9b7bf7dfSDavid du Colombier 	Setbaud		= 0x1E,
20*9b7bf7dfSDavid du Colombier 	Setlcr		= 0x03,
21*9b7bf7dfSDavid du Colombier 	Getlcr		= 0x04,
22*9b7bf7dfSDavid du Colombier 		Bitsmask	= 0x0F00,
23*9b7bf7dfSDavid du Colombier 		Bitsshift	= 8,
24*9b7bf7dfSDavid du Colombier 		Parmask		= 0x00F0,
25*9b7bf7dfSDavid du Colombier 		Parshift	= 4,
26*9b7bf7dfSDavid du Colombier 		Stopmask	= 0x000F,
27*9b7bf7dfSDavid du Colombier 		Stop1		= 0x0000,
28*9b7bf7dfSDavid du Colombier 		Stop1_5		= 0x0001,
29*9b7bf7dfSDavid du Colombier 		Stop2		= 0x0002,
30*9b7bf7dfSDavid du Colombier };
31*9b7bf7dfSDavid du Colombier 
slmatch(char * info)32*9b7bf7dfSDavid du Colombier slmatch(char *info)
33*9b7bf7dfSDavid du Colombier {
34*9b7bf7dfSDavid du Colombier 	Cinfo *ip;
35*9b7bf7dfSDavid du Colombier 	char buf[50];
36*9b7bf7dfSDavid du Colombier 
37*9b7bf7dfSDavid du Colombier 	for(ip = slinfo; ip->vid != 0; ip++){
38*9b7bf7dfSDavid du Colombier 		snprint(buf, sizeof buf, "vid %#06x did %#06x",
39*9b7bf7dfSDavid du Colombier 			ip->vid, ip->did);
40*9b7bf7dfSDavid du Colombier 		if(strstr(info, buf) != nil)
41*9b7bf7dfSDavid du Colombier 			return 0;
42*9b7bf7dfSDavid du Colombier 	}
43*9b7bf7dfSDavid du Colombier 	return -1;
44*9b7bf7dfSDavid du Colombier }
45*9b7bf7dfSDavid du Colombier 
46*9b7bf7dfSDavid du Colombier static int
slwrite(Serialport * p,int req,void * buf,int len)47*9b7bf7dfSDavid du Colombier slwrite(Serialport *p, int req, void *buf, int len)
48*9b7bf7dfSDavid du Colombier {
49*9b7bf7dfSDavid du Colombier 	Serial *ser;
50*9b7bf7dfSDavid du Colombier 
51*9b7bf7dfSDavid du Colombier 	ser = p->s;
52*9b7bf7dfSDavid du Colombier 	return usbcmd(ser->dev, Rh2d | Rvendor | Riface, req, 0, p->interfc,
53*9b7bf7dfSDavid du Colombier 		buf, len);
54*9b7bf7dfSDavid du Colombier }
55*9b7bf7dfSDavid du Colombier 
56*9b7bf7dfSDavid du Colombier static int
slput(Serialport * p,uint op,uint val)57*9b7bf7dfSDavid du Colombier slput(Serialport *p, uint op, uint val)
58*9b7bf7dfSDavid du Colombier {
59*9b7bf7dfSDavid du Colombier 	Serial *ser;
60*9b7bf7dfSDavid du Colombier 
61*9b7bf7dfSDavid du Colombier 	ser = p->s;
62*9b7bf7dfSDavid du Colombier 	return usbcmd(ser->dev, Rh2d | Rvendor | Riface, op, val, p->interfc,
63*9b7bf7dfSDavid du Colombier 		nil, 0);
64*9b7bf7dfSDavid du Colombier }
65*9b7bf7dfSDavid du Colombier 
66*9b7bf7dfSDavid du Colombier static int
slread(Serialport * p,int req,void * buf,int len)67*9b7bf7dfSDavid du Colombier slread(Serialport *p, int req, void *buf, int len)
68*9b7bf7dfSDavid du Colombier {
69*9b7bf7dfSDavid du Colombier 	Serial *ser;
70*9b7bf7dfSDavid du Colombier 
71*9b7bf7dfSDavid du Colombier 	ser = p->s;
72*9b7bf7dfSDavid du Colombier 	return usbcmd(ser->dev, Rd2h | Rvendor | Riface, req, 0, p->interfc,
73*9b7bf7dfSDavid du Colombier 		buf, len);
74*9b7bf7dfSDavid du Colombier }
75*9b7bf7dfSDavid du Colombier 
76*9b7bf7dfSDavid du Colombier static int
slinit(Serialport * p)77*9b7bf7dfSDavid du Colombier slinit(Serialport *p)
78*9b7bf7dfSDavid du Colombier {
79*9b7bf7dfSDavid du Colombier 	Serial *ser;
80*9b7bf7dfSDavid du Colombier 
81*9b7bf7dfSDavid du Colombier 	ser = p->s;
82*9b7bf7dfSDavid du Colombier 	dsprint(2, "slinit\n");
83*9b7bf7dfSDavid du Colombier 
84*9b7bf7dfSDavid du Colombier 	slput(p, Enable, 1);
85*9b7bf7dfSDavid du Colombier 
86*9b7bf7dfSDavid du Colombier 	slops.getparam(p);
87*9b7bf7dfSDavid du Colombier 
88*9b7bf7dfSDavid du Colombier 	/* p gets freed by closedev, the process has a reference */
89*9b7bf7dfSDavid du Colombier 	incref(ser->dev);
90*9b7bf7dfSDavid du Colombier 	return 0;
91*9b7bf7dfSDavid du Colombier }
92*9b7bf7dfSDavid du Colombier 
93*9b7bf7dfSDavid du Colombier static int
slgetparam(Serialport * p)94*9b7bf7dfSDavid du Colombier slgetparam(Serialport *p)
95*9b7bf7dfSDavid du Colombier {
96*9b7bf7dfSDavid du Colombier 	u16int lcr;
97*9b7bf7dfSDavid du Colombier 
98*9b7bf7dfSDavid du Colombier 	slread(p, Getbaud, &p->baud, sizeof(p->baud));
99*9b7bf7dfSDavid du Colombier 	slread(p, Getlcr, &lcr, sizeof(lcr));
100*9b7bf7dfSDavid du Colombier 	p->bits = (lcr&Bitsmask)>>Bitsshift;
101*9b7bf7dfSDavid du Colombier 	p->parity = (lcr&Parmask)>>Parshift;
102*9b7bf7dfSDavid du Colombier 	p->stop = (lcr&Stopmask) == Stop1? 1 : 2;
103*9b7bf7dfSDavid du Colombier 	return 0;
104*9b7bf7dfSDavid du Colombier }
105*9b7bf7dfSDavid du Colombier 
106*9b7bf7dfSDavid du Colombier static int
slsetparam(Serialport * p)107*9b7bf7dfSDavid du Colombier slsetparam(Serialport *p)
108*9b7bf7dfSDavid du Colombier {
109*9b7bf7dfSDavid du Colombier 	u16int lcr;
110*9b7bf7dfSDavid du Colombier 
111*9b7bf7dfSDavid du Colombier 	lcr = p->stop == 1? Stop1 : Stop2;
112*9b7bf7dfSDavid du Colombier 	lcr |= (p->bits<<Bitsshift) | (p->parity<<Parshift);
113*9b7bf7dfSDavid du Colombier 	slput(p, Setlcr, lcr);
114*9b7bf7dfSDavid du Colombier 	slwrite(p, Setbaud, &p->baud, sizeof(p->baud));
115*9b7bf7dfSDavid du Colombier 	return 0;
116*9b7bf7dfSDavid du Colombier }
117*9b7bf7dfSDavid du Colombier 
118*9b7bf7dfSDavid du Colombier static int
seteps(Serialport * p)119*9b7bf7dfSDavid du Colombier seteps(Serialport *p)
120*9b7bf7dfSDavid du Colombier {
121*9b7bf7dfSDavid du Colombier 	if(devctl(p->epin, "timeout 0") < 0){
122*9b7bf7dfSDavid du Colombier 		fprint(2, "can't set timeout on %s: %r\n", p->epin->dir);
123*9b7bf7dfSDavid du Colombier 		return -1;
124*9b7bf7dfSDavid du Colombier 	}
125*9b7bf7dfSDavid du Colombier 	return 0;
126*9b7bf7dfSDavid du Colombier }
127*9b7bf7dfSDavid du Colombier 
128*9b7bf7dfSDavid du Colombier static int
wait4data(Serialport * p,uchar * data,int count)129*9b7bf7dfSDavid du Colombier wait4data(Serialport *p, uchar *data, int count)
130*9b7bf7dfSDavid du Colombier {
131*9b7bf7dfSDavid du Colombier 	int n;
132*9b7bf7dfSDavid du Colombier 
133*9b7bf7dfSDavid du Colombier 	qunlock(p->s);
134*9b7bf7dfSDavid du Colombier 	while ((n = read(p->epin->dfd, data, count)) == 0)
135*9b7bf7dfSDavid du Colombier 		;
136*9b7bf7dfSDavid du Colombier 	qlock(p->s);
137*9b7bf7dfSDavid du Colombier 	return n;
138*9b7bf7dfSDavid du Colombier }
139*9b7bf7dfSDavid du Colombier 
140*9b7bf7dfSDavid du Colombier Serialops slops = {
141*9b7bf7dfSDavid du Colombier 	.init		= slinit,
142*9b7bf7dfSDavid du Colombier 	.getparam	= slgetparam,
143*9b7bf7dfSDavid du Colombier 	.setparam	= slsetparam,
144*9b7bf7dfSDavid du Colombier 	.seteps		= seteps,
145*9b7bf7dfSDavid du Colombier 	.wait4data	= wait4data,
146*9b7bf7dfSDavid du Colombier };
147