midi.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (c) 2006,2007 Daniel Mack
  4. */
  5. #include <linux/device.h>
  6. #include <linux/usb.h>
  7. #include <linux/gfp.h>
  8. #include <sound/rawmidi.h>
  9. #include <sound/core.h>
  10. #include <sound/pcm.h>
  11. #include "device.h"
  12. #include "midi.h"
  13. static int snd_usb_caiaq_midi_input_open(struct snd_rawmidi_substream *substream)
  14. {
  15. return 0;
  16. }
  17. static int snd_usb_caiaq_midi_input_close(struct snd_rawmidi_substream *substream)
  18. {
  19. return 0;
  20. }
  21. static void snd_usb_caiaq_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
  22. {
  23. struct snd_usb_caiaqdev *cdev = substream->rmidi->private_data;
  24. if (!cdev)
  25. return;
  26. cdev->midi_receive_substream = up ? substream : NULL;
  27. }
  28. static int snd_usb_caiaq_midi_output_open(struct snd_rawmidi_substream *substream)
  29. {
  30. return 0;
  31. }
  32. static int snd_usb_caiaq_midi_output_close(struct snd_rawmidi_substream *substream)
  33. {
  34. struct snd_usb_caiaqdev *cdev = substream->rmidi->private_data;
  35. if (cdev->midi_out_active) {
  36. usb_kill_urb(&cdev->midi_out_urb);
  37. cdev->midi_out_active = 0;
  38. }
  39. return 0;
  40. }
  41. static void snd_usb_caiaq_midi_send(struct snd_usb_caiaqdev *cdev,
  42. struct snd_rawmidi_substream *substream)
  43. {
  44. int len, ret;
  45. struct device *dev = caiaqdev_to_dev(cdev);
  46. cdev->midi_out_buf[0] = EP1_CMD_MIDI_WRITE;
  47. cdev->midi_out_buf[1] = 0; /* port */
  48. len = snd_rawmidi_transmit(substream, cdev->midi_out_buf + 3,
  49. EP1_BUFSIZE - 3);
  50. if (len <= 0)
  51. return;
  52. cdev->midi_out_buf[2] = len;
  53. cdev->midi_out_urb.transfer_buffer_length = len+3;
  54. ret = usb_submit_urb(&cdev->midi_out_urb, GFP_ATOMIC);
  55. if (ret < 0)
  56. dev_err(dev,
  57. "snd_usb_caiaq_midi_send(%p): usb_submit_urb() failed,"
  58. "ret=%d, len=%d\n", substream, ret, len);
  59. else
  60. cdev->midi_out_active = 1;
  61. }
  62. static void snd_usb_caiaq_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
  63. {
  64. struct snd_usb_caiaqdev *cdev = substream->rmidi->private_data;
  65. if (up) {
  66. cdev->midi_out_substream = substream;
  67. if (!cdev->midi_out_active)
  68. snd_usb_caiaq_midi_send(cdev, substream);
  69. } else {
  70. cdev->midi_out_substream = NULL;
  71. }
  72. }
  73. static const struct snd_rawmidi_ops snd_usb_caiaq_midi_output =
  74. {
  75. .open = snd_usb_caiaq_midi_output_open,
  76. .close = snd_usb_caiaq_midi_output_close,
  77. .trigger = snd_usb_caiaq_midi_output_trigger,
  78. };
  79. static const struct snd_rawmidi_ops snd_usb_caiaq_midi_input =
  80. {
  81. .open = snd_usb_caiaq_midi_input_open,
  82. .close = snd_usb_caiaq_midi_input_close,
  83. .trigger = snd_usb_caiaq_midi_input_trigger,
  84. };
  85. void snd_usb_caiaq_midi_handle_input(struct snd_usb_caiaqdev *cdev,
  86. int port, const char *buf, int len)
  87. {
  88. if (!cdev->midi_receive_substream)
  89. return;
  90. snd_rawmidi_receive(cdev->midi_receive_substream, buf, len);
  91. }
  92. int snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *device)
  93. {
  94. int ret;
  95. struct snd_rawmidi *rmidi;
  96. ret = snd_rawmidi_new(device->chip.card, device->product_name, 0,
  97. device->spec.num_midi_out,
  98. device->spec.num_midi_in,
  99. &rmidi);
  100. if (ret < 0)
  101. return ret;
  102. strscpy(rmidi->name, device->product_name, sizeof(rmidi->name));
  103. rmidi->info_flags = SNDRV_RAWMIDI_INFO_DUPLEX;
  104. rmidi->private_data = device;
  105. if (device->spec.num_midi_out > 0) {
  106. rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
  107. snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
  108. &snd_usb_caiaq_midi_output);
  109. }
  110. if (device->spec.num_midi_in > 0) {
  111. rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
  112. snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
  113. &snd_usb_caiaq_midi_input);
  114. }
  115. device->rmidi = rmidi;
  116. return 0;
  117. }
  118. void snd_usb_caiaq_midi_output_done(struct urb* urb)
  119. {
  120. struct snd_usb_caiaqdev *cdev = urb->context;
  121. cdev->midi_out_active = 0;
  122. if (urb->status != 0)
  123. return;
  124. if (!cdev->midi_out_substream)
  125. return;
  126. snd_usb_caiaq_midi_send(cdev, cdev->midi_out_substream);
  127. }