usbmouse.c 3.5 KB

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