git: 9front

Download patch

ref: 83211181e3887787e48b45af3065de269f2e70c0
parent: ac808982a6bdd8dfefffe829094c35330809cea2
author: aiju <aiju@phicode.de>
date: Mon May 9 04:59:11 EDT 2011

added aux/wacom and aux/tablet

--- a/sys/src/cmd/aux/mkfile
+++ b/sys/src/cmd/aux/mkfile
@@ -34,11 +34,13 @@
 	searchfs\
 	statusbar\
 	stub\
+	tablet\
 	timesync\
 	trampoline\
 	unbflz\
 	usage\
 	write\
+	wacom\
 	zerotrunc\
 
 BIN=/$objtype/bin/aux
--- /dev/null
+++ b/sys/src/cmd/aux/tablet.c
@@ -1,0 +1,32 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+Biobuf *tablet;
+int mouseout;
+
+int
+main()
+{
+	mouseout = open("/dev/mousein", OWRITE);
+	if(mouseout < 0) sysfatal("%r");
+	tablet = Bopen("/dev/tablet", OREAD);
+	if(tablet == nil) sysfatal("%r");
+	while(1) {
+		char *line, *p;
+		int x, y, b;
+		
+		line = Brdline(tablet, 10);
+		if(!line) sysfatal("%r");
+		p = line;
+		if(*p++ != 'm') continue;
+		if(*p++ != ' ') continue;
+		x = strtol(p, &p, 10);
+		if(*p++ != ' ') continue;
+		y = strtol(p, &p, 10);
+		if(*p++ != ' ') continue;
+		b = strtol(p, &p, 10);
+		if(*p++ != ' ') continue;
+		fprint(mouseout, "A %d %d %d\n", x, y, b);
+	}
+}
\ No newline at end of file
--- /dev/null
+++ b/sys/src/cmd/aux/wacom.c
@@ -1,0 +1,352 @@
+#include <u.h>
+#include <libc.h>
+#include <fcall.h>
+#include <thread.h>
+#include <9p.h>
+
+typedef struct Tablet Tablet;
+typedef struct Message Message;
+typedef struct QItem QItem;
+typedef struct Queue Queue;
+typedef struct Reader Reader;
+
+
+enum { MAX = 1000 };
+
+struct Tablet {
+	int ser;
+	int xmax, ymax, pmax, version;
+	int sx, sy;
+};
+
+struct Message {
+	Ref;
+	int b, x, y, p;
+	char *msg;
+};
+
+Tablet*
+newtablet(char* dev)
+{
+	int serctl;
+	char* ctl;
+	Tablet* t;
+
+	ctl = smprint("%sctl", dev);
+	t = calloc(sizeof(Tablet), 1);
+	t->ser = open(dev, ORDWR);
+	if(t->ser < 0) {
+		free(t);
+		return 0;
+	}
+	serctl = open(ctl, OWRITE);
+	free(ctl);
+	if(serctl < 0) {
+		free(t);
+		close(t->ser);
+		return 0;
+	}
+	if(fprint(serctl, "b19200\n") < 0) {
+		free(t);
+		close(t->ser);
+		close(serctl);
+		return 0;
+	}
+	close(serctl);
+	return t;
+}
+
+int
+query(Tablet* t)
+{
+	uchar buf[11];
+
+	if(write(t->ser, "&0*", 3) < 3) return -1;
+	do {
+		if(read(t->ser, buf, 1) < 1) return -1;
+	} while(buf[0] != 0xC0);
+	if(readn(t->ser, buf+1, 10) < 10) return -1;
+	t->xmax = (buf[1] << 9) | (buf[2] << 2) | ((buf[6] >> 5) & 3);
+	t->ymax = (buf[3] << 9) | (buf[4] << 2) | ((buf[6] >> 3) & 3);
+	t->pmax = buf[5] | (buf[6] & 7);
+	t->version = (buf[9] << 7) | buf[10];
+	if(write(t->ser, "1", 1) < 1) return -1;
+	return 0;
+}
+
+int
+screensize(Tablet* t)
+{
+	int fd;
+	char buf[189], buf2[12], *p;
+	
+	fd = open("/dev/draw/new", OREAD);
+	if(fd < 0) return -1;
+	read(fd, buf, 189);
+	memcpy(buf2, buf + 72, 11);
+	buf2[11] = 0;
+	for(p = buf2; *p == ' '; p++);
+	t->sx = atoi(p);
+	memcpy(buf2, buf + 84, 11);
+	for(p = buf2; *p == ' '; p++);
+	t->sy = atoi(p);
+	if(t->sx == 0 || t->sy == 0) {
+		close(fd);
+		werrstr("invalid resolution read from /dev/draw/new");
+		return -1;
+	}
+	
+	close(fd);
+	return 0;
+}
+
+int
+findheader(Tablet* t)
+{
+	uchar c;
+	
+	do {
+		if(read(t->ser, &c, 1) < 1) return -1;
+	} while((c & 0x80) == 0);
+	return c;
+}
+
+Message*
+readpacket(Tablet* t)
+{
+	uchar buf[9];
+	int head;
+	Message *m;
+
+	head = findheader(t);
+	if(head < 0) return 0;
+	if(readn(t->ser, buf, 9) < 9) return 0;
+	
+	m = calloc(sizeof(Message), 1);
+	incref(m);
+	
+	m->b = head & 7;
+	m->x = (buf[0] << 9) | (buf[1] << 2) | ((buf[5] >> 5) & 3);
+	m->y = (buf[2] << 9) | (buf[3] << 2) | ((buf[5] >> 3) & 3);
+	m->p = ((buf[5] & 7) << 7) | buf[4];
+	
+	m->p *= MAX;
+	m->p /= t->pmax;
+	m->x *= t->sx;
+	m->x /= t->xmax;
+	m->y *= t->sy;
+	m->y /= t->ymax;
+	
+	m->msg = smprint("m %d %d %d %d\n", m->x, m->y, m->b, m->p);
+	return m;
+}
+
+void
+msgdecref(Message *m)
+{
+	if(decref(m) == 0) {
+		free(m->msg);
+		free(m);
+	}
+}
+
+struct QItem {
+	Message *m;
+	QItem *next;
+};
+
+struct Queue {
+	Lock;
+	QItem *first, *last;
+};
+
+void
+qput(Queue* q, Message* m)
+{
+	QItem *i;
+	
+	lock(q);
+	i = malloc(sizeof(QItem));
+	i->m = m;
+	i->next = 0;
+	if(q->last == nil) {
+		q->last = q->first = i;
+	} else {
+		q->last->next = i;
+		q->last = i;
+	}
+	unlock(q);
+}
+
+Message*
+qget(Queue* q)
+{
+	QItem *i;
+	Message *m;
+	
+	if(q->first == nil) return nil;
+	lock(q);
+	i = q->first;
+	if(q->first == q->last) {
+		q->first = q->last = nil;
+	} else {
+		q->first = i->next;
+	}
+	m = i->m;
+	free(i);
+	unlock(q);
+	return m;
+}
+
+void
+freequeue(Queue *q)
+{
+	Message *m;
+	
+	while(m = qget(q))
+		msgdecref(m);
+	free(q);
+}
+
+struct Reader {
+	Queue *e;
+	Reader *prev, *next;
+	Req* req;
+};
+
+Lock readers;
+Reader *rfirst, *rlast;
+
+void
+reply(Req *req, Message *m)
+{
+	req->ofcall.count = strlen(m->msg);
+	if(req->ofcall.count > req->ifcall.count)
+		req->ofcall.count = req->ifcall.count;
+	memmove(req->ofcall.data, m->msg, req->ofcall.count);
+	respond(req, nil);
+}
+
+void
+sendout(Message *m)
+{
+	Reader *r;
+	
+	lock(&readers);
+	for(r = rfirst; r; r = r->next) {
+		if(r->req) {
+			reply(r->req, m);
+			r->req = nil;
+		} else {
+			incref(m);
+			qput(r->e, m);
+		}
+	}
+	unlock(&readers);
+}
+
+void
+tabletopen(Req *req)
+{
+	Reader *r;
+	
+	lock(&readers);
+	r = calloc(sizeof(Reader), 1);
+	r->e = calloc(sizeof(Queue), 1);
+	if(rlast) rlast->next = r;
+	r->prev = rlast;
+	rlast = r;
+	if(rfirst == nil) rfirst = r;
+	unlock(&readers);
+	req->fid->aux = r;
+	respond(req, nil);
+}
+
+void
+tabletdestroyfid(Fid *fid)
+{
+	Reader *r;
+
+	r = fid->aux;
+	if(r == nil) return;
+	lock(&readers);
+	if(r->prev) r->prev->next = r->next;
+	if(r->next) r->next->prev = r->prev;
+	if(r == rfirst) rfirst = r->next;
+	if(r == rlast) rlast = r->prev;
+	freequeue(r->e);
+	free(r);
+	unlock(&readers);
+}
+
+void
+tabletdestroyreq(Req *req)
+{
+	Reader *r;
+	
+	if(req->fid == nil) return;
+	r = req->fid->aux;
+	if(r == nil) return;
+	if(req == r->req) {
+		r->req = nil;
+	}
+}
+
+void
+tabletread(Req* req)
+{
+	Reader *r;
+	Message *m;
+	
+	r = req->fid->aux;
+	if(m = qget(r->e)) {
+		reply(req, m);
+		msgdecref(m);
+	} else {
+		if(r->req) {
+			respond(req, "no concurrent reads, please");
+		} else {
+			r->req = req;
+		}
+	}
+}
+
+Srv tabletsrv = {
+	.open = tabletopen,	
+	.read = tabletread,
+	.destroyfid = tabletdestroyfid,
+	.destroyreq = tabletdestroyreq,
+};
+
+File *tfile;
+
+void
+main()
+{
+	Tablet *t;
+	Message *m;
+	int fd[2];
+	
+	pipe(fd);
+	tabletsrv.infd = tabletsrv.outfd = fd[0];
+	tabletsrv.srvfd = fd[1];
+	tabletsrv.tree = alloctree(getuser(), getuser(), 0555, 0);
+	tfile = createfile(tabletsrv.tree->root, "tablet", getuser(), 0400, 0);
+	if(rfork(RFPROC | RFMEM | RFNOWAIT | RFNOTEG) > 0) exits(nil);
+	if(rfork(RFPROC | RFMEM) == 0) {
+		srv(&tabletsrv);
+		exits(nil);
+	}
+	mount(fd[1], -1, "/dev", MAFTER, "");
+	
+	t = newtablet("/dev/eia2");
+	if(!t) sysfatal("%r");
+	if(screensize(t) < 0) sysfatal("%r");
+	if(query(t) < 0) sysfatal("%r");
+	while(1) {
+		m = readpacket(t);
+		if(!m) sysfatal("%r");
+		sendout(m);
+		msgdecref(m);
+	}
+}
\ No newline at end of file
--