main.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <thread.h>
  4. #include "usb.h"
  5. #include "usbproto.h"
  6. #include "dat.h"
  7. #include "fns.h"
  8. #include "audioclass.h"
  9. #define STACKSIZE 16*1024
  10. extern char *srvpost;
  11. char * mntpt;
  12. int debug;
  13. int debugdebug;
  14. int verbose;
  15. Channel *controlchan;
  16. char audstr[] = "Enabled 0x000101\n"; /* audio.control.0 */
  17. Nexus *nexushd;
  18. Nexus *nexustl;
  19. void
  20. makenexus(Audiofunc *af, Funcalt *alt, Unit *output)
  21. {
  22. int i, ch;
  23. Nexus *nx;
  24. Unit *u, *feat;
  25. static int idgen;
  26. Audiocontrol *c;
  27. Stream *ins, *outs;
  28. nx = emallocz(sizeof(Nexus), 1);
  29. nx->af = af;
  30. nx->alt = alt;
  31. nx->output = output;
  32. nx->id = idgen++;
  33. for(u = output; u != nil; u = u->source[0]) {
  34. switch(u->type) {
  35. case INPUT_TERMINAL:
  36. nx->input = u;
  37. break;
  38. case MIXER_UNIT:
  39. nx->mixer = u;
  40. break;
  41. case FEATURE_UNIT:
  42. nx->feat = u;
  43. break;
  44. }
  45. if(u->nsource == 0)
  46. break;
  47. }
  48. if(nx->input == nil) {
  49. free(nx);
  50. return;
  51. }
  52. ins = nx->output->stream;
  53. outs = nx->input->stream;
  54. if(ins == nil && outs == nil || ins != nil && outs != nil) {
  55. free(nx);
  56. return;
  57. }
  58. if(ins != nil) {
  59. nx->s = ins;
  60. nx->dir = Nin;
  61. }
  62. else {
  63. nx->s = outs;
  64. nx->dir = Nout;
  65. }
  66. memset(nx->control, 0, sizeof(nx->control));
  67. for(i = 0; i < Ncontrol; i++) {
  68. c = &nx->control[i];
  69. c->step = Undef;
  70. }
  71. calcbounds(nx);
  72. feat = nx->feat;
  73. if(feat != nil) {
  74. for(i = Mute_control; i < Mixer_control; i++) {
  75. c = &nx->control[i];
  76. for(ch = 0; ch <= feat->nchan; ch++) {
  77. if((feat->hascontrol[ch] & (1<<(i-1))) == 0)
  78. continue;
  79. c->readable = 1;
  80. c->settable = 1;
  81. if(ch > 0)
  82. c->chans |= (1<<ch);
  83. }
  84. }
  85. }
  86. feat = nx->mixer;
  87. if(feat != nil) {
  88. c = &nx->control[Mixer_control];
  89. for(ch = 1; ch <= feat->nchan; ch++) {
  90. if((feat->hascontrol[((ch-1)*feat->nsource)>>5] & (1 << (((ch-1)*feat->nsource) & 31))) == 0)
  91. continue;
  92. c->readable = 1;
  93. c->settable = 1;
  94. c->chans |= (1<<ch);
  95. }
  96. }
  97. if(nexushd == nil)
  98. nexushd = nx;
  99. else
  100. nexustl->next = nx;
  101. nexustl = nx;
  102. }
  103. int
  104. adddevice(Device *d)
  105. {
  106. int i;
  107. Unit *u;
  108. Dconf *c;
  109. Dinf *intf;
  110. ulong csp;
  111. Audiofunc *af;
  112. if(d->nconf < 1)
  113. sysfatal("no configurations???");
  114. /* we only handle first config for now -- most devices only have 1 anyway */
  115. c = &d->config[0];
  116. for(i = 0; i < c->nif; i++) {
  117. intf = &c->iface[i];
  118. if(intf == nil)
  119. continue;
  120. csp = intf->csp;
  121. if(Class(csp) == CL_AUDIO && Subclass(csp) == AUDIOCONTROL) {
  122. if((af = getaudiofunc(intf)) == nil)
  123. return -1;
  124. if(debug)
  125. dumpaudiofunc(af);
  126. for(u = af->falt->unit; u != nil; u = u->next)
  127. if(u->type == OUTPUT_TERMINAL)
  128. makenexus(af, af->falt, u);
  129. }
  130. if(Class(csp) == CL_HID && Subclass(csp) == 0) {
  131. if (verbose)
  132. fprint(2, "Buttons on endpoint %d\n", i);
  133. if(intf->alt->npt == 1)
  134. buttonendpt = intf->alt->ep[0].addr;
  135. }
  136. }
  137. return 0;
  138. }
  139. void
  140. controlproc(void *)
  141. {
  142. /* Proc that looks after /dev/usb/%d/ctl */
  143. int nf;
  144. Nexus *nx;
  145. long value[8];
  146. Audiocontrol *c;
  147. char *req, *args[8];
  148. Channel *replchan;
  149. while(req = recvp(controlchan)) {
  150. nf = tokenize(req, args, nelem(args));
  151. if (nf < 3)
  152. sysfatal("controlproc: not enough arguments");
  153. replchan = (Channel*)strtol(args[0], nil, 0);
  154. nx = findnexus(args[2]);
  155. if(nx == nil) {
  156. /* illegal request */
  157. if (debug) fprint(2, "%s must be record or playback", args[2]);
  158. if (replchan) chanprint(replchan, "%s must be record or playback", args[2]);
  159. free(req);
  160. continue;
  161. }
  162. c = findcontrol(nx, args[1]);
  163. if (c == nil){
  164. if (debug) fprint(2, "Illegal control name: %s", args[1]);
  165. if (replchan) chanprint(replchan, "Illegal control name: %s", args[1]);
  166. }else if (!c->settable){
  167. if (debug & Dbginfo) fprint(2, "%s %s is not settable", args[1], args[2]);
  168. if (replchan)
  169. chanprint(replchan, "%s %s is not settable", args[1], args[2]);
  170. }else if (nf < 4){
  171. if (debug & Dbginfo) fprint(2, "insufficient arguments for %s %s",
  172. args[1], args[2]);
  173. if (replchan)
  174. chanprint(replchan, "insufficient arguments for %s %s",
  175. args[1], args[2]);
  176. }else if (ctlparse(args[3], c, value) < 0) {
  177. if (replchan)
  178. chanprint(replchan, "parse error in %s %s", args[1], args[2]);
  179. } else {
  180. if (debug & Dbginfo)
  181. fprint(2, "controlproc: setcontrol %s %s %s\n", nx->name, args[1], args[3]);
  182. if (setcontrol(nx, args[1], value) < 0){
  183. if (replchan)
  184. chanprint(replchan, "setting %s %s failed", args[1], args[2]);
  185. }else{
  186. if (replchan) chanprint(replchan, "ok");
  187. }
  188. ctlevent();
  189. }
  190. free(req);
  191. }
  192. }
  193. void
  194. buttonproc(void *x)
  195. {
  196. int i, fd, b;
  197. Device *d;
  198. uchar buf[1];
  199. Audiocontrol *c;
  200. char fname[64], err[32];
  201. d = x;
  202. sprint(fname, "/dev/usb%d/%d/ep%ddata", d->ctlrno, d->id, buttonendpt);
  203. if (debug & Dbginfo) fprint(2, "buttonproc opening %s\n", fname);
  204. if ((fd = open(fname, OREAD)) < 0)
  205. sysfatal("Can't open %s: %r", fname);
  206. c = &nexus[Play]->control[Volume_control];
  207. for (;;) {
  208. if ((b = read(fd, buf, 1)) < 0){
  209. rerrstr(err, sizeof err);
  210. if (strcmp(err, "interrupted") == 0){
  211. if (debug & Dbginfo) fprint(2, "read interrupted\n");
  212. continue;
  213. }
  214. sysfatal("read %s: %r", fname);
  215. }
  216. if (b == 0 || buf[0] == 0){
  217. continue;
  218. }else if (buf[0] == 1){
  219. if (c->chans == 0)
  220. c->value[0] += c->step;
  221. else
  222. for (i = 1; i < 8; i++)
  223. if (c->chans & 1 << i)
  224. c->value[i] += c->step;
  225. chanprint(controlchan, "0 volume playback %A", c);
  226. }else if (buf[0] == 2){
  227. if (c->chans == 0)
  228. c->value[0] -= c->step;
  229. else
  230. for (i = 1; i < 8; i++)
  231. if (c->chans & 1 << i)
  232. c->value[i] -= c->step;
  233. chanprint(controlchan, "0 volume playback %A", c);
  234. }else if (debug & Dbginfo){
  235. fprint(2, "button");
  236. for (i = 0; i < b; i++)
  237. fprint(2, " %#2.2x", buf[i]);
  238. fprint(2, "\n");
  239. }
  240. }
  241. }
  242. void
  243. findendpoints(void)
  244. {
  245. Nexus *nx;
  246. for(nx = nexushd; nx != nil; nx = nx->next) {
  247. switch(nx->dir) {
  248. case Nin:
  249. nx->name = "record";
  250. nexus[Record] = nx;
  251. break;
  252. case Nout:
  253. nx->name = "play";
  254. nexus[Play] = nx;
  255. break;
  256. }
  257. }
  258. }
  259. void
  260. usage(void)
  261. {
  262. fprint(2, "usage: usbaudio [-d] [-v volume[%%]] [-s srvname] [-m mountpoint] [ctrlno id]\n");
  263. threadexitsall("usage");
  264. }
  265. void
  266. threadmain(int argc, char **argv)
  267. {
  268. Device *d;
  269. Nexus *nx;
  270. long value[8];
  271. long volume[8];
  272. Audiocontrol *c;
  273. int ctlrno, id, i, sfd;
  274. char buf[32], *p, line[256];
  275. ctlrno = -1;
  276. id = -1;
  277. volume[0] = Undef;
  278. for (i = 0; i<8; i++)
  279. value[i] = 0;
  280. fmtinstall('A', Aconv);
  281. quotefmtinstall();
  282. usbfmtinit();
  283. ARGBEGIN{
  284. case 'd':
  285. debug = strtol(ARGF(), nil, 0);
  286. if (debug == -1) debugdebug++;
  287. verbose++;
  288. break;
  289. case 'v':
  290. volume[0] = strtol(ARGF(), &p, 0);
  291. for(i = 1; i < 8; i++)
  292. volume[i] = volume[0];
  293. break;
  294. case 'm':
  295. mntpt = ARGF();
  296. break;
  297. case 's':
  298. srvpost = ARGF();
  299. break;
  300. default:
  301. usage();
  302. }ARGEND
  303. switch (argc) {
  304. case 0:
  305. for (ctlrno = 0; ctlrno < 16; ctlrno++) {
  306. for (i = 1; i < 128; i++) {
  307. sprint(buf, "/dev/usb%d/%d/status", ctlrno, i);
  308. sfd = open(buf, OREAD);
  309. if (sfd < 0)
  310. break;
  311. if (read(sfd, line, strlen(audstr)) == strlen(audstr)
  312. && strncmp(audstr, line, strlen(audstr)) == 0) {
  313. id = i;
  314. goto found;
  315. }
  316. close(sfd);
  317. }
  318. }
  319. if (verbose) fprint(2, "No usb audio\n");
  320. threadexitsall("usbaudio not found");
  321. found:
  322. break;
  323. case 2:
  324. ctlrno = atoi(argv[0]);
  325. id = atoi(argv[1]);
  326. break;
  327. default:
  328. usage();
  329. }
  330. d = opendev(ctlrno, id);
  331. if(describedevice(d) < 0)
  332. sysfatal("usbaudio: %r");
  333. if(adddevice(d) < 0)
  334. sysfatal("usbaudio: adddevice: %r");
  335. controlchan = chancreate(sizeof(char*), 8);
  336. findendpoints();
  337. nx = nexus[Play];
  338. if(nx != nil) {
  339. value[0] = 2;
  340. if(setcontrol(nx, "channels", value) == Undef)
  341. sysfatal("Can't set play channels");
  342. value[0] = 16;
  343. if(setcontrol(nx, "resolution", value) == Undef)
  344. sysfatal("Can't set play resolution");
  345. getcontrols(nx); /* Get the initial value of all controls */
  346. value[0] = 44100;
  347. if(setcontrol(nx, "speed", value) < 0){
  348. fprint(2, "warning: Can't set play speed to %d\n", value[0]);
  349. value[0] = 48000;
  350. if(setcontrol(nx, "speed", value) < 0)
  351. fprint(2, "warning: Can't set play speed to %d\n", value[0]);
  352. else
  353. fprint(2, "warning: Play speed set to %d\n", value[0]);
  354. }
  355. value[0] = 0;
  356. setcontrol(nx, "mute", value);
  357. if(volume[0] != Undef) {
  358. c = &nx->control[Volume_control];
  359. if(*p == '%' && c->min != Undef)
  360. for (i = 0; i < 8; i++)
  361. volume[i] = (volume[i]*c->max + (100-volume[i])*c->min)/100;
  362. if(c->settable)
  363. setcontrol(nx, "volume", volume);
  364. }
  365. }
  366. nx = nexus[Record];
  367. if(nx != nil) {
  368. value[0] = 2;
  369. if(setcontrol(nx, "channels", value) == Undef)
  370. sysfatal("Can't set record channels");
  371. value[0] = 16;
  372. if(setcontrol(nx, "resolution", value) == Undef)
  373. sysfatal("Can't set record resolution");
  374. getcontrols(nx); /* Get the initial value of all controls */
  375. value[0] = 44100;
  376. if(setcontrol(nx, "speed", value) < 0)
  377. fprint(2, "Can't set record speed\n");
  378. if(volume[0] != Undef) {
  379. c = &nx->control[Volume_control];
  380. if(c->settable)
  381. setcontrol(nx, "volume", volume);
  382. }
  383. }
  384. nx = nexus[Play];
  385. if(buttonendpt > 0 && nx != nil) {
  386. sprint(buf, "ep %d bulk r 1 1", buttonendpt);
  387. if(debug) fprint(2, "sending `%s' to /dev/usb/%d/ctl\n", buf, id);
  388. if(write(d->ctl, buf, strlen(buf)) > 0)
  389. proccreate(buttonproc, nx->s->intf->d, STACKSIZE);
  390. else
  391. fprint(2, "Could not configure button endpoint: %r\n");
  392. }
  393. proccreate(controlproc, nil, STACKSIZE);
  394. proccreate(serve, nil, STACKSIZE);
  395. threadexits(nil);
  396. }