summaryrefslogtreecommitdiff
path: root/sys/src/cmd/reform
diff options
context:
space:
mode:
authorSigrid Solveig Haflínudóttir <sigrid@ftrv.se>2022-10-06 23:21:16 +0000
committerSigrid Solveig Haflínudóttir <sigrid@ftrv.se>2022-10-06 23:21:16 +0000
commite1949eedf6893c76472360189b6539bc0d573378 (patch)
tree98b1f453ca3defbf48c164d271260283edf4559c /sys/src/cmd/reform
parenta945c6f5b1f69b9bf7a6a3a5404b14b9fe6c5e5c (diff)
reform/pm: add keyboard light level controlling to /dev/light
Diffstat (limited to 'sys/src/cmd/reform')
-rw-r--r--sys/src/cmd/reform/pm.c135
1 files changed, 111 insertions, 24 deletions
diff --git a/sys/src/cmd/reform/pm.c b/sys/src/cmd/reform/pm.c
index 27de4ac83..3b12b140e 100644
--- a/sys/src/cmd/reform/pm.c
+++ b/sys/src/cmd/reform/pm.c
@@ -8,6 +8,7 @@ enum
{
Mhz = 1000*1000,
Pwmsrcclk = 25*Mhz,
+ Kbdlightmax = 8,
Scharge = 0,
Sovervolted,
@@ -24,6 +25,9 @@ enum
Battery,
Pmctl,
+ Lcd = 0,
+ Kbd,
+
PWMSAR = 0x0c/4,
PWMPR = 0x10/4,
@@ -70,6 +74,8 @@ enum
static Reqqueue *lpcreq;
static u32int *pwm2, *tmu, *spi2;
+static int kbdlight = 0;
+static int kbdhidfd = -1;
static char *uid = "pm";
static void
@@ -86,8 +92,60 @@ rd(u32int *base, int reg)
return base != nil ? base[reg] : -1;
}
-static void
-setlight(int p)
+static char *
+readall(int f)
+{
+ int bufsz, sz, n;
+ char *s;
+
+ bufsz = 2047;
+ s = nil;
+ for(sz = 0;; sz += n){
+ if(bufsz-sz < 2048){
+ bufsz *= 2;
+ s = realloc(s, bufsz);
+ }
+ if((n = readn(f, s+sz, bufsz-sz-1)) < 1)
+ break;
+ }
+ if(n < 0 || sz < 1){
+ if(n == 0)
+ werrstr("empty");
+ free(s);
+ return nil;
+ }
+ s[sz] = 0;
+
+ return s;
+}
+
+static int
+openkbdhid(void)
+{
+ char path[32], *s, *k, *e;
+ int f;
+
+ if(kbdhidfd >= 0)
+ return kbdhidfd;
+
+ if((f = open("/dev/usb/ctl", OREAD)) >= 0){
+ if((s = readall(f)) != nil &&
+ (k = strstr(s, "MNT 'Reform Keyboard'")) != nil &&
+ (e = strchr(k+22, ' ')) != nil){
+ *e = 0;
+ snprint(path, sizeof(path), "/dev/hidU%sctl", k+22);
+ if((kbdhidfd = open(path, OWRITE)) >= 0)
+ write(kbdhidfd, "rawon", 5);
+ }
+ free(s);
+ close(f);
+ }
+
+ return kbdhidfd;
+}
+
+static int
+setlight(int k, int p)
{
u32int v;
@@ -96,17 +154,37 @@ setlight(int p)
if(p > 100)
p = 100;
- v = Pwmsrcclk / rd(pwm2, PWMSAR);
- wr(pwm2, PWMPR, (Pwmsrcclk/(v*p/100))-2);
+ if(k == Lcd){
+ v = Pwmsrcclk / rd(pwm2, PWMSAR);
+ wr(pwm2, PWMPR, (Pwmsrcclk/(v*p/100))-2);
+ return 0;
+ }else if(k == Kbd && (kbdhidfd = openkbdhid()) >= 0){
+ v = Kbdlightmax*p/100;
+ if(fprint(kbdhidfd, "LITE%c", '0'+v) > 0){
+ kbdlight = v;
+ return 0;
+ }
+ close(kbdhidfd);
+ kbdhidfd = -1;
+ kbdlight = 0;
+ }
+
+ return -1;
}
static int
-getlight(void)
+getlight(int k)
{
u32int m, v;
- m = Pwmsrcclk / rd(pwm2, PWMSAR);
- v = Pwmsrcclk / (rd(pwm2, PWMPR)+2);
+ SET(m, v);
+ if(k == Lcd){
+ m = Pwmsrcclk / rd(pwm2, PWMSAR);
+ v = Pwmsrcclk / (rd(pwm2, PWMPR)+2);
+ }else if(k == Kbd){
+ m = Kbdlightmax;
+ v = kbdlight;
+ }
return v*100/m;
}
@@ -194,16 +272,16 @@ lpccall(char cmd, u8int arg, void *ret)
wr(spi2, SPIx_TXDATA, cmd);
wr(spi2, SPIx_TXDATA, arg);
wr(spi2, SPIx_CONREG, con | CON_XCH);
- sleep(60);
-
- /* LPC buffers 3 bytes without responding, ignore (including garbage) */
- while(rd(spi2, SPIx_STATREG) & STAT_RR)
- rd(spi2, SPIx_RXDATA);
/*
- * at this point LPC hopefully is blocked waiting for
- * chip select to go active
+ * LPC buffers 3 bytes without responding, but spends some time
+ * to prepare the response. 50ms should be safe, add a bit more
+ * to be sure LPC is blocked waiting for the chip select to go
+ * active again.
*/
+ sleep(60);
+ while(rd(spi2, SPIx_STATREG) & STAT_RR)
+ rd(spi2, SPIx_RXDATA);
/* expecting 8 bytes, start the exchange */
for(i = 0; i < 8; i++)
@@ -315,7 +393,7 @@ fsread(Req *r)
if(r->ifcall.offset == 0){
aux = r->fid->file->aux;
if(aux == (void*)Light){
- snprint(msg, sizeof(msg), "lcd %d\n", getlight());
+ snprint(msg, sizeof(msg), "lcd %d\nkbd %d\n", getlight(Lcd), getlight(Kbd));
}else if(aux == (void*)Temp){
if((c = getcputemp()) < 0){
responderror(r);
@@ -339,7 +417,7 @@ static void
fswrite(Req *r)
{
char msg[256], *f[4];
- int nf, v, p;
+ int nf, v, p, k;
void *aux;
snprint(msg, sizeof(msg), "%.*s",
@@ -352,16 +430,25 @@ Bad:
respond(r, "invalid ctl message");
return;
}
- if(strcmp(f[0], "lcd") == 0){
- v = atoi(f[1]);
- if(*f[1] == '+' || *f[1] == '-')
- v += getlight();
- setlight(v);
+ if(strcmp(f[0], "lcd") == 0)
+ k = Lcd;
+ else if(strcmp(f[0], "kbd") == 0)
+ k = Kbd;
+ else
+ goto Bad;
+ v = atoi(f[1]);
+ if(*f[1] == '+' || *f[1] == '-')
+ v += getlight(k);
+ if(setlight(k, v) != 0){
+ responderror(r);
+ return;
}
}else if(aux == (void*)Pmctl){
p = -1;
- if(nf == 2 && strcmp(f[0], "power") == 0 && strcmp(f[1], "off") == 0)
- p = Psomoff;
+ if(nf >= 2 && strcmp(f[0], "power") == 0){
+ if(nf == 2 && strcmp(f[1], "off") == 0)
+ p = Psomoff;
+ }
if(p < 0)
goto Bad;
lpccall('p', p, msg);
@@ -427,7 +514,7 @@ threadmain(int argc, char **argv)
tmuinit();
lpcreq = reqqueuecreate();
fs.tree = alloctree(uid, uid, DMDIR|0555, nil);
- createfile(fs.tree->root, "battery", uid, 0444,(void*)Battery);
+ createfile(fs.tree->root, "battery", uid, 0444, (void*)Battery);
createfile(fs.tree->root, "cputemp", uid, 0444, (void*)Temp);
createfile(fs.tree->root, "light", uid, 0666, (void*)Light);
createfile(fs.tree->root, "pmctl", uid, 0666, (void*)Pmctl);