123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234 |
- #include <u.h>
- #include <libc.h>
- #include <thread.h>
- #include "usb.h"
- #include "hid.h"
- /*
- * Rough hid descriptor parsing and interpretation for mice
- *
- * Chain and its operations build the infrastructure needed
- * to manipulate non-aligned fields, which do appear (sigh!).
- */
- /* Get, at most, 8 bits*/
- static uchar
- get8bits(Chain *ch, int nbits)
- {
- int b, nbyb, nbib, nlb;
- uchar low, high;
- b = ch->b + nbits - 1;
- nbib = ch->b % 8;
- nbyb = ch->b / 8;
- nlb = 8 - nbib;
- if(nlb > nbits)
- nlb = nbits;
- low = MSK(nlb) & (ch->buf[nbyb] >> nbib);
- if(IsCut(ch->b, b))
- high = (ch->buf[nbyb + 1] & MSK(nbib)) << nlb;
- else
- high = 0;
- ch->b += nbits;
- return MSK(nbits)&(high | low);
- }
- static void
- getbits(void *p, Chain *ch, int nbits)
- {
- int nby, nbi, i;
- uchar *vp;
- assert(ch->e >= ch->b);
- nby = nbits / 8;
- nbi = nbits % 8;
- vp = p;
- for(i = 0; i < nby; i++)
- *vp++ = get8bits(ch, 8);
- if(nbi != 0)
- *vp = get8bits(ch, nbi);
- }
- int
- parsereportdesc(HidRepTempl *temp, uchar *repdesc, int repsz)
- {
- int i, j, l, n, isptr, hasxy, hasbut, nk, ncoll, dsize;
- uchar ks[MaxVals+1];
- HidInterface *ifs;
- ifs = temp->ifcs;
- isptr = 0;
- hasxy = hasbut = 0;
- ncoll = 0;
- n = 0;
- nk = 0;
- memset(ifs, 0, sizeof *ifs * MaxIfc);
- for(i = 0; i < repsz; i += dsize+1){
- dsize = (1 << (repdesc[i] & 03)) >> 1;
- if(nk > MaxVals){
- fprint(2, "bad report: too many input types\n");
- return -1;
- }
- if(n == MaxIfc)
- break;
- if(repdesc[i] == HidEnd){
- ncoll--;
- if(ncoll == 0)
- break;
- }
- switch(repdesc[i]){
- case HidReportId:
- switch(repdesc[i+1]){
- case HidReportIdPtr:
- temp->id = repdesc[i+1];
- break;
- default:
- fprint(2, "report type %#ux bad\n",
- repdesc[i+1]);
- return -1;
- }
- break;
- case HidTypeUsg:
- switch(repdesc[i+1]){
- case HidX:
- hasxy++;
- ks[nk++] = KindX;
- break;
- case HidY:
- hasxy++;
- ks[nk++] = KindY;
- break;
- case HidZ:
- ks[nk++] = KindPad;
- break;
- case HidWheel:
- ks[nk++] = KindWheel;
- break;
- case HidPtr:
- isptr++;
- break;
- }
- break;
- case HidTypeUsgPg:
- switch(repdesc[i+1]){
- case HidPgButts:
- hasbut++;
- ks[nk++] = KindButtons;
- break;
- }
- break;
- case HidTypeRepSz:
- ifs[n].nbits = repdesc[i+1];
- break;
- case HidTypeCnt:
- ifs[n].count = repdesc[i+1];
- break;
- case HidInput:
- if(ifs[n].count > MaxVals){
- fprint(2, "bad report: input count too big\n");
- return -1;
- }
- for(j = 0; j <nk; j++)
- ifs[n].kind[j] = ks[j];
- if(nk != 0 && nk < ifs[n].count)
- for(l = j; l <ifs[n].count; l++)
- ifs[n].kind[l] = ks[j-1];
- n++;
- if(n < MaxIfc){
- ifs[n].count = ifs[n-1].count; /* inherit values */
- ifs[n].nbits = ifs[n-1].nbits;
- if(ifs[n].nbits == 0)
- ifs[n].nbits = 1;
- }
- nk = 0;
- break;
- case HidCollection:
- ncoll++;
- break;
- }
- }
- temp->nifcs = n;
- for(i = 0; i < n; i++)
- temp->sz += temp->ifcs[i].nbits * temp->ifcs[i].count;
- temp->sz = (temp->sz + 7) / 8;
-
- if(isptr && hasxy && hasbut)
- return 0;
- fprint(2, "bad report: isptr %d, hasxy %d, hasbut %d\n",
- isptr, hasxy, hasbut);
- return -1;
- }
- int
- parsereport(HidRepTempl *templ, Chain *rep)
- {
- int i, j, k, ifssz;
- ulong u;
- uchar *p;
- HidInterface *ifs;
- ifssz = templ->nifcs;
- ifs = templ->ifcs;
- for(i = 0; i < ifssz; i++)
- for(j = 0; j < ifs[i].count; j++){
- if(ifs[i].nbits > 8 * sizeof ifs[i].v[0]){
- fprint(2, "ptr: bad bits in parsereport");
- return -1;
- }
- u =0;
- getbits(&u, rep, ifs[i].nbits);
- p = (uchar *)&u;
- /* le to host */
- ifs[i].v[j] = p[3]<<24 | p[2]<<16 | p[1]<<8 | p[0]<<0;
- k = ifs[i].kind[j];
- if(k == KindX || k == KindY || k == KindWheel){
- /* propagate sign */
- if(ifs[i].v[j] & (1 << (ifs[i].nbits - 1)))
- ifs[i].v[j] |= ~MSK(ifs[i].nbits);
- }
- }
- return 0;
- }
- /* TODO: fmt representation */
- void
- dumpreport(HidRepTempl *templ)
- {
- int i, j, ifssz;
- HidInterface *ifs;
- ifssz = templ->nifcs;
- ifs = templ->ifcs;
- for(i = 0; i < ifssz; i++){
- fprint(2, "\tcount %#ux", ifs[i].count);
- fprint(2, " nbits %d ", ifs[i].nbits);
- fprint(2, "\n");
- for(j = 0; j < ifs[i].count; j++){
- fprint(2, "\t\tkind %#ux ", ifs[i].kind[j]);
- fprint(2, "v %#lux\n", ifs[i].v[j]);
- }
- fprint(2, "\n");
- }
- fprint(2, "\n");
- }
- /* could precalculate indices after parsing the descriptor */
- int
- hidifcval(HidRepTempl *templ, int kind, int n)
- {
- int i, j, ifssz;
- HidInterface *ifs;
- ifssz = templ->nifcs;
- ifs = templ->ifcs;
- assert(n <= nelem(ifs[i].v));
- for(i = 0; i < ifssz; i++)
- for(j = 0; j < ifs[i].count; j++)
- if(ifs[i].kind[j] == kind && n-- == 0)
- return (int)ifs[i].v[j];
- return 0; /* least damage (no buttons, no movement) */
- }
|