8 typedef struct Batstat Batstat;
9 typedef struct Battery Battery;
10 typedef struct Dfile Dfile;
11 typedef struct Tbl Tbl;
12 typedef struct Thermal Thermal;
59 Tblsz = 4+4+1+1+6+8+4+4+4,
67 static void rootread(Req*);
68 static void ctlread(Req*);
69 static void ctlwrite(Req*);
70 static void batteryread(Req*);
71 static void tmpread(Req*);
73 int ec, mem, iofd[5], nbats, ntherms, rp, wp;
74 char *units[] = {"mW", "mA"};
77 Channel *creq, *cevent;
81 {{Qroot,0,QTDIR}, "/", DMDIR|0555, rootread, nil},
82 {{Qbattery}, "battery", 0444, batteryread, nil},
83 {{Qcputemp}, "cputemp", 0444, tmpread, nil},
84 {{Qctl}, "ctl", 0666, ctlread, ctlwrite},
88 enumbat(void *dot, void *)
94 if(nbats >= nelem(bats))
97 if((p = amlwalk(dot, "^_STA")) == nil)
99 if(amleval(p, "", &r) < 0 || (amlint(r)&3) != 3)
101 if(amleval(dot, "", &r) < 0) /* _BIF */
103 if(r == nil || amltag(r) != 'p' || amllen(r) < 7)
108 if((n = amlint(rr[0])) >= nelem(units) || n < 0)
112 b->capacity = amlint(rr[1]);
113 if((int)b->capacity < 0) /* even though _STA tells it's there */
115 b->fullcharge = amlint(rr[2]);
116 b->voltage = amlint(rr[4]);
117 b->capacitywarn = amlint(rr[5]);
118 b->capacitylow = amlint(rr[6]);
119 b->bst = amlwalk(dot, "^_BST");
129 enumtmp(void *dot, void *)
137 if(ntherms < nelem(therms) && amleval(dot, "", &r) >= 0 && amllen(r) > 0 && (rr = amlval(r)) != nil){
138 for(i = 0; i < amllen(r); i++){
139 snprint(s, sizeof(s), "%N", amlval(rr[i]));
140 if((n = strlen(s)) > 0){
141 for(n--; n > 3; n--){
142 if(s[n-2] == 'C' && s[n-1] == 'P' && s[n] == 'U' && s[n+1] >= '0' && s[n+1] <= '9'){
143 cpus |= 1<<atoi(&s[n+1]);
151 if(cpus != 0 && (dot = amlwalk(dot, "^_TMP")) != nil){
152 therms[ntherms].cpus = cpus;
153 therms[ntherms].tmp = dot;
161 batstat(Battery *b, Batstat *s)
165 if(amleval(b->bst, "", &r) < 0)
167 if(r == nil || amltag(r) != 'p' || amllen(r) < 4)
170 s->state = amlint(rr[0]);
171 s->rate = amlint(rr[1]);
172 s->capacity = amlint(rr[2]);
173 s->voltage = amlint(rr[3]);
180 char buf[nelem(bats)*120], *ep, *p, *state;
187 ep = buf + sizeof(buf);
188 for(n = 0; n < nbats; n++){
200 else if(st.state & 1)
201 state = "discharging";
202 else if(st.state & 2)
207 s = ((st.state & 2) ? bats[n].fullcharge - st.capacity : st.capacity) * 3600 / st.rate;
213 x = bats[n].fullcharge > 0 ? st.capacity * 100 / bats[n].fullcharge : -1;
214 p += snprint(p, ep-p, "%d %s %d %d %d %d %d %s %d %d %02d:%02d:%02d %s\n",
216 bats[n].unit, st.capacity, b->fullcharge, b->capacity, b->capacitywarn, b->capacitylow,
217 "mV", st.voltage, b->voltage,
230 char buf[32], *ep, *p;
235 ep = buf + sizeof(buf);
237 for(n = 0; n < ntherms; n++){
239 if(amleval(therms[n].tmp, "", &er) >= 0)
241 p += snprint(p, ep-p, "%d\n", (t - 2732)/10);
267 sysfatal("out of memory allocating %lud", n);
269 setmalloctag(v, getcallerpc(&n));
284 setmalloctag(t, getcallerpc(&s));
289 fillstat(uvlong path, Dir *d, int doalloc)
293 for(i=0; i<nelem(dfile); i++)
294 if(path == dfile[i].qid.path)
296 if(i == nelem(dfile))
299 memset(d, 0, sizeof *d);
300 d->uid = doalloc ? estrdup("acpi") : "acpi";
301 d->gid = doalloc ? estrdup("acpi") : "acpi";
303 d->name = doalloc ? estrdup(dfile[i].name) : dfile[i].name;
304 d->mode = dfile[i].mode;
305 d->atime = d->mtime = time(0);
306 d->qid = dfile[i].qid;
311 fswalk1(Fid *fid, char *name, Qid *qid)
315 if(strcmp(name, "..") == 0){
321 for(i = 1; i < nelem(dfile); i++){ /* i=1: 0 is root dir */
322 if(strcmp(dfile[i].name, name) == 0){
328 return "file does not exist";
334 switch((ulong)r->fid->qid.path){
336 r->fid->aux = (void*)0;
342 if(r->ifcall.mode == OREAD){
349 if((r->ifcall.mode & ~(OTRUNC|OREAD|OWRITE|ORDWR)) == 0){
355 respond(r, "permission denied");
362 fillstat(r->fid->qid.path, &r->d, 1);
369 dfile[r->fid->qid.path].read(r);
375 dfile[r->fid->qid.path].write(r);
386 offset = r->ifcall.offset == 0 ? 0 : (uvlong)r->fid->aux;
388 ep = r->ofcall.data + r->ifcall.count;
390 if(offset == 0) /* skip root */
392 for(; p+2 < ep; p += n){
393 if(fillstat(offset, &d, 0) < 0)
395 n = convD2M(&d, (uchar*)p, ep-p);
400 r->fid->aux = (void*)offset;
401 r->ofcall.count = p - r->ofcall.data;
408 if(r->ifcall.aname && r->ifcall.aname[0]){
409 respond(r, "invalid attach specifier");
412 r->fid->qid = dfile[0].qid;
413 r->ofcall.qid = dfile[0].qid;
420 fprint(2, "usage: aux/acpi [-Di] [-d /dev] [-m /mnt/acpi] [-s service]\n");
426 return p[3]<<24 | p[2]<<16 | p[1]<<8 | p[0];
439 threadmain(int argc, char **argv)
458 mtpt = EARGF(usage());
461 srv = EARGF(usage());
465 if((ec = open("/dev/ec", ORDWR)) < 0)
466 if((ec = open("#P/ec", ORDWR)) < 0)
468 if((mem = open("/dev/acpimem", ORDWR)) < 0)
469 mem = open("#P/acpimem", ORDWR);
470 if((iofd[1] = open("/dev/iob", ORDWR)) < 0)
471 if((iofd[1] = open("#P/iob", ORDWR)) < 0)
473 if((iofd[2] = open("/dev/iow", ORDWR)) < 0)
474 if((iofd[2] = open("#P/iow", ORDWR)) < 0)
476 if((iofd[4] = open("/dev/iol", ORDWR)) < 0)
477 if((iofd[4] = open("#P/iol", ORDWR)) < 0)
479 if((fd = open("/dev/acpitbls", OREAD)) < 0)
480 if((fd = open("#P/acpitbls", OREAD)) < 0)
485 t = malloc(sizeof(*t));
486 if((n = readn(fd, t, Tblsz)) <= 0)
494 t = realloc(t, sizeof(*t) + l);
495 if(readn(fd, t->data, l) != l)
497 if(memcmp("DSDT", t->sig, 4) == 0){
498 amlintmask = (~0ULL) >> (t->rev <= 1)*32;
500 }else if(memcmp("SSDT", t->sig, 4) == 0)
505 amlenum(amlroot, "_BIF", enumbat, nil);
506 amlenum(amlroot, "_PSL", enumtmp, nil);
509 threadpostmountsrv(&fs, srv, mtpt, MREPL);
515 threadexitsall("acpi");
519 readec(Amlio *, void *data, int len, int off)
521 return pread(ec, data, len, off);
525 writeec(Amlio *, void *data, int len, int off)
527 return pwrite(ec, data, len, off);
531 readio(Amlio *io, void *data, int len, int port)
533 assert(len == 1 || len == 2 || len == 4);
534 return pread(iofd[len], data, len, io->off+port);
538 writeio(Amlio *io, void *data, int len, int port)
540 assert(len == 1 || len == 2 || len == 4);
541 return pwrite(iofd[len], data, len, io->off+port);
545 memread(Amlio *io, void *data, int len, int addr)
547 return pread(mem, data, len, io->off+addr);
551 memwrite(Amlio *io, void *data, int len, int addr)
553 return pwrite(mem, data, len, io->off+addr);
557 dummy(Amlio *, void *, int len, int)
575 io->read = mem >= 0 ? memread : dummy;
576 io->write = mem >= 0 ? memwrite : dummy;