ref: 845607a5dd0724b9b897745d025c8e5d19a34991
parent: 921d96ea15e2f544ac24ee2c715161ac406f828c
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Wed May 24 18:55:26 EDT 2023
reform/pm: several improvements and fixes * turning trackball leds on/off via /dev/light * give the keyboard a chance to finish shutdown animation * report combined voltage of all cells * instead of an error "battery is missing" just report the state as "missing" * fix LPC shutdown fallback if keyboard failed to shut down the computer
--- a/sys/man/1/reform
+++ b/sys/man/1/reform
@@ -115,11 +115,12 @@
.TP
.B light
Provides a way to control the backlight of the built-in LCD by
-writing \fIlcd [-+]N\fR or \fIkbd [-+]N\fR,
+writing \fIlcd [-+]N\fR, \fIkbd [-+]N\fR, or \fItb N N N N N\fR,
where
.I N
is expressed in percentage, either as an absolute value (0-100) or
-relative to the current brightness - by prefixing with a sign.
+relative to the current brightness - by prefixing with a sign. For the
+trackball (\fItb\fR) only 0 and 1 are valid values.
Reading
.B light
returns the current brightness.
--- a/sys/src/cmd/reform/pm.c
+++ b/sys/src/cmd/reform/pm.c
@@ -33,6 +33,8 @@
Lcd = 0,
Kbd,
+ Tb,
+ Nlights = 5, /* trackball has 5 leds */
PWMSAR = 0x0c/4,
PWMPR = 0x10/4,
@@ -81,10 +83,12 @@
static char *uid = "pm";
static Reqqueue *lpcreq;
static u32int *pwm2, *tmu, *spi2;
-static int kbdlight = 0;
-static int kbdhidfd = -1;
+static int kbdlight = 0, tbleds[5] = {0};
+static int hidkb = -1, hidtb = -1;
static Memimage *kbdoled, *image;
static u8int kbdoledraw[4+KbdoledW*KbdoledH/8] = {'W', 'B', 'I', 'T', 0};
+static char udidkb[] = "Reform Keyboard";
+static char udidtb[] = "Reform Trackball";
static void
wr(u32int *base, int reg, u32int v)
@@ -128,20 +132,21 @@
}
static int
-openkbdhid(void)
+openhidctl(int *fd, char *match)
{
char path[32], *s, *k, *e;
int f;
- if(kbdhidfd < 0 && (f = open("/dev/usb/ctl", OREAD)) >= 0){
+ if(*fd < 0 && (f = open("/dev/usb/ctl", OREAD)) >= 0){
if((s = readall(f)) != nil &&
- (k = strstr(s, "MNT 'Reform Keyboard'")) != nil &&
- (e = strchr(k+22, ' ')) != nil){
+ (k = strstr(s, match)) != nil &&
+ (k = strstr(k+strlen(match), "' ")) != nil &&
+ (e = strchr(k+2, ' ')) != nil){
*e = 0;
- snprint(path, sizeof(path), "/dev/hidU%sctl", k+22);
- if((kbdhidfd = open(path, OWRITE)) >= 0 && write(kbdhidfd, "rawon", 5) != 5){
- close(kbdhidfd);
- kbdhidfd = -1;
+ snprint(path, sizeof(path), "/dev/hidU%sctl", k+2);
+ if((*fd = open(path, OWRITE)) >= 0 && write(*fd, "rawon", 5) != 5){
+ close(*fd);
+ *fd = -1;
}
}
free(s);
@@ -148,7 +153,7 @@
close(f);
}
- return kbdhidfd < 0;
+ return *fd < 0;
}
static int
@@ -160,10 +165,10 @@
u8int *p, q;
ulong chan;
- if(openkbdhid() != 0)
+ if(openhidctl(&hidkb, udidkb) != 0)
return -1;
if(size == 0)
- return write(kbdhidfd, "WCLR", 4);
+ return write(hidkb, "WCLR", 4);
used = 0;
if(offset == 0){
@@ -228,7 +233,7 @@
}
}
- if(write(kbdhidfd, kbdoledraw, sizeof(kbdoledraw)) != sizeof(kbdoledraw))
+ if(write(hidkb, kbdoledraw, sizeof(kbdoledraw)) != sizeof(kbdoledraw))
return -1;
return used;
@@ -235,47 +240,62 @@
}
static int
-setlight(int k, int p)
+setlight(int k, int *p)
{
- u32int v;
+ u32int v, i;
- if(p < 0)
- p = 0;
- if(p > 100)
- p = 100;
+ for(i = 0; i < Nlights; i++){
+ if(p[i] < 0)
+ p[i] = 0;
+ else if(k == Tb)
+ p[i] = p[i] > 0;
+ else if(p[i] > 100)
+ p[i] = 100;
+ }
if(k == Lcd){
v = Pwmsrcclk / rd(pwm2, PWMSAR);
- wr(pwm2, PWMPR, (Pwmsrcclk/(v*p/100))-2);
+ wr(pwm2, PWMPR, (Pwmsrcclk/(v*p[0]/100))-2);
return 0;
- }else if(k == Kbd && openkbdhid() == 0){
- v = Kbdlightmax*p/100;
- if(fprint(kbdhidfd, "LITE%c", '0'+v) > 0){
- kbdlight = v;
+ }else if(k == Kbd && openhidctl(&hidkb, udidkb) == 0){
+ v = Kbdlightmax*p[0]/100;
+ if(fprint(hidkb, "LITE%d", v) > 0){
+ kbdlight = p[0];
return 0;
}
- close(kbdhidfd);
- kbdhidfd = -1;
- kbdlight = 0;
+ close(hidkb);
+ hidkb = -1;
+ }else if(k == Tb && openhidctl(&hidtb, udidtb) == 0){
+ if(fprint(hidtb, "LEDS%d%d%d%d%d", p[0], p[1], p[2], p[3], p[4]) > 0){
+ memmove(tbleds, p, sizeof(tbleds));
+ return 0;
+ }
+ close(hidtb);
+ hidtb = -1;
}
return -1;
}
-static int
-getlight(int k)
+static void
+getlight(int k, int *v)
{
- u32int m, v;
+ u32int m;
+ int i;
- SET(m, v);
+ SET(m);
if(k == Lcd){
m = Pwmsrcclk / rd(pwm2, PWMSAR);
- v = Pwmsrcclk / (rd(pwm2, PWMPR)+2);
+ v[0] = Pwmsrcclk / (rd(pwm2, PWMPR)+2);
}else if(k == Kbd){
- m = Kbdlightmax;
- v = kbdlight;
+ m = 100;
+ v[0] = kbdlight;
+ }else if(k == Tb){
+ m = 100;
+ memmove(v, tbleds, sizeof(tbleds));
}
- return v*100/m;
+ for(i = 0; i < Nlights; i++)
+ v[i] = v[i]*100/m;
}
static int
@@ -423,9 +443,8 @@
}
break;
case Smissing:
- respond(r, "battery is missing");
- return;
-
+ state = "missing";
+ break;
}
snprint(msg, sizeof(msg), "%d mA %d %d %d %d ? mV %d ? %02d:%02d:%02d %s\n",
@@ -461,11 +480,12 @@
s = msg;
e = s+sizeof(msg);
s = seprint(s, e, "version %s\n", lpcfw);
+ s = seprint(s, e, "voltage(mV) %d\n", (s16int)(q[0] | q[1]<<8));
+ s = seprint(s, e, "current(mA) %d\n", (s16int)(q[2] | q[3]<<8));
s = seprint(s, e, "cells(mV)");
for(i = 0; i < 16; i += 2)
s = seprint(s, e, " %d", v[i] | v[i+1]<<8);
s = seprint(s, e, "\n");
- s = seprint(s, e, "current(mA) %d\n", (s16int)(q[2] | q[3]<<8));
USED(s);
readstr(r, msg);
@@ -475,15 +495,21 @@
static void
fsread(Req *r)
{
+ int c, v[2+Nlights];
char msg[256];
void *aux;
- int c;
msg[0] = 0;
if(r->ifcall.offset == 0){
aux = r->fid->file->aux;
if(aux == (void*)Light){
- snprint(msg, sizeof(msg), "lcd %d\nkbd %d\n", getlight(Lcd), getlight(Kbd));
+ getlight(Lcd, v);
+ getlight(Kbd, v+1);
+ getlight(Tb, v+2);
+ snprint(msg, sizeof(msg),
+ "lcd %d\nkbd %d\ntb %d %d %d %d %d\n",
+ v[0], v[1], v[2], v[3], v[4], v[5], v[6]
+ );
}else if(aux == (void*)Temp){
if((c = getcputemp()) < 0){
responderror(r);
@@ -506,19 +532,19 @@
static void
fswrite(Req *r)
{
- char msg[256], *f[4];
- int nf, v, p, k;
+ int nf, v[Nlights], p, k, i;
+ char msg[256], *f[1+Nlights];
void *aux;
aux = r->fid->file->aux;
if(aux == (void*)Kbdoled){
- if((v = loadkbdoled(r->ifcall.data, r->ifcall.offset, r->ifcall.count)) < 0){
+ if((k = loadkbdoled(r->ifcall.data, r->ifcall.offset, r->ifcall.count)) < 0){
Err:
responderror(r);
return;
}
- r->ofcall.count = v;
+ r->ofcall.count = k;
respond(r, nil);
return;
}
@@ -535,11 +561,17 @@
k = Lcd;
else if(strcmp(f[0], "kbd") == 0)
k = Kbd;
+ else if(strcmp(f[0], "tb") == 0)
+ k = Tb;
else
goto Bad;
- v = atoi(f[1]);
- if(*f[1] == '+' || *f[1] == '-')
- v += getlight(k);
+
+ getlight(k, v);
+ for(i = 0; i < nf-1; i++){
+ if(*f[i+1] != '+' && *f[i+1] != '-')
+ v[i] = 0;
+ v[i] += atoi(f[i+1]);
+ }
if(setlight(k, v) != 0)
goto Err;
}else if(aux == (void*)Pmctl){
@@ -550,9 +582,10 @@
* LPC firmware might not be up to date so try
* shutting down through the keyboard first
*/
- if(openkbdhid() == 0){
- write(kbdhidfd, "PWR0", 4);
+ if(openhidctl(&hidkb, udidkb) == 0){
+ write(hidkb, "PWR0", 4);
sleep(2000); /* give it a chance */
+ p = 1; /* fall back to lpc shutdown */
}
}
}