hid.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  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 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. /* TODO check report id, when it does appear (not all devices) */
  47. int
  48. parsereportdesc(HidRepTempl *temp, uchar *repdesc, int repsz)
  49. {
  50. int i, j, l, n, isptr, hasxy, hasbut, nk;
  51. int ks[MaxVals];
  52. HidInterface *ifs;
  53. ifs = temp->ifcs;
  54. isptr = 0;
  55. hasxy = hasbut = 0;
  56. n = 0;
  57. nk = 0;
  58. memset(ifs, 0, sizeof *ifs * MaxIfc);
  59. for(i = 0; i < repsz / 2; i += 2){
  60. if(n == MaxIfc || repdesc[i] == HidEnd)
  61. break;
  62. switch(repdesc[i]){
  63. case HidTypeUsg:
  64. switch(repdesc[i+1]){
  65. case HidX:
  66. hasxy++;
  67. ks[nk++] = KindX;
  68. break;
  69. case HidY:
  70. hasxy++;
  71. ks[nk++] = KindY;
  72. break;
  73. case HidWheel:
  74. ks[nk++] = KindWheel;
  75. break;
  76. case HidPtr:
  77. isptr++;
  78. break;
  79. }
  80. break;
  81. case HidTypeUsgPg:
  82. switch(repdesc[i+1]){
  83. case HidPgButts:
  84. hasbut++;
  85. ks[nk++] = KindButtons;
  86. break;
  87. }
  88. break;
  89. case HidTypeRepSz:
  90. ifs[n].nbits = repdesc[i+1];
  91. break;
  92. case HidTypeCnt:
  93. ifs[n].count = repdesc[i+1];
  94. break;
  95. case HidInput:
  96. for(j = 0; j <nk; j++)
  97. ifs[n].kind[j] = ks[j];
  98. if(nk < ifs[n].count)
  99. for(l = j; l <ifs[n].count; l++)
  100. ifs[n].kind[l] = ks[j-1];
  101. n++;
  102. nk = 0;
  103. break;
  104. }
  105. }
  106. temp->nifcs = n;
  107. if(isptr && hasxy && hasbut)
  108. return 0;
  109. fprint(2, "bad report: isptr %d, hasxy %d, hasbut %d\n",
  110. isptr, hasxy, hasbut);
  111. return -1;
  112. }
  113. int
  114. parsereport(HidRepTempl *templ, Chain *rep)
  115. {
  116. int i, j, k, ifssz;
  117. ulong u;
  118. uchar *p;
  119. HidInterface *ifs;
  120. ifssz = templ->nifcs;
  121. ifs = templ->ifcs;
  122. for(i = 0; i < ifssz; i++)
  123. for(j = 0; j < ifs[i].count; j++){
  124. if(ifs[i].nbits > 8 * sizeof ifs[i].v[0]){
  125. fprint(2, "ptr: bad bits in parsereport");
  126. return -1;
  127. }
  128. u =0;
  129. getbits(&u, rep, ifs[i].nbits);
  130. p = (uchar *)&u;
  131. /* le to host */
  132. ifs[i].v[j] = p[3]<<24 | p[2]<<16 | p[1]<<8 | p[0]<<0;
  133. k = ifs[i].kind[j];
  134. if(k == KindX || k == KindY || k == KindWheel){
  135. /* propagate sign */
  136. if(ifs[i].v[j] & (1 << (ifs[i].nbits - 1)))
  137. ifs[i].v[j] |= ~MSK(ifs[i].nbits);
  138. }
  139. }
  140. return 0;
  141. }
  142. /* TODO: fmt representation */
  143. void
  144. dumpreport(HidRepTempl *templ)
  145. {
  146. int i, j, ifssz;
  147. HidInterface *ifs;
  148. ifssz = templ->nifcs;
  149. ifs = templ->ifcs;
  150. for(i = 0; i < ifssz; i++){
  151. fprint(2, "\tcount %#ux", ifs[i].count);
  152. fprint(2, " nbits %d ", ifs[i].nbits);
  153. fprint(2, "\n");
  154. for(j = 0; j < ifs[i].count; j++){
  155. fprint(2, "\t\tkind %#ux ", ifs[i].kind[j]);
  156. fprint(2, "v %#lux\n", ifs[i].v[j]);
  157. }
  158. fprint(2, "\n");
  159. }
  160. fprint(2, "\n");
  161. }
  162. /* could cache indices after parsing the descriptor */
  163. int
  164. hidifcval(HidRepTempl *templ, int kind, int n)
  165. {
  166. int i, j, ifssz;
  167. HidInterface *ifs;
  168. ifssz = templ->nifcs;
  169. ifs = templ->ifcs;
  170. assert(n <= nelem(ifs[i].v));
  171. for(i = 0; i < ifssz; i++)
  172. for(j = 0; j < ifs[i].count; j++)
  173. if(ifs[i].kind[j] == kind && n-- == 0)
  174. return (int)ifs[i].v[j];
  175. return 0; /* least damage (no buttons, no movement) */
  176. }