summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@centraldogma>2011-05-09 10:04:36 +0000
committercinap_lenrek <cinap_lenrek@centraldogma>2011-05-09 10:04:36 +0000
commitd763dcc91b6dbafab7b663b7c5043f4bded8abe1 (patch)
treea2b7d52078c2619a286f30eab4df541af42b1139
parent489d71b9ba9dc62fa8ada0bcad5d6bbe8cbb375b (diff)
parent51c9ad341376cf62c223264d1cf5eaddb48ab29f (diff)
downloadplan9front-d763dcc91b6dbafab7b663b7c5043f4bded8abe1.tar.xz
merge
-rw-r--r--sys/src/9/pc/screen.h1
-rw-r--r--sys/src/9/port/devmouse.c48
-rw-r--r--sys/src/9/port/error.h2
-rw-r--r--sys/src/cmd/aux/mkfile2
-rw-r--r--sys/src/cmd/aux/tablet.c32
-rw-r--r--sys/src/cmd/aux/wacom.c352
6 files changed, 433 insertions, 4 deletions
diff --git a/sys/src/9/pc/screen.h b/sys/src/9/pc/screen.h
index a9d1b66a4..87771f60b 100644
--- a/sys/src/9/pc/screen.h
+++ b/sys/src/9/pc/screen.h
@@ -7,6 +7,7 @@ struct Cursorinfo {
/* devmouse.c */
extern void mousetrack(int, int, int, int);
+extern void absmousetrack(int, int, int, int);
extern Point mousexy(void);
extern void mouseaccelerate(int);
diff --git a/sys/src/9/port/devmouse.c b/sys/src/9/port/devmouse.c
index 5b620720c..24c66ec45 100644
--- a/sys/src/9/port/devmouse.c
+++ b/sys/src/9/port/devmouse.c
@@ -454,16 +454,19 @@ mousewrite(Chan *c, void *va, long n, vlong)
buf[n] = 0;
p = 0;
pt.x = strtol(buf+1, &p, 0);
- if(p == 0)
+ if(*p == 0)
error(Eshort);
pt.y = strtol(p, &p, 0);
- if(p == 0)
+ if(*p == 0)
error(Eshort);
b = strtol(p, &p, 0);
msec = strtol(p, &p, 0);
if(msec == 0)
msec = TK2MS(MACHP(0)->ticks);
- mousetrack(pt.x, pt.y, b, msec);
+ if(buf[0] == 'A')
+ absmousetrack(pt.x, pt.y, b, msec);
+ else
+ mousetrack(pt.x, pt.y, b, msec);
return n;
case Qmouse:
@@ -620,6 +623,45 @@ mousetrack(int dx, int dy, int b, int msec)
drawactive(1);
}
+void
+absmousetrack(int x, int y, int b, int msec)
+{
+ int lastb;
+
+ if(gscreen==nil)
+ return;
+
+ if(x < gscreen->clipr.min.x)
+ x = gscreen->clipr.min.x;
+ if(x >= gscreen->clipr.max.x)
+ x = gscreen->clipr.max.x;
+ if(y < gscreen->clipr.min.y)
+ y = gscreen->clipr.min.y;
+ if(y >= gscreen->clipr.max.y)
+ y = gscreen->clipr.max.y;
+
+ lastb = mouse.buttons;
+ mouse.xy = Pt(x, y);
+ mouse.buttons = b|kbdbuttons;
+ mouse.redraw = 1;
+ mouse.counter++;
+ mouse.msec = msec;
+
+ /*
+ * if the queue fills, we discard the entire queue and don't
+ * queue any more events until a reader polls the mouse.
+ */
+ if(!mouse.qfull && lastb != b) { /* add to ring */
+ mouse.queue[mouse.wi] = mouse.Mousestate;
+ if(++mouse.wi == nelem(mouse.queue))
+ mouse.wi = 0;
+ if(mouse.wi == mouse.ri)
+ mouse.qfull = 1;
+ }
+ wakeup(&mouse.r);
+ drawactive(1);
+}
+
/*
* microsoft 3 button, 7 bit bytes
*
diff --git a/sys/src/9/port/error.h b/sys/src/9/port/error.h
index e9ff15023..e9a4367dc 100644
--- a/sys/src/9/port/error.h
+++ b/sys/src/9/port/error.h
@@ -41,7 +41,7 @@ extern char Enoswap[]; /* swap space full */
extern char Esoverlap[]; /* segments overlap */
extern char Emouseset[]; /* mouse type already set */
extern char Eshort[]; /* i/o count too small */
-extern char Egreg[]; /* jmk added reentrancy for threads */
+extern char Egreg[]; /* the front fell off */
extern char Ebadspec[]; /* bad attach specifier */
extern char Enoreg[]; /* process has no saved registers */
extern char Enoattach[]; /* mount/attach disallowed */
diff --git a/sys/src/cmd/aux/mkfile b/sys/src/cmd/aux/mkfile
index d6284a1d9..b640e3664 100644
--- a/sys/src/cmd/aux/mkfile
+++ b/sys/src/cmd/aux/mkfile
@@ -34,11 +34,13 @@ TARG=\
searchfs\
statusbar\
stub\
+ tablet\
timesync\
trampoline\
unbflz\
usage\
write\
+ wacom\
zerotrunc\
BIN=/$objtype/bin/aux
diff --git a/sys/src/cmd/aux/tablet.c b/sys/src/cmd/aux/tablet.c
new file mode 100644
index 000000000..797f60b47
--- /dev/null
+++ b/sys/src/cmd/aux/tablet.c
@@ -0,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
diff --git a/sys/src/cmd/aux/wacom.c b/sys/src/cmd/aux/wacom.c
new file mode 100644
index 000000000..5b076873c
--- /dev/null
+++ b/sys/src/cmd/aux/wacom.c
@@ -0,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