1*74a4d8c2SCharles.Forsyth /*
2*74a4d8c2SCharles.Forsyth * iPAQ H3650 touch screen and other devices
3*74a4d8c2SCharles.Forsyth *
4*74a4d8c2SCharles.Forsyth * Inferno driver derived from sketchy documentation and
5*74a4d8c2SCharles.Forsyth * information gleaned from linux/char/h3650_ts.c
6*74a4d8c2SCharles.Forsyth * by Charles Flynn.
7*74a4d8c2SCharles.Forsyth *
8*74a4d8c2SCharles.Forsyth * Copyright © 2000,2001 Vita Nuova Holdings Limited. All rights reserved.
9*74a4d8c2SCharles.Forsyth */
10*74a4d8c2SCharles.Forsyth #include "u.h"
11*74a4d8c2SCharles.Forsyth #include "../port/lib.h"
12*74a4d8c2SCharles.Forsyth #include "mem.h"
13*74a4d8c2SCharles.Forsyth #include "dat.h"
14*74a4d8c2SCharles.Forsyth #include "fns.h"
15*74a4d8c2SCharles.Forsyth #include "io.h"
16*74a4d8c2SCharles.Forsyth #include "../port/error.h"
17*74a4d8c2SCharles.Forsyth
18*74a4d8c2SCharles.Forsyth #include "keyboard.h"
19*74a4d8c2SCharles.Forsyth #include <kernel.h>
20*74a4d8c2SCharles.Forsyth
21*74a4d8c2SCharles.Forsyth #include <draw.h>
22*74a4d8c2SCharles.Forsyth #include <memdraw.h>
23*74a4d8c2SCharles.Forsyth #include "screen.h"
24*74a4d8c2SCharles.Forsyth
25*74a4d8c2SCharles.Forsyth #define DEBUG 0
26*74a4d8c2SCharles.Forsyth
27*74a4d8c2SCharles.Forsyth /*
28*74a4d8c2SCharles.Forsyth * packet format
29*74a4d8c2SCharles.Forsyth *
30*74a4d8c2SCharles.Forsyth * SOF (0x02)
31*74a4d8c2SCharles.Forsyth * (id<<4) | len byte length
32*74a4d8c2SCharles.Forsyth * data[len] bytes
33*74a4d8c2SCharles.Forsyth * chk checksum mod 256 excluding SOF
34*74a4d8c2SCharles.Forsyth */
35*74a4d8c2SCharles.Forsyth
36*74a4d8c2SCharles.Forsyth enum {
37*74a4d8c2SCharles.Forsyth Csof = 0x02,
38*74a4d8c2SCharles.Forsyth Ceof = 0x03,
39*74a4d8c2SCharles.Forsyth Hdrlen = 3,
40*74a4d8c2SCharles.Forsyth
41*74a4d8c2SCharles.Forsyth /* opcodes */
42*74a4d8c2SCharles.Forsyth
43*74a4d8c2SCharles.Forsyth Oversion = 0,
44*74a4d8c2SCharles.Forsyth Okeys = 2,
45*74a4d8c2SCharles.Forsyth Otouch = 3,
46*74a4d8c2SCharles.Forsyth Ordeeprom = 4,
47*74a4d8c2SCharles.Forsyth Owreeprom = 5,
48*74a4d8c2SCharles.Forsyth Othermal = 6,
49*74a4d8c2SCharles.Forsyth Oled = 8,
50*74a4d8c2SCharles.Forsyth Obattery = 9,
51*74a4d8c2SCharles.Forsyth Ospiread = 11,
52*74a4d8c2SCharles.Forsyth Ospiwrite = 12,
53*74a4d8c2SCharles.Forsyth Obacklight = 13,
54*74a4d8c2SCharles.Forsyth Oextstatus = 0xA1,
55*74a4d8c2SCharles.Forsyth };
56*74a4d8c2SCharles.Forsyth
57*74a4d8c2SCharles.Forsyth enum {
58*74a4d8c2SCharles.Forsyth Powerbit = 0, /* GPIO bit for power on/off key */
59*74a4d8c2SCharles.Forsyth };
60*74a4d8c2SCharles.Forsyth
61*74a4d8c2SCharles.Forsyth enum{
62*74a4d8c2SCharles.Forsyth Qdir,
63*74a4d8c2SCharles.Forsyth Qctl,
64*74a4d8c2SCharles.Forsyth Qtouchctl,
65*74a4d8c2SCharles.Forsyth Qbattery,
66*74a4d8c2SCharles.Forsyth Qversion,
67*74a4d8c2SCharles.Forsyth };
68*74a4d8c2SCharles.Forsyth
69*74a4d8c2SCharles.Forsyth static
70*74a4d8c2SCharles.Forsyth Dirtab ipaqtab[]={
71*74a4d8c2SCharles.Forsyth ".", {Qdir, 0, QTDIR}, 0, 0555,
72*74a4d8c2SCharles.Forsyth "ipaqctl", {Qctl}, 0, 0600,
73*74a4d8c2SCharles.Forsyth "battery", {Qbattery}, 0, 0444,
74*74a4d8c2SCharles.Forsyth "version", {Qversion}, 0, 0444,
75*74a4d8c2SCharles.Forsyth "touchctl", {Qtouchctl}, 0, 0644,
76*74a4d8c2SCharles.Forsyth };
77*74a4d8c2SCharles.Forsyth
78*74a4d8c2SCharles.Forsyth static struct {
79*74a4d8c2SCharles.Forsyth QLock;
80*74a4d8c2SCharles.Forsyth Chan* c;
81*74a4d8c2SCharles.Forsyth
82*74a4d8c2SCharles.Forsyth Lock rl; /* protect cmd, reply */
83*74a4d8c2SCharles.Forsyth int cmd;
84*74a4d8c2SCharles.Forsyth Block* reply;
85*74a4d8c2SCharles.Forsyth Rendez r;
86*74a4d8c2SCharles.Forsyth } atmel;
87*74a4d8c2SCharles.Forsyth
88*74a4d8c2SCharles.Forsyth /* to and from fixed point */
89*74a4d8c2SCharles.Forsyth #define FX(a,b) (((a)<<16)/(b))
90*74a4d8c2SCharles.Forsyth #define XF(v) ((v)>>16)
91*74a4d8c2SCharles.Forsyth
92*74a4d8c2SCharles.Forsyth static struct {
93*74a4d8c2SCharles.Forsyth Lock;
94*74a4d8c2SCharles.Forsyth int rate;
95*74a4d8c2SCharles.Forsyth int m[2][3]; /* transformation matrix */
96*74a4d8c2SCharles.Forsyth Point avg;
97*74a4d8c2SCharles.Forsyth Point diff;
98*74a4d8c2SCharles.Forsyth Point pts[4];
99*74a4d8c2SCharles.Forsyth int n; /* number of points in pts */
100*74a4d8c2SCharles.Forsyth int p; /* current index in pts */
101*74a4d8c2SCharles.Forsyth int down;
102*74a4d8c2SCharles.Forsyth int nout;
103*74a4d8c2SCharles.Forsyth } touch = {
104*74a4d8c2SCharles.Forsyth {0},
105*74a4d8c2SCharles.Forsyth .m {{-FX(1,3), 0, FX(346,1)},{0, -FX(1,4), FX(256, 1)}},
106*74a4d8c2SCharles.Forsyth };
107*74a4d8c2SCharles.Forsyth
108*74a4d8c2SCharles.Forsyth /*
109*74a4d8c2SCharles.Forsyth * map rocker positions to same codes as plan 9
110*74a4d8c2SCharles.Forsyth */
111*74a4d8c2SCharles.Forsyth static Rune rockermap[2][4] ={
112*74a4d8c2SCharles.Forsyth {Right, Down, Up, Left}, /* landscape */
113*74a4d8c2SCharles.Forsyth {Up, Right, Left, Down}, /* portrait */
114*74a4d8c2SCharles.Forsyth };
115*74a4d8c2SCharles.Forsyth
116*74a4d8c2SCharles.Forsyth static Rendez powerevent;
117*74a4d8c2SCharles.Forsyth
118*74a4d8c2SCharles.Forsyth static void cmdack(int, void*, int);
119*74a4d8c2SCharles.Forsyth static int cmdio(int, void*, int, void*, int);
120*74a4d8c2SCharles.Forsyth static void ipaqreadproc(void*);
121*74a4d8c2SCharles.Forsyth static void powerwaitproc(void*);
122*74a4d8c2SCharles.Forsyth static Block* rdevent(Block**);
123*74a4d8c2SCharles.Forsyth static long touchctl(char*, long);
124*74a4d8c2SCharles.Forsyth static void touched(Block*, int);
125*74a4d8c2SCharles.Forsyth static int wrcmd(int, void*, int, void*, int);
126*74a4d8c2SCharles.Forsyth static char* acstatus(int);
127*74a4d8c2SCharles.Forsyth static char* batstatus(int);
128*74a4d8c2SCharles.Forsyth static void powerintr(Ureg*, void*);
129*74a4d8c2SCharles.Forsyth
130*74a4d8c2SCharles.Forsyth static void
ipaqreset(void)131*74a4d8c2SCharles.Forsyth ipaqreset(void)
132*74a4d8c2SCharles.Forsyth {
133*74a4d8c2SCharles.Forsyth intrenable(Powerbit, powerintr, nil, BusGPIOfalling, "power off");
134*74a4d8c2SCharles.Forsyth }
135*74a4d8c2SCharles.Forsyth
136*74a4d8c2SCharles.Forsyth static void
ipaqinit(void)137*74a4d8c2SCharles.Forsyth ipaqinit(void)
138*74a4d8c2SCharles.Forsyth {
139*74a4d8c2SCharles.Forsyth kproc("powerwait", powerwaitproc, nil, 0);
140*74a4d8c2SCharles.Forsyth }
141*74a4d8c2SCharles.Forsyth
142*74a4d8c2SCharles.Forsyth static Chan*
ipaqattach(char * spec)143*74a4d8c2SCharles.Forsyth ipaqattach(char* spec)
144*74a4d8c2SCharles.Forsyth {
145*74a4d8c2SCharles.Forsyth int fd;
146*74a4d8c2SCharles.Forsyth
147*74a4d8c2SCharles.Forsyth qlock(&atmel);
148*74a4d8c2SCharles.Forsyth if(waserror()){
149*74a4d8c2SCharles.Forsyth qunlock(&atmel);
150*74a4d8c2SCharles.Forsyth nexterror();
151*74a4d8c2SCharles.Forsyth }
152*74a4d8c2SCharles.Forsyth if(atmel.c == nil){
153*74a4d8c2SCharles.Forsyth fd = kopen("#t/eia1ctl", ORDWR);
154*74a4d8c2SCharles.Forsyth if(fd < 0)
155*74a4d8c2SCharles.Forsyth error(up->env->errstr);
156*74a4d8c2SCharles.Forsyth kwrite(fd, "b115200", 7); /* it's already pn, l8 */
157*74a4d8c2SCharles.Forsyth kclose(fd);
158*74a4d8c2SCharles.Forsyth fd = kopen("#t/eia1", ORDWR);
159*74a4d8c2SCharles.Forsyth if(fd < 0)
160*74a4d8c2SCharles.Forsyth error(up->env->errstr);
161*74a4d8c2SCharles.Forsyth atmel.c = fdtochan(up->env->fgrp, fd, ORDWR, 0, 1);
162*74a4d8c2SCharles.Forsyth kclose(fd);
163*74a4d8c2SCharles.Forsyth atmel.cmd = -1;
164*74a4d8c2SCharles.Forsyth kproc("ipaqread", ipaqreadproc, nil, 0);
165*74a4d8c2SCharles.Forsyth }
166*74a4d8c2SCharles.Forsyth poperror();
167*74a4d8c2SCharles.Forsyth qunlock(&atmel);
168*74a4d8c2SCharles.Forsyth return devattach('T', spec);
169*74a4d8c2SCharles.Forsyth }
170*74a4d8c2SCharles.Forsyth
171*74a4d8c2SCharles.Forsyth static Walkqid*
ipaqwalk(Chan * c,Chan * nc,char ** name,int nname)172*74a4d8c2SCharles.Forsyth ipaqwalk(Chan *c, Chan *nc, char **name, int nname)
173*74a4d8c2SCharles.Forsyth {
174*74a4d8c2SCharles.Forsyth return devwalk(c, nc, name, nname, ipaqtab, nelem(ipaqtab), devgen);
175*74a4d8c2SCharles.Forsyth }
176*74a4d8c2SCharles.Forsyth
177*74a4d8c2SCharles.Forsyth static int
ipaqstat(Chan * c,uchar * db,int n)178*74a4d8c2SCharles.Forsyth ipaqstat(Chan* c, uchar *db, int n)
179*74a4d8c2SCharles.Forsyth {
180*74a4d8c2SCharles.Forsyth return devstat(c, db, n, ipaqtab, nelem(ipaqtab), devgen);
181*74a4d8c2SCharles.Forsyth }
182*74a4d8c2SCharles.Forsyth
183*74a4d8c2SCharles.Forsyth static Chan*
ipaqopen(Chan * c,int omode)184*74a4d8c2SCharles.Forsyth ipaqopen(Chan* c, int omode)
185*74a4d8c2SCharles.Forsyth {
186*74a4d8c2SCharles.Forsyth return devopen(c, omode, ipaqtab, nelem(ipaqtab), devgen);
187*74a4d8c2SCharles.Forsyth }
188*74a4d8c2SCharles.Forsyth
189*74a4d8c2SCharles.Forsyth static void
ipaqclose(Chan *)190*74a4d8c2SCharles.Forsyth ipaqclose(Chan*)
191*74a4d8c2SCharles.Forsyth {
192*74a4d8c2SCharles.Forsyth }
193*74a4d8c2SCharles.Forsyth
194*74a4d8c2SCharles.Forsyth static long
ipaqread(Chan * c,void * a,long n,vlong offset)195*74a4d8c2SCharles.Forsyth ipaqread(Chan* c, void* a, long n, vlong offset)
196*74a4d8c2SCharles.Forsyth {
197*74a4d8c2SCharles.Forsyth char *tmp, buf[64];
198*74a4d8c2SCharles.Forsyth uchar reply[12];
199*74a4d8c2SCharles.Forsyth int v, p, l;
200*74a4d8c2SCharles.Forsyth
201*74a4d8c2SCharles.Forsyth switch((ulong)c->qid.path){
202*74a4d8c2SCharles.Forsyth case Qdir:
203*74a4d8c2SCharles.Forsyth return devdirread(c, a, n, ipaqtab, nelem(ipaqtab), devgen);
204*74a4d8c2SCharles.Forsyth case Qtouchctl:
205*74a4d8c2SCharles.Forsyth tmp = malloc(READSTR);
206*74a4d8c2SCharles.Forsyth if(waserror()){
207*74a4d8c2SCharles.Forsyth free(tmp);
208*74a4d8c2SCharles.Forsyth nexterror();
209*74a4d8c2SCharles.Forsyth }
210*74a4d8c2SCharles.Forsyth snprint(tmp, READSTR, "s%d\nr%d\nR%d\nX %d %d %d\nY %d %d %d\n",
211*74a4d8c2SCharles.Forsyth 1000, 0, 1,
212*74a4d8c2SCharles.Forsyth touch.m[0][0], touch.m[0][1], touch.m[0][2],
213*74a4d8c2SCharles.Forsyth touch.m[1][0], touch.m[1][1], touch.m[1][2]);
214*74a4d8c2SCharles.Forsyth n = readstr(offset, a, n, tmp);
215*74a4d8c2SCharles.Forsyth poperror();
216*74a4d8c2SCharles.Forsyth free(tmp);
217*74a4d8c2SCharles.Forsyth break;
218*74a4d8c2SCharles.Forsyth case Qbattery:
219*74a4d8c2SCharles.Forsyth cmdio(Obattery, reply, 0, reply, sizeof(reply));
220*74a4d8c2SCharles.Forsyth tmp = malloc(READSTR);
221*74a4d8c2SCharles.Forsyth if(waserror()){
222*74a4d8c2SCharles.Forsyth free(tmp);
223*74a4d8c2SCharles.Forsyth nexterror();
224*74a4d8c2SCharles.Forsyth }
225*74a4d8c2SCharles.Forsyth v = (reply[4]<<8)|reply[3];
226*74a4d8c2SCharles.Forsyth p = 425*v/1000 - 298;
227*74a4d8c2SCharles.Forsyth snprint(tmp, READSTR, "voltage: %d %dmV %d%% %d\nac: %s\nstatus: %d %s\nchem: %d\n",
228*74a4d8c2SCharles.Forsyth v, 1000*v/228, p, 300*p/100, acstatus(reply[1]), reply[5], batstatus(reply[5]), reply[2]);
229*74a4d8c2SCharles.Forsyth n = readstr(offset, a, n, tmp);
230*74a4d8c2SCharles.Forsyth poperror();
231*74a4d8c2SCharles.Forsyth free(tmp);
232*74a4d8c2SCharles.Forsyth break;
233*74a4d8c2SCharles.Forsyth case Qversion:
234*74a4d8c2SCharles.Forsyth l = cmdio(Oversion, reply, 0, reply, sizeof(reply));
235*74a4d8c2SCharles.Forsyth if(l > 4){
236*74a4d8c2SCharles.Forsyth l--;
237*74a4d8c2SCharles.Forsyth memmove(buf, reply+1, 4);
238*74a4d8c2SCharles.Forsyth if(l > 8){
239*74a4d8c2SCharles.Forsyth buf[4] = ' ';
240*74a4d8c2SCharles.Forsyth memmove(buf+5, reply+5, 4); /* pack version */
241*74a4d8c2SCharles.Forsyth sprint(buf+9, " %.2x\n", reply[9]); /* ``boot type'' */
242*74a4d8c2SCharles.Forsyth }else{
243*74a4d8c2SCharles.Forsyth buf[4] = '\n';
244*74a4d8c2SCharles.Forsyth buf[5] = 0;
245*74a4d8c2SCharles.Forsyth }
246*74a4d8c2SCharles.Forsyth return readstr(offset, a, n, buf);
247*74a4d8c2SCharles.Forsyth }
248*74a4d8c2SCharles.Forsyth n=0;
249*74a4d8c2SCharles.Forsyth break;
250*74a4d8c2SCharles.Forsyth default:
251*74a4d8c2SCharles.Forsyth n=0;
252*74a4d8c2SCharles.Forsyth break;
253*74a4d8c2SCharles.Forsyth }
254*74a4d8c2SCharles.Forsyth return n;
255*74a4d8c2SCharles.Forsyth }
256*74a4d8c2SCharles.Forsyth
257*74a4d8c2SCharles.Forsyth static long
ipaqwrite(Chan * c,void * a,long n,vlong)258*74a4d8c2SCharles.Forsyth ipaqwrite(Chan* c, void* a, long n, vlong)
259*74a4d8c2SCharles.Forsyth {
260*74a4d8c2SCharles.Forsyth char cmd[64], op[32], *fields[6];
261*74a4d8c2SCharles.Forsyth int nf;
262*74a4d8c2SCharles.Forsyth
263*74a4d8c2SCharles.Forsyth switch((ulong)c->qid.path){
264*74a4d8c2SCharles.Forsyth case Qctl:
265*74a4d8c2SCharles.Forsyth if(n >= sizeof(cmd)-1)
266*74a4d8c2SCharles.Forsyth n = sizeof(cmd)-1;
267*74a4d8c2SCharles.Forsyth memmove(cmd, a, n);
268*74a4d8c2SCharles.Forsyth cmd[n] = 0;
269*74a4d8c2SCharles.Forsyth nf = getfields(cmd, fields, nelem(fields), 1, " \t\n");
270*74a4d8c2SCharles.Forsyth if(nf <= 0)
271*74a4d8c2SCharles.Forsyth error(Ebadarg);
272*74a4d8c2SCharles.Forsyth if(nf >= 4 && strcmp(fields[0], "light") == 0){
273*74a4d8c2SCharles.Forsyth op[0] = atoi(fields[1]); /* mode */
274*74a4d8c2SCharles.Forsyth op[1] = atoi(fields[2]); /* power */
275*74a4d8c2SCharles.Forsyth op[2] = atoi(fields[3]); /* brightness */
276*74a4d8c2SCharles.Forsyth cmdack(Obacklight, op, 3);
277*74a4d8c2SCharles.Forsyth }else if(nf >= 5 && strcmp(fields[0], "led") == 0){
278*74a4d8c2SCharles.Forsyth op[0] = atoi(fields[1]);
279*74a4d8c2SCharles.Forsyth op[1] = atoi(fields[2]);
280*74a4d8c2SCharles.Forsyth op[2] = atoi(fields[3]);
281*74a4d8c2SCharles.Forsyth op[3] = atoi(fields[4]);
282*74a4d8c2SCharles.Forsyth cmdack(Oled, op, 4);
283*74a4d8c2SCharles.Forsyth }else if(strcmp(fields[0], "suspend") == 0){
284*74a4d8c2SCharles.Forsyth /* let the kproc do it */
285*74a4d8c2SCharles.Forsyth wakeup(&powerevent);
286*74a4d8c2SCharles.Forsyth }else
287*74a4d8c2SCharles.Forsyth error(Ebadarg);
288*74a4d8c2SCharles.Forsyth break;
289*74a4d8c2SCharles.Forsyth case Qtouchctl:
290*74a4d8c2SCharles.Forsyth return touchctl(a, n);
291*74a4d8c2SCharles.Forsyth default:
292*74a4d8c2SCharles.Forsyth error(Ebadusefd);
293*74a4d8c2SCharles.Forsyth }
294*74a4d8c2SCharles.Forsyth return n;
295*74a4d8c2SCharles.Forsyth }
296*74a4d8c2SCharles.Forsyth
297*74a4d8c2SCharles.Forsyth static void
powerintr(Ureg *,void *)298*74a4d8c2SCharles.Forsyth powerintr(Ureg*, void*)
299*74a4d8c2SCharles.Forsyth {
300*74a4d8c2SCharles.Forsyth wakeup(&powerevent);
301*74a4d8c2SCharles.Forsyth }
302*74a4d8c2SCharles.Forsyth
303*74a4d8c2SCharles.Forsyth static void
cmdack(int id,void * a,int n)304*74a4d8c2SCharles.Forsyth cmdack(int id, void *a, int n)
305*74a4d8c2SCharles.Forsyth {
306*74a4d8c2SCharles.Forsyth uchar reply[16];
307*74a4d8c2SCharles.Forsyth
308*74a4d8c2SCharles.Forsyth cmdio(id, a, n, reply, sizeof(reply));
309*74a4d8c2SCharles.Forsyth }
310*74a4d8c2SCharles.Forsyth
311*74a4d8c2SCharles.Forsyth static int
cmdio(int id,void * a,int n,void * reply,int lim)312*74a4d8c2SCharles.Forsyth cmdio(int id, void *a, int n, void *reply, int lim)
313*74a4d8c2SCharles.Forsyth {
314*74a4d8c2SCharles.Forsyth qlock(&atmel);
315*74a4d8c2SCharles.Forsyth if(waserror()){
316*74a4d8c2SCharles.Forsyth qunlock(&atmel);
317*74a4d8c2SCharles.Forsyth nexterror();
318*74a4d8c2SCharles.Forsyth }
319*74a4d8c2SCharles.Forsyth n = wrcmd(id, a, n, reply, lim);
320*74a4d8c2SCharles.Forsyth poperror();
321*74a4d8c2SCharles.Forsyth qunlock(&atmel);
322*74a4d8c2SCharles.Forsyth return n;
323*74a4d8c2SCharles.Forsyth }
324*74a4d8c2SCharles.Forsyth
325*74a4d8c2SCharles.Forsyth static int
havereply(void *)326*74a4d8c2SCharles.Forsyth havereply(void*)
327*74a4d8c2SCharles.Forsyth {
328*74a4d8c2SCharles.Forsyth return atmel.reply != nil;
329*74a4d8c2SCharles.Forsyth }
330*74a4d8c2SCharles.Forsyth
331*74a4d8c2SCharles.Forsyth static int
wrcmd(int id,void * a,int n,void * b,int lim)332*74a4d8c2SCharles.Forsyth wrcmd(int id, void *a, int n, void *b, int lim)
333*74a4d8c2SCharles.Forsyth {
334*74a4d8c2SCharles.Forsyth uchar buf[32];
335*74a4d8c2SCharles.Forsyth int i, sum;
336*74a4d8c2SCharles.Forsyth Block *e;
337*74a4d8c2SCharles.Forsyth
338*74a4d8c2SCharles.Forsyth if(n >= 16)
339*74a4d8c2SCharles.Forsyth error(Eio);
340*74a4d8c2SCharles.Forsyth lock(&atmel.rl);
341*74a4d8c2SCharles.Forsyth atmel.cmd = id;
342*74a4d8c2SCharles.Forsyth unlock(&atmel.rl);
343*74a4d8c2SCharles.Forsyth buf[0] = Csof;
344*74a4d8c2SCharles.Forsyth buf[1] = (id<<4) | (n&0xF);
345*74a4d8c2SCharles.Forsyth if(n)
346*74a4d8c2SCharles.Forsyth memmove(buf+2, a, n);
347*74a4d8c2SCharles.Forsyth sum = 0;
348*74a4d8c2SCharles.Forsyth for(i=1; i<n+2; i++)
349*74a4d8c2SCharles.Forsyth sum += buf[i];
350*74a4d8c2SCharles.Forsyth buf[i++] = sum;
351*74a4d8c2SCharles.Forsyth if(0){
352*74a4d8c2SCharles.Forsyth iprint("msg=");
353*74a4d8c2SCharles.Forsyth for(sum=0; sum<i; sum++)
354*74a4d8c2SCharles.Forsyth iprint(" %2.2ux", buf[sum]);
355*74a4d8c2SCharles.Forsyth iprint("\n");
356*74a4d8c2SCharles.Forsyth }
357*74a4d8c2SCharles.Forsyth if(kchanio(atmel.c, buf, i, OWRITE) != i)
358*74a4d8c2SCharles.Forsyth error(Eio);
359*74a4d8c2SCharles.Forsyth tsleep(&atmel.r, havereply, nil, 500);
360*74a4d8c2SCharles.Forsyth lock(&atmel.rl);
361*74a4d8c2SCharles.Forsyth e = atmel.reply;
362*74a4d8c2SCharles.Forsyth atmel.reply = nil;
363*74a4d8c2SCharles.Forsyth atmel.cmd = -1;
364*74a4d8c2SCharles.Forsyth unlock(&atmel.rl);
365*74a4d8c2SCharles.Forsyth if(e == nil){
366*74a4d8c2SCharles.Forsyth print("ipaq: no reply\n");
367*74a4d8c2SCharles.Forsyth error(Eio);
368*74a4d8c2SCharles.Forsyth }
369*74a4d8c2SCharles.Forsyth if(waserror()){
370*74a4d8c2SCharles.Forsyth freeb(e);
371*74a4d8c2SCharles.Forsyth nexterror();
372*74a4d8c2SCharles.Forsyth }
373*74a4d8c2SCharles.Forsyth if(e->rp[0] != id){
374*74a4d8c2SCharles.Forsyth print("ipaq: rdreply: mismatched reply %d :: %d\n", id, e->rp[0]);
375*74a4d8c2SCharles.Forsyth error(Eio);
376*74a4d8c2SCharles.Forsyth }
377*74a4d8c2SCharles.Forsyth n = BLEN(e);
378*74a4d8c2SCharles.Forsyth if(n < lim)
379*74a4d8c2SCharles.Forsyth lim = n;
380*74a4d8c2SCharles.Forsyth memmove(b, e->rp, lim);
381*74a4d8c2SCharles.Forsyth poperror();
382*74a4d8c2SCharles.Forsyth freeb(e);
383*74a4d8c2SCharles.Forsyth return lim;
384*74a4d8c2SCharles.Forsyth }
385*74a4d8c2SCharles.Forsyth
386*74a4d8c2SCharles.Forsyth static void
ipaqreadproc(void *)387*74a4d8c2SCharles.Forsyth ipaqreadproc(void*)
388*74a4d8c2SCharles.Forsyth {
389*74a4d8c2SCharles.Forsyth Block *e, *b, *partial;
390*74a4d8c2SCharles.Forsyth int c, mousemod;
391*74a4d8c2SCharles.Forsyth
392*74a4d8c2SCharles.Forsyth while(waserror())
393*74a4d8c2SCharles.Forsyth print("ipaqread: %r\n");
394*74a4d8c2SCharles.Forsyth partial = nil;
395*74a4d8c2SCharles.Forsyth mousemod = 0;
396*74a4d8c2SCharles.Forsyth for(;;){
397*74a4d8c2SCharles.Forsyth e = rdevent(&partial);
398*74a4d8c2SCharles.Forsyth if(e == nil){
399*74a4d8c2SCharles.Forsyth print("ipaqread: rdevent: %r\n");
400*74a4d8c2SCharles.Forsyth continue;
401*74a4d8c2SCharles.Forsyth }
402*74a4d8c2SCharles.Forsyth switch(e->rp[0]){
403*74a4d8c2SCharles.Forsyth case Otouch:
404*74a4d8c2SCharles.Forsyth touched(e, mousemod);
405*74a4d8c2SCharles.Forsyth freeb(e);
406*74a4d8c2SCharles.Forsyth break;
407*74a4d8c2SCharles.Forsyth case Okeys:
408*74a4d8c2SCharles.Forsyth //print("key %2.2ux\n", e->rp[1]);
409*74a4d8c2SCharles.Forsyth c = e->rp[1] & 0xF;
410*74a4d8c2SCharles.Forsyth if(c >= 6 && c < 10){ /* rocker */
411*74a4d8c2SCharles.Forsyth if((e->rp[1] & 0x80) == 0){
412*74a4d8c2SCharles.Forsyth kbdrepeat(0);
413*74a4d8c2SCharles.Forsyth kbdputc(kbdq, rockermap[conf.portrait&1][c-6]);
414*74a4d8c2SCharles.Forsyth }else
415*74a4d8c2SCharles.Forsyth kbdrepeat(0);
416*74a4d8c2SCharles.Forsyth }else{
417*74a4d8c2SCharles.Forsyth /* TO DO: change tkmouse and mousetrack to allow extra buttons */
418*74a4d8c2SCharles.Forsyth if(--c == 0)
419*74a4d8c2SCharles.Forsyth c = 5;
420*74a4d8c2SCharles.Forsyth if(e->rp[1] & 0x80)
421*74a4d8c2SCharles.Forsyth mousemod &= ~(1<<c);
422*74a4d8c2SCharles.Forsyth else
423*74a4d8c2SCharles.Forsyth mousemod |= 1<<c;
424*74a4d8c2SCharles.Forsyth }
425*74a4d8c2SCharles.Forsyth freeb(e);
426*74a4d8c2SCharles.Forsyth break;
427*74a4d8c2SCharles.Forsyth default:
428*74a4d8c2SCharles.Forsyth lock(&atmel.rl);
429*74a4d8c2SCharles.Forsyth if(atmel.cmd == e->rp[0]){
430*74a4d8c2SCharles.Forsyth b = atmel.reply;
431*74a4d8c2SCharles.Forsyth atmel.reply = e;
432*74a4d8c2SCharles.Forsyth unlock(&atmel.rl);
433*74a4d8c2SCharles.Forsyth wakeup(&atmel.r);
434*74a4d8c2SCharles.Forsyth if(b != nil)
435*74a4d8c2SCharles.Forsyth freeb(b);
436*74a4d8c2SCharles.Forsyth }else{
437*74a4d8c2SCharles.Forsyth unlock(&atmel.rl);
438*74a4d8c2SCharles.Forsyth print("ipaqread: discard op %d\n", e->rp[0]);
439*74a4d8c2SCharles.Forsyth freeb(e);
440*74a4d8c2SCharles.Forsyth }
441*74a4d8c2SCharles.Forsyth }
442*74a4d8c2SCharles.Forsyth }
443*74a4d8c2SCharles.Forsyth }
444*74a4d8c2SCharles.Forsyth
445*74a4d8c2SCharles.Forsyth static Block *
rdevent(Block ** bp)446*74a4d8c2SCharles.Forsyth rdevent(Block **bp)
447*74a4d8c2SCharles.Forsyth {
448*74a4d8c2SCharles.Forsyth Block *b, *e;
449*74a4d8c2SCharles.Forsyth int s, c, len, csum;
450*74a4d8c2SCharles.Forsyth enum {Ssof=16, Sid, Ssum};
451*74a4d8c2SCharles.Forsyth
452*74a4d8c2SCharles.Forsyth s = Ssof;
453*74a4d8c2SCharles.Forsyth csum = 0;
454*74a4d8c2SCharles.Forsyth len = 0;
455*74a4d8c2SCharles.Forsyth e = nil;
456*74a4d8c2SCharles.Forsyth if(waserror()){
457*74a4d8c2SCharles.Forsyth if(e != nil)
458*74a4d8c2SCharles.Forsyth freeb(e);
459*74a4d8c2SCharles.Forsyth nexterror();
460*74a4d8c2SCharles.Forsyth }
461*74a4d8c2SCharles.Forsyth for(;;){
462*74a4d8c2SCharles.Forsyth b = *bp;
463*74a4d8c2SCharles.Forsyth *bp = nil;
464*74a4d8c2SCharles.Forsyth if(b == nil){
465*74a4d8c2SCharles.Forsyth b = devtab[atmel.c->type]->bread(atmel.c, 128, 0);
466*74a4d8c2SCharles.Forsyth if(b == nil)
467*74a4d8c2SCharles.Forsyth error(Eio);
468*74a4d8c2SCharles.Forsyth if(DEBUG)
469*74a4d8c2SCharles.Forsyth iprint("r: %ld\n", BLEN(b));
470*74a4d8c2SCharles.Forsyth }
471*74a4d8c2SCharles.Forsyth while(b->rp < b->wp){
472*74a4d8c2SCharles.Forsyth c = *b->rp++;
473*74a4d8c2SCharles.Forsyth switch(s){
474*74a4d8c2SCharles.Forsyth case Ssof:
475*74a4d8c2SCharles.Forsyth if(c == Csof)
476*74a4d8c2SCharles.Forsyth s = Sid;
477*74a4d8c2SCharles.Forsyth else if(1)
478*74a4d8c2SCharles.Forsyth iprint("!sof: %2.2ux %d\n", c, s);
479*74a4d8c2SCharles.Forsyth break;
480*74a4d8c2SCharles.Forsyth case Sid:
481*74a4d8c2SCharles.Forsyth csum = c;
482*74a4d8c2SCharles.Forsyth len = c & 0xF;
483*74a4d8c2SCharles.Forsyth e = allocb(len+1);
484*74a4d8c2SCharles.Forsyth if(e == nil)
485*74a4d8c2SCharles.Forsyth error(Eio);
486*74a4d8c2SCharles.Forsyth *e->wp++ = c>>4; /* id */
487*74a4d8c2SCharles.Forsyth if(len)
488*74a4d8c2SCharles.Forsyth s = 0;
489*74a4d8c2SCharles.Forsyth else
490*74a4d8c2SCharles.Forsyth s = Ssum;
491*74a4d8c2SCharles.Forsyth break;
492*74a4d8c2SCharles.Forsyth case Ssum:
493*74a4d8c2SCharles.Forsyth csum &= 0xFF;
494*74a4d8c2SCharles.Forsyth if(c != csum){
495*74a4d8c2SCharles.Forsyth iprint("cksum: %2.2ux != %2.2ux\n", c, csum);
496*74a4d8c2SCharles.Forsyth s = Ssof; /* try to resynchronise */
497*74a4d8c2SCharles.Forsyth if(e != nil){
498*74a4d8c2SCharles.Forsyth freeb(e);
499*74a4d8c2SCharles.Forsyth e = nil;
500*74a4d8c2SCharles.Forsyth }
501*74a4d8c2SCharles.Forsyth break;
502*74a4d8c2SCharles.Forsyth }
503*74a4d8c2SCharles.Forsyth if(b->rp < b->wp)
504*74a4d8c2SCharles.Forsyth *bp = b;
505*74a4d8c2SCharles.Forsyth else
506*74a4d8c2SCharles.Forsyth freeb(b);
507*74a4d8c2SCharles.Forsyth if(DEBUG){
508*74a4d8c2SCharles.Forsyth int i;
509*74a4d8c2SCharles.Forsyth iprint("event: [%ld]", BLEN(e));
510*74a4d8c2SCharles.Forsyth for(i=0; i<BLEN(e);i++)
511*74a4d8c2SCharles.Forsyth iprint(" %2.2ux", e->rp[i]);
512*74a4d8c2SCharles.Forsyth iprint("\n");
513*74a4d8c2SCharles.Forsyth }
514*74a4d8c2SCharles.Forsyth poperror();
515*74a4d8c2SCharles.Forsyth return e;
516*74a4d8c2SCharles.Forsyth default:
517*74a4d8c2SCharles.Forsyth csum += c;
518*74a4d8c2SCharles.Forsyth *e->wp++ = c;
519*74a4d8c2SCharles.Forsyth if(++s >= len)
520*74a4d8c2SCharles.Forsyth s = Ssum;
521*74a4d8c2SCharles.Forsyth break;
522*74a4d8c2SCharles.Forsyth }
523*74a4d8c2SCharles.Forsyth }
524*74a4d8c2SCharles.Forsyth freeb(b);
525*74a4d8c2SCharles.Forsyth }
526*74a4d8c2SCharles.Forsyth return 0; /* not reached */
527*74a4d8c2SCharles.Forsyth }
528*74a4d8c2SCharles.Forsyth
529*74a4d8c2SCharles.Forsyth static char *
acstatus(int x)530*74a4d8c2SCharles.Forsyth acstatus(int x)
531*74a4d8c2SCharles.Forsyth {
532*74a4d8c2SCharles.Forsyth switch(x){
533*74a4d8c2SCharles.Forsyth case 0: return "offline";
534*74a4d8c2SCharles.Forsyth case 1: return "online";
535*74a4d8c2SCharles.Forsyth case 2: return "backup";
536*74a4d8c2SCharles.Forsyth }
537*74a4d8c2SCharles.Forsyth return "unknown";
538*74a4d8c2SCharles.Forsyth }
539*74a4d8c2SCharles.Forsyth
540*74a4d8c2SCharles.Forsyth static char *
batstatus(int x)541*74a4d8c2SCharles.Forsyth batstatus(int x)
542*74a4d8c2SCharles.Forsyth {
543*74a4d8c2SCharles.Forsyth if(x & 0x40)
544*74a4d8c2SCharles.Forsyth return "charging"; /* not in linux but seems to be on mine */
545*74a4d8c2SCharles.Forsyth switch(x){
546*74a4d8c2SCharles.Forsyth case 0: return "ok";
547*74a4d8c2SCharles.Forsyth case 1: return "high";
548*74a4d8c2SCharles.Forsyth case 2: return "low";
549*74a4d8c2SCharles.Forsyth case 4: return "critical";
550*74a4d8c2SCharles.Forsyth case 8: return "charging";
551*74a4d8c2SCharles.Forsyth case 0x80: return "none";
552*74a4d8c2SCharles.Forsyth }
553*74a4d8c2SCharles.Forsyth return "unknown";
554*74a4d8c2SCharles.Forsyth }
555*74a4d8c2SCharles.Forsyth
556*74a4d8c2SCharles.Forsyth static int
ptmap(int * m,int x,int y)557*74a4d8c2SCharles.Forsyth ptmap(int *m, int x, int y)
558*74a4d8c2SCharles.Forsyth {
559*74a4d8c2SCharles.Forsyth return XF(m[0]*x + m[1]*y + m[2]);
560*74a4d8c2SCharles.Forsyth }
561*74a4d8c2SCharles.Forsyth
562*74a4d8c2SCharles.Forsyth static void
touched(Block * b,int buttons)563*74a4d8c2SCharles.Forsyth touched(Block *b, int buttons)
564*74a4d8c2SCharles.Forsyth {
565*74a4d8c2SCharles.Forsyth int rx, ry, x, y, dx, dy, n;
566*74a4d8c2SCharles.Forsyth Point op, *lp, cur;
567*74a4d8c2SCharles.Forsyth
568*74a4d8c2SCharles.Forsyth if(BLEN(b) == 5){
569*74a4d8c2SCharles.Forsyth /* id Xhi Xlo Yhi Ylo */
570*74a4d8c2SCharles.Forsyth if(touch.down < 0){
571*74a4d8c2SCharles.Forsyth touch.down = 0;
572*74a4d8c2SCharles.Forsyth return;
573*74a4d8c2SCharles.Forsyth }
574*74a4d8c2SCharles.Forsyth rx = (b->rp[1]<<8)|b->rp[2];
575*74a4d8c2SCharles.Forsyth ry = (b->rp[3]<<8)|b->rp[4];
576*74a4d8c2SCharles.Forsyth if(conf.portrait){
577*74a4d8c2SCharles.Forsyth dx = rx; rx = ry; ry = dx;
578*74a4d8c2SCharles.Forsyth }
579*74a4d8c2SCharles.Forsyth if(touch.down == 0){
580*74a4d8c2SCharles.Forsyth touch.nout = 0;
581*74a4d8c2SCharles.Forsyth touch.p = 1;
582*74a4d8c2SCharles.Forsyth touch.n = 1;
583*74a4d8c2SCharles.Forsyth touch.avg = Pt(rx, ry);
584*74a4d8c2SCharles.Forsyth touch.pts[0] = touch.avg;
585*74a4d8c2SCharles.Forsyth touch.down = 1;
586*74a4d8c2SCharles.Forsyth return;
587*74a4d8c2SCharles.Forsyth }
588*74a4d8c2SCharles.Forsyth n = touch.p-1;
589*74a4d8c2SCharles.Forsyth if(n < 0)
590*74a4d8c2SCharles.Forsyth n = nelem(touch.pts)-1;
591*74a4d8c2SCharles.Forsyth lp = &touch.pts[n]; /* last point */
592*74a4d8c2SCharles.Forsyth if(touch.n > 0 && (rx-lp->x)*(ry-lp->y) > 50*50){ /* far out */
593*74a4d8c2SCharles.Forsyth if(++touch.nout > 3){
594*74a4d8c2SCharles.Forsyth touch.down = 0;
595*74a4d8c2SCharles.Forsyth touch.n = 0;
596*74a4d8c2SCharles.Forsyth }
597*74a4d8c2SCharles.Forsyth return;
598*74a4d8c2SCharles.Forsyth }
599*74a4d8c2SCharles.Forsyth op = touch.pts[touch.p];
600*74a4d8c2SCharles.Forsyth touch.pts[touch.p] = Pt(rx, ry);
601*74a4d8c2SCharles.Forsyth touch.p = (touch.p+1) % nelem(touch.pts);
602*74a4d8c2SCharles.Forsyth touch.avg.x += rx;
603*74a4d8c2SCharles.Forsyth touch.avg.y += ry;
604*74a4d8c2SCharles.Forsyth if(touch.n < nelem(touch.pts)){
605*74a4d8c2SCharles.Forsyth touch.n++;
606*74a4d8c2SCharles.Forsyth return;
607*74a4d8c2SCharles.Forsyth }
608*74a4d8c2SCharles.Forsyth touch.avg.x -= op.x;
609*74a4d8c2SCharles.Forsyth touch.avg.y -= op.y;
610*74a4d8c2SCharles.Forsyth cur = mousexy();
611*74a4d8c2SCharles.Forsyth rx = touch.avg.x/touch.n;
612*74a4d8c2SCharles.Forsyth ry = touch.avg.y/touch.n;
613*74a4d8c2SCharles.Forsyth x = ptmap(touch.m[0], rx, ry);
614*74a4d8c2SCharles.Forsyth dx = x-cur.x;
615*74a4d8c2SCharles.Forsyth y = ptmap(touch.m[1], rx, ry);
616*74a4d8c2SCharles.Forsyth dy = y-cur.y;
617*74a4d8c2SCharles.Forsyth if(dx*dx + dy*dy <= 2){
618*74a4d8c2SCharles.Forsyth dx = 0;
619*74a4d8c2SCharles.Forsyth dy = 0;
620*74a4d8c2SCharles.Forsyth }
621*74a4d8c2SCharles.Forsyth if(buttons == 0)
622*74a4d8c2SCharles.Forsyth buttons = 1<<0; /* by default, stylus down implies button 1 */
623*74a4d8c2SCharles.Forsyth mousetrack(buttons&0x1f, dx, dy, 1); /* TO DO: allow more than 3 buttons */
624*74a4d8c2SCharles.Forsyth /* TO DO: swcursupdate(oldx, oldy, x, y); */
625*74a4d8c2SCharles.Forsyth touch.down = 1;
626*74a4d8c2SCharles.Forsyth }else{
627*74a4d8c2SCharles.Forsyth if(touch.down){
628*74a4d8c2SCharles.Forsyth mousetrack(0, 0, 0, 1); /* stylus up */
629*74a4d8c2SCharles.Forsyth touch.down = 0;
630*74a4d8c2SCharles.Forsyth }else
631*74a4d8c2SCharles.Forsyth touch.down = -1;
632*74a4d8c2SCharles.Forsyth touch.n = 0;
633*74a4d8c2SCharles.Forsyth touch.p = 0;
634*74a4d8c2SCharles.Forsyth touch.avg.x = 0;
635*74a4d8c2SCharles.Forsyth touch.avg.y = 0;
636*74a4d8c2SCharles.Forsyth }
637*74a4d8c2SCharles.Forsyth }
638*74a4d8c2SCharles.Forsyth
639*74a4d8c2SCharles.Forsyth /*
640*74a4d8c2SCharles.Forsyth * touchctl commands:
641*74a4d8c2SCharles.Forsyth * X a b c - set X transformation
642*74a4d8c2SCharles.Forsyth * Y d e f - set Y transformation
643*74a4d8c2SCharles.Forsyth * s<delay> - set sample delay in millisec per sample
644*74a4d8c2SCharles.Forsyth * r<delay> - set read delay in microsec
645*74a4d8c2SCharles.Forsyth * R<l2nr> - set log2 of number of readings to average
646*74a4d8c2SCharles.Forsyth */
647*74a4d8c2SCharles.Forsyth static long
touchctl(char * a,long n)648*74a4d8c2SCharles.Forsyth touchctl(char* a, long n)
649*74a4d8c2SCharles.Forsyth {
650*74a4d8c2SCharles.Forsyth char buf[64];
651*74a4d8c2SCharles.Forsyth char *cp;
652*74a4d8c2SCharles.Forsyth int n0 = n;
653*74a4d8c2SCharles.Forsyth int bn;
654*74a4d8c2SCharles.Forsyth char *field[8];
655*74a4d8c2SCharles.Forsyth int nf, cmd, pn, m[2][3];
656*74a4d8c2SCharles.Forsyth
657*74a4d8c2SCharles.Forsyth while(n) {
658*74a4d8c2SCharles.Forsyth bn = (cp = memchr(a, '\n', n))!=nil ? cp-a+1 : n;
659*74a4d8c2SCharles.Forsyth n -= bn;
660*74a4d8c2SCharles.Forsyth cp = a;
661*74a4d8c2SCharles.Forsyth a += bn;
662*74a4d8c2SCharles.Forsyth bn = bn > sizeof(buf)-1 ? sizeof(buf)-1 : bn;
663*74a4d8c2SCharles.Forsyth memmove(buf, cp, bn);
664*74a4d8c2SCharles.Forsyth buf[bn] = '\0';
665*74a4d8c2SCharles.Forsyth nf = getfields(buf, field, nelem(field), 1, " \t\n");
666*74a4d8c2SCharles.Forsyth if(nf <= 0)
667*74a4d8c2SCharles.Forsyth continue;
668*74a4d8c2SCharles.Forsyth if(strcmp(field[0], "calibrate") == 0){
669*74a4d8c2SCharles.Forsyth if(nf == 1){
670*74a4d8c2SCharles.Forsyth lock(&touch);
671*74a4d8c2SCharles.Forsyth memset(touch.m, 0, sizeof(touch.m));
672*74a4d8c2SCharles.Forsyth touch.m[0][0] = FX(1,1);
673*74a4d8c2SCharles.Forsyth touch.m[1][1] = FX(1,1);
674*74a4d8c2SCharles.Forsyth unlock(&touch);
675*74a4d8c2SCharles.Forsyth }else if(nf >= 5){
676*74a4d8c2SCharles.Forsyth memset(m, 0, sizeof(m));
677*74a4d8c2SCharles.Forsyth m[0][0] = strtol(field[1], 0, 0);
678*74a4d8c2SCharles.Forsyth m[1][1] = strtol(field[2], 0, 0);
679*74a4d8c2SCharles.Forsyth m[0][2] = strtol(field[3], 0, 0);
680*74a4d8c2SCharles.Forsyth m[1][2] = strtol(field[4], 0, 0);
681*74a4d8c2SCharles.Forsyth if(nf > 5)
682*74a4d8c2SCharles.Forsyth m[0][1] = strtol(field[5], 0, 0);
683*74a4d8c2SCharles.Forsyth if(nf > 6)
684*74a4d8c2SCharles.Forsyth m[1][0] = strtol(field[6], 0, 0);
685*74a4d8c2SCharles.Forsyth lock(&touch);
686*74a4d8c2SCharles.Forsyth memmove(touch.m, m, sizeof(touch.m[0]));
687*74a4d8c2SCharles.Forsyth unlock(&touch);
688*74a4d8c2SCharles.Forsyth }else
689*74a4d8c2SCharles.Forsyth error(Ebadarg);
690*74a4d8c2SCharles.Forsyth continue;
691*74a4d8c2SCharles.Forsyth }
692*74a4d8c2SCharles.Forsyth cmd = *field[0]++;
693*74a4d8c2SCharles.Forsyth pn = *field[0] == 0;
694*74a4d8c2SCharles.Forsyth switch(cmd) {
695*74a4d8c2SCharles.Forsyth case 's':
696*74a4d8c2SCharles.Forsyth pn = strtol(field[pn], 0, 0);
697*74a4d8c2SCharles.Forsyth if(pn <= 0)
698*74a4d8c2SCharles.Forsyth error(Ebadarg);
699*74a4d8c2SCharles.Forsyth touch.rate = pn;
700*74a4d8c2SCharles.Forsyth break;
701*74a4d8c2SCharles.Forsyth case 'r':
702*74a4d8c2SCharles.Forsyth /* touch read delay */
703*74a4d8c2SCharles.Forsyth break;
704*74a4d8c2SCharles.Forsyth case 'X':
705*74a4d8c2SCharles.Forsyth case 'Y':
706*74a4d8c2SCharles.Forsyth if(nf < pn+2)
707*74a4d8c2SCharles.Forsyth error(Ebadarg);
708*74a4d8c2SCharles.Forsyth m[0][0] = strtol(field[pn], 0, 0);
709*74a4d8c2SCharles.Forsyth m[0][1] = strtol(field[pn+1], 0, 0);
710*74a4d8c2SCharles.Forsyth m[0][2] = strtol(field[pn+2], 0, 0);
711*74a4d8c2SCharles.Forsyth lock(&touch);
712*74a4d8c2SCharles.Forsyth memmove(touch.m[cmd=='Y'], m[0], sizeof(touch.m[0]));
713*74a4d8c2SCharles.Forsyth unlock(&touch);
714*74a4d8c2SCharles.Forsyth break;
715*74a4d8c2SCharles.Forsyth default:
716*74a4d8c2SCharles.Forsyth error(Ebadarg);
717*74a4d8c2SCharles.Forsyth }
718*74a4d8c2SCharles.Forsyth }
719*74a4d8c2SCharles.Forsyth return n0-n;
720*74a4d8c2SCharles.Forsyth }
721*74a4d8c2SCharles.Forsyth
722*74a4d8c2SCharles.Forsyth /*
723*74a4d8c2SCharles.Forsyth * this might belong elsewhere
724*74a4d8c2SCharles.Forsyth */
725*74a4d8c2SCharles.Forsyth static int
powerwait(void *)726*74a4d8c2SCharles.Forsyth powerwait(void*)
727*74a4d8c2SCharles.Forsyth {
728*74a4d8c2SCharles.Forsyth return (GPIOREG->gplr & GPIO_PWR_ON_i) == 0;
729*74a4d8c2SCharles.Forsyth }
730*74a4d8c2SCharles.Forsyth
731*74a4d8c2SCharles.Forsyth static void
powerwaitproc(void *)732*74a4d8c2SCharles.Forsyth powerwaitproc(void*)
733*74a4d8c2SCharles.Forsyth {
734*74a4d8c2SCharles.Forsyth for(;;){
735*74a4d8c2SCharles.Forsyth sleep(&powerevent, powerwait, nil);
736*74a4d8c2SCharles.Forsyth do{
737*74a4d8c2SCharles.Forsyth tsleep(&up->sleep, return0, nil, 50);
738*74a4d8c2SCharles.Forsyth }while((GPIOREG->gplr & GPIO_PWR_ON_i) == 0);
739*74a4d8c2SCharles.Forsyth powersuspend();
740*74a4d8c2SCharles.Forsyth }
741*74a4d8c2SCharles.Forsyth }
742*74a4d8c2SCharles.Forsyth
743*74a4d8c2SCharles.Forsyth Dev ipaqdevtab = {
744*74a4d8c2SCharles.Forsyth 'T',
745*74a4d8c2SCharles.Forsyth "ipaq",
746*74a4d8c2SCharles.Forsyth
747*74a4d8c2SCharles.Forsyth ipaqreset,
748*74a4d8c2SCharles.Forsyth ipaqinit,
749*74a4d8c2SCharles.Forsyth devshutdown,
750*74a4d8c2SCharles.Forsyth ipaqattach,
751*74a4d8c2SCharles.Forsyth ipaqwalk,
752*74a4d8c2SCharles.Forsyth ipaqstat,
753*74a4d8c2SCharles.Forsyth ipaqopen,
754*74a4d8c2SCharles.Forsyth devcreate,
755*74a4d8c2SCharles.Forsyth ipaqclose,
756*74a4d8c2SCharles.Forsyth ipaqread,
757*74a4d8c2SCharles.Forsyth devbread,
758*74a4d8c2SCharles.Forsyth ipaqwrite,
759*74a4d8c2SCharles.Forsyth devbwrite,
760*74a4d8c2SCharles.Forsyth devremove,
761*74a4d8c2SCharles.Forsyth devwstat,
762*74a4d8c2SCharles.Forsyth };
763