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