usbmouse.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  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. #include "usb.h"
  10. typedef struct {
  11. int epno;
  12. int maxpkt;
  13. int pollms;
  14. } Mouseinfo;
  15. void (*dprinter[])(Device *, int, ulong, void *b, int n) = {
  16. [STRING] pstring,
  17. [DEVICE] pdevice,
  18. [HID] phid,
  19. };
  20. int mousefd, ctlfd, mousein;
  21. char hbm[] = "0x020103";
  22. char *mouseinfile = "/dev/mousein";
  23. char *statfmt = "/dev/usb%d/%d/status";
  24. char *ctlfmt = "/dev/usb%d/%d/ctl";
  25. char *msefmt = "/dev/usb%d/%d/ep%ddata";
  26. char *ctlmsgfmt = "ep %d %d r %d";
  27. char ctlfile[32];
  28. char msefile[32];
  29. int verbose;
  30. int nofork;
  31. int debug;
  32. int accel;
  33. int scroll;
  34. int maxacc = 3;
  35. int nbuts;
  36. void work(void *);
  37. int
  38. findendpoint(int ctlr, int id, Mouseinfo *mp)
  39. {
  40. int i;
  41. Device *d;
  42. Endpt *ep;
  43. d = opendev(ctlr, id);
  44. d->config[0] = emallocz(sizeof(*d->config[0]), 1);
  45. if (describedevice(d) < 0 || loadconfig(d, 0) < 0) {
  46. closedev(d);
  47. return -1;
  48. }
  49. for (i = 1; i < Nendpt; i++) {
  50. if ((ep = d->ep[i]) == nil)
  51. continue;
  52. if (ep->csp == 0x020103 && ep->type == Eintr && ep->dir != Eout) {
  53. if (ep->iface == nil || ep->iface->dalt[0] == nil)
  54. continue;
  55. mp->epno = i;
  56. mp->maxpkt = ep->maxpkt;
  57. mp->pollms = ep->iface->dalt[0]->interval;
  58. closedev(d);
  59. return 0;
  60. }
  61. }
  62. closedev(d);
  63. return -1;
  64. }
  65. int
  66. robusthandler(void*, char *s)
  67. {
  68. if (debug)
  69. fprint(2, "inthandler: %s\n", s);
  70. return s && (strstr(s, "interrupted") || strstr(s, "hangup"));
  71. }
  72. long
  73. robustread(int fd, void *buf, long sz)
  74. {
  75. long r;
  76. char err[ERRMAX];
  77. do {
  78. r = read(fd , buf, sz);
  79. if (r < 0)
  80. rerrstr(err, sizeof(err));
  81. } while (r < 0 && robusthandler(nil, err));
  82. return r;
  83. }
  84. static int
  85. scale(int x)
  86. {
  87. int sign = 1;
  88. if(x < 0){
  89. sign = -1;
  90. x = -x;
  91. }
  92. switch(x){
  93. case 0:
  94. case 1:
  95. case 2:
  96. case 3:
  97. break;
  98. case 4:
  99. x = 6 + (accel>>2);
  100. break;
  101. case 5:
  102. x = 9 + (accel>>1);
  103. break;
  104. default:
  105. x *= maxacc;
  106. break;
  107. }
  108. return sign*x;
  109. }
  110. char maptab[] = {
  111. 0x0, 0x1, 0x4, 0x5, 0x2, 0x3, 0x6, 0x7
  112. };
  113. void
  114. usage(void)
  115. {
  116. fprint(2, "usage: %s [-fsv] [-a accel] [ctlrno usbport]\n", argv0);
  117. threadexitsall("usage");
  118. }
  119. void
  120. threadmain(int argc, char *argv[])
  121. {
  122. int ctlrno, i;
  123. char *p;
  124. char buf[256];
  125. Biobuf *f;
  126. Mouseinfo mouse;
  127. ARGBEGIN{
  128. case 'd':
  129. debug=1;
  130. break;
  131. case 's':
  132. scroll=1;
  133. break;
  134. case 'v':
  135. verbose=1;
  136. break;
  137. case 'f':
  138. nofork=1;
  139. break;
  140. case 'a':
  141. accel=strtol(EARGF(usage()), nil, 0);
  142. break;
  143. default:
  144. usage();
  145. }ARGEND
  146. memset(&mouse, 0, sizeof mouse);
  147. f = nil;
  148. switch (argc) {
  149. case 0:
  150. for (ctlrno = 0; ctlrno < 16; ctlrno++) {
  151. sprint(buf, "/dev/usb%d", ctlrno);
  152. if (access(buf, AEXIST) < 0)
  153. continue;
  154. for (i = 1; i < 128; i++) {
  155. snprint(buf, sizeof buf, statfmt, ctlrno, i);
  156. f = Bopen(buf, OREAD);
  157. if (f == nil)
  158. break;
  159. while ((p = Brdline(f, '\n')) != 0) {
  160. p[Blinelen(f)-1] = '\0';
  161. if (strncmp(p, "Enabled ", 8) == 0)
  162. continue;
  163. if (strstr(p, hbm) != nil) {
  164. Bterm(f);
  165. goto found;
  166. }
  167. }
  168. Bterm(f);
  169. }
  170. }
  171. threadexitsall("no mouse");
  172. case 2:
  173. ctlrno = atoi(argv[0]);
  174. i = atoi(argv[1]);
  175. found:
  176. if(findendpoint(ctlrno, i, &mouse) < 0) {
  177. fprint(2, "%s: invalid usb device configuration\n",
  178. argv0);
  179. threadexitsall("no mouse");
  180. }
  181. snprint(ctlfile, sizeof ctlfile, ctlfmt, ctlrno, i);
  182. snprint(msefile, sizeof msefile, msefmt, ctlrno, i, mouse.epno);
  183. break;
  184. default:
  185. usage();
  186. }
  187. if (f)
  188. Bterm(f);
  189. nbuts = (scroll? 5: 3);
  190. if (nbuts > mouse.maxpkt)
  191. nbuts = mouse.maxpkt;
  192. if ((ctlfd = open(ctlfile, OWRITE)) < 0)
  193. sysfatal("%s: %r", ctlfile);
  194. if (verbose)
  195. fprint(2, "Send mouse.ep %d %d r %d to %s\n",
  196. mouse.epno, mouse.pollms, mouse.maxpkt, ctlfile);
  197. fprint(ctlfd, ctlmsgfmt, mouse.epno, mouse.pollms, mouse.maxpkt);
  198. close(ctlfd);
  199. if ((mousefd = open(msefile, OREAD)) < 0)
  200. sysfatal("%s: %r", msefile);
  201. if (verbose)
  202. fprint(2, "Start reading from %s\n", msefile);
  203. if ((mousein = open(mouseinfile, OWRITE)) < 0)
  204. sysfatal("%s: %r", mouseinfile);
  205. atnotify(robusthandler, 1);
  206. if (nofork)
  207. work(nil);
  208. else
  209. proccreate(work, nil, 4*1024);
  210. threadexits(nil);
  211. }
  212. void
  213. work(void *)
  214. {
  215. char buf[6];
  216. int x, y, buts;
  217. for (;;) {
  218. buts = 0;
  219. switch (robustread(mousefd, buf, nbuts)) {
  220. case 4:
  221. if(buf[3] == 1)
  222. buts |= 0x08;
  223. else if(buf[3] == -1)
  224. buts |= 0x10;
  225. /* Fall through */
  226. case 5:
  227. if(buf[3] > 10)
  228. buts |= 0x08;
  229. else if(buf[3] < -10)
  230. buts |= 0x10;
  231. /* Fall through */
  232. case 3:
  233. if (accel) {
  234. x = scale(buf[1]);
  235. y = scale(buf[2]);
  236. } else {
  237. x = buf[1];
  238. y = buf[2];
  239. }
  240. fprint(mousein, "m%11d %11d %11d",
  241. x, y, buts | maptab[buf[0]&0x7]);
  242. break;
  243. case -1:
  244. sysfatal("read error: %r");
  245. }
  246. }
  247. }