757 lines · 13.7 KB · C
RawDownload
#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.