diff options
author | Sigrid Solveig Haflínudóttir <sigrid@ftrv.se> | 2022-10-06 23:21:16 +0000 |
---|---|---|
committer | Sigrid Solveig Haflínudóttir <sigrid@ftrv.se> | 2022-10-06 23:21:16 +0000 |
commit | e1949eedf6893c76472360189b6539bc0d573378 (patch) | |
tree | 98b1f453ca3defbf48c164d271260283edf4559c /sys/src/cmd/reform | |
parent | a945c6f5b1f69b9bf7a6a3a5404b14b9fe6c5e5c (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.c | 135 |
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); |