1d40255d8SDavid du Colombier #include <u.h> 2d40255d8SDavid du Colombier #include <libc.h> 3d40255d8SDavid du Colombier #include <thread.h> 4d40255d8SDavid du Colombier #include "usb.h" 5d40255d8SDavid du Colombier #include "hid.h" 6d40255d8SDavid du Colombier 7d40255d8SDavid du Colombier /* 8d40255d8SDavid du Colombier * Rough hid descriptor parsing and interpretation for mice 9d40255d8SDavid du Colombier * 10d40255d8SDavid du Colombier * Chain and its operations build the infrastructure needed 11d40255d8SDavid du Colombier * to manipulate non-aligned fields, which do appear (sigh!). 12d40255d8SDavid du Colombier */ 13d40255d8SDavid du Colombier 14d40255d8SDavid du Colombier /* Get, at most, 8 bits*/ 15d40255d8SDavid du Colombier static uchar 16d40255d8SDavid du Colombier get8bits(Chain *ch, int nbits) 17d40255d8SDavid du Colombier { 18d40255d8SDavid du Colombier int b, nbyb, nbib, nlb; 19d40255d8SDavid du Colombier uchar low, high; 20d40255d8SDavid du Colombier 21d40255d8SDavid du Colombier b = ch->b + nbits - 1; 22d40255d8SDavid du Colombier nbib = ch->b % 8; 23d40255d8SDavid du Colombier nbyb = ch->b / 8; 24d40255d8SDavid du Colombier nlb = 8 - nbib; 25d40255d8SDavid du Colombier if(nlb > nbits) 26d40255d8SDavid du Colombier nlb = nbits; 27d40255d8SDavid du Colombier 28d40255d8SDavid du Colombier low = MSK(nlb) & (ch->buf[nbyb] >> nbib); 29d40255d8SDavid du Colombier if(IsCut(ch->b, b)) 30d40255d8SDavid du Colombier high = (ch->buf[nbyb + 1] & MSK(nbib)) << nlb; 31d40255d8SDavid du Colombier else 32d40255d8SDavid du Colombier high = 0; 33d40255d8SDavid du Colombier ch->b += nbits; 34*f7db6155SDavid du Colombier return MSK(nbits)&(high | low); 35d40255d8SDavid du Colombier } 36d40255d8SDavid du Colombier 37d40255d8SDavid du Colombier static void 38d40255d8SDavid du Colombier getbits(void *p, Chain *ch, int nbits) 39d40255d8SDavid du Colombier { 40d40255d8SDavid du Colombier int nby, nbi, i; 41d40255d8SDavid du Colombier uchar *vp; 42d40255d8SDavid du Colombier 43d40255d8SDavid du Colombier assert(ch->e >= ch->b); 44d40255d8SDavid du Colombier nby = nbits / 8; 45d40255d8SDavid du Colombier nbi = nbits % 8; 46d40255d8SDavid du Colombier 47d40255d8SDavid du Colombier vp = p; 48d40255d8SDavid du Colombier for(i = 0; i < nby; i++) 49d40255d8SDavid du Colombier *vp++ = get8bits(ch, 8); 50d40255d8SDavid du Colombier 51d40255d8SDavid du Colombier if(nbi != 0) 52d40255d8SDavid du Colombier *vp = get8bits(ch, nbi); 53d40255d8SDavid du Colombier } 54d40255d8SDavid du Colombier 55d40255d8SDavid du Colombier int 56d40255d8SDavid du Colombier parsereportdesc(HidRepTempl *temp, uchar *repdesc, int repsz) 57d40255d8SDavid du Colombier { 58*f7db6155SDavid du Colombier int i, j, l, n, isptr, hasxy, hasbut, nk, ncoll; 59d40255d8SDavid du Colombier int ks[MaxVals]; 60d40255d8SDavid du Colombier HidInterface *ifs; 61d40255d8SDavid du Colombier 62d40255d8SDavid du Colombier ifs = temp->ifcs; 63d40255d8SDavid du Colombier isptr = 0; 64d40255d8SDavid du Colombier hasxy = hasbut = 0; 65*f7db6155SDavid du Colombier ncoll = 0; 66d40255d8SDavid du Colombier n = 0; 67d40255d8SDavid du Colombier nk = 0; 68d40255d8SDavid du Colombier memset(ifs, 0, sizeof *ifs * MaxIfc); 69*f7db6155SDavid du Colombier for(i = 0; i < repsz; i += 2){ 70*f7db6155SDavid du Colombier if(n == MaxIfc) 71d40255d8SDavid du Colombier break; 72*f7db6155SDavid du Colombier if(repdesc[i] == HidEnd){ 73*f7db6155SDavid du Colombier i--; 74*f7db6155SDavid du Colombier ncoll--; 75*f7db6155SDavid du Colombier if(ncoll == 0) 76*f7db6155SDavid du Colombier break; 77*f7db6155SDavid du Colombier } 78d40255d8SDavid du Colombier 79d40255d8SDavid du Colombier switch(repdesc[i]){ 80*f7db6155SDavid du Colombier case HidReportId: 81*f7db6155SDavid du Colombier switch(repdesc[i+1]){ 82*f7db6155SDavid du Colombier case HidReportApp: 83*f7db6155SDavid du Colombier temp->id = repdesc[i+1]; 84*f7db6155SDavid du Colombier break; 85*f7db6155SDavid du Colombier default: 86*f7db6155SDavid du Colombier fprint(2, "report type %#ux bad\n", 87*f7db6155SDavid du Colombier repdesc[i+1]); 88*f7db6155SDavid du Colombier return -1; 89*f7db6155SDavid du Colombier } 90*f7db6155SDavid du Colombier break; 91d40255d8SDavid du Colombier case HidTypeUsg: 92d40255d8SDavid du Colombier switch(repdesc[i+1]){ 93d40255d8SDavid du Colombier case HidX: 94d40255d8SDavid du Colombier hasxy++; 95d40255d8SDavid du Colombier ks[nk++] = KindX; 96d40255d8SDavid du Colombier break; 97d40255d8SDavid du Colombier case HidY: 98d40255d8SDavid du Colombier hasxy++; 99d40255d8SDavid du Colombier ks[nk++] = KindY; 100d40255d8SDavid du Colombier break; 101d40255d8SDavid du Colombier case HidWheel: 102d40255d8SDavid du Colombier ks[nk++] = KindWheel; 103d40255d8SDavid du Colombier break; 104d40255d8SDavid du Colombier case HidPtr: 105d40255d8SDavid du Colombier isptr++; 106d40255d8SDavid du Colombier break; 107d40255d8SDavid du Colombier } 108d40255d8SDavid du Colombier break; 109d40255d8SDavid du Colombier case HidTypeUsgPg: 110d40255d8SDavid du Colombier switch(repdesc[i+1]){ 111d40255d8SDavid du Colombier case HidPgButts: 112d40255d8SDavid du Colombier hasbut++; 113d40255d8SDavid du Colombier ks[nk++] = KindButtons; 114d40255d8SDavid du Colombier break; 115d40255d8SDavid du Colombier } 116d40255d8SDavid du Colombier break; 117d40255d8SDavid du Colombier case HidTypeRepSz: 118d40255d8SDavid du Colombier ifs[n].nbits = repdesc[i+1]; 119d40255d8SDavid du Colombier break; 120d40255d8SDavid du Colombier case HidTypeCnt: 121d40255d8SDavid du Colombier ifs[n].count = repdesc[i+1]; 122d40255d8SDavid du Colombier break; 123d40255d8SDavid du Colombier case HidInput: 124d40255d8SDavid du Colombier for(j = 0; j <nk; j++) 125d40255d8SDavid du Colombier ifs[n].kind[j] = ks[j]; 126eb2d6162SDavid du Colombier if(nk != 0 && nk < ifs[n].count) 127d40255d8SDavid du Colombier for(l = j; l <ifs[n].count; l++) 128d40255d8SDavid du Colombier ifs[n].kind[l] = ks[j-1]; 129d40255d8SDavid du Colombier n++; 130eb2d6162SDavid du Colombier if(n < MaxIfc){ 131eb2d6162SDavid du Colombier ifs[n].count = ifs[n-1].count; /* inherit values */ 132eb2d6162SDavid du Colombier ifs[n].nbits = ifs[n-1].nbits; 133eb2d6162SDavid du Colombier } 134eb2d6162SDavid du Colombier if(ifs[n].nbits == 0) 135eb2d6162SDavid du Colombier ifs[n].nbits = 1; 136d40255d8SDavid du Colombier nk = 0; 137d40255d8SDavid du Colombier break; 138*f7db6155SDavid du Colombier case HidCollection: 139*f7db6155SDavid du Colombier ncoll++; 140*f7db6155SDavid du Colombier break; 141d40255d8SDavid du Colombier } 142d40255d8SDavid du Colombier } 143d40255d8SDavid du Colombier temp->nifcs = n; 144*f7db6155SDavid du Colombier for(i = 0; i < n; i++) 145*f7db6155SDavid du Colombier temp->sz += temp->ifcs[i].nbits * temp->ifcs[i].count; 146*f7db6155SDavid du Colombier temp->sz = (temp->sz + 7) / 8; 147*f7db6155SDavid du Colombier 148d40255d8SDavid du Colombier if(isptr && hasxy && hasbut) 149d40255d8SDavid du Colombier return 0; 150d40255d8SDavid du Colombier fprint(2, "bad report: isptr %d, hasxy %d, hasbut %d\n", 151d40255d8SDavid du Colombier isptr, hasxy, hasbut); 152d40255d8SDavid du Colombier return -1; 153d40255d8SDavid du Colombier } 154d40255d8SDavid du Colombier 155d40255d8SDavid du Colombier int 156d40255d8SDavid du Colombier parsereport(HidRepTempl *templ, Chain *rep) 157d40255d8SDavid du Colombier { 158d40255d8SDavid du Colombier int i, j, k, ifssz; 159d40255d8SDavid du Colombier ulong u; 160d40255d8SDavid du Colombier uchar *p; 161d40255d8SDavid du Colombier HidInterface *ifs; 162d40255d8SDavid du Colombier 163d40255d8SDavid du Colombier ifssz = templ->nifcs; 164d40255d8SDavid du Colombier ifs = templ->ifcs; 165d40255d8SDavid du Colombier for(i = 0; i < ifssz; i++) 166d40255d8SDavid du Colombier for(j = 0; j < ifs[i].count; j++){ 167d40255d8SDavid du Colombier if(ifs[i].nbits > 8 * sizeof ifs[i].v[0]){ 168d40255d8SDavid du Colombier fprint(2, "ptr: bad bits in parsereport"); 169d40255d8SDavid du Colombier return -1; 170d40255d8SDavid du Colombier } 171d40255d8SDavid du Colombier u =0; 172d40255d8SDavid du Colombier getbits(&u, rep, ifs[i].nbits); 173d40255d8SDavid du Colombier p = (uchar *)&u; 174d40255d8SDavid du Colombier /* le to host */ 175d40255d8SDavid du Colombier ifs[i].v[j] = p[3]<<24 | p[2]<<16 | p[1]<<8 | p[0]<<0; 176d40255d8SDavid du Colombier k = ifs[i].kind[j]; 177d40255d8SDavid du Colombier if(k == KindX || k == KindY || k == KindWheel){ 178d40255d8SDavid du Colombier /* propagate sign */ 179d40255d8SDavid du Colombier if(ifs[i].v[j] & (1 << (ifs[i].nbits - 1))) 180d40255d8SDavid du Colombier ifs[i].v[j] |= ~MSK(ifs[i].nbits); 181d40255d8SDavid du Colombier } 182d40255d8SDavid du Colombier } 183d40255d8SDavid du Colombier return 0; 184d40255d8SDavid du Colombier } 185d40255d8SDavid du Colombier 186d40255d8SDavid du Colombier /* TODO: fmt representation */ 187d40255d8SDavid du Colombier void 188d40255d8SDavid du Colombier dumpreport(HidRepTempl *templ) 189d40255d8SDavid du Colombier { 190d40255d8SDavid du Colombier int i, j, ifssz; 191d40255d8SDavid du Colombier HidInterface *ifs; 192d40255d8SDavid du Colombier 193d40255d8SDavid du Colombier ifssz = templ->nifcs; 194d40255d8SDavid du Colombier ifs = templ->ifcs; 195d40255d8SDavid du Colombier for(i = 0; i < ifssz; i++){ 196d40255d8SDavid du Colombier fprint(2, "\tcount %#ux", ifs[i].count); 197d40255d8SDavid du Colombier fprint(2, " nbits %d ", ifs[i].nbits); 198d40255d8SDavid du Colombier fprint(2, "\n"); 199d40255d8SDavid du Colombier for(j = 0; j < ifs[i].count; j++){ 200d40255d8SDavid du Colombier fprint(2, "\t\tkind %#ux ", ifs[i].kind[j]); 201d40255d8SDavid du Colombier fprint(2, "v %#lux\n", ifs[i].v[j]); 202d40255d8SDavid du Colombier } 203d40255d8SDavid du Colombier fprint(2, "\n"); 204d40255d8SDavid du Colombier } 205d40255d8SDavid du Colombier fprint(2, "\n"); 206d40255d8SDavid du Colombier } 207d40255d8SDavid du Colombier 208eb2d6162SDavid du Colombier /* could precalculate indices after parsing the descriptor */ 209d40255d8SDavid du Colombier int 210d40255d8SDavid du Colombier hidifcval(HidRepTempl *templ, int kind, int n) 211d40255d8SDavid du Colombier { 212d40255d8SDavid du Colombier int i, j, ifssz; 213d40255d8SDavid du Colombier HidInterface *ifs; 214d40255d8SDavid du Colombier 215d40255d8SDavid du Colombier ifssz = templ->nifcs; 216d40255d8SDavid du Colombier ifs = templ->ifcs; 217d40255d8SDavid du Colombier assert(n <= nelem(ifs[i].v)); 218d40255d8SDavid du Colombier for(i = 0; i < ifssz; i++) 219d40255d8SDavid du Colombier for(j = 0; j < ifs[i].count; j++) 220d40255d8SDavid du Colombier if(ifs[i].kind[j] == kind && n-- == 0) 221d40255d8SDavid du Colombier return (int)ifs[i].v[j]; 222d40255d8SDavid du Colombier return 0; /* least damage (no buttons, no movement) */ 223d40255d8SDavid du Colombier } 224