#include "dat.h"#include "fns.h"#include "error.h"#include "version.h"#include "mp.h"#include "libsec.h"#include "keyboard.h"#include "listenerqueue.h"#include <stdio.h> extern int cflag;int exdebug;extern int keepbroken; enum{ Qdir, Qevents, Qcons, Qconsctl, Qdrivers, Qhostowner, Qhoststdin, Qhoststdout, Qhoststderr, Qjit, Qkeyboard, Qkprint, Qmemory, Qmsec, Qnotquiterandom, Qnull, Qrandom, Qscancode, Qsysctl, Qsysname, Qtime, Quser, Qbattery, Qtype, Qbrightness,}; Dirtab contab[] ={ ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555, "brightness", {Qbrightness}, 0, 0666, "type", {Qtype}, 0, 0666, "battery", {Qbattery}, 0, 0666, "events", {Qevents}, 0, 0666, "cons", {Qcons}, 0, 0666, "consctl", {Qconsctl}, 0, 0222, "drivers", {Qdrivers}, 0, 0444, "hostowner", {Qhostowner}, 0, 0644, "hoststdin", {Qhoststdin}, 0, 0444, "hoststdout", {Qhoststdout}, 0, 0222, "hoststderr", {Qhoststderr}, 0, 0222, "jit", {Qjit}, 0, 0666, "keyboard", {Qkeyboard}, 0, 0666, "kprint", {Qkprint}, 0, 0444, "memory", {Qmemory}, 0, 0444, "msec", {Qmsec}, NUMSIZE, 0444, "notquiterandom", {Qnotquiterandom}, 0, 0444, "null", {Qnull}, 0, 0666, "random", {Qrandom}, 0, 0444, "scancode", {Qscancode}, 0, 0444, "sysctl", {Qsysctl}, 0, 0644, "sysname", {Qsysname}, 0, 0644, "time", {Qtime}, 0, 0644, "user", {Quser}, 0, 0644,}; Queue* gkscanq; /* Graphics keyboard raw scancodes */char* gkscanid; /* name of raw scan format (if defined) */Queue* gkbdq; /* Graphics keyboard unprocessed input */Queue* kbdq; /* Console window unprocessed keyboard input */Queue* lineq; /* processed console input */Queue* eventq; /* Events imported from Linux host devices */Queue* batteryq; /* Battery level */Queue* typeq; /* Device type */Queue* brightnessq; /* Screen brightness control */ int eventfds[MAX_EVENTFDS]; char *ossysname; static struct{ RWlock l; Queue* q;} kprintq; vlong timeoffset; extern int dflag; static int sysconwrite(void*, ulong);extern char** rebootargv; static struct{ QLock q; QLock gq; /* separate lock for the graphical input */ int raw; /* true if we shouldn't process input */ Ref ctl; /* number of opens to the control file */ Ref ptr; /* number of opens to the ptr file */ int scan; /* true if reading raw scancodes */ int x; /* index into line */ char line[1024]; /* current input line */ Rune c; int count;} kbd; struct listener *event_listeners = NULL; #ifndef __linux__void eventslave(void *a) { fprintf(stderr, "Events device currently only supported under Linux hosts\n");}#endif voidkbdslave(void *a){ char b; USED(a); for(;;) { b = readkbd(); if(kbd.raw == 0){ switch(b){ case 0x15: write(1, "^U\n", 3); break; default: write(1, &b, 1); break; } } qproduce(kbdq, &b, 1); } /* pexit("kbdslave", 0); */ /* not reached */} voidgkbdputc(Queue *q, int ch){ int n; Rune r; static uchar kc[5*UTFmax]; static int nk, collecting = 0; char buf[UTFmax]; r = ch; if(r == Latin) { collecting = 1; nk = 0; return; } if(collecting) { int c; nk += runetochar((char*)&kc[nk], &r); c = latin1(kc, nk); if(c < -1) /* need more keystrokes */ return; collecting = 0; if(c == -1) { /* invalid sequence */ qproduce(q, kc, nk); return; } r = (Rune)c; } n = runetochar(buf, &r); if(n == 0) return; /* if(!isdbgkey(r)) */ qproduce(q, buf, n);} voidconsinit(void){ kbdq = qopen(512, 0, nil, nil); if(kbdq == 0) panic("no memory"); lineq = qopen(2*1024, 0, nil, nil); if(lineq == 0) panic("no memory"); gkbdq = qopen(512, 0, nil, nil); if(gkbdq == 0) panic("no memory"); batteryq = qopen(512, 0, nil, nil); if(batteryq == 0) panic("no memory"); typeq = qopen(512, 0, nil, nil); if(typeq == 0) panic("no memory"); brightnessq = qopen(512, 0, nil, nil); if(brightnessq == 0) panic("no memory"); randominit();} /* * return true if current user is eve */intiseve(void){ return strcmp(eve, up->env->user) == 0;} static Chan*consattach(char *spec){ static int kp; if(kp == 0 && !dflag) { int i; kp = 1; if(eventfiles != NULL) { for(i = 0; eventfiles[i] != NULL; i++) { int *event_num = malloc(sizeof(int)); char buf[40]; snprintf(buf, 40, "events%d", i); if(i >= MAX_EVENTFDS) { // temporary fprintf(stderr, "too many event devices\n"); break; } eventfds[i] = open(eventfiles[i], O_RDONLY); if(eventfds[i] == -1) { perror("could not open event device"); } *event_num = i; kproc(buf, eventslave, event_num, 0); } } kproc("kbd", kbdslave, 0, 0); } return devattach('c', spec);} static Walkqid*conswalk(Chan *c, Chan *nc, char **name, int nname){ return devwalk(c, nc, name, nname, contab, nelem(contab), devgen);} static intconsstat(Chan *c, uchar *db, int n){ return devstat(c, db, n, contab, nelem(contab), devgen);} static Chan*consopen(Chan *c, int omode){ c = devopen(c, omode, contab, nelem(contab), devgen); switch((ulong)c->qid.path) { case Qconsctl: incref(&kbd.ctl); break; case Qscancode: qlock(&kbd.gq); if(gkscanq != nil || gkscanid == nil) { qunlock(&kbd.q); c->flag &= ~COPEN; if(gkscanq) error(Einuse); else error("not supported"); } gkscanq = qopen(256, 0, nil, nil); qunlock(&kbd.gq); break; case Qkprint: wlock(&kprintq.l); if(waserror()){ wunlock(&kprintq.l); c->flag &= ~COPEN; nexterror(); } if(kprintq.q != nil) error(Einuse); kprintq.q = qopen(32*1024, Qcoalesce, nil, nil); if(kprintq.q == nil) error(Enomem); qnoblock(kprintq.q, 1); poperror(); wunlock(&kprintq.l); c->iounit = qiomaxatomic; break; case Qevents: c->aux = qopen(512, 0, nil, nil); add_listener(&event_listeners, c->aux); break; } return c;} static voidconsclose(Chan *c){ if((c->flag & COPEN) == 0) return; switch((ulong)c->qid.path) { case Qconsctl: /* last close of control file turns off raw */ if(decref(&kbd.ctl) == 0) kbd.raw = 0; break; case Qscancode: qlock(&kbd.gq); if(gkscanq) { qfree(gkscanq); gkscanq = nil; } qunlock(&kbd.gq); break; case Qkprint: wlock(&kprintq.l); qfree(kprintq.q); kprintq.q = nil; wunlock(&kprintq.l); break; case Qevents: del_listener(&event_listeners, c->aux); qfree(c->aux); c->aux = NULL; break; }} static longconsread(Chan *c, void *va, long n, vlong offset){ int send; char *p, buf[64], ch; FILE * battery; FILE * brightness; int size; if(c->qid.type & QTDIR) return devdirread(c, va, n, contab, nelem(contab), devgen); switch((ulong)c->qid.path) { default: error(Egreg); case Qsysctl: return readstr(offset, va, n, VERSION); case Qsysname: if(ossysname == nil) return 0; return readstr(offset, va, n, ossysname); case Qrandom: return randomread(va, n); case Qnotquiterandom: genrandom(va, n); return n; case Qhostowner: return readstr(offset, va, n, eve); case Qhoststdin: return read(0, va, n); /* should be pread */ case Quser: return readstr(offset, va, n, up->env->user); case Qjit: snprint(buf, sizeof(buf), "%d", cflag); return readstr(offset, va, n, buf); case Qtime: snprint(buf, sizeof(buf), "%.lld", timeoffset + osusectime()); return readstr(offset, va, n, buf); case Qdrivers: return devtabread(c, va, n, offset); case Qmemory: return poolread(va, n, offset); case Qnull: return 0; case Qmsec: return readnum(offset, va, n, osmillisec(), NUMSIZE); case Qcons: qlock(&kbd.q); if(waserror()){ qunlock(&kbd.q); nexterror(); } if(dflag) error(Enonexist); while(!qcanread(lineq)) { if(qread(kbdq, &ch, 1) == 0) continue; send = 0; if(ch == 0){ /* flush output on rawoff -> rawon */ if(kbd.x > 0) send = !qcanread(kbdq); }else if(kbd.raw){ kbd.line[kbd.x++] = ch; send = !qcanread(kbdq); }else{ switch(ch){ case '\b': if(kbd.x) kbd.x--; break; case 0x15: kbd.x = 0; break; case 0x04: send = 1; break; case '\n': send = 1; default: kbd.line[kbd.x++] = ch; break; } } if(send || kbd.x == sizeof kbd.line){ qwrite(lineq, kbd.line, kbd.x); kbd.x = 0; } } n = qread(lineq, va, n); qunlock(&kbd.q); poperror(); return n; case Qscancode: if(offset == 0) return readstr(0, va, n, gkscanid); return qread(gkscanq, va, n); case Qkeyboard: return qread(gkbdq, va, n); case Qevents: return qread(c->aux, va, n); case Qkprint: rlock(&kprintq.l); if(waserror()){ runlock(&kprintq.l); nexterror(); } n = qread(kprintq.q, va, n); poperror(); runlock(&kprintq.l); return n; case Qbattery: if(type == 's') battery = fopen("/sys/class/power_supply/battery/capacity", "r"); else if(type == 'c') battery = fopen("/sys/class/power_supply/max17042-0/capacity", "r"); else battery = fopen("/sys/class/power_supply/battery/capacity", "r"); size = fread(buf, 1, sizeof(buf), battery); fclose(battery); buf[size - 1] = '\0'; return readstr(offset, va, n, buf); case Qtype: if(type == 's') strncpy(buf, "nexus s", sizeof(buf)); else if(type == 'c') strncpy(buf, "nook color", sizeof(buf)); else if(type == 'e') strncpy(buf, "emulator", sizeof(buf)); else strncpy(buf, "nexus s", sizeof(buf)); return readstr(offset, va, n, buf); case Qbrightness: if(type == 'c') brightness = fopen("/sys/devices/platform/omap_pwm_led/leds/lcd-backlight/brightness", "r"); else if(type == 'e') return; else brightness = fopen("/sys/class/backlight/s5p_bl/brightness", "r");Lines 1–500 of 757. Load more
#include "dat.h" #include "fns.h" #include "error.h" #include "version.h" #include "mp.h" #include "libsec.h" #include "keyboard.h" #include "listenerqueue.h" #include <stdio.h> extern int cflag; int exdebug; extern int keepbroken; enum { Qdir, Qevents, Qcons, Qconsctl, Qdrivers, Qhostowner, Qhoststdin, Qhoststdout, Qhoststderr, Qjit, Qkeyboard, Qkprint, Qmemory, Qmsec, Qnotquiterandom, Qnull, Qrandom, Qscancode, Qsysctl, Qsysname, Qtime, Quser, Qbattery, Qtype, Qbrightness, }; Dirtab contab[] = { ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555, "brightness", {Qbrightness}, 0, 0666, "type", {Qtype}, 0, 0666, "battery", {Qbattery}, 0, 0666, "events", {Qevents}, 0, 0666, "cons", {Qcons}, 0, 0666, "consctl", {Qconsctl}, 0, 0222, "drivers", {Qdrivers}, 0, 0444, "hostowner", {Qhostowner}, 0, 0644, "hoststdin", {Qhoststdin}, 0, 0444, "hoststdout", {Qhoststdout}, 0, 0222, "hoststderr", {Qhoststderr}, 0, 0222, "jit", {Qjit}, 0, 0666, "keyboard", {Qkeyboard}, 0, 0666, "kprint", {Qkprint}, 0, 0444, "memory", {Qmemory}, 0, 0444, "msec", {Qmsec}, NUMSIZE, 0444, "notquiterandom", {Qnotquiterandom}, 0, 0444, "null", {Qnull}, 0, 0666, "random", {Qrandom}, 0, 0444, "scancode", {Qscancode}, 0, 0444, "sysctl", {Qsysctl}, 0, 0644, "sysname", {Qsysname}, 0, 0644, "time", {Qtime}, 0, 0644, "user", {Quser}, 0, 0644, }; Queue* gkscanq; /* Graphics keyboard raw scancodes */ char* gkscanid; /* name of raw scan format (if defined) */ Queue* gkbdq; /* Graphics keyboard unprocessed input */ Queue* kbdq; /* Console window unprocessed keyboard input */ Queue* lineq; /* processed console input */ Queue* eventq; /* Events imported from Linux host devices */ Queue* batteryq; /* Battery level */ Queue* typeq; /* Device type */ Queue* brightnessq; /* Screen brightness control */ int eventfds[MAX_EVENTFDS]; char *ossysname; static struct { RWlock l; Queue* q; } kprintq; vlong timeoffset; extern int dflag; static int sysconwrite(void*, ulong); extern char** rebootargv; static struct { QLock q; QLock gq; /* separate lock for the graphical input */ int raw; /* true if we shouldn't process input */ Ref ctl; /* number of opens to the control file */ Ref ptr; /* number of opens to the ptr file */ int scan; /* true if reading raw scancodes */ int x; /* index into line */ char line[1024]; /* current input line */ Rune c; int count; } kbd; struct listener *event_listeners = NULL; #ifndef __linux__ void eventslave(void *a) { fprintf(stderr, "Events device currently only supported under Linux hosts\n"); } #endif void kbdslave(void *a) { char b; USED(a); for(;;) { b = readkbd(); if(kbd.raw == 0){ switch(b){ case 0x15: write(1, "^U\n", 3); break; default: write(1, &b, 1); break; } } qproduce(kbdq, &b, 1); } /* pexit("kbdslave", 0); */ /* not reached */ } void gkbdputc(Queue *q, int ch) { int n; Rune r; static uchar kc[5*UTFmax]; static int nk, collecting = 0; char buf[UTFmax]; r = ch; if(r == Latin) { collecting = 1; nk = 0; return; } if(collecting) { int c; nk += runetochar((char*)&kc[nk], &r); c = latin1(kc, nk); if(c < -1) /* need more keystrokes */ return; collecting = 0; if(c == -1) { /* invalid sequence */ qproduce(q, kc, nk); return; } r = (Rune)c; } n = runetochar(buf, &r); if(n == 0) return; /* if(!isdbgkey(r)) */ qproduce(q, buf, n); } void consinit(void) { kbdq = qopen(512, 0, nil, nil); if(kbdq == 0) panic("no memory"); lineq = qopen(2*1024, 0, nil, nil); if(lineq == 0) panic("no memory"); gkbdq = qopen(512, 0, nil, nil); if(gkbdq == 0) panic("no memory"); batteryq = qopen(512, 0, nil, nil); if(batteryq == 0) panic("no memory"); typeq = qopen(512, 0, nil, nil); if(typeq == 0) panic("no memory"); brightnessq = qopen(512, 0, nil, nil); if(brightnessq == 0) panic("no memory"); randominit(); } /* * return true if current user is eve */ int iseve(void) { return strcmp(eve, up->env->user) == 0; } static Chan* consattach(char *spec) { static int kp; if(kp == 0 && !dflag) { int i; kp = 1; if(eventfiles != NULL) { for(i = 0; eventfiles[i] != NULL; i++) { int *event_num = malloc(sizeof(int)); char buf[40]; snprintf(buf, 40, "events%d", i); if(i >= MAX_EVENTFDS) { // temporary fprintf(stderr, "too many event devices\n"); break; } eventfds[i] = open(eventfiles[i], O_RDONLY); if(eventfds[i] == -1) { perror("could not open event device"); } *event_num = i; kproc(buf, eventslave, event_num, 0); } } kproc("kbd", kbdslave, 0, 0); } return devattach('c', spec); } static Walkqid* conswalk(Chan *c, Chan *nc, char **name, int nname) { return devwalk(c, nc, name, nname, contab, nelem(contab), devgen); } static int consstat(Chan *c, uchar *db, int n) { return devstat(c, db, n, contab, nelem(contab), devgen); } static Chan* consopen(Chan *c, int omode) { c = devopen(c, omode, contab, nelem(contab), devgen); switch((ulong)c->qid.path) { case Qconsctl: incref(&kbd.ctl); break; case Qscancode: qlock(&kbd.gq); if(gkscanq != nil || gkscanid == nil) { qunlock(&kbd.q); c->flag &= ~COPEN; if(gkscanq) error(Einuse); else error("not supported"); } gkscanq = qopen(256, 0, nil, nil); qunlock(&kbd.gq); break; case Qkprint: wlock(&kprintq.l); if(waserror()){ wunlock(&kprintq.l); c->flag &= ~COPEN; nexterror(); } if(kprintq.q != nil) error(Einuse); kprintq.q = qopen(32*1024, Qcoalesce, nil, nil); if(kprintq.q == nil) error(Enomem); qnoblock(kprintq.q, 1); poperror(); wunlock(&kprintq.l); c->iounit = qiomaxatomic; break; case Qevents: c->aux = qopen(512, 0, nil, nil); add_listener(&event_listeners, c->aux); break; } return c; } static void consclose(Chan *c) { if((c->flag & COPEN) == 0) return; switch((ulong)c->qid.path) { case Qconsctl: /* last close of control file turns off raw */ if(decref(&kbd.ctl) == 0) kbd.raw = 0; break; case Qscancode: qlock(&kbd.gq); if(gkscanq) { qfree(gkscanq); gkscanq = nil; } qunlock(&kbd.gq); break; case Qkprint: wlock(&kprintq.l); qfree(kprintq.q); kprintq.q = nil; wunlock(&kprintq.l); break; case Qevents: del_listener(&event_listeners, c->aux); qfree(c->aux); c->aux = NULL; break; } } static long consread(Chan *c, void *va, long n, vlong offset) { int send; char *p, buf[64], ch; FILE * battery; FILE * brightness; int size; if(c->qid.type & QTDIR) return devdirread(c, va, n, contab, nelem(contab), devgen); switch((ulong)c->qid.path) { default: error(Egreg); case Qsysctl: return readstr(offset, va, n, VERSION); case Qsysname: if(ossysname == nil) return 0; return readstr(offset, va, n, ossysname); case Qrandom: return randomread(va, n); case Qnotquiterandom: genrandom(va, n); return n; case Qhostowner: return readstr(offset, va, n, eve); case Qhoststdin: return read(0, va, n); /* should be pread */ case Quser: return readstr(offset, va, n, up->env->user); case Qjit: snprint(buf, sizeof(buf), "%d", cflag); return readstr(offset, va, n, buf); case Qtime: snprint(buf, sizeof(buf), "%.lld", timeoffset + osusectime()); return readstr(offset, va, n, buf); case Qdrivers: return devtabread(c, va, n, offset); case Qmemory: return poolread(va, n, offset); case Qnull: return 0; case Qmsec: return readnum(offset, va, n, osmillisec(), NUMSIZE); case Qcons: qlock(&kbd.q); if(waserror()){ qunlock(&kbd.q); nexterror(); } if(dflag) error(Enonexist); while(!qcanread(lineq)) { if(qread(kbdq, &ch, 1) == 0) continue; send = 0; if(ch == 0){ /* flush output on rawoff -> rawon */ if(kbd.x > 0) send = !qcanread(kbdq); }else if(kbd.raw){ kbd.line[kbd.x++] = ch; send = !qcanread(kbdq); }else{ switch(ch){ case '\b': if(kbd.x) kbd.x--; break; case 0x15: kbd.x = 0; break; case 0x04: send = 1; break; case '\n': send = 1; default: kbd.line[kbd.x++] = ch; break; } } if(send || kbd.x == sizeof kbd.line){ qwrite(lineq, kbd.line, kbd.x); kbd.x = 0; } } n = qread(lineq, va, n); qunlock(&kbd.q); poperror(); return n; case Qscancode: if(offset == 0) return readstr(0, va, n, gkscanid); return qread(gkscanq, va, n); case Qkeyboard: return qread(gkbdq, va, n); case Qevents: return qread(c->aux, va, n); case Qkprint: rlock(&kprintq.l); if(waserror()){ runlock(&kprintq.l); nexterror(); } n = qread(kprintq.q, va, n); poperror(); runlock(&kprintq.l); return n; case Qbattery: if(type == 's') battery = fopen("/sys/class/power_supply/battery/capacity", "r"); else if(type == 'c') battery = fopen("/sys/class/power_supply/max17042-0/capacity", "r"); else battery = fopen("/sys/class/power_supply/battery/capacity", "r"); size = fread(buf, 1, sizeof(buf), battery); fclose(battery); buf[size - 1] = '\0'; return readstr(offset, va, n, buf); case Qtype: if(type == 's') strncpy(buf, "nexus s", sizeof(buf)); else if(type == 'c') strncpy(buf, "nook color", sizeof(buf)); else if(type == 'e') strncpy(buf, "emulator", sizeof(buf)); else strncpy(buf, "nexus s", sizeof(buf)); return readstr(offset, va, n, buf); case Qbrightness: if(type == 'c') brightness = fopen("/sys/devices/platform/omap_pwm_led/leds/lcd-backlight/brightness", "r"); else if(type == 'e') return; else brightness = fopen("/sys/class/backlight/s5p_bl/brightness", "r");