2 #include "../port/lib.h"
7 #include "../port/error.h"
21 BLbuttons= 2, /* button events */
22 BLtouch= 3, /* read touch screen events */
23 BLled= 8, /* turn LED on/off */
24 BLbattery= 9, /* read battery status */
25 BLbacklight= 0xd, /* backlight control */
27 SOF= 0x2, /* start of frame */
31 ".", { Qdir, 0, QTDIR }, 0, DMDIR|0755,
32 "backlight", { Qbacklight, 0 }, 0, 0664,
33 "battery", { Qbattery, 0 }, 0, 0664,
34 "buttons", { Qbuttons, 0 }, 0, 0664,
35 "cruft", { Qcruft, 0 }, 0, 0664,
36 "led", { Qled, 0 }, 0, 0664,
37 "version", { Qversion, 0 }, 0, 0664,
38 "power", { Qpower, 0 }, 0, 0600,
41 static struct µcontroller
43 /* message being rcvd */
48 /* for messages that require acks */
65 µcputc(Queue*, int ch)
71 static int touching; /* guard against something we call going spllo() */
72 static int buttoning; /* guard against something we call going spllo() */
74 if(ctlr.n > sizeof(ctlr.buf))
77 ctlr.buf[ctlr.n++] = (uchar)ch;
80 /* message hasn't started yet? */
81 if(ctlr.buf[0] != SOF){
82 p = memchr(ctlr.buf, SOF, ctlr.n);
88 memmove(ctlr.buf, p, ctlr.n);
93 len = ctlr.buf[1] & 0xf;
94 if(ctlr.n < 3 || ctlr.n < len+3)
98 ctlr.buf[0] = ~SOF; /* make sure we process this msg exactly once */
100 for(i = 1; i < len+2; i++)
101 cksum += ctlr.buf[i];
102 if(ctlr.buf[len+2] != cksum)
105 /* parse resulting message */
107 switch(ctlr.buf[1] >> 4){
109 strncpy(ctlr.version, (char*)p, len);
110 ctlr.version[len] = '0';
111 strcat(ctlr.version, "\n");
115 if(len < 1 || buttoning)
122 /* like mouse buttons */
136 pentrackxy((p[0]<<8)|p[1], (p[2]<<8)|p[3]);
138 pentrackxy((p[2]<<8)|p[3], (p[0]<<8)|p[1]);
151 ctlr.acstatus = p[0];
152 ctlr.voltage = (p[3]<<8)|p[2];
153 ctlr.batstatus = p[4];
162 print("unknown µc message: %ux", ctlr.buf[1] >> 4);
163 for(i = 0; i < len; i++)
169 /* remove the message */
171 memmove(ctlr.buf, &ctlr.buf[len+3], ctlr.n);
177 _sendmsg(uchar id, uchar *data, int len)
185 /* create the message */
186 if(sizeof(buf) < len+4)
188 cksum = (id<<4) | len;
191 for(i = 0; i < len; i++){
198 /* send the message - there should be a more generic way to do this */
199 serialµcputs(buf, p-buf);
202 /* the tsleep takes care of lost acks */
204 sendmsgwithack(uchar id, uchar *data, int len)
211 _sendmsg(id, data, len);
212 tsleep(&ctlr.r, return0, 0, 100);
218 sendmsg(uchar id, uchar *data, int len)
225 _sendmsg(id, data, len);
238 return devattach('r', spec);
242 µcwalk(Chan *c, Chan *nc, char **name, int nname)
244 return devwalk(c, nc, name, nname, µcdir, nelem(µcdir), devgen);
248 µcstat(Chan *c, uchar *dp, int n)
250 return devstat(c, dp, n, µcdir, nelem(µcdir), devgen);
254 µcopen(Chan* c, int omode)
256 omode = openmode(omode);
259 return devopen(c, omode, µcdir, nelem(µcdir), devgen);
280 case 1: return "high";
281 case 2: return "low";
282 case 4: return "critical";
283 case 8: return "charging";
284 case 0x80: return "none";
290 µcread(Chan* c, void* a, long n, vlong off)
294 if(c->qid.path == Qdir)
295 return devdirread(c, a, n, µcdir, nelem(µcdir), devgen);
297 switch((ulong)c->qid.path){
299 sendmsgwithack(BLbattery, nil, 0); /* send a battery request */
300 sprint(buf, "voltage: %d\nac: %s\nstatus: %s\n", ctlr.voltage,
301 acstatus(ctlr.acstatus),
302 batstatus(ctlr.batstatus));
303 return readstr(off, a, n, buf);
305 sendmsgwithack(BLversion, nil, 0); /* send a battery request */
306 return readstr(off, a, n, ctlr.version);
312 #define PUTBCD(n,o) bcdclock[o] = (n % 10) | (((n / 10) % 10)<<4)
314 static uchar lightdata[16];
317 µcwrite(Chan* c, void* a, long n, vlong)
325 extern ulong resumeaddr[];
326 extern void power_resume(void);
328 if(c->qid.path == Qpower){
331 if(strncmp(a, "suspend", 7) == 0)
332 *resumeaddr = (ulong)power_resume;
333 else if(strncmp(a, "halt", 4) == 0)
335 else if(strncmp(a, "wakeup", 6) == 0){
336 cmd = parsecmd(a, n);
339 l = strtoul(cmd->f[1], 0, 0);
348 cmd = parsecmd(a, n);
351 for(i = 0; i < cmd->nf; i++)
352 data[i] = atoi(cmd->f[i]);
354 switch((ulong)c->qid.path){
356 sendmsgwithack(BLled, data, cmd->nf);
359 memmove(lightdata, data, 16);
360 sendmsgwithack(BLbacklight, data, cmd->nf);
377 /* maybe dangerous, not holding the lock */
378 if (lightdata[0] == 0){
383 memmove(data, lightdata, 16);
384 _sendmsg(0xd, data, 3);