0001
0002
0003
0004
0005
0006 #include <linux/device.h>
0007 #include <linux/usb.h>
0008 #include <linux/gfp.h>
0009 #include <sound/rawmidi.h>
0010 #include <sound/core.h>
0011 #include <sound/pcm.h>
0012
0013 #include "device.h"
0014 #include "midi.h"
0015
0016 static int snd_usb_caiaq_midi_input_open(struct snd_rawmidi_substream *substream)
0017 {
0018 return 0;
0019 }
0020
0021 static int snd_usb_caiaq_midi_input_close(struct snd_rawmidi_substream *substream)
0022 {
0023 return 0;
0024 }
0025
0026 static void snd_usb_caiaq_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
0027 {
0028 struct snd_usb_caiaqdev *cdev = substream->rmidi->private_data;
0029
0030 if (!cdev)
0031 return;
0032
0033 cdev->midi_receive_substream = up ? substream : NULL;
0034 }
0035
0036
0037 static int snd_usb_caiaq_midi_output_open(struct snd_rawmidi_substream *substream)
0038 {
0039 return 0;
0040 }
0041
0042 static int snd_usb_caiaq_midi_output_close(struct snd_rawmidi_substream *substream)
0043 {
0044 struct snd_usb_caiaqdev *cdev = substream->rmidi->private_data;
0045 if (cdev->midi_out_active) {
0046 usb_kill_urb(&cdev->midi_out_urb);
0047 cdev->midi_out_active = 0;
0048 }
0049 return 0;
0050 }
0051
0052 static void snd_usb_caiaq_midi_send(struct snd_usb_caiaqdev *cdev,
0053 struct snd_rawmidi_substream *substream)
0054 {
0055 int len, ret;
0056 struct device *dev = caiaqdev_to_dev(cdev);
0057
0058 cdev->midi_out_buf[0] = EP1_CMD_MIDI_WRITE;
0059 cdev->midi_out_buf[1] = 0;
0060 len = snd_rawmidi_transmit(substream, cdev->midi_out_buf + 3,
0061 EP1_BUFSIZE - 3);
0062
0063 if (len <= 0)
0064 return;
0065
0066 cdev->midi_out_buf[2] = len;
0067 cdev->midi_out_urb.transfer_buffer_length = len+3;
0068
0069 ret = usb_submit_urb(&cdev->midi_out_urb, GFP_ATOMIC);
0070 if (ret < 0)
0071 dev_err(dev,
0072 "snd_usb_caiaq_midi_send(%p): usb_submit_urb() failed,"
0073 "ret=%d, len=%d\n", substream, ret, len);
0074 else
0075 cdev->midi_out_active = 1;
0076 }
0077
0078 static void snd_usb_caiaq_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
0079 {
0080 struct snd_usb_caiaqdev *cdev = substream->rmidi->private_data;
0081
0082 if (up) {
0083 cdev->midi_out_substream = substream;
0084 if (!cdev->midi_out_active)
0085 snd_usb_caiaq_midi_send(cdev, substream);
0086 } else {
0087 cdev->midi_out_substream = NULL;
0088 }
0089 }
0090
0091
0092 static const struct snd_rawmidi_ops snd_usb_caiaq_midi_output =
0093 {
0094 .open = snd_usb_caiaq_midi_output_open,
0095 .close = snd_usb_caiaq_midi_output_close,
0096 .trigger = snd_usb_caiaq_midi_output_trigger,
0097 };
0098
0099 static const struct snd_rawmidi_ops snd_usb_caiaq_midi_input =
0100 {
0101 .open = snd_usb_caiaq_midi_input_open,
0102 .close = snd_usb_caiaq_midi_input_close,
0103 .trigger = snd_usb_caiaq_midi_input_trigger,
0104 };
0105
0106 void snd_usb_caiaq_midi_handle_input(struct snd_usb_caiaqdev *cdev,
0107 int port, const char *buf, int len)
0108 {
0109 if (!cdev->midi_receive_substream)
0110 return;
0111
0112 snd_rawmidi_receive(cdev->midi_receive_substream, buf, len);
0113 }
0114
0115 int snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *device)
0116 {
0117 int ret;
0118 struct snd_rawmidi *rmidi;
0119
0120 ret = snd_rawmidi_new(device->chip.card, device->product_name, 0,
0121 device->spec.num_midi_out,
0122 device->spec.num_midi_in,
0123 &rmidi);
0124
0125 if (ret < 0)
0126 return ret;
0127
0128 strscpy(rmidi->name, device->product_name, sizeof(rmidi->name));
0129
0130 rmidi->info_flags = SNDRV_RAWMIDI_INFO_DUPLEX;
0131 rmidi->private_data = device;
0132
0133 if (device->spec.num_midi_out > 0) {
0134 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
0135 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
0136 &snd_usb_caiaq_midi_output);
0137 }
0138
0139 if (device->spec.num_midi_in > 0) {
0140 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
0141 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
0142 &snd_usb_caiaq_midi_input);
0143 }
0144
0145 device->rmidi = rmidi;
0146
0147 return 0;
0148 }
0149
0150 void snd_usb_caiaq_midi_output_done(struct urb* urb)
0151 {
0152 struct snd_usb_caiaqdev *cdev = urb->context;
0153
0154 cdev->midi_out_active = 0;
0155 if (urb->status != 0)
0156 return;
0157
0158 if (!cdev->midi_out_substream)
0159 return;
0160
0161 snd_usb_caiaq_midi_send(cdev, cdev->midi_out_substream);
0162 }