diff options
author | aiju <aiju@phicode.de> | 2011-05-09 08:59:11 +0000 |
---|---|---|
committer | aiju <aiju@phicode.de> | 2011-05-09 08:59:11 +0000 |
commit | 908a525ef5ed769f0621df6df4184b1349920d94 (patch) | |
tree | c817f51b4cecf6133835641674ea3f9615b1e2cf /sys/src/cmd/aux/wacom.c | |
parent | ed3a999828fa841c803993ed4ad8ab545b876aeb (diff) |
added aux/wacom and aux/tablet
Diffstat (limited to 'sys/src/cmd/aux/wacom.c')
-rw-r--r-- | sys/src/cmd/aux/wacom.c | 352 |
1 files changed, 352 insertions, 0 deletions
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 |