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