usbaudio.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. /*
  2. * USB audio driver for Plan 9
  3. */
  4. #include <u.h>
  5. #include <libc.h>
  6. #include <thread.h>
  7. #include "usb.h"
  8. #include "usbaudio.h"
  9. #include "usbaudioctl.h"
  10. #define STACKSIZE 16*1024
  11. extern char* srvpost;
  12. char * mntpt;
  13. Channel *controlchan;
  14. char audstr[] = "Enabled 0x000101"; /* audio.control.0 */
  15. int setrec = 0;
  16. int defaultspeed[2] = {44100, 44100};
  17. static void
  18. audio_endpoint(Device *d, int c, ulong csp, void *bb, int n)
  19. {
  20. int ifc;
  21. int dalt;
  22. byte *b = bb;
  23. if (c >= nelem(d->config)) {
  24. fprint(2, "Too many interfaces (%d of %d)\n",
  25. c, nelem(d->config));
  26. return;
  27. }
  28. dalt=csp>>24;
  29. ifc = csp>>16 & 0xff;
  30. switch(b[2]) {
  31. case 0x01:
  32. if (debug){
  33. fprint(2, "CS_ENDPOINT for attributes 0x%x, lockdelayunits %d, lockdelay %#ux, ",
  34. b[3], b[4], b[5] | (b[6]<<8));
  35. if (b[3] & has_setspeed)
  36. fprint(2, "has sampling-frequency control");
  37. else
  38. fprint(2, "does not have sampling-frequency control");
  39. if (b[3] & 0x1<<1)
  40. fprint(2, ", has pitch control");
  41. else
  42. fprint(2, ", does not have pitch control");
  43. if (b[3] & 0x1<<7)
  44. fprint(2, ", max packets only");
  45. fprint(2, "\n");
  46. }
  47. if (d->config[c] == nil)
  48. sysfatal("d->config[%d] == nil", c);
  49. if (d->config[c]->iface[ifc] == nil)
  50. sysfatal("d->config[%d]->iface[%d] == nil", c, ifc);
  51. if (d->config[c]->iface[ifc]->dalt[dalt] == nil)
  52. d->config[c]->iface[ifc]->dalt[dalt] = mallocz(sizeof(Dalt),1);
  53. if (d->config[c]->iface[ifc]->dalt[dalt]->devspec == nil)
  54. d->config[c]->iface[ifc]->dalt[dalt]->devspec= mallocz(sizeof(Audioalt),1);
  55. ((Audioalt*)d->config[c]->iface[ifc]->dalt[dalt]->devspec)->caps |= b[3];
  56. break;
  57. case 0x02:
  58. if (debug){
  59. fprint(2, "CS_INTERFACE FORMAT_TYPE %d, channels %d, subframesize %d, resolution %d, freqtype %d, ",
  60. b[3], b[4], b[5], b[6], b[7]);
  61. fprint(2, "freq0 %d, freq1 %d\n",
  62. b[8] | (b[9]<<8) | (b[10]<<16), b[11] | (b[12]<<8) | (b[13]<<16));
  63. }
  64. break;
  65. default:
  66. if (debug) pcs_raw("CS_INTERFACE", bb, n);
  67. }
  68. }
  69. void (*dprinter[])(Device *, int, ulong, void *b, int n) = {
  70. [STRING] pstring,
  71. [DEVICE] pdevice,
  72. [0x21] phid,
  73. [0x24] audio_interface,
  74. [0x25] audio_endpoint,
  75. };
  76. enum {
  77. None,
  78. Volumeset,
  79. Volumeget,
  80. Altset,
  81. Altget,
  82. Speedget,
  83. };
  84. void
  85. controlproc(void *)
  86. {
  87. /* Proc that looks after /dev/usb/%d/ctl */
  88. int i, nf;
  89. char *req, *args[8];
  90. Audiocontrol *c;
  91. long value[8];
  92. Channel *replchan;
  93. while(req = recvp(controlchan)){
  94. int rec;
  95. nf = tokenize(req, args, nelem(args));
  96. if (nf < 3)
  97. sysfatal("controlproc: not enough arguments");
  98. replchan = (Channel*)strtol(args[0], nil, 0);
  99. if (strcmp(args[2], "playback") == 0)
  100. rec = Play;
  101. else if (strcmp(args[2], "record") == 0)
  102. rec = Record;
  103. else{
  104. /* illegal request */
  105. if (debug) fprint(2, "%s must be record or playback", args[2]);
  106. if (replchan) chanprint(replchan, "%s must be record or playback", args[2]);
  107. free(req);
  108. continue;
  109. }
  110. c = nil;
  111. for (i = 0; i < Ncontrol; i++){
  112. c = &controls[rec][i];
  113. if (strcmp(args[1], c->name) == 0)
  114. break;
  115. }
  116. if (i == Ncontrol){
  117. if (debug) fprint(2, "Illegal control name: %s", args[1]);
  118. if (replchan) chanprint(replchan, "Illegal control name: %s", args[1]);
  119. }else if (!c->settable){
  120. if (debug & Dbginfo) fprint(2, "%s %s is not settable", args[1], args[2]);
  121. if (replchan)
  122. chanprint(replchan, "%s %s is not settable", args[1], args[2]);
  123. }else if (nf < 4){
  124. if (debug & Dbginfo) fprint(2, "insufficient arguments for %s %s",
  125. args[1], args[2]);
  126. if (replchan)
  127. chanprint(replchan, "insufficient arguments for %s %s",
  128. args[1], args[2]);
  129. }else if (ctlparse(args[3], c, value) < 0) {
  130. if (replchan)
  131. chanprint(replchan, "parse error in %s %s", args[1], args[2]);
  132. } else {
  133. if (debug & Dbginfo)
  134. fprint(2, "controlproc: setcontrol %s %s %s\n",
  135. rec?"in":"out", args[1], args[3]);
  136. if (setcontrol(rec, args[1], value) < 0){
  137. if (replchan)
  138. chanprint(replchan, "setting %s %s failed", args[1], args[2]);
  139. }else{
  140. if (replchan) chanprint(replchan, "ok");
  141. }
  142. ctlevent();
  143. }
  144. free(req);
  145. }
  146. }
  147. void
  148. buttonproc(void *)
  149. {
  150. int i, fd, b;
  151. char fname[64], err[32];
  152. byte buf[1];
  153. Audiocontrol *c;
  154. sprint(fname, "/dev/usb%d/%d/ep%ddata", ad->ctlrno, ad->id, buttonendpt);
  155. if (debug & Dbginfo) fprint(2, "buttonproc opening %s\n", fname);
  156. if ((fd = open(fname, OREAD)) < 0)
  157. sysfatal("Can't open %s: %r", fname);
  158. c = &controls[Play][Volume_control];
  159. for(;;){
  160. if((b = read(fd, buf, 1)) < 0){
  161. rerrstr(err, sizeof err);
  162. if (strcmp(err, "interrupted") == 0){
  163. if (debug & Dbginfo) fprint(2, "read interrupted\n");
  164. continue;
  165. }
  166. sysfatal("read %s: %r", fname);
  167. }
  168. if(b == 0 || buf[0] == 0){
  169. continue;
  170. }else if(buf[0] == 1){
  171. if (c->chans == 0)
  172. c->value[0] += c->step;
  173. else
  174. for (i = 1; i < 8; i++)
  175. if (c->chans & 1 << i)
  176. c->value[i] += c->step;
  177. chanprint(controlchan, "0 volume playback %A", c);
  178. }else if(buf[0] == 2){
  179. if (c->chans == 0)
  180. c->value[0] -= c->step;
  181. else
  182. for (i = 1; i < 8; i++)
  183. if (c->chans & 1 << i)
  184. c->value[i] -= c->step;
  185. chanprint(controlchan, "0 volume playback %A", c);
  186. }else if(debug & Dbginfo){
  187. fprint(2, "button");
  188. for (i = 0; i < b; i++)
  189. fprint(2, " %#2.2x", buf[i]);
  190. fprint(2, "\n");
  191. }
  192. }
  193. }
  194. void
  195. findendpoints(void)
  196. {
  197. Endpt *ep;
  198. int i, rec;
  199. for (i = 0; i < Nendpt; i++) {
  200. if ((ep = ad->ep[i]) == nil)
  201. continue;
  202. switch(ep->csp){
  203. default:
  204. break;
  205. case CSP(CL_AUDIO, 2, 0):
  206. if (ep->iface == nil)
  207. break;
  208. rec = (ep->addr & 0x80)?1:0;
  209. if (verbose)
  210. fprint(2, "%s on endpoint %d\n", rec?"Record":"Playback", i);
  211. endpt[rec] = i;
  212. interface[rec] = ep->iface->interface;
  213. break;
  214. case CSP(CL_HID, 0, 0):
  215. if (verbose)
  216. fprint(2, "Buttons on endpoint %d\n", i);
  217. buttonendpt = i;
  218. break;
  219. }
  220. }
  221. }
  222. void
  223. usage(void)
  224. {
  225. fprint(2, "usage: usbaudio [-pV] [-m mountpoint] [-s srvname] "
  226. "[-v volume] [ctrlno n]\n");
  227. threadexitsall("usage");
  228. }
  229. void
  230. threadmain(int argc, char **argv)
  231. {
  232. int ctlrno, id, i, sfd;
  233. long value[8], volume[8];
  234. Audiocontrol *c;
  235. char buf[32], *p, line[256];
  236. extern int attachok;
  237. ctlrno = id = -1;
  238. volume[0] = Undef;
  239. for (i = 0; i<8; i++)
  240. value[i] = 0;
  241. fmtinstall('A', Aconv);
  242. quotefmtinstall();
  243. ARGBEGIN{
  244. case 'd':
  245. debug = strtol(EARGF(usage()), nil, 0);
  246. if (debug == -1)
  247. debugdebug++;
  248. verbose++;
  249. break;
  250. case 'm':
  251. mntpt = EARGF(usage());
  252. break;
  253. case 'p':
  254. attachok++;
  255. break;
  256. case 's':
  257. srvpost = EARGF(usage());
  258. break;
  259. case 'v':
  260. volume[0] = strtol(EARGF(usage()), &p, 0);
  261. for(i = 1; i < 8; i++)
  262. volume[i] = volume[0];
  263. break;
  264. case 'V':
  265. verbose++;
  266. break;
  267. default:
  268. usage();
  269. }ARGEND
  270. switch(argc){
  271. case 0:
  272. for (ctlrno = 0; ctlrno < 16; ctlrno++) {
  273. for (i = 1; i < 128; i++) {
  274. sprint(buf, "/dev/usb%d/%d/status", ctlrno, i);
  275. sfd = open(buf, OREAD);
  276. if (sfd < 0)
  277. break;
  278. if (read(sfd, line, strlen(audstr)) == strlen(audstr)
  279. && strncmp(audstr, line, strlen(audstr)) == 0) {
  280. id = i;
  281. goto found;
  282. }
  283. close(sfd);
  284. }
  285. }
  286. if (verbose) fprint(2, "No usb audio\n");
  287. threadexitsall("usbaudio not found");
  288. found:
  289. break;
  290. case 2:
  291. ctlrno = atoi(argv[0]);
  292. id = atoi(argv[1]);
  293. break;
  294. default:
  295. usage();
  296. }
  297. ad = opendev(ctlrno, id);
  298. if (describedevice(ad) < 0)
  299. sysfatal("describedevice");
  300. for(i=0; i<ad->nconf; i++) {
  301. if (ad->config[i] == nil)
  302. ad->config[i] = mallocz(sizeof(*ad->config[i]),1);
  303. loadconfig(ad, i);
  304. }
  305. controlchan = chancreate(sizeof(char*), 8);
  306. findendpoints();
  307. if(endpt[Play] >= 0){
  308. if(verbose)
  309. fprint(2, "Setting default play parameters: %d Hz, %d channels at %d bits\n",
  310. defaultspeed[Play], 2, 16);
  311. if(findalt(Play, 2, 16, defaultspeed[Play]) < 0){
  312. if(findalt(Play, 2, 16, 48000) < 0)
  313. sysfatal("Can't configure playout for %d or %d Hz", defaultspeed[Play], 48000);
  314. fprint(2, "Warning, can't configure playout for %d Hz, configuring for %d Hz instead\n",
  315. defaultspeed[Play], 48000);
  316. defaultspeed[Play] = 48000;
  317. }
  318. value[0] = 2;
  319. if (setcontrol(Play, "channels", value) == Undef)
  320. sysfatal("Can't set play channels");
  321. value[0] = 16;
  322. if (setcontrol(Play, "resolution", value) == Undef)
  323. sysfatal("Can't set play resolution");
  324. }
  325. if(endpt[Record] >= 0){
  326. setrec = 1;
  327. if(verbose)
  328. fprint(2, "Setting default record parameters: "
  329. "%d Hz, %d channels at %d bits\n",
  330. defaultspeed[Record], 2, 16);
  331. i = 2;
  332. while(findalt(Record, i, 16, defaultspeed[Record]) < 0)
  333. if(i == 2 && controls[Record][Channel_control].max == 1){
  334. fprint(2, "Warning, can't configure stereo "
  335. "recording, configuring mono instead\n");
  336. i = 1;
  337. } else
  338. break;
  339. if(findalt(Record, i, 16, 48000) < 0) {
  340. endpt[Record] = -1; /* disable recording */
  341. setrec = 0;
  342. fprint(2, "Warning, can't configure record for %d Hz or %d Hz\n",
  343. defaultspeed[Record], 48000);
  344. } else
  345. fprint(2, "Warning, can't configure record for %d Hz, "
  346. "configuring for %d Hz instead\n",
  347. defaultspeed[Record], 48000);
  348. defaultspeed[Record] = 48000;
  349. if (setrec) {
  350. value[0] = i;
  351. if (setcontrol(Record, "channels", value) == Undef)
  352. sysfatal("Can't set record channels");
  353. value[0] = 16;
  354. if (setcontrol(Record, "resolution", value) == Undef)
  355. sysfatal("Can't set record resolution");
  356. }
  357. }
  358. getcontrols(); /* Get the initial value of all controls */
  359. value[0] = defaultspeed[Play];
  360. if (endpt[Play] >= 0 && setcontrol(Play, "speed", value) < 0)
  361. sysfatal("can't set play speed");
  362. value[0] = defaultspeed[Record];
  363. if (endpt[Record] >= 0 && setcontrol(Record, "speed", value) < 0)
  364. fprint(2, "%s: can't set record speed\n", argv0);
  365. value[0] = 0;
  366. setcontrol(Play, "mute", value);
  367. if (volume[0] != Undef){
  368. c = &controls[Play][Volume_control];
  369. if (*p == '%' && c->min != Undef)
  370. for (i = 0; i < 8; i++)
  371. volume[i] = (volume[i]*c->max + (100-volume[i])*c->min)/100;
  372. if (c->settable)
  373. setcontrol(Play, "volume", volume);
  374. c = &controls[Record][Volume_control];
  375. if (c->settable && setrec)
  376. setcontrol(Record, "volume", volume);
  377. }
  378. if (buttonendpt > 0){
  379. sprint(buf, "ep %d 10 r 1", buttonendpt);
  380. if (debug) fprint(2, "sending `%s' to /dev/usb/%d/ctl\n", buf, id);
  381. if (write(ad->ctl, buf, strlen(buf)) > 0)
  382. proccreate(buttonproc, nil, STACKSIZE);
  383. else
  384. fprint(2, "Could not configure button endpoint: %r\n");
  385. }
  386. proccreate(controlproc, nil, STACKSIZE);
  387. proccreate(serve, nil, STACKSIZE);
  388. threadexits(nil);
  389. }