usbmouse.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /*
  2. * usbmouse - listen for usb mouse events and turn them into
  3. * writes on /dev/mousein.
  4. */
  5. #include <u.h>
  6. #include <libc.h>
  7. #include <bio.h>
  8. #include <thread.h>
  9. int mousefd, ctlfd, mousein;
  10. char hbm[] = "0x020103";
  11. char *mouseinfile = "/dev/mousein";
  12. char *statfmt = "/dev/usb%d/%d/status";
  13. char *ctlfmt = "/dev/usb%d/%d/ctl";
  14. char *msefmt = "/dev/usb%d/%d/ep%ddata";
  15. char *ctlmsgfmt = "ep %d bulk r %d 32";
  16. char ctlfile[32];
  17. char msefile[32];
  18. int verbose;
  19. int nofork;
  20. int accel;
  21. int scroll;
  22. int maxacc = 3;
  23. int debug;
  24. int nbuts;
  25. void work(void *);
  26. int
  27. robusthandler(void*, char *s)
  28. {
  29. if (debug) fprint(2, "inthandler: %s\n", s);
  30. return s && (strstr(s, "interrupted") || strstr(s, "hangup"));
  31. }
  32. long
  33. robustread(int fd, void *buf, long sz)
  34. {
  35. long r;
  36. char err[ERRMAX];
  37. do {
  38. r = read(fd , buf, sz);
  39. if (r < 0)
  40. rerrstr(err, sizeof(err));
  41. } while (r < 0 && robusthandler(nil, err));
  42. return r;
  43. }
  44. static int
  45. scale(int x)
  46. {
  47. int sign = 1;
  48. if(x < 0){
  49. sign = -1;
  50. x = -x;
  51. }
  52. switch(x){
  53. case 0:
  54. case 1:
  55. case 2:
  56. case 3:
  57. break;
  58. case 4:
  59. x = 6 + (accel>>2);
  60. break;
  61. case 5:
  62. x = 9 + (accel>>1);
  63. break;
  64. default:
  65. x *= maxacc;
  66. break;
  67. }
  68. return sign*x;
  69. }
  70. char maptab[] = {
  71. 0x0, 0x1, 0x4, 0x5, 0x2, 0x3, 0x6, 0x7
  72. };
  73. void
  74. usage(void)
  75. {
  76. fprint(2, "usage: %s [-fsv] [-a accel] [ctlrno usbport]\n", argv0);
  77. threadexitsall("usage");
  78. }
  79. void
  80. threadmain(int argc, char *argv[])
  81. {
  82. int ctlrno, i, ep = 0;
  83. char *p, *ctlstr;
  84. char buf[256];
  85. Biobuf *f;
  86. ARGBEGIN{
  87. case 's':
  88. scroll=1;
  89. break;
  90. case 'v':
  91. verbose=1;
  92. break;
  93. case 'f':
  94. nofork=1;
  95. break;
  96. case 'a':
  97. accel=strtol(EARGF(usage()), nil, 0);
  98. break;
  99. default:
  100. usage();
  101. }ARGEND
  102. switch (argc) {
  103. case 0:
  104. for (ctlrno = 0; ctlrno < 16; ctlrno++) {
  105. sprint(buf, "/dev/usb%d", ctlrno);
  106. if (access(buf, AEXIST) < 0)
  107. continue;
  108. for (i = 1; i < 128; i++) {
  109. snprint(buf, sizeof buf, statfmt, ctlrno, i);
  110. f = Bopen(buf, OREAD);
  111. if (f == nil)
  112. break;
  113. while ((p = Brdline(f, '\n')) != 0) {
  114. p[Blinelen(f)-1] = '\0';
  115. if (strncmp(p, "Enabled ", 8) == 0)
  116. continue;
  117. if (strstr(p, hbm) != nil) {
  118. ep = atoi(p);
  119. goto found;
  120. }
  121. }
  122. Bterm(f);
  123. }
  124. }
  125. threadexitsall("no mouse");
  126. case 2:
  127. ctlrno = atoi(argv[0]);
  128. i = atoi(argv[1]);
  129. ep = 1; /* a guess */
  130. if (verbose)
  131. fprint(2, "assuming endpoint %d\n", ep);
  132. found:
  133. snprint(ctlfile, sizeof ctlfile, ctlfmt, ctlrno, i);
  134. snprint(msefile, sizeof msefile, msefmt, ctlrno, i, ep);
  135. break;
  136. default:
  137. usage();
  138. }
  139. nbuts = (scroll? 5: 3);
  140. ctlstr = smprint(ctlmsgfmt, ep, nbuts);
  141. if ((ctlfd = open(ctlfile, OWRITE)) < 0)
  142. sysfatal("%s: %r", ctlfile);
  143. if (verbose)
  144. fprint(2, "Send %s to %s\n", ctlstr, ctlfile);
  145. write(ctlfd, ctlstr, strlen(ctlstr));
  146. close(ctlfd);
  147. free(ctlstr);
  148. if ((mousefd = open(msefile, OREAD)) < 0)
  149. sysfatal("%s: %r", msefile);
  150. if (verbose)
  151. fprint(2, "Start reading from %s\n", msefile);
  152. if ((mousein = open(mouseinfile, OWRITE)) < 0)
  153. sysfatal("%s: %r", mouseinfile);
  154. atnotify(robusthandler, 1);
  155. if (nofork)
  156. work(nil);
  157. else
  158. proccreate(work, nil, 4*1024);
  159. threadexits(nil);
  160. }
  161. void
  162. work(void *)
  163. {
  164. char buf[6];
  165. int x, y, buts;
  166. for (;;) {
  167. buts = 0;
  168. switch (robustread(mousefd, buf, nbuts)) {
  169. case 4:
  170. if(buf[3] == 1)
  171. buts |= 0x08;
  172. else if(buf[3] == -1)
  173. buts |= 0x10;
  174. /* Fall through */
  175. case 5:
  176. if(buf[3] > 10)
  177. buts |= 0x08;
  178. else if(buf[3] < -10)
  179. buts |= 0x10;
  180. /* Fall through */
  181. case 3:
  182. if (accel) {
  183. x = scale(buf[1]);
  184. y = scale(buf[2]);
  185. } else {
  186. x = buf[1];
  187. y = buf[2];
  188. }
  189. fprint(mousein, "m%11d %11d %11d",
  190. x, y, buts | maptab[buf[0]&0x7]);
  191. break;
  192. case -1:
  193. sysfatal("read error: %r");
  194. }
  195. }
  196. }