tascam-midi.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  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. /* Initialize internal status. */
  18. tscm->running_status[substream->number] = 0;
  19. tscm->on_sysex[substream->number] = 0;
  20. return 0;
  21. }
  22. static int midi_capture_close(struct snd_rawmidi_substream *substream)
  23. {
  24. /* Do nothing. */
  25. return 0;
  26. }
  27. static int midi_playback_close(struct snd_rawmidi_substream *substream)
  28. {
  29. struct snd_tscm *tscm = substream->rmidi->private_data;
  30. snd_fw_async_midi_port_finish(&tscm->out_ports[substream->number]);
  31. return 0;
  32. }
  33. static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up)
  34. {
  35. struct snd_tscm *tscm = substrm->rmidi->private_data;
  36. unsigned long flags;
  37. spin_lock_irqsave(&tscm->lock, flags);
  38. if (up)
  39. tscm->tx_midi_substreams[substrm->number] = substrm;
  40. else
  41. tscm->tx_midi_substreams[substrm->number] = NULL;
  42. spin_unlock_irqrestore(&tscm->lock, flags);
  43. }
  44. static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
  45. {
  46. struct snd_tscm *tscm = substrm->rmidi->private_data;
  47. unsigned long flags;
  48. spin_lock_irqsave(&tscm->lock, flags);
  49. if (up)
  50. snd_fw_async_midi_port_run(&tscm->out_ports[substrm->number],
  51. substrm);
  52. spin_unlock_irqrestore(&tscm->lock, flags);
  53. }
  54. static struct snd_rawmidi_ops midi_capture_ops = {
  55. .open = midi_capture_open,
  56. .close = midi_capture_close,
  57. .trigger = midi_capture_trigger,
  58. };
  59. static struct snd_rawmidi_ops midi_playback_ops = {
  60. .open = midi_playback_open,
  61. .close = midi_playback_close,
  62. .trigger = midi_playback_trigger,
  63. };
  64. int snd_tscm_create_midi_devices(struct snd_tscm *tscm)
  65. {
  66. struct snd_rawmidi *rmidi;
  67. struct snd_rawmidi_str *stream;
  68. struct snd_rawmidi_substream *subs;
  69. int err;
  70. err = snd_rawmidi_new(tscm->card, tscm->card->driver, 0,
  71. tscm->spec->midi_playback_ports,
  72. tscm->spec->midi_capture_ports,
  73. &rmidi);
  74. if (err < 0)
  75. return err;
  76. snprintf(rmidi->name, sizeof(rmidi->name),
  77. "%s MIDI", tscm->card->shortname);
  78. rmidi->private_data = tscm;
  79. rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
  80. snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
  81. &midi_capture_ops);
  82. stream = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
  83. /* Set port names for MIDI input. */
  84. list_for_each_entry(subs, &stream->substreams, list) {
  85. /* TODO: support virtual MIDI ports. */
  86. if (subs->number < tscm->spec->midi_capture_ports) {
  87. /* Hardware MIDI ports. */
  88. snprintf(subs->name, sizeof(subs->name),
  89. "%s MIDI %d",
  90. tscm->card->shortname, subs->number + 1);
  91. }
  92. }
  93. rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
  94. snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
  95. &midi_playback_ops);
  96. stream = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
  97. /* Set port names for MIDI ourput. */
  98. list_for_each_entry(subs, &stream->substreams, list) {
  99. if (subs->number < tscm->spec->midi_playback_ports) {
  100. /* Hardware MIDI ports only. */
  101. snprintf(subs->name, sizeof(subs->name),
  102. "%s MIDI %d",
  103. tscm->card->shortname, subs->number + 1);
  104. }
  105. }
  106. rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
  107. return 0;
  108. }