hid.c 4.6 KB

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