diff options
author | cinap_lenrek <cinap_lenrek@centraldogma> | 2011-05-09 10:04:36 +0000 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@centraldogma> | 2011-05-09 10:04:36 +0000 |
commit | d763dcc91b6dbafab7b663b7c5043f4bded8abe1 (patch) | |
tree | a2b7d52078c2619a286f30eab4df541af42b1139 | |
parent | 489d71b9ba9dc62fa8ada0bcad5d6bbe8cbb375b (diff) | |
parent | 51c9ad341376cf62c223264d1cf5eaddb48ab29f (diff) | |
download | plan9front-d763dcc91b6dbafab7b663b7c5043f4bded8abe1.tar.xz |
merge
-rw-r--r-- | sys/src/9/pc/screen.h | 1 | ||||
-rw-r--r-- | sys/src/9/port/devmouse.c | 48 | ||||
-rw-r--r-- | sys/src/9/port/error.h | 2 | ||||
-rw-r--r-- | sys/src/cmd/aux/mkfile | 2 | ||||
-rw-r--r-- | sys/src/cmd/aux/tablet.c | 32 | ||||
-rw-r--r-- | sys/src/cmd/aux/wacom.c | 352 |
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 |