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