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