midi.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614
  1. /* $OpenBSD: midi.c,v 1.40 2015/05/22 12:52:00 jsg Exp $ */
  2. /*
  3. * Copyright (c) 2003, 2004 Alexandre Ratchov
  4. *
  5. * Permission to use, copy, modify, and distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  10. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  12. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  14. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  15. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. #include <sys/param.h>
  18. #include <sys/fcntl.h>
  19. #include <sys/systm.h>
  20. #include <sys/ioctl.h>
  21. #include <sys/conf.h>
  22. #include <sys/poll.h>
  23. #include <sys/kernel.h>
  24. #include <sys/timeout.h>
  25. #include <sys/vnode.h>
  26. #include <sys/signalvar.h>
  27. #include <sys/malloc.h>
  28. #include <sys/device.h>
  29. #include <dev/midi_if.h>
  30. #include <dev/audio_if.h>
  31. #include <dev/midivar.h>
  32. int midiopen(dev_t, int, int, struct proc *);
  33. int midiclose(dev_t, int, int, struct proc *);
  34. int midiread(dev_t, struct uio *, int);
  35. int midiwrite(dev_t, struct uio *, int);
  36. int midipoll(dev_t, int, struct proc *);
  37. int midikqfilter(dev_t, struct knote *);
  38. int midiioctl(dev_t, u_long, caddr_t, int, struct proc *);
  39. int midiprobe(struct device *, void *, void *);
  40. void midiattach(struct device *, struct device *, void *);
  41. int mididetach(struct device *, int);
  42. int midiprint(void *, const char *);
  43. void midi_iintr(void *, int);
  44. void midi_ointr(void *);
  45. void midi_timeout(void *);
  46. void midi_out_start(struct midi_softc *);
  47. void midi_out_stop(struct midi_softc *);
  48. void midi_out_do(struct midi_softc *);
  49. void midi_attach(struct midi_softc *, struct device *);
  50. struct cfattach midi_ca = {
  51. sizeof(struct midi_softc), midiprobe, midiattach, mididetach
  52. };
  53. struct cfdriver midi_cd = {
  54. NULL, "midi", DV_DULL
  55. };
  56. void filt_midiwdetach(struct knote *);
  57. int filt_midiwrite(struct knote *, long);
  58. struct filterops midiwrite_filtops = {
  59. 1, NULL, filt_midiwdetach, filt_midiwrite
  60. };
  61. void filt_midirdetach(struct knote *);
  62. int filt_midiread(struct knote *, long);
  63. struct filterops midiread_filtops = {
  64. 1, NULL, filt_midirdetach, filt_midiread
  65. };
  66. void
  67. midi_iintr(void *addr, int data)
  68. {
  69. struct midi_softc *sc = (struct midi_softc *)addr;
  70. struct midi_buffer *mb = &sc->inbuf;
  71. MUTEX_ASSERT_LOCKED(&audio_lock);
  72. if (!(sc->dev.dv_flags & DVF_ACTIVE) || !(sc->flags & FREAD))
  73. return;
  74. if (MIDIBUF_ISFULL(mb))
  75. return; /* discard data */
  76. MIDIBUF_WRITE(mb, data);
  77. if (mb->used == 1) {
  78. if (sc->rchan) {
  79. sc->rchan = 0;
  80. wakeup(&sc->rchan);
  81. }
  82. selwakeup(&sc->rsel);
  83. if (sc->async)
  84. psignal(sc->async, SIGIO);
  85. }
  86. }
  87. int
  88. midiread(dev_t dev, struct uio *uio, int ioflag)
  89. {
  90. struct midi_softc *sc;
  91. struct midi_buffer *mb;
  92. size_t count;
  93. int error;
  94. sc = (struct midi_softc *)device_lookup(&midi_cd, minor(dev));
  95. if (sc == NULL)
  96. return ENXIO;
  97. if (!(sc->flags & FREAD)) {
  98. error = ENXIO;
  99. goto done;
  100. }
  101. mb = &sc->inbuf;
  102. /* if there is no data then sleep (unless IO_NDELAY flag is set) */
  103. error = 0;
  104. mtx_enter(&audio_lock);
  105. while (MIDIBUF_ISEMPTY(mb)) {
  106. if (ioflag & IO_NDELAY) {
  107. mtx_leave(&audio_lock);
  108. error = EWOULDBLOCK;
  109. goto done;
  110. }
  111. sc->rchan = 1;
  112. error = msleep(&sc->rchan, &audio_lock, PWAIT | PCATCH, "mid_rd", 0);
  113. if (!(sc->dev.dv_flags & DVF_ACTIVE))
  114. error = EIO;
  115. if (error) {
  116. mtx_leave(&audio_lock);
  117. goto done;
  118. }
  119. }
  120. /* at this stage, there is at least 1 byte */
  121. while (uio->uio_resid > 0 && mb->used > 0) {
  122. count = MIDIBUF_SIZE - mb->start;
  123. if (count > mb->used)
  124. count = mb->used;
  125. if (count > uio->uio_resid)
  126. count = uio->uio_resid;
  127. mtx_leave(&audio_lock);
  128. error = uiomove(mb->data + mb->start, count, uio);
  129. if (error)
  130. goto done;
  131. mtx_enter(&audio_lock);
  132. MIDIBUF_REMOVE(mb, count);
  133. }
  134. mtx_leave(&audio_lock);
  135. done:
  136. device_unref(&sc->dev);
  137. return error;
  138. }
  139. void
  140. midi_ointr(void *addr)
  141. {
  142. struct midi_softc *sc = (struct midi_softc *)addr;
  143. struct midi_buffer *mb;
  144. MUTEX_ASSERT_LOCKED(&audio_lock);
  145. if (!(sc->dev.dv_flags & DVF_ACTIVE) || !(sc->flags & FWRITE))
  146. return;
  147. mb = &sc->outbuf;
  148. if (mb->used > 0) {
  149. #ifdef MIDI_DEBUG
  150. if (!sc->isbusy) {
  151. printf("midi_ointr: output must be busy\n");
  152. }
  153. #endif
  154. midi_out_do(sc);
  155. } else if (sc->isbusy)
  156. midi_out_stop(sc);
  157. }
  158. void
  159. midi_timeout(void *addr)
  160. {
  161. mtx_enter(&audio_lock);
  162. midi_ointr(addr);
  163. mtx_leave(&audio_lock);
  164. }
  165. void
  166. midi_out_start(struct midi_softc *sc)
  167. {
  168. if (!sc->isbusy) {
  169. sc->isbusy = 1;
  170. midi_out_do(sc);
  171. }
  172. }
  173. void
  174. midi_out_stop(struct midi_softc *sc)
  175. {
  176. sc->isbusy = 0;
  177. if (sc->wchan) {
  178. sc->wchan = 0;
  179. wakeup(&sc->wchan);
  180. }
  181. selwakeup(&sc->wsel);
  182. if (sc->async)
  183. psignal(sc->async, SIGIO);
  184. }
  185. void
  186. midi_out_do(struct midi_softc *sc)
  187. {
  188. struct midi_buffer *mb = &sc->outbuf;
  189. while (mb->used > 0) {
  190. if (!sc->hw_if->output(sc->hw_hdl, mb->data[mb->start]))
  191. break;
  192. MIDIBUF_REMOVE(mb, 1);
  193. if (MIDIBUF_ISEMPTY(mb)) {
  194. if (sc->hw_if->flush != NULL)
  195. sc->hw_if->flush(sc->hw_hdl);
  196. midi_out_stop(sc);
  197. return;
  198. }
  199. }
  200. if (!(sc->props & MIDI_PROP_OUT_INTR)) {
  201. if (MIDIBUF_ISEMPTY(mb))
  202. midi_out_stop(sc);
  203. else
  204. timeout_add(&sc->timeo, 1);
  205. }
  206. }
  207. int
  208. midiwrite(dev_t dev, struct uio *uio, int ioflag)
  209. {
  210. struct midi_softc *sc;
  211. struct midi_buffer *mb;
  212. size_t count;
  213. int error;
  214. sc = (struct midi_softc *)device_lookup(&midi_cd, minor(dev));
  215. if (sc == NULL)
  216. return ENXIO;
  217. if (!(sc->flags & FWRITE)) {
  218. error = ENXIO;
  219. goto done;
  220. }
  221. mb = &sc->outbuf;
  222. /*
  223. * If IO_NDELAY flag is set then check if there is enough room
  224. * in the buffer to store at least one byte. If not then dont
  225. * start the write process.
  226. */
  227. error = 0;
  228. mtx_enter(&audio_lock);
  229. if ((ioflag & IO_NDELAY) && MIDIBUF_ISFULL(mb) && (uio->uio_resid > 0)) {
  230. mtx_leave(&audio_lock);
  231. error = EWOULDBLOCK;
  232. goto done;
  233. }
  234. while (uio->uio_resid > 0) {
  235. while (MIDIBUF_ISFULL(mb)) {
  236. if (ioflag & IO_NDELAY) {
  237. /*
  238. * At this stage at least one byte is already
  239. * moved so we do not return EWOULDBLOCK
  240. */
  241. mtx_leave(&audio_lock);
  242. goto done;
  243. }
  244. sc->wchan = 1;
  245. error = msleep(&sc->wchan, &audio_lock,
  246. PWAIT | PCATCH, "mid_wr", 0);
  247. if (!(sc->dev.dv_flags & DVF_ACTIVE))
  248. error = EIO;
  249. if (error) {
  250. mtx_leave(&audio_lock);
  251. goto done;
  252. }
  253. }
  254. count = MIDIBUF_SIZE - MIDIBUF_END(mb);
  255. if (count > MIDIBUF_AVAIL(mb))
  256. count = MIDIBUF_AVAIL(mb);
  257. if (count > uio->uio_resid)
  258. count = uio->uio_resid;
  259. mtx_leave(&audio_lock);
  260. error = uiomove(mb->data + MIDIBUF_END(mb), count, uio);
  261. if (error)
  262. goto done;
  263. mtx_enter(&audio_lock);
  264. mb->used += count;
  265. midi_out_start(sc);
  266. }
  267. mtx_leave(&audio_lock);
  268. done:
  269. device_unref(&sc->dev);
  270. return error;
  271. }
  272. int
  273. midipoll(dev_t dev, int events, struct proc *p)
  274. {
  275. struct midi_softc *sc;
  276. int revents;
  277. sc = (struct midi_softc *)device_lookup(&midi_cd, minor(dev));
  278. if (sc == NULL)
  279. return POLLERR;
  280. revents = 0;
  281. mtx_enter(&audio_lock);
  282. if (events & (POLLIN | POLLRDNORM)) {
  283. if (!MIDIBUF_ISEMPTY(&sc->inbuf))
  284. revents |= events & (POLLIN | POLLRDNORM);
  285. }
  286. if (events & (POLLOUT | POLLWRNORM)) {
  287. if (!MIDIBUF_ISFULL(&sc->outbuf))
  288. revents |= events & (POLLOUT | POLLWRNORM);
  289. }
  290. if (revents == 0) {
  291. if (events & (POLLIN | POLLRDNORM))
  292. selrecord(p, &sc->rsel);
  293. if (events & (POLLOUT | POLLWRNORM))
  294. selrecord(p, &sc->wsel);
  295. }
  296. mtx_leave(&audio_lock);
  297. device_unref(&sc->dev);
  298. return (revents);
  299. }
  300. int
  301. midikqfilter(dev_t dev, struct knote *kn)
  302. {
  303. struct midi_softc *sc;
  304. struct klist *klist;
  305. int error;
  306. sc = (struct midi_softc *)device_lookup(&midi_cd, minor(dev));
  307. if (sc == NULL)
  308. return ENXIO;
  309. error = 0;
  310. switch (kn->kn_filter) {
  311. case EVFILT_READ:
  312. klist = &sc->rsel.si_note;
  313. kn->kn_fop = &midiread_filtops;
  314. break;
  315. case EVFILT_WRITE:
  316. klist = &sc->wsel.si_note;
  317. kn->kn_fop = &midiwrite_filtops;
  318. break;
  319. default:
  320. error = EINVAL;
  321. goto done;
  322. }
  323. kn->kn_hook = (void *)sc;
  324. mtx_enter(&audio_lock);
  325. SLIST_INSERT_HEAD(klist, kn, kn_selnext);
  326. mtx_leave(&audio_lock);
  327. done:
  328. device_unref(&sc->dev);
  329. return error;
  330. }
  331. void
  332. filt_midirdetach(struct knote *kn)
  333. {
  334. struct midi_softc *sc = (struct midi_softc *)kn->kn_hook;
  335. mtx_enter(&audio_lock);
  336. SLIST_REMOVE(&sc->rsel.si_note, kn, knote, kn_selnext);
  337. mtx_leave(&audio_lock);
  338. }
  339. int
  340. filt_midiread(struct knote *kn, long hint)
  341. {
  342. struct midi_softc *sc = (struct midi_softc *)kn->kn_hook;
  343. int retval;
  344. mtx_enter(&audio_lock);
  345. retval = !MIDIBUF_ISEMPTY(&sc->inbuf);
  346. mtx_leave(&audio_lock);
  347. return (retval);
  348. }
  349. void
  350. filt_midiwdetach(struct knote *kn)
  351. {
  352. struct midi_softc *sc = (struct midi_softc *)kn->kn_hook;
  353. mtx_enter(&audio_lock);
  354. SLIST_REMOVE(&sc->wsel.si_note, kn, knote, kn_selnext);
  355. mtx_leave(&audio_lock);
  356. }
  357. int
  358. filt_midiwrite(struct knote *kn, long hint)
  359. {
  360. struct midi_softc *sc = (struct midi_softc *)kn->kn_hook;
  361. int retval;
  362. mtx_enter(&audio_lock);
  363. retval = !MIDIBUF_ISFULL(&sc->outbuf);
  364. mtx_leave(&audio_lock);
  365. return (retval);
  366. }
  367. int
  368. midiioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
  369. {
  370. struct midi_softc *sc;
  371. int error;
  372. sc = (struct midi_softc *)device_lookup(&midi_cd, minor(dev));
  373. if (sc == NULL)
  374. return ENXIO;
  375. error = 0;
  376. switch(cmd) {
  377. case FIONBIO:
  378. /* All handled in the upper FS layer */
  379. break;
  380. case FIOASYNC:
  381. if (*(int *)addr) {
  382. if (sc->async) {
  383. error = EBUSY;
  384. goto done;
  385. }
  386. sc->async = p;
  387. } else
  388. sc->async = 0;
  389. break;
  390. default:
  391. error = ENOTTY;
  392. }
  393. done:
  394. device_unref(&sc->dev);
  395. return error;
  396. }
  397. int
  398. midiopen(dev_t dev, int flags, int mode, struct proc *p)
  399. {
  400. struct midi_softc *sc;
  401. int error;
  402. sc = (struct midi_softc *)device_lookup(&midi_cd, minor(dev));
  403. if (sc == NULL)
  404. return ENXIO;
  405. error = 0;
  406. if (sc->flags) {
  407. error = EBUSY;
  408. goto done;
  409. }
  410. MIDIBUF_INIT(&sc->inbuf);
  411. MIDIBUF_INIT(&sc->outbuf);
  412. sc->isbusy = 0;
  413. sc->rchan = sc->wchan = 0;
  414. sc->async = 0;
  415. sc->flags = flags;
  416. error = sc->hw_if->open(sc->hw_hdl, flags, midi_iintr, midi_ointr, sc);
  417. if (error)
  418. sc->flags = 0;
  419. done:
  420. device_unref(&sc->dev);
  421. return error;
  422. }
  423. int
  424. midiclose(dev_t dev, int fflag, int devtype, struct proc *p)
  425. {
  426. struct midi_softc *sc;
  427. struct midi_buffer *mb;
  428. int error;
  429. sc = (struct midi_softc *)device_lookup(&midi_cd, minor(dev));
  430. if (sc == NULL)
  431. return ENXIO;
  432. /* start draining output buffer */
  433. error = 0;
  434. mb = &sc->outbuf;
  435. mtx_enter(&audio_lock);
  436. if (!MIDIBUF_ISEMPTY(mb))
  437. midi_out_start(sc);
  438. while (sc->isbusy) {
  439. sc->wchan = 1;
  440. error = msleep(&sc->wchan, &audio_lock,
  441. PWAIT, "mid_dr", 5 * hz);
  442. if (!(sc->dev.dv_flags & DVF_ACTIVE))
  443. error = EIO;
  444. if (error)
  445. break;
  446. }
  447. mtx_leave(&audio_lock);
  448. /*
  449. * some hw_if->close() reset immediately the midi uart
  450. * which flushes the internal buffer of the uart device,
  451. * so we may lose some (important) data. To avoid this,
  452. * sleep 20ms (around 64 bytes) to give the time to the
  453. * uart to drain its internal buffers.
  454. */
  455. tsleep(&sc->wchan, PWAIT, "mid_cl", hz * MIDI_MAXWRITE / MIDI_RATE);
  456. sc->hw_if->close(sc->hw_hdl);
  457. sc->flags = 0;
  458. device_unref(&sc->dev);
  459. return 0;
  460. }
  461. int
  462. midiprobe(struct device *parent, void *match, void *aux)
  463. {
  464. struct audio_attach_args *sa = aux;
  465. return (sa != NULL && (sa->type == AUDIODEV_TYPE_MIDI) ? 1 : 0);
  466. }
  467. void
  468. midiattach(struct device *parent, struct device *self, void *aux)
  469. {
  470. struct midi_info mi;
  471. struct midi_softc *sc = (struct midi_softc *)self;
  472. struct audio_attach_args *sa = (struct audio_attach_args *)aux;
  473. struct midi_hw_if *hwif = sa->hwif;
  474. void *hdl = sa->hdl;
  475. #ifdef DIAGNOSTIC
  476. if (hwif == 0 ||
  477. hwif->open == 0 ||
  478. hwif->close == 0 ||
  479. hwif->output == 0 ||
  480. hwif->getinfo == 0) {
  481. printf("midi: missing method\n");
  482. return;
  483. }
  484. #endif
  485. sc->hw_if = hwif;
  486. sc->hw_hdl = hdl;
  487. sc->hw_if->getinfo(sc->hw_hdl, &mi);
  488. sc->props = mi.props;
  489. sc->flags = 0;
  490. timeout_set(&sc->timeo, midi_timeout, sc);
  491. printf(": <%s>\n", mi.name);
  492. }
  493. int
  494. mididetach(struct device *self, int flags)
  495. {
  496. struct midi_softc *sc = (struct midi_softc *)self;
  497. int maj, mn;
  498. /* locate the major number */
  499. for (maj = 0; maj < nchrdev; maj++) {
  500. if (cdevsw[maj].d_open == midiopen) {
  501. /* Nuke the vnodes for any open instances (calls close). */
  502. mn = self->dv_unit;
  503. vdevgone(maj, mn, mn, VCHR);
  504. }
  505. }
  506. /*
  507. * The close() method did nothing (device_lookup() returns
  508. * NULL), so quickly halt transfers (normally parent is already
  509. * gone, and code below is no-op), and wake-up user-land blocked
  510. * in read/write/ioctl, which return EIO.
  511. */
  512. if (sc->flags) {
  513. if (sc->flags & FREAD) {
  514. sc->rchan = 0;
  515. wakeup(&sc->rchan);
  516. selwakeup(&sc->rsel);
  517. }
  518. if (sc->flags & FWRITE) {
  519. sc->wchan = 0;
  520. wakeup(&sc->wchan);
  521. selwakeup(&sc->wsel);
  522. }
  523. sc->hw_if->close(sc->hw_hdl);
  524. sc->flags = 0;
  525. }
  526. return 0;
  527. }
  528. int
  529. midiprint(void *aux, const char *pnp)
  530. {
  531. if (pnp)
  532. printf("midi at %s", pnp);
  533. return (UNCONF);
  534. }
  535. struct device *
  536. midi_attach_mi(struct midi_hw_if *hwif, void *hdl, struct device *dev)
  537. {
  538. struct audio_attach_args arg;
  539. arg.type = AUDIODEV_TYPE_MIDI;
  540. arg.hwif = hwif;
  541. arg.hdl = hdl;
  542. return config_found(dev, &arg, midiprint);
  543. }