keyb.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <fcall.h>
  12. #include <thread.h>
  13. #include <9p.h>
  14. typedef struct Usbkeyb Usbkeyb;
  15. typedef struct Dirtab Dirtab;
  16. enum {
  17. Qdir = 0,
  18. Qkeyb,
  19. Qmouse,
  20. Qmax,
  21. };
  22. struct Usbkeyb {
  23. Usbkeyb *next;
  24. Dev *dev;
  25. char name[32];
  26. int pid;
  27. };
  28. struct Dirtab {
  29. char *name;
  30. Qid qid;
  31. int64_t length;
  32. int32_t mode;
  33. };
  34. static uint32_t time0;
  35. static Usbkeyb *keybs;
  36. static Dirtab dirtab[] = {
  37. {".", {Qdir, 0, QTDIR}, 0, 0555},
  38. {"keyb", {Qkeyb, 0, 0}, 0, 0444},
  39. {"mouse", {Qmouse, 0, 0}, 0, 0444},
  40. };
  41. static int
  42. keybdirgen(int qidpath, Dir *dirp, void *v)
  43. {
  44. if(qidpath >= Qmax)
  45. return -1;
  46. memset(dirp, 0, sizeof dirp[0]);
  47. dirp->qid = dirtab[qidpath].qid;
  48. dirp->name = estrdup9p(dirtab[qidpath].name);
  49. dirp->mode = dirtab[qidpath].mode;
  50. dirp->atime = time0;
  51. dirp->mtime = time0;
  52. dirp->uid = estrdup9p("");
  53. dirp->gid = estrdup9p("");
  54. dirp->muid = estrdup9p("");
  55. return 0;
  56. }
  57. static void
  58. keybattach(Req *r)
  59. {
  60. char *spec;
  61. spec = r->ifcall.aname;
  62. if(spec && spec[0]){
  63. respond(r, "invalid attach specifier");
  64. return;
  65. }
  66. r->ofcall.qid = dirtab[Qdir].qid;
  67. r->fid->qid = r->ofcall.qid;
  68. respond(r, nil);
  69. }
  70. static char *
  71. keybwalk1(Fid *fid, char *name, Qid *qid)
  72. {
  73. int i;
  74. if(fid->qid.path != Qdir)
  75. return "fswalk1: bad qid";
  76. for(i = 1; i < Qmax; i++){
  77. if(!strcmp(dirtab[i].name, name)){
  78. fid->qid = dirtab[i].qid;
  79. *qid = dirtab[i].qid;
  80. return nil;
  81. }
  82. }
  83. return "no such file or directory";
  84. }
  85. static void
  86. keybstat(Req *r)
  87. {
  88. if(keybdirgen((int)r->fid->qid.path, &r->d, nil) == -1)
  89. respond(r, "bad qid");
  90. respond(r, nil);
  91. }
  92. static void
  93. keybread(Req *r)
  94. {
  95. int qidpath;
  96. qidpath = r->fid->qid.path;
  97. switch(qidpath){
  98. case Qdir:
  99. dirread9p(r, keybdirgen, nil);
  100. respond(r, nil);
  101. return;
  102. default:
  103. respond(r, "not implemented");
  104. return;
  105. }
  106. }
  107. static void
  108. keybwrite(Req *r)
  109. {
  110. respond(r, "prohibition ale");
  111. }
  112. static void
  113. keybopen(Req *r)
  114. {
  115. if(r->fid->qid.path >= Qmax){
  116. respond(r, "bad qid");
  117. return;
  118. }
  119. if(r->ifcall.mode != OREAD)
  120. respond(r, "permission denied");
  121. respond(r, nil);
  122. }
  123. Srv keybsrv = {
  124. .attach = keybattach,
  125. .open = keybopen,
  126. .read = keybread,
  127. .write = keybwrite,
  128. .stat = keybstat,
  129. .walk1 = keybwalk1,
  130. };
  131. static void
  132. usage(void)
  133. {
  134. fprint(2, "usage: usb/keyb [-D] [-m mtpt] [-S srvname]\n");
  135. exits("usage");
  136. }
  137. static int
  138. cmdreq(Dev *d, int type, int req, int value, int index, uint8_t *data, int count)
  139. {
  140. int ndata, n;
  141. uint8_t *wp;
  142. uint8_t buf[8];
  143. char *hd, *rs;
  144. assert(d != nil);
  145. if(data == nil){
  146. wp = buf;
  147. ndata = 0;
  148. }else{
  149. ndata = count;
  150. wp = emallocz(8+ndata, 0);
  151. }
  152. wp[0] = type;
  153. wp[1] = req;
  154. PUT2(wp+2, value);
  155. PUT2(wp+4, index);
  156. PUT2(wp+6, count);
  157. if(data != nil)
  158. memmove(wp+8, data, ndata);
  159. if(usbdebug>2){
  160. hd = hexstr(wp, ndata+8);
  161. rs = reqstr(type, req);
  162. fprint(2, "%s: %s val %d|%d idx %d cnt %d out[%d] %s\n",
  163. d->dir, rs, value>>8, value&0xFF,
  164. index, count, ndata+8, hd);
  165. free(hd);
  166. }
  167. n = write(d->dfd, wp, 8+ndata);
  168. if(wp != buf)
  169. free(wp);
  170. if(n < 0)
  171. return -1;
  172. if(n != 8+ndata){
  173. dprint(2, "%s: cmd: short write: %d\n", argv0, n);
  174. return -1;
  175. }
  176. return n;
  177. }
  178. static int
  179. cmdrep(Dev *d, void *buf, int nb)
  180. {
  181. char *hd;
  182. nb = read(d->dfd, buf, nb);
  183. if(nb >0 && usbdebug > 2){
  184. hd = hexstr(buf, nb);
  185. fprint(2, "%s: in[%d] %s\n", d->dir, nb, hd);
  186. free(hd);
  187. }
  188. return nb;
  189. }
  190. int
  191. usbcmd(Dev *d, int type, int req, int value, int index, uint8_t *data, int count)
  192. {
  193. int i, r, nerr;
  194. char err[64];
  195. /*
  196. * Some devices do not respond to commands some times.
  197. * Others even report errors but later work just fine. Retry.
  198. */
  199. r = -1;
  200. *err = 0;
  201. for(i = nerr = 0; i < Uctries; i++){
  202. if(type & Rd2h)
  203. r = cmdreq(d, type, req, value, index, nil, count);
  204. else
  205. r = cmdreq(d, type, req, value, index, data, count);
  206. if(r > 0){
  207. if((type & Rd2h) == 0)
  208. break;
  209. r = cmdrep(d, data, count);
  210. if(r > 0)
  211. break;
  212. if(r == 0)
  213. werrstr("no data from device");
  214. }
  215. nerr++;
  216. if(*err == 0)
  217. rerrstr(err, sizeof(err));
  218. sleep(Ucdelay);
  219. }
  220. if(r > 0 && i >= 2)
  221. /* let the user know the device is not in good shape */
  222. fprint(2, "%s: usbcmd: %s: required %d attempts (%s)\n",
  223. argv0, d->dir, i, err);
  224. return r;
  225. }
  226. int
  227. loaddevdesc(Dev *d)
  228. {
  229. uint8_t buf[Ddevlen+255];
  230. int nr;
  231. int type;
  232. Ep *ep0;
  233. type = Rd2h|Rstd|Rdev;
  234. nr = sizeof(buf);
  235. memset(buf, 0, Ddevlen);
  236. if((nr=usbcmd(d, type, Rgetdesc, Ddev<<8|0, 0, buf, nr)) < 0)
  237. return -1;
  238. /*
  239. * Several hubs are returning descriptors of 17 bytes, not 18.
  240. * We accept them and leave number of configurations as zero.
  241. * (a get configuration descriptor also fails for them!)
  242. */
  243. if(nr < Ddevlen){
  244. print("%s: %s: warning: device with short descriptor\n",
  245. argv0, d->dir);
  246. if(nr < Ddevlen-1){
  247. werrstr("short device descriptor (%d bytes)", nr);
  248. return -1;
  249. }
  250. }
  251. d->usb = emallocz(sizeof(Usbdev), 1);
  252. ep0 = mkep(d->usb, 0);
  253. ep0->dir = Eboth;
  254. ep0->type = Econtrol;
  255. ep0->maxpkt = d->maxpkt = 8; /* a default */
  256. nr = parsedev(d, buf, nr);
  257. if(nr >= 0){
  258. d->usb->vendor = loaddevstr(d, d->usb->vsid);
  259. if(strcmp(d->usb->vendor, "none") != 0){
  260. d->usb->product = loaddevstr(d, d->usb->psid);
  261. d->usb->serial = loaddevstr(d, d->usb->ssid);
  262. }
  263. }
  264. return nr;
  265. }
  266. static void
  267. keybscanproc(void)
  268. {
  269. static char path[256];
  270. static char buf[256];
  271. Keyb *keyb, **kpp;
  272. Dir *dir, *dirs;
  273. int i, nrd, ndirs;
  274. int fd, waitfd;
  275. int pid;
  276. snprint(path, sizeof path, "/proc/%d/wait", getpid());
  277. waitfd = open(path, OREAD);
  278. if(waitfd == -1)
  279. sysfatal("open %s", path);
  280. for(;;){
  281. fd = open("/dev/usb", OREAD);
  282. if(fd == -1)
  283. sysfatal("/dev/usb: %r");
  284. ndirs = dirreadall(fd, &dirs);
  285. close(fd);
  286. kpp = &keybs;
  287. for(i = 0; i < ndirs; i++){
  288. dir = dirs+i;
  289. if(strcmp(dir->name, "ctl") == 0 || strstr(dir->name, ".0") == nil)
  290. continue;
  291. snprint(path, sizeof path, "/dev/usb/%s/ctl", dir->name);
  292. fd = open(path, ORDWR);
  293. if(fd == -1)
  294. continue; /* went away */
  295. nrd = read(fd, buf, sizeof buf - 1);
  296. close(fd);
  297. if(nrd == -1)
  298. continue; /* went away */
  299. buf[nrd-1] = '\0';
  300. if(strstr(buf, "enabled ") != nil && strstr(buf, " busy") == nil){
  301. /* is it a keyboard? */
  302. if(strstr(buf, "csp 0x010103")){
  303. for(keyb = keybs; keyb != nil; keyb = keyb->next)
  304. if(!strcmp(keyb->name, dir->name))
  305. break;
  306. if(keyb != nil)
  307. continue; /* already in use */
  308. keyb = mallocz(sizeof keyb[0], 1);
  309. snprint(path, sizeof path, "/dev/usb/%s/ctl", dir->name);
  310. strncpy(keyb->name, dir->name);
  311. keyb->name[sizeof keyb->name - 1] = '\0';
  312. keyb->dev = dev;
  313. keyb->ep = openep(keyb->dev, ep->id);
  314. if(keyb->ep == nil){
  315. fprint(2, "keyb: %s: openep %d: %r\n", dev->dir, ep->id);
  316. closedev(dev);
  317. free(keyb);
  318. continue;
  319. }
  320. switch(pid = rfork(RFPROC|RFMEM)){
  321. case -1:
  322. fprint(2, "rfork failed. keep moving...");
  323. free(keyb);
  324. continue;
  325. case 0:
  326. keybproc(keyb);
  327. exits(nil);
  328. default:
  329. keyb->pid = pid;
  330. break;
  331. }
  332. *kpp = keyb;
  333. kpp = &keyb->next;
  334. }
  335. }
  336. }
  337. free(dirs);
  338. /* collect dead children */
  339. for(;;){
  340. dir = dirfstat(waitfd);
  341. if(dir == nil)
  342. sysfatal("dirfstat waitfd %s", path);
  343. if(dir->length > 0){
  344. nrd = read(waitfd, buf, sizeof buf-1);
  345. if(nrd == -1){
  346. fprint(2, "read waitfd");
  347. break;
  348. }
  349. buf[nrd] = '\0';
  350. pid = atoi(fld[0]);
  351. for(kpp = &keybs; *kpp != nil; kpp = &(*kpp)->next){
  352. keyb = *kpp;
  353. if(keyb->pid == pid){
  354. close(keyb->ctlfd);
  355. if(keyb->datafd != -1)
  356. close(keyb->datafd);
  357. if(keyb->epfd != -1)
  358. close(keyb->epfd);
  359. *kpp = keyb->next;
  360. free(keyb);
  361. break;
  362. }
  363. }
  364. free(dir);
  365. continue;
  366. }
  367. free(dir);
  368. break;
  369. }
  370. sleep(1000);
  371. }
  372. }
  373. void
  374. main(int argc, char **argv)
  375. {
  376. char *mtpt, *srvname;
  377. srvname = nil;
  378. mtpt = "/dev/usb";
  379. time0 = time(0);
  380. ARGBEGIN{
  381. case 'm':
  382. mtpt = EARGF(usage());
  383. break;
  384. case 'S':
  385. srvname = EARGF(usage());
  386. break;
  387. case 'D':
  388. chatty9p++;
  389. break;
  390. default:
  391. usage();
  392. }ARGEND
  393. /* don't leave standard descriptors open to confuse mk */
  394. close(0);
  395. close(1);
  396. close(2);
  397. postmountsrv(&keybsrv, srvname, mtpt, MBEFORE);
  398. exits(nil);
  399. }