bebob_midi.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /*
  2. * bebob_midi.c - a part of driver for BeBoB based devices
  3. *
  4. * Copyright (c) 2013-2014 Takashi Sakamoto
  5. *
  6. * Licensed under the terms of the GNU General Public License, version 2.
  7. */
  8. #include "bebob.h"
  9. static int midi_capture_open(struct snd_rawmidi_substream *substream)
  10. {
  11. struct snd_bebob *bebob = substream->rmidi->private_data;
  12. int err;
  13. err = snd_bebob_stream_lock_try(bebob);
  14. if (err < 0)
  15. goto end;
  16. mutex_lock(&bebob->mutex);
  17. bebob->substreams_counter++;
  18. err = snd_bebob_stream_start_duplex(bebob, 0);
  19. mutex_unlock(&bebob->mutex);
  20. if (err < 0)
  21. snd_bebob_stream_lock_release(bebob);
  22. end:
  23. return err;
  24. }
  25. static int midi_playback_open(struct snd_rawmidi_substream *substream)
  26. {
  27. struct snd_bebob *bebob = substream->rmidi->private_data;
  28. int err;
  29. err = snd_bebob_stream_lock_try(bebob);
  30. if (err < 0)
  31. goto end;
  32. mutex_lock(&bebob->mutex);
  33. bebob->substreams_counter++;
  34. err = snd_bebob_stream_start_duplex(bebob, 0);
  35. mutex_unlock(&bebob->mutex);
  36. if (err < 0)
  37. snd_bebob_stream_lock_release(bebob);
  38. end:
  39. return err;
  40. }
  41. static int midi_capture_close(struct snd_rawmidi_substream *substream)
  42. {
  43. struct snd_bebob *bebob = substream->rmidi->private_data;
  44. mutex_lock(&bebob->mutex);
  45. bebob->substreams_counter--;
  46. snd_bebob_stream_stop_duplex(bebob);
  47. mutex_unlock(&bebob->mutex);
  48. snd_bebob_stream_lock_release(bebob);
  49. return 0;
  50. }
  51. static int midi_playback_close(struct snd_rawmidi_substream *substream)
  52. {
  53. struct snd_bebob *bebob = substream->rmidi->private_data;
  54. mutex_lock(&bebob->mutex);
  55. bebob->substreams_counter--;
  56. snd_bebob_stream_stop_duplex(bebob);
  57. mutex_unlock(&bebob->mutex);
  58. snd_bebob_stream_lock_release(bebob);
  59. return 0;
  60. }
  61. static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up)
  62. {
  63. struct snd_bebob *bebob = substrm->rmidi->private_data;
  64. unsigned long flags;
  65. spin_lock_irqsave(&bebob->lock, flags);
  66. if (up)
  67. amdtp_am824_midi_trigger(&bebob->tx_stream,
  68. substrm->number, substrm);
  69. else
  70. amdtp_am824_midi_trigger(&bebob->tx_stream,
  71. substrm->number, NULL);
  72. spin_unlock_irqrestore(&bebob->lock, flags);
  73. }
  74. static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
  75. {
  76. struct snd_bebob *bebob = substrm->rmidi->private_data;
  77. unsigned long flags;
  78. spin_lock_irqsave(&bebob->lock, flags);
  79. if (up)
  80. amdtp_am824_midi_trigger(&bebob->rx_stream,
  81. substrm->number, substrm);
  82. else
  83. amdtp_am824_midi_trigger(&bebob->rx_stream,
  84. substrm->number, NULL);
  85. spin_unlock_irqrestore(&bebob->lock, flags);
  86. }
  87. static struct snd_rawmidi_ops midi_capture_ops = {
  88. .open = midi_capture_open,
  89. .close = midi_capture_close,
  90. .trigger = midi_capture_trigger,
  91. };
  92. static struct snd_rawmidi_ops midi_playback_ops = {
  93. .open = midi_playback_open,
  94. .close = midi_playback_close,
  95. .trigger = midi_playback_trigger,
  96. };
  97. static void set_midi_substream_names(struct snd_bebob *bebob,
  98. struct snd_rawmidi_str *str)
  99. {
  100. struct snd_rawmidi_substream *subs;
  101. list_for_each_entry(subs, &str->substreams, list) {
  102. snprintf(subs->name, sizeof(subs->name),
  103. "%s MIDI %d",
  104. bebob->card->shortname, subs->number + 1);
  105. }
  106. }
  107. int snd_bebob_create_midi_devices(struct snd_bebob *bebob)
  108. {
  109. struct snd_rawmidi *rmidi;
  110. struct snd_rawmidi_str *str;
  111. int err;
  112. /* create midi ports */
  113. err = snd_rawmidi_new(bebob->card, bebob->card->driver, 0,
  114. bebob->midi_output_ports, bebob->midi_input_ports,
  115. &rmidi);
  116. if (err < 0)
  117. return err;
  118. snprintf(rmidi->name, sizeof(rmidi->name),
  119. "%s MIDI", bebob->card->shortname);
  120. rmidi->private_data = bebob;
  121. if (bebob->midi_input_ports > 0) {
  122. rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
  123. snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
  124. &midi_capture_ops);
  125. str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
  126. set_midi_substream_names(bebob, str);
  127. }
  128. if (bebob->midi_output_ports > 0) {
  129. rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
  130. snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
  131. &midi_playback_ops);
  132. str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
  133. set_midi_substream_names(bebob, str);
  134. }
  135. if ((bebob->midi_output_ports > 0) && (bebob->midi_input_ports > 0))
  136. rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
  137. return 0;
  138. }