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; 34d40255d8SDavid du Colombier return 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 /* TODO check report id, when it does appear (not all devices) */ 56d40255d8SDavid du Colombier int 57d40255d8SDavid du Colombier parsereportdesc(HidRepTempl *temp, uchar *repdesc, int repsz) 58d40255d8SDavid du Colombier { 59d40255d8SDavid du Colombier int i, j, l, n, isptr, hasxy, hasbut, nk; 60d40255d8SDavid du Colombier int ks[MaxVals]; 61d40255d8SDavid du Colombier HidInterface *ifs; 62d40255d8SDavid du Colombier 63d40255d8SDavid du Colombier ifs = temp->ifcs; 64d40255d8SDavid du Colombier isptr = 0; 65d40255d8SDavid du Colombier hasxy = hasbut = 0; 66d40255d8SDavid du Colombier n = 0; 67d40255d8SDavid du Colombier nk = 0; 68d40255d8SDavid du Colombier memset(ifs, 0, sizeof *ifs * MaxIfc); 69d40255d8SDavid du Colombier for(i = 0; i < repsz / 2; i += 2){ 70d40255d8SDavid du Colombier if(n == MaxIfc || repdesc[i] == HidEnd) 71d40255d8SDavid du Colombier break; 72d40255d8SDavid du Colombier 73d40255d8SDavid du Colombier switch(repdesc[i]){ 74d40255d8SDavid du Colombier case HidTypeUsg: 75d40255d8SDavid du Colombier switch(repdesc[i+1]){ 76d40255d8SDavid du Colombier case HidX: 77d40255d8SDavid du Colombier hasxy++; 78d40255d8SDavid du Colombier ks[nk++] = KindX; 79d40255d8SDavid du Colombier break; 80d40255d8SDavid du Colombier case HidY: 81d40255d8SDavid du Colombier hasxy++; 82d40255d8SDavid du Colombier ks[nk++] = KindY; 83d40255d8SDavid du Colombier break; 84d40255d8SDavid du Colombier case HidWheel: 85d40255d8SDavid du Colombier ks[nk++] = KindWheel; 86d40255d8SDavid du Colombier break; 87d40255d8SDavid du Colombier case HidPtr: 88d40255d8SDavid du Colombier isptr++; 89d40255d8SDavid du Colombier break; 90d40255d8SDavid du Colombier } 91d40255d8SDavid du Colombier break; 92d40255d8SDavid du Colombier case HidTypeUsgPg: 93d40255d8SDavid du Colombier switch(repdesc[i+1]){ 94d40255d8SDavid du Colombier case HidPgButts: 95d40255d8SDavid du Colombier hasbut++; 96d40255d8SDavid du Colombier ks[nk++] = KindButtons; 97d40255d8SDavid du Colombier break; 98d40255d8SDavid du Colombier } 99d40255d8SDavid du Colombier break; 100d40255d8SDavid du Colombier case HidTypeRepSz: 101d40255d8SDavid du Colombier ifs[n].nbits = repdesc[i+1]; 102d40255d8SDavid du Colombier break; 103d40255d8SDavid du Colombier case HidTypeCnt: 104d40255d8SDavid du Colombier ifs[n].count = repdesc[i+1]; 105d40255d8SDavid du Colombier break; 106d40255d8SDavid du Colombier case HidInput: 107d40255d8SDavid du Colombier for(j = 0; j <nk; j++) 108d40255d8SDavid du Colombier ifs[n].kind[j] = ks[j]; 109*eb2d6162SDavid du Colombier if(nk != 0 && nk < ifs[n].count) 110d40255d8SDavid du Colombier for(l = j; l <ifs[n].count; l++) 111d40255d8SDavid du Colombier ifs[n].kind[l] = ks[j-1]; 112d40255d8SDavid du Colombier n++; 113*eb2d6162SDavid du Colombier if(n < MaxIfc){ 114*eb2d6162SDavid du Colombier ifs[n].count = ifs[n-1].count; /* inherit values */ 115*eb2d6162SDavid du Colombier ifs[n].nbits = ifs[n-1].nbits; 116*eb2d6162SDavid du Colombier } 117*eb2d6162SDavid du Colombier if(ifs[n].nbits == 0) 118*eb2d6162SDavid du Colombier ifs[n].nbits = 1; 119d40255d8SDavid du Colombier nk = 0; 120d40255d8SDavid du Colombier break; 121d40255d8SDavid du Colombier } 122d40255d8SDavid du Colombier } 123d40255d8SDavid du Colombier temp->nifcs = n; 124d40255d8SDavid du Colombier if(isptr && hasxy && hasbut) 125d40255d8SDavid du Colombier return 0; 126d40255d8SDavid du Colombier fprint(2, "bad report: isptr %d, hasxy %d, hasbut %d\n", 127d40255d8SDavid du Colombier isptr, hasxy, hasbut); 128d40255d8SDavid du Colombier return -1; 129d40255d8SDavid du Colombier } 130d40255d8SDavid du Colombier 131d40255d8SDavid du Colombier int 132d40255d8SDavid du Colombier parsereport(HidRepTempl *templ, Chain *rep) 133d40255d8SDavid du Colombier { 134d40255d8SDavid du Colombier int i, j, k, ifssz; 135d40255d8SDavid du Colombier ulong u; 136d40255d8SDavid du Colombier uchar *p; 137d40255d8SDavid du Colombier HidInterface *ifs; 138d40255d8SDavid du Colombier 139d40255d8SDavid du Colombier ifssz = templ->nifcs; 140d40255d8SDavid du Colombier ifs = templ->ifcs; 141d40255d8SDavid du Colombier for(i = 0; i < ifssz; i++) 142d40255d8SDavid du Colombier for(j = 0; j < ifs[i].count; j++){ 143d40255d8SDavid du Colombier if(ifs[i].nbits > 8 * sizeof ifs[i].v[0]){ 144d40255d8SDavid du Colombier fprint(2, "ptr: bad bits in parsereport"); 145d40255d8SDavid du Colombier return -1; 146d40255d8SDavid du Colombier } 147d40255d8SDavid du Colombier u =0; 148d40255d8SDavid du Colombier getbits(&u, rep, ifs[i].nbits); 149d40255d8SDavid du Colombier p = (uchar *)&u; 150d40255d8SDavid du Colombier /* le to host */ 151d40255d8SDavid du Colombier ifs[i].v[j] = p[3]<<24 | p[2]<<16 | p[1]<<8 | p[0]<<0; 152d40255d8SDavid du Colombier k = ifs[i].kind[j]; 153d40255d8SDavid du Colombier if(k == KindX || k == KindY || k == KindWheel){ 154d40255d8SDavid du Colombier /* propagate sign */ 155d40255d8SDavid du Colombier if(ifs[i].v[j] & (1 << (ifs[i].nbits - 1))) 156d40255d8SDavid du Colombier ifs[i].v[j] |= ~MSK(ifs[i].nbits); 157d40255d8SDavid du Colombier } 158d40255d8SDavid du Colombier } 159d40255d8SDavid du Colombier return 0; 160d40255d8SDavid du Colombier } 161d40255d8SDavid du Colombier 162d40255d8SDavid du Colombier /* TODO: fmt representation */ 163d40255d8SDavid du Colombier void 164d40255d8SDavid du Colombier dumpreport(HidRepTempl *templ) 165d40255d8SDavid du Colombier { 166d40255d8SDavid du Colombier int i, j, ifssz; 167d40255d8SDavid du Colombier HidInterface *ifs; 168d40255d8SDavid du Colombier 169d40255d8SDavid du Colombier ifssz = templ->nifcs; 170d40255d8SDavid du Colombier ifs = templ->ifcs; 171d40255d8SDavid du Colombier for(i = 0; i < ifssz; i++){ 172d40255d8SDavid du Colombier fprint(2, "\tcount %#ux", ifs[i].count); 173d40255d8SDavid du Colombier fprint(2, " nbits %d ", ifs[i].nbits); 174d40255d8SDavid du Colombier fprint(2, "\n"); 175d40255d8SDavid du Colombier for(j = 0; j < ifs[i].count; j++){ 176d40255d8SDavid du Colombier fprint(2, "\t\tkind %#ux ", ifs[i].kind[j]); 177d40255d8SDavid du Colombier fprint(2, "v %#lux\n", ifs[i].v[j]); 178d40255d8SDavid du Colombier } 179d40255d8SDavid du Colombier fprint(2, "\n"); 180d40255d8SDavid du Colombier } 181d40255d8SDavid du Colombier fprint(2, "\n"); 182d40255d8SDavid du Colombier } 183d40255d8SDavid du Colombier 184*eb2d6162SDavid du Colombier /* could precalculate indices after parsing the descriptor */ 185d40255d8SDavid du Colombier int 186d40255d8SDavid du Colombier hidifcval(HidRepTempl *templ, int kind, int n) 187d40255d8SDavid du Colombier { 188d40255d8SDavid du Colombier int i, j, ifssz; 189d40255d8SDavid du Colombier HidInterface *ifs; 190d40255d8SDavid du Colombier 191d40255d8SDavid du Colombier ifssz = templ->nifcs; 192d40255d8SDavid du Colombier ifs = templ->ifcs; 193d40255d8SDavid du Colombier assert(n <= nelem(ifs[i].v)); 194d40255d8SDavid du Colombier for(i = 0; i < ifssz; i++) 195d40255d8SDavid du Colombier for(j = 0; j < ifs[i].count; j++) 196d40255d8SDavid du Colombier if(ifs[i].kind[j] == kind && n-- == 0) 197d40255d8SDavid du Colombier return (int)ifs[i].v[j]; 198d40255d8SDavid du Colombier return 0; /* least damage (no buttons, no movement) */ 199d40255d8SDavid du Colombier } 200