This commit is contained in:
cinap_lenrek 2011-05-09 10:04:36 +00:00
commit d763dcc91b
6 changed files with 433 additions and 4 deletions

View file

@ -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);

View file

@ -454,15 +454,18 @@ 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);
if(buf[0] == 'A')
absmousetrack(pt.x, pt.y, b, msec);
else
mousetrack(pt.x, pt.y, b, msec);
return n;
@ -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
*

View file

@ -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 */

View file

@ -34,11 +34,13 @@ TARG=\
searchfs\
statusbar\
stub\
tablet\
timesync\
trampoline\
unbflz\
usage\
write\
wacom\
zerotrunc\
BIN=/$objtype/bin/aux

32
sys/src/cmd/aux/tablet.c Normal file
View file

@ -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);
}
}

352
sys/src/cmd/aux/wacom.c Normal file
View file

@ -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);
}
}