From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=-0.1 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU autolearn=ham autolearn_force=no version=3.4.4 Received: (qmail 16689 invoked from network); 19 Apr 2021 16:58:34 -0000 Received: from 1ess.inri.net (216.126.196.35) by inbox.vuxu.org with ESMTPUTF8; 19 Apr 2021 16:58:34 -0000 Received: from out1-smtp.messagingengine.com ([66.111.4.25]) by 1ess; Mon Apr 19 12:49:35 -0400 2021 Received: from compute6.internal (compute6.nyi.internal [10.202.2.46]) by mailout.nyi.internal (Postfix) with ESMTP id 413D95C0219; Mon, 19 Apr 2021 12:49:32 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute6.internal (MEProxy); Mon, 19 Apr 2021 12:49:32 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=biobuf.link; h= message-id:content-type:content-transfer-encoding:to:subject :date:from:in-reply-to:mime-version:content-type :content-transfer-encoding; s=fm2; bh=JsWqePrIW9nfsTHgyjNx2+55mO j2aFzzcAbVI4XpIsc=; b=N1ztNsxM8QsQzXoROZizDA1oLlgbbCRgINVbCy+Nrx /1G269PaVKyGvP8VRytuGB4L3HtcUPSWoMJ/56xzh7/ho3Fptu6zG8Hrd/EzaQHu gPCXq8KWd13ZX43k/K78gQ7k0Tw5aByiF/Y9cMvfDeTFFI0sJk5+uawvfNdmWHWN RfrmeGjZVGuteaqmacPohMd3lcNDDBegOxwvY7nOgUTItWGpeKIAWxGQ2T4mqq4T 16mBDeqAd3cJI1c3kueoB0lFJedP8aZ7DIf8kCZugbSwDtFx5hDEHUnUH5mkRbWi l0sqjr7RI7Q6818lJ91xM1y1OOgHmSCBZ1IM5Ro+mg0Q== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=content-transfer-encoding :content-transfer-encoding:content-type:content-type:date:from :in-reply-to:message-id:mime-version:subject:to:x-me-proxy :x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm2; bh=JsWqeP rIW9nfsTHgyjNx2+55mOj2aFzzcAbVI4XpIsc=; b=rywzmDDPNZsCrRo+9Tn9Q+ ECWGtRH/yrXyYDtCPkMLQiV1/w80Ng1YzKSidyzu8lo8/rQ0Xr0HWUg2fn3wnqbA Gb4Lje3q4CjXNGSjKzbf+U/TwBPTtzxYuFHfuomryX1/yKk+NTYCNXM6/R2rDIOb QWp2CKPiPfVHr6wGwZXg2MeutndkZ0ATjxRNmkEZxohJY6P3hOJXEpP59CJhzkPz dUdwJQfYlso36m7U4BcN4z5Xm0swDKhBxVqciKsByiRJ0mIngVOlJinBON0wAjCz Ss2gURpMWmtdWp8o+rmXcXR2dkI7DvLiQDQEc96tj1PdrrK7ZSjW8q6vntN8u6sQ == X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrvddtgedguddtjecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfgh necuuegrihhlohhuthemuceftddtnecuogfthfevqddqjfgurhdqufhushhpvggtthdqlh hoficuldehmdenucfjughrpefktgfgvffufffhjgggtgfgsehtjeejtddttddvnecuhfhr ohhmpehjrghmvghsuchprghlmhgvrhcuoehjrghmvghssegsihhosghufhdrlhhinhhkqe enucggtffrrghtthgvrhhnpeetleetleegfedulefgudeivddugfeitedtleehleffgeeg jeehieejtdetvdekgfenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrih hlfhhrohhmpehjrghmvghssegsihhosghufhdrlhhinhhk X-ME-Proxy: Message-ID: <1D28830ADA4C552A88C8ED5D3D2025F2@biobuf.link> Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 8bit To: 9front@9front.org Date: Mon, 19 Apr 2021 16:49:25 +0100 From: james palmer In-Reply-To: MIME-Version: 1.0 Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit List-ID: <9front.9front.org> List-Help: X-Glyph: ➈ X-Bullshit: secure hypervisor just-in-time rails self-signing markup Subject: Re: [9front] [patch] aux/wacom: prevent "no concurrent reads please" error when moving the pen too fast and support screen tilt Reply-To: 9front@9front.org Precedence: bulk Quoth cinap_lenrek@felloff.net: > the way todo this is using srvrelease()/srvacquire(): > > Srvrelease temporarily releases the calling process from the > server loop and if neccesary spawns a new process to handle > 9p requests. When released, the process can do blocking work > that would otherwise halt processing of 9p requests. > Srvacquire rejoins the calling process with the server loop > after a srvrelease. i have updated this to use srvrelease() and srvacquire(). polling of /dev/vgactl has been kept because this driver is specific to tablet pcs; you would always want the mouse cursor to line up with where the pen is pointed on the screen. let me know if you have any other issues with it. thanks, - james # HG changeset patch # User foura # Date 1618846948 -3600 # Node ID 7e0db6f829a50e8c1af98a3be6600aef8436a628 # Parent b31369df5d7d30ceb3bc104d9d4a4a3dba989b12 aux/wacom: rewrite using multiple procs. allow for screen tilt. fixes "no concurrent reads please" when moving the pen too quickly. rotates the tablet input with the screen tilt so that the pointer is always under the pen position. diff -r b31369df5d7d -r 7e0db6f829a5 sys/src/cmd/aux/wacom.c --- a/sys/src/cmd/aux/wacom.c Sun Apr 18 16:20:04 2021 +0200 +++ b/sys/src/cmd/aux/wacom.c Mon Apr 19 16:42:28 2021 +0100 @@ -1,352 +1,309 @@ #include #include +#include +#include #include -#include #include <9p.h> -typedef struct Tablet Tablet; -typedef struct Message Message; -typedef struct QItem QItem; -typedef struct Queue Queue; -typedef struct Reader Reader; +enum { + None, + Left, + Right, + Inverted, - -enum { MAX = 1000 }; - -struct Tablet { - int ser; - int xmax, ymax, pmax, version; - int sx, sy; + MAX = 1000, + STACK = 2048, }; -struct Message { - Ref; - int b, x, y, p; - char *msg; +typedef struct Tablet Tablet; +struct Tablet { + + int fd; + char dev[64]; + int version; + + int x, y, b, p; + int xmax, ymax, pmax; + + int sx, sy, srot; }; -Tablet* -newtablet(char* dev) +void +setuptablet(Tablet *t) { - int serctl; - char* ctl; - Tablet* t; + int ctlfd; + char *ctl; + + ctl = smprint("%sctl", t->dev); + t->fd = open(t->dev, ORDWR); + if(t->fd < 0) + sysfatal("%r"); + + ctlfd = open(ctl, OWRITE); + if(ctlfd < 0) + sysfatal("%r"); + free(ctl); - 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; + if(fprint(ctlfd, "b19200\n") < 0) + sysfatal("set baud rate: %r"); } int -query(Tablet* t) +query(Tablet *t) { uchar buf[11]; - if(write(t->ser, "&0*", 3) < 3) return -1; + if(write(t->fd, "&0*", 3) < 3) return 0; do { - if(read(t->ser, buf, 1) < 1) return -1; + if(read(t->fd, buf, 1) < 1) return 0; } while(buf[0] != 0xC0); - if(readn(t->ser, buf+1, 10) < 10) return -1; + + if(readn(t->fd, buf+1, 10) < 10) return 0; + 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; + + if(write(t->fd, "1", 1) < 1) return 0; + return 1; } int -screensize(Tablet* t) +findheader(Tablet *t) +{ + uchar c; + + do { + if(read(t->fd, &c, 1) < 1) return -1; + } while((c & 0x80) == 0); + + return c; +} + +void +readpacket(Tablet *t) +{ + uchar buf[9]; + int head; + + head = findheader(t); + if(head < 0) sysfatal("%r"); + if(readn(t->fd, buf, 9) < 9) sysfatal("%r"); + + t->b = head & 7; + t->x = (buf[0] << 9) | (buf[1] << 2) | ((buf[5] >> 5) & 3); + t->y = (buf[2] << 9) | (buf[3] << 2) | ((buf[5] >> 3) & 3); + t->p = ((buf[5] & 7) << 7) | buf[4]; +} + +void +screensize(Tablet *t) { int fd; char buf[189], buf2[12], *p; - + fd = open("/dev/draw/new", OREAD); - if(fd < 0) return -1; + if(fd < 0) sysfatal("%r"); 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; + sysfatal("invalid resolution read from /dev/draw/new"); } - + 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) +screenrot(Tablet *t) { - if(decref(m) == 0) { - free(m->msg); - free(m); + char *ln; + Biobuf *fd; + + fd = Bopen("/dev/vgactl", OREAD); + if(!fd) { + t->srot = None; + return; } -} -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; + while(ln = Brdstr(fd, '\n', 1)) { + if(strncmp("tilt ", ln, 5) == 0) + switch(ln[5]) { + case 'l': + t->srot = Left; + break; + case 'r': + t->srot = Right; + break; + case 'i': + t->srot = Inverted; + break; + default: + t->srot = None; + } + free(ln); } - 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; + Bterm(fd); } void -freequeue(Queue *q) +updateproc(void *aux) { - Message *m; - - while(m = qget(q)) - msgdecref(m); - free(q); -} + Tablet t; + Channel *c; -struct Reader { - Queue *e; - Reader *prev, *next; - Req* req; -}; + c = aux; + recv(c, &t); + t.b = 0; + t.x = 0; + t.y = 0; + t.p = 0; -Lock readers; -Reader *rfirst, *rlast; + setuptablet(&t); + query(&t); -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; + for(;;) { + screensize(&t); + screenrot(&t); + readpacket(&t); + send(c, &t); } } void -tabletread(Req* req) +scaleinput(Tablet *t) { - 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; - } + int temp; + + t->p *= MAX; + t->p /= t->pmax; + + switch(t->srot) { + case Left: + /* flip */ + t->y = t->ymax - t->y; + /* scale */ + t->x *= t->sx; + t->x /= t->ymax; + t->y *= t->sy; + t->y /= t->xmax; + /* swap */ + temp = t->x; + t->x = t->y; + t->y = temp; + break; + case Right: + /* flip */ + t->x = t->xmax - t->x; + /* scale */ + t->x *= t->sx; + t->x /= t->ymax; + t->y *= t->sy; + t->y /= t->xmax; + /* swap */ + temp = t->x; + t->x = t->y; + t->y = temp; + break; + case Inverted: + /* flip */ + t->y = t->ymax - t->y; + t->x = t->xmax - t->x; + /* scale */ + t->x *= t->sx; + t->x /= t->xmax; + t->y *= t->sy; + t->y /= t->ymax; + break; + default: + /* scale */ + t->x *= t->sx; + t->x /= t->xmax; + t->y *= t->sy; + t->y /= t->ymax; } } -Srv tabletsrv = { - .open = tabletopen, - .read = tabletread, - .destroyfid = tabletdestroyfid, - .destroyreq = tabletdestroyreq, +void +fsread(Req *req) +{ + Channel *c; + Tablet t; + char *reply; + + c = req->srv->aux; + + srvrelease(req->srv); + recv(c, &t); + scaleinput(&t); + srvacquire(req->srv); + + reply = smprint("m %d %d %d %d\n", + t.x, t.y, t.b, t.p); + + req->ofcall.count = strlen(reply); + if(req->ofcall.count > req->ifcall.count) + req->ofcall.count = req->ifcall.count; + memmove(req->ofcall.data, reply, req->ofcall.count); + respond(req, nil); + + free(reply); +} + +Srv fs = { + .read = fsread, }; -File *tfile; +void +srvproc(void *aux) +{ + Channel *c; + + c = aux; + fs.aux = c; + fs.tree = alloctree(getuser(), getuser(), 0555, nil); + createfile(fs.tree->root, "tablet", getuser(), 0400, nil); + + threadpostmountsrv(&fs, nil, "/dev", MAFTER); +} void -main() +usage(void) { - 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 + fprint(2, "usage: %s [-D] [-d dev]\n", argv0); + exits("usage"); +} + +void +threadmain(int argc, char *argv[]) +{ + Channel *c; + Tablet t; + + ARGBEGIN { + case 'd': + strncmp(t.dev, EARGF(usage()), sizeof(t.dev)); + break; + case 'D': + chatty9p++; + break; + default: + usage(); + } ARGEND + + c = chancreate(sizeof(Tablet), 10); + strncpy(t.dev, "/dev/eia2", sizeof(t.dev)); + + proccreate(updateproc, c, STACK); + send(c, &t); + proccreate(srvproc, c, STACK); +}