1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (c) 2006,2007 Daniel Mack
6 #include <linux/device.h>
9 #include <sound/rawmidi.h>
10 #include <sound/core.h>
11 #include <sound/pcm.h>
16 static int snd_usb_caiaq_midi_input_open(struct snd_rawmidi_substream
*substream
)
21 static int snd_usb_caiaq_midi_input_close(struct snd_rawmidi_substream
*substream
)
26 static void snd_usb_caiaq_midi_input_trigger(struct snd_rawmidi_substream
*substream
, int up
)
28 struct snd_usb_caiaqdev
*cdev
= substream
->rmidi
->private_data
;
33 cdev
->midi_receive_substream
= up
? substream
: NULL
;
37 static int snd_usb_caiaq_midi_output_open(struct snd_rawmidi_substream
*substream
)
42 static int snd_usb_caiaq_midi_output_close(struct snd_rawmidi_substream
*substream
)
44 struct snd_usb_caiaqdev
*cdev
= substream
->rmidi
->private_data
;
45 if (cdev
->midi_out_active
) {
46 usb_kill_urb(&cdev
->midi_out_urb
);
47 cdev
->midi_out_active
= 0;
52 static void snd_usb_caiaq_midi_send(struct snd_usb_caiaqdev
*cdev
,
53 struct snd_rawmidi_substream
*substream
)
56 struct device
*dev
= caiaqdev_to_dev(cdev
);
58 cdev
->midi_out_buf
[0] = EP1_CMD_MIDI_WRITE
;
59 cdev
->midi_out_buf
[1] = 0; /* port */
60 len
= snd_rawmidi_transmit(substream
, cdev
->midi_out_buf
+ 3,
66 cdev
->midi_out_buf
[2] = len
;
67 cdev
->midi_out_urb
.transfer_buffer_length
= len
+3;
69 ret
= usb_submit_urb(&cdev
->midi_out_urb
, GFP_ATOMIC
);
72 "snd_usb_caiaq_midi_send(%p): usb_submit_urb() failed,"
73 "ret=%d, len=%d\n", substream
, ret
, len
);
75 cdev
->midi_out_active
= 1;
78 static void snd_usb_caiaq_midi_output_trigger(struct snd_rawmidi_substream
*substream
, int up
)
80 struct snd_usb_caiaqdev
*cdev
= substream
->rmidi
->private_data
;
83 cdev
->midi_out_substream
= substream
;
84 if (!cdev
->midi_out_active
)
85 snd_usb_caiaq_midi_send(cdev
, substream
);
87 cdev
->midi_out_substream
= NULL
;
92 static const struct snd_rawmidi_ops snd_usb_caiaq_midi_output
=
94 .open
= snd_usb_caiaq_midi_output_open
,
95 .close
= snd_usb_caiaq_midi_output_close
,
96 .trigger
= snd_usb_caiaq_midi_output_trigger
,
99 static const struct snd_rawmidi_ops snd_usb_caiaq_midi_input
=
101 .open
= snd_usb_caiaq_midi_input_open
,
102 .close
= snd_usb_caiaq_midi_input_close
,
103 .trigger
= snd_usb_caiaq_midi_input_trigger
,
106 void snd_usb_caiaq_midi_handle_input(struct snd_usb_caiaqdev
*cdev
,
107 int port
, const char *buf
, int len
)
109 if (!cdev
->midi_receive_substream
)
112 snd_rawmidi_receive(cdev
->midi_receive_substream
, buf
, len
);
115 int snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev
*device
)
118 struct snd_rawmidi
*rmidi
;
120 ret
= snd_rawmidi_new(device
->chip
.card
, device
->product_name
, 0,
121 device
->spec
.num_midi_out
,
122 device
->spec
.num_midi_in
,
128 strlcpy(rmidi
->name
, device
->product_name
, sizeof(rmidi
->name
));
130 rmidi
->info_flags
= SNDRV_RAWMIDI_INFO_DUPLEX
;
131 rmidi
->private_data
= device
;
133 if (device
->spec
.num_midi_out
> 0) {
134 rmidi
->info_flags
|= SNDRV_RAWMIDI_INFO_OUTPUT
;
135 snd_rawmidi_set_ops(rmidi
, SNDRV_RAWMIDI_STREAM_OUTPUT
,
136 &snd_usb_caiaq_midi_output
);
139 if (device
->spec
.num_midi_in
> 0) {
140 rmidi
->info_flags
|= SNDRV_RAWMIDI_INFO_INPUT
;
141 snd_rawmidi_set_ops(rmidi
, SNDRV_RAWMIDI_STREAM_INPUT
,
142 &snd_usb_caiaq_midi_input
);
145 device
->rmidi
= rmidi
;
150 void snd_usb_caiaq_midi_output_done(struct urb
* urb
)
152 struct snd_usb_caiaqdev
*cdev
= urb
->context
;
154 cdev
->midi_out_active
= 0;
155 if (urb
->status
!= 0)
158 if (!cdev
->midi_out_substream
)
161 snd_usb_caiaq_midi_send(cdev
, cdev
->midi_out_substream
);