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