usbaudio.c 9.9 KB

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