tascam-midi.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. /*
  2. * tascam-midi.c - a part of driver for TASCAM FireWire series
  3. *
  4. * Copyright (c) 2015 Takashi Sakamoto
  5. *
  6. * Licensed under the terms of the GNU General Public License, version 2.
  7. */
  8. #include "tascam.h"
  9. static int midi_capture_open(struct snd_rawmidi_substream *substream)
  10. {
  11. /* Do nothing. */
  12. return 0;
  13. }
  14. static int midi_playback_open(struct snd_rawmidi_substream *substream)
  15. {
  16. struct snd_tscm *tscm = substream->rmidi->private_data;
  17. snd_fw_async_midi_port_init(&tscm->out_ports[substream->number]);
  18. return 0;
  19. }
  20. static int midi_capture_close(struct snd_rawmidi_substream *substream)
  21. {
  22. /* Do nothing. */
  23. return 0;
  24. }
  25. static int midi_playback_close(struct snd_rawmidi_substream *substream)
  26. {
  27. return 0;
  28. }
  29. static void midi_playback_drain(struct snd_rawmidi_substream *substream)
  30. {
  31. struct snd_tscm *tscm = substream->rmidi->private_data;
  32. snd_fw_async_midi_port_finish(&tscm->out_ports[substream->number]);
  33. }
  34. static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up)
  35. {
  36. struct snd_tscm *tscm = substrm->rmidi->private_data;
  37. unsigned long flags;
  38. spin_lock_irqsave(&tscm->lock, flags);
  39. if (up)
  40. tscm->tx_midi_substreams[substrm->number] = substrm;
  41. else
  42. tscm->tx_midi_substreams[substrm->number] = NULL;
  43. spin_unlock_irqrestore(&tscm->lock, flags);
  44. }
  45. static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
  46. {
  47. struct snd_tscm *tscm = substrm->rmidi->private_data;
  48. unsigned long flags;
  49. spin_lock_irqsave(&tscm->lock, flags);
  50. if (up)
  51. snd_fw_async_midi_port_run(&tscm->out_ports[substrm->number],
  52. substrm);
  53. spin_unlock_irqrestore(&tscm->lock, flags);
  54. }
  55. int snd_tscm_create_midi_devices(struct snd_tscm *tscm)
  56. {
  57. static const struct snd_rawmidi_ops capture_ops = {
  58. .open = midi_capture_open,
  59. .close = midi_capture_close,
  60. .trigger = midi_capture_trigger,
  61. };
  62. static const struct snd_rawmidi_ops playback_ops = {
  63. .open = midi_playback_open,
  64. .close = midi_playback_close,
  65. .drain = midi_playback_drain,
  66. .trigger = midi_playback_trigger,
  67. };
  68. struct snd_rawmidi *rmidi;
  69. struct snd_rawmidi_str *stream;
  70. struct snd_rawmidi_substream *subs;
  71. int err;
  72. err = snd_rawmidi_new(tscm->card, tscm->card->driver, 0,
  73. tscm->spec->midi_playback_ports,
  74. tscm->spec->midi_capture_ports,
  75. &rmidi);
  76. if (err < 0)
  77. return err;
  78. snprintf(rmidi->name, sizeof(rmidi->name),
  79. "%s MIDI", tscm->card->shortname);
  80. rmidi->private_data = tscm;
  81. rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
  82. snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
  83. &capture_ops);
  84. stream = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
  85. /* Set port names for MIDI input. */
  86. list_for_each_entry(subs, &stream->substreams, list) {
  87. /* TODO: support virtual MIDI ports. */
  88. if (subs->number < tscm->spec->midi_capture_ports) {
  89. /* Hardware MIDI ports. */
  90. snprintf(subs->name, sizeof(subs->name),
  91. "%s MIDI %d",
  92. tscm->card->shortname, subs->number + 1);
  93. }
  94. }
  95. rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
  96. snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
  97. &playback_ops);
  98. stream = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
  99. /* Set port names for MIDI ourput. */
  100. list_for_each_entry(subs, &stream->substreams, list) {
  101. if (subs->number < tscm->spec->midi_playback_ports) {
  102. /* Hardware MIDI ports only. */
  103. snprintf(subs->name, sizeof(subs->name),
  104. "%s MIDI %d",
  105. tscm->card->shortname, subs->number + 1);
  106. }
  107. }
  108. rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
  109. return 0;
  110. }