Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/bitsy/devµc.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


## diffname bitsy/devµc.c 2000/1021
## diff -e /dev/null /n/emeliedump/2000/1021/sys/src/9/bitsy/devµc.c
0a
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"io.h"
#include	"../port/error.h"

enum{
	Qbacklight = 1,
	Qbattery,
	Qbuttons,
	Qled,
	Qversion,

	/* command types */
	BLversion=	0,
	BLbuttons=	2,	/* button events */
	BLtouch=	3,	/* read touch screen events */
	BLled=		8,	/* turn LED on/off */
	BLbattery=	9,	/* read battery status */
	BLbacklight=	0xd,	/* backlight control */

	SOF=	0x2,		/* start of frame */

	/* key definitions */
	Up=		0xFF0E,
	Left=		0xFF11,
	Right=		0xFF12,
	Down=		0x8000,
};

Dirtab µcdir[]={
	"backlight",	{ Qbacklight, 0 },	0,	0664,
	"battery",	{ Qbattery, 0 },	0,	0664,
	"buttons",	{ Qbuttons, 0 },	0,	0664,
	"led",		{ Qled, 0 },		0,	0664,
	"version",	{ Qversion, 0 },	0,	0664,
};

static struct µcontroller
{
	/* message being rcvd */
	int	state;
	uchar	buf[16+4];
	uchar	n;

	/* for messages that require acks */
	QLock;
	Rendez	r;

	/* battery */
	uchar	acstatus;
	uchar	voltage;
	ushort	batstatus;
	uchar	batchem;

	/* version string */
	char	version[16+2];
} ctlr;

/* button map */
Rune bmap[4] = 
{
	Up, Right, Down, Left
};

int
µcputc(Queue*, int ch)
{
	int i, len, b, up;
	uchar cksum;
	uchar *p;

	if(ctlr.n > sizeof(ctlr.buf))
		panic("µcputc");

	ctlr.buf[ctlr.n++] = (uchar)ch;
		
	for(;;){
		/* message hasn't started yet */
		if(ctlr.buf[0] != SOF){
			ctlr.n = 0;
			break;
		}
	
		/* if it's too short, wait */
		len = ctlr.buf[1] & 0xf;
		if(ctlr.n < 3 || ctlr.n < len+3)
			break;
	
		/* check the sum */
		ctlr.buf[0] = ~SOF;
		cksum = 0;
		for(i = 1; i < len+2; i++)
			cksum += ctlr.buf[i];
	
		/* ignore bad checksums */
		if(ctlr.buf[len+2] != cksum){
			p = memchr(ctlr.buf+1, SOF, ctlr.n);
			if(p == nil){
				ctlr.n = 0;
				break;
			} else {
				ctlr.n -= p-ctlr.buf;
				memmove(ctlr.buf, p, ctlr.n);
				continue;
			}
		}
	
		/* parse resulting message */
		p = ctlr.buf+2;
		switch(ctlr.buf[1] >> 4){
		case BLversion:
			strncpy(ctlr.version, (char*)p, len);
			ctlr.version[len] = '0';
			strcat(ctlr.version, "\n");
			wakeup(&ctlr.r);
			break;
		case BLbuttons:
			if(len < 1)
				break;
			b = p[0] & 0x7f;
			up = p[0] & 80;
	
			if(b > 5){
				/* rocker panel acts like arrow keys */
				if(b < 10)
					kbdputc(kbdq, bmap[b-6]);
			} else {
				/* the rest like mouse buttons */
				if(--b == 0)
					b = 5;
				penbutton(up, 1<<b);
			}
			break;
		case BLtouch:
			if(len == 4)
				pentrackxy((p[0]<<8)|p[1], (p[2]<<8)|p[3]);
			else
				pentrackxy(-1, -1);
			break;
		case BLled:
			wakeup(&ctlr.r);
			break;
		case BLbattery:
			if(len >= 5){
				ctlr.acstatus = p[0];
				ctlr.voltage = (p[3]<<8)|p[2];
				ctlr.batstatus = p[4];
				ctlr.batchem = p[1];
			}
			wakeup(&ctlr.r);
			break;
		case BLbacklight:
			wakeup(&ctlr.r);
			break;
		}
	
		/* remove the message */
		ctlr.n -= len+3;
		memmove(ctlr.buf, &ctlr.buf[len+3], ctlr.n);
	}
	return 0;
}

static void
_sendmsg(uchar id, uchar *data, int len)
{
	uchar buf[20];
	uchar cksum;
	uchar c;
	uchar *p = buf;
	int i;

	/* create the message */
	if(sizeof(buf) < len+4)
		return;
	cksum = (id<<4) | len;
	*p++ = SOF;
	*p++ = cksum;
	for(i = 0; i < len; i++){
		c = data[i];
		cksum += c;
		*p++ = c;
	}
	*p++ = cksum;

	/* send the message - there should be a more generic way to do this */
	serialµcputs(buf, p-buf);
}

static void
sendmsgwithack(uchar id, uchar *data, int len)
{
	if(waserror()){
		qunlock(&ctlr);
		nexterror();
	}
	qlock(&ctlr);
	_sendmsg(id, data, len);
	tsleep(&ctlr.r, return0, 0, 100);
	qunlock(&ctlr);
	poperror();
}

static void
sendmsg(uchar id, uchar *data, int len)
{
	if(waserror()){
		qunlock(&ctlr);
		nexterror();
	}
	qlock(&ctlr);
	_sendmsg(id, data, len);
	qunlock(&ctlr);
	poperror();
}

void
µcinit(void)
{
}

static Chan*
µcattach(char* spec)
{
	return devattach('r', spec);
}

static int	 
µcwalk(Chan* c, char* name)
{
	return devwalk(c, name, µcdir, nelem(µcdir), devgen);
}

static void	 
µcstat(Chan* c, char* dp)
{
	devstat(c, dp, µcdir, nelem(µcdir), devgen);
}

static Chan*
µcopen(Chan* c, int omode)
{
	omode = openmode(omode);
	if(strcmp(up->user, eve)!=0)
		error(Eperm);
	return devopen(c, omode, µcdir, nelem(µcdir), devgen);
}

static void	 
µcclose(Chan*)
{
}

char*
acstatus(int x)
{
	if(x)
		return "attached";
	else
		return "detached";
}

char*
batstatus(int x)
{
	switch(x){
	case 1:		return "high";
	case 2:		return "low";
	case 4:		return "critical";
	case 8:		return "charging";
	case 0x80:	return "none";
	}
	return "ok";
}

static long	 
µcread(Chan* c, void* a, long n, vlong off)
{
	char buf[64];

	if(c->qid.path & CHDIR)
		return devdirread(c, a, n, µcdir, nelem(µcdir), devgen);

	switch(c->qid.path){
	case Qbattery:
		sendmsgwithack(BLbattery, nil, 0);		/* send a battery request */
		sprint(buf, "voltage: %d\nac: %s\nstatus: %s\n", ctlr.voltage,
			acstatus(ctlr.acstatus),
			batstatus(ctlr.batstatus));
		return readstr(off, a, n, buf);
	case Qversion:
		sendmsgwithack(BLversion, nil, 0);		/* send a battery request */
		return readstr(off, a, n, ctlr.version);
	}
	error(Ebadarg);
	return 0;
}

#define PUTBCD(n,o) bcdclock[o] = (n % 10) | (((n / 10) % 10)<<4)

static long	 
µcwrite(Chan* c, void* a, long n, vlong off)
{
	Cmdbuf *cmd;
	uchar data[16];
	int i;

	if(off != 0)
		error(Ebadarg);

	cmd = parsecmd(a, n);
	if(cmd->nf > 15)
		error(Ebadarg);
	for(i = 0; i < cmd->nf; i++)
		data[i] = atoi(cmd->f[i]);

	switch(c->qid.path){
	case Qled:
		sendmsgwithack(BLled, data, cmd->nf);
		break;
	case Qbacklight:
		sendmsgwithack(BLbacklight, data, cmd->nf);
		break;
	default:
		error(Ebadarg);
	}
	return n;
}

Dev µcdevtab = {
	'r',
	"µc",

	devreset,
	µcinit,
	µcattach,
	devclone,
	µcwalk,
	µcstat,
	µcopen,
	devcreate,
	µcclose,
	µcread,
	devbread,
	µcwrite,
	devbwrite,
	devremove,
	devwstat,
};
.
## diffname bitsy/devµc.c 2000/1022
## diff -e /n/emeliedump/2000/1021/sys/src/9/bitsy/devµc.c /n/emeliedump/2000/1022/sys/src/9/bitsy/devµc.c
192a
/* the tsleep takes care of lost acks */
.
98,110d
96a
		if(ctlr.buf[len+2] != cksum)
			continue;
.
93c
		ctlr.buf[0] = ~SOF;	/* make sure we process this msg exactly once */
.
87c
		/* whole msg? */
.
83,84c
			p = memchr(ctlr.buf, SOF, ctlr.n);
			if(p == nil){
				ctlr.n = 0;
				break;
			} else {
				ctlr.n -= p-ctlr.buf;
				memmove(ctlr.buf, p, ctlr.n);
			}
.
81c
		/* message hasn't started yet? */
.
## diffname bitsy/devµc.c 2000/1024
## diff -e /n/emeliedump/2000/1022/sys/src/9/bitsy/devµc.c /n/emeliedump/2000/1024/sys/src/9/bitsy/devµc.c
121c
			if(b > 5) {
.
## diffname bitsy/devµc.c 2000/1028
## diff -e /n/emeliedump/2000/1024/sys/src/9/bitsy/devµc.c /n/emeliedump/2000/1028/sys/src/9/bitsy/devµc.c
119,120c
			up = p[0] & 0x80;

.
## diffname bitsy/devµc.c 2000/1031
## diff -e /n/emeliedump/2000/1028/sys/src/9/bitsy/devµc.c /n/emeliedump/2000/1031/sys/src/9/bitsy/devµc.c
316a
	case Qkbdin:
		if(n >= sizeof(str))
			n = sizeof(str)-1;
		memmove(str, a, n);
		str[n] = 0;
		for(i = 0; i < n; i += j){
          		j = chartorune(&r, &str[i]);
			kbdputc(nil, r);
		}
		break;
.
305c
	char str[64];
	int i, j;
	Rune r;
.
136a
			}
.
133,135c
			if(len == 4) {
				if (samseq++ > 10)
					pentrackxy((p[0]<<8)|p[1], (p[2]<<8)|p[3]);
			} else {
				samseq = 0;
.
73a
	static int samseq;
.
36a
	"kbdin",	{ Qkbdin, 0 },		0,	0664,
.
12a
	Qkbdin,
.
## diffname bitsy/devµc.c 2000/1101
## diff -e /n/emeliedump/2000/1031/sys/src/9/bitsy/devµc.c /n/emeliedump/2000/1101/sys/src/9/bitsy/devµc.c
325,334d
315,316c
	if(c->qid.path == Qkbdin){
		if(n >= sizeof(str))
			n = sizeof(str)-1;
		memmove(str, a, n);
		str[n] = 0;
		for(i = 0; i < n; i += j){
			j = chartorune(&r, &str[i]);
			kbdcr2nl(nil, r);
		}
		return n;
	}
.
## diffname bitsy/devµc.c 2000/1102
## diff -e /n/emeliedump/2000/1101/sys/src/9/bitsy/devµc.c /n/emeliedump/2000/1102/sys/src/9/bitsy/devµc.c
158a
		default:
			print("unknown µc message: %ux");
			for(i = 0; i < len; i++)
				print(" %ux", p[i]);
			print("\n");
			break;
.
## diffname bitsy/devµc.c 2000/1103
## diff -e /n/emeliedump/2000/1102/sys/src/9/bitsy/devµc.c /n/emeliedump/2000/1103/sys/src/9/bitsy/devµc.c
344a
		break;
	case Qcruft:
		lcdtweak(cmd);
.
313c
µcwrite(Chan* c, void* a, long n, vlong)
.
160c
			print("unknown µc message: %ux", ctlr.buf[1] >> 4);
.
37a
	"cruft",	{ Qcruft, 0 },		0,	0664,
.
12a
	Qcruft,
.
## diffname bitsy/devµc.c 2000/1104
## diff -e /n/emeliedump/2000/1103/sys/src/9/bitsy/devµc.c /n/emeliedump/2000/1104/sys/src/9/bitsy/devµc.c
140c
					pentrackxy((p[2]<<8)|p[3], (p[0]<<8)|p[1]);
.
## diffname bitsy/devµc.c 2000/1106
## diff -e /n/emeliedump/2000/1104/sys/src/9/bitsy/devµc.c /n/emeliedump/2000/1106/sys/src/9/bitsy/devµc.c
349c
//		lcdtweak(cmd);
.
## diffname bitsy/devµc.c 2000/1207
## diff -e /n/emeliedump/2000/1106/sys/src/9/bitsy/devµc.c /n/emeliedump/2000/1207/sys/src/9/bitsy/devµc.c
144a
			touching = 0;
.
137a
			if(touching)
				break;
			touching = 1;
.
135a
			buttoning = 0;
.
122a
			buttoning = 1;
.
121c
			if(len < 1 || buttoning)
.
78a
	static int touching;		/* guard against something we call going spllo() */
	static int buttoning;		/* guard against something we call going spllo() */
.
69c
	Kup, Kright, Kdown, Kleft
.
28,32c
/* from /sys/include/keyboard.h */
enum {
	KF=	0xF000,	/* Rune: beginning of private Unicode space */
	/* KF|1, KF|2, ..., KF|0xC is F1, F2, ..., F12 */
	Khome=	KF|0x0D,
	Kup=	KF|0x0E,
	Kpgup=	KF|0x0F,
	Kprint=	KF|0x10,
	Kleft=	KF|0x11,
	Kright=	KF|0x12,
	Kdown=	0x80,
	Kview=	0x80,
	Kpgdown=	KF|0x13,
	Kins=	KF|0x14,
	Kend=	'\r',	/* [sic] */

	Kalt=		KF|0x15,
	Kshift=	KF|0x16,
	Kctl=		KF|0x17,
.
26a
};
.
## diffname bitsy/devµc.c 2000/1212
## diff -e /n/emeliedump/2000/1207/sys/src/9/bitsy/devµc.c /n/emeliedump/2000/1212/sys/src/9/bitsy/devµc.c
146c
				if(b < 10 && !up)
.
84c
	Kup, Kright, Kleft, Kdown
.
## diffname bitsy/devµc.c 2001/0529
## diff -e /n/emeliedump/2000/1212/sys/src/9/bitsy/devµc.c /n/emeliedump/2001/0529/sys/src/9/bitsy/devµc.c
387d
364c
	switch((ulong)c->qid.path){
.
320c
	switch((ulong)c->qid.path){
.
317c
	if(c->qid.path == Qdir)
.
273c
	return devstat(c, dp, n, µcdir, nelem(µcdir), devgen);
.
270,271c
static int	 
µcstat(Chan *c, uchar *dp, int n)
.
267c
	return devwalk(c, nc, name, nname, µcdir, nelem(µcdir), devgen);
.
264,265c
static Walkqid*
µcwalk(Chan *c, Chan *nc, char **name, int nname)
.
63c
	int		state;
.
52,57c
	"battery",		{ Qbattery, 0 },		0,	0664,
	"buttons",		{ Qbuttons, 0 },		0,	0664,
	"cruft",		{ Qcruft, 0 },		0,	0664,
	"kbdin",		{ Qkbdin, 0 },		0,	0664,
	"led",		{ Qled, 0 },			0,	0664,
	"version",		{ Qversion, 0 },		0,	0664,
.
50a
	".",			{ Qdir, 0, QTDIR },	0,	DMDIR|0755,
.
10c
	Qdir,
	Qbacklight,
.
## diffname bitsy/devµc.c 2001/0605
## diff -e /n/emeliedump/2001/0529/sys/src/9/bitsy/devµc.c /n/emeliedump/2001/0605/sys/src/9/bitsy/devµc.c
22c
	BLtouch=		3,	/* read touch screen events */
.
## diffname bitsy/devµc.c 2001/0606
## diff -e /n/emeliedump/2001/0605/sys/src/9/bitsy/devµc.c /n/emeliedump/2001/0606/sys/src/9/bitsy/devµc.c
103c

.
96,97c
	static int touching;	/* guard against something we call going spllo() */
	static int buttoning;	/* guard against something we call going spllo() */
.
## diffname bitsy/devµc.c 2001/0618
## diff -e /n/emeliedump/2001/0606/sys/src/9/bitsy/devµc.c /n/emeliedump/2001/0618/sys/src/9/bitsy/devµc.c
381a
void 
µcpower(int on)
{
	uchar data[16];
	if (on == 0)
		return;
	/* maybe dangerous, not holding the lock */
	data[0]= 2;
	data[1]= 1;
	data[2]= 0x80;
	_sendmsg(0xd, data, 3);
	wakeup(&ctlr.r);
}

.
## diffname bitsy/devµc.c 2001/0621
## diff -e /n/emeliedump/2001/0618/sys/src/9/bitsy/devµc.c /n/emeliedump/2001/0621/sys/src/9/bitsy/devµc.c
357a
	}
	if(c->qid.path == Qsuspend){
		if(!iseve())
			error(Eperm);
		if(strncmp(a, "suspend", 7) != 0)
			error(Ebadarg);
		powerflag = 1;
		wakeup(&powerr);
.
346a
	extern Rendez	powerr;
	extern ulong	powerflag;
.
59a
	"suspend",	{ Qsuspend, 0 },	0,	0222,
.
17a
	Qsuspend,
.
## diffname bitsy/devµc.c 2001/1130
## diff -e /n/emeliedump/2001/0621/sys/src/9/bitsy/devµc.c /n/emeliedump/2001/1130/sys/src/9/bitsy/devµc.c
165,166c
				if (samseq++ > 10){
					if (landscape)
						pentrackxy((p[0]<<8)|p[1], (p[2]<<8)|p[3]);
					else
						pentrackxy((p[2]<<8)|p[3], (p[0]<<8)|p[1]);
				}
.
90a
extern int landscape;

.
## diffname bitsy/devµc.c 2002/0109
## diff -e /n/emeliedump/2001/1130/sys/src/9/bitsy/devµc.c /n/emeliedump/2002/0109/sys/src/9/bitsy/devµc.c
419a
	devshutdown,
.
## diffname bitsy/devµc.c 2002/0119
## diff -e /n/emeliedump/2002/0109/sys/src/9/bitsy/devµc.c /n/emeliedump/2002/0119/sys/src/9/bitsy/devµc.c
153c
					kbdputc(kbdq, bmap[landscape][b-6]);
.
88c
	{Kup, Kright, Kleft, Kdown},	/* portrait mode */
	{Kright, Kdown, Kup, Kleft},	/* landscape mode */
.
86c
Rune bmap[2][4] = 
.
## diffname bitsy/devµc.c 2002/0604
## diff -e /n/emeliedump/2002/0119/sys/src/9/bitsy/devµc.c /n/emeliedump/2002/0604/sys/src/9/bitsy/devµc.c
375,376c
		deepsleep();
		return n;
.
373c
		if(strncmp(a, "suspend", 7) == 0)
			*resumeaddr = (ulong)power_resume;
		else if(strncmp(a, "halt", 4) == 0)
			*resumeaddr = 0;
		else
.
370c
	if(c->qid.path == Qpower){
.
356,357c
	extern ulong resumeaddr[];
	extern void power_resume(void);
.
61c
	"power",		{ Qpower, 0 },		0,	0600,
.
18c
	Qpower,
.
## diffname bitsy/devµc.c 2002/1112
## diff -e /n/emeliedump/2002/0604/sys/src/9/bitsy/devµc.c /n/emeliedump/2002/1112/sys/src/9/bitsy/devµc.c
412,414c
	if (lightdata[0] == 0){
		data[0]= 2;
		data[1]= 1;
		data[2]= 0;
	} else
		memmove(data, lightdata, 16);
.
393a
		memmove(lightdata, data, 16);
.
377c
		else if(strncmp(a, "wakeup", 6) == 0){
			cmd = parsecmd(a, n);
			if (cmd->nf != 2)
				error(Ebadarg);
			l = strtoul(cmd->f[1], 0, 0);
			rtcalarm(l);
			return n;
		} else
.
354a
	ulong l;
.
347a
static uchar lightdata[16];

.
59c
	"led",			{ Qled, 0 },			0,	0664,
.
54c
	"backlight",		{ Qbacklight, 0 },	0,	0664,
.

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].