1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Virtual Raw MIDI client on Sequencer
4 *
5 * Copyright (c) 2000 by Takashi Iwai <tiwai@suse.de>,
6 * Jaroslav Kysela <perex@perex.cz>
7 */
8
9 /*
10 * Virtual Raw MIDI client
11 *
12 * The virtual rawmidi client is a sequencer client which associate
13 * a rawmidi device file. The created rawmidi device file can be
14 * accessed as a normal raw midi, but its MIDI source and destination
15 * are arbitrary. For example, a user-client software synth connected
16 * to this port can be used as a normal midi device as well.
17 *
18 * The virtual rawmidi device accepts also multiple opens. Each file
19 * has its own input buffer, so that no conflict would occur. The drain
20 * of input/output buffer acts only to the local buffer.
21 *
22 */
23
24 #include <linux/init.h>
25 #include <linux/wait.h>
26 #include <linux/module.h>
27 #include <linux/slab.h>
28 #include <sound/core.h>
29 #include <sound/rawmidi.h>
30 #include <sound/info.h>
31 #include <sound/control.h>
32 #include <sound/minors.h>
33 #include <sound/seq_kernel.h>
34 #include <sound/seq_midi_event.h>
35 #include <sound/seq_virmidi.h>
36
37 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
38 MODULE_DESCRIPTION("Virtual Raw MIDI client on Sequencer");
39 MODULE_LICENSE("GPL");
40
41 /*
42 * initialize an event record
43 */
snd_virmidi_init_event(struct snd_virmidi * vmidi,struct snd_seq_event * ev)44 static void snd_virmidi_init_event(struct snd_virmidi *vmidi,
45 struct snd_seq_event *ev)
46 {
47 memset(ev, 0, sizeof(*ev));
48 ev->source.port = vmidi->port;
49 switch (vmidi->seq_mode) {
50 case SNDRV_VIRMIDI_SEQ_DISPATCH:
51 ev->dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS;
52 break;
53 case SNDRV_VIRMIDI_SEQ_ATTACH:
54 /* FIXME: source and destination are same - not good.. */
55 ev->dest.client = vmidi->client;
56 ev->dest.port = vmidi->port;
57 break;
58 }
59 ev->type = SNDRV_SEQ_EVENT_NONE;
60 }
61
62 /*
63 * decode input event and put to read buffer of each opened file
64 */
65
66 /* callback for snd_seq_dump_var_event(), bridging to snd_rawmidi_receive() */
dump_to_rawmidi(void * ptr,void * buf,int count)67 static int dump_to_rawmidi(void *ptr, void *buf, int count)
68 {
69 return snd_rawmidi_receive(ptr, buf, count);
70 }
71
snd_virmidi_dev_receive_event(struct snd_virmidi_dev * rdev,struct snd_seq_event * ev,bool atomic)72 static int snd_virmidi_dev_receive_event(struct snd_virmidi_dev *rdev,
73 struct snd_seq_event *ev,
74 bool atomic)
75 {
76 struct snd_virmidi *vmidi;
77 unsigned char msg[4];
78 int len;
79
80 if (atomic)
81 rcu_read_lock();
82 else
83 down_read(&rdev->filelist_sem);
84 list_for_each_entry_rcu(vmidi, &rdev->filelist, list,
85 lockdep_is_held(&rdev->filelist_sem)) {
86 if (!READ_ONCE(vmidi->trigger))
87 continue;
88 if (ev->type == SNDRV_SEQ_EVENT_SYSEX) {
89 if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARIABLE)
90 continue;
91 snd_seq_dump_var_event(ev, dump_to_rawmidi, vmidi->substream);
92 snd_midi_event_reset_decode(vmidi->parser);
93 } else {
94 len = snd_midi_event_decode(vmidi->parser, msg, sizeof(msg), ev);
95 if (len > 0)
96 snd_rawmidi_receive(vmidi->substream, msg, len);
97 }
98 }
99 if (atomic)
100 rcu_read_unlock();
101 else
102 up_read(&rdev->filelist_sem);
103
104 return 0;
105 }
106
107 /*
108 * event handler of virmidi port
109 */
snd_virmidi_event_input(struct snd_seq_event * ev,int direct,void * private_data,int atomic,int hop)110 static int snd_virmidi_event_input(struct snd_seq_event *ev, int direct,
111 void *private_data, int atomic, int hop)
112 {
113 struct snd_virmidi_dev *rdev;
114
115 rdev = private_data;
116 if (!(rdev->flags & SNDRV_VIRMIDI_USE))
117 return 0; /* ignored */
118 return snd_virmidi_dev_receive_event(rdev, ev, atomic);
119 }
120
121 /*
122 * trigger rawmidi stream for input
123 */
snd_virmidi_input_trigger(struct snd_rawmidi_substream * substream,int up)124 static void snd_virmidi_input_trigger(struct snd_rawmidi_substream *substream, int up)
125 {
126 struct snd_virmidi *vmidi = substream->runtime->private_data;
127
128 WRITE_ONCE(vmidi->trigger, !!up);
129 }
130
131 /* process rawmidi bytes and send events;
132 * we need no lock here for vmidi->event since it's handled only in this work
133 */
snd_vmidi_output_work(struct work_struct * work)134 static void snd_vmidi_output_work(struct work_struct *work)
135 {
136 struct snd_virmidi *vmidi;
137 struct snd_rawmidi_substream *substream;
138 unsigned char input;
139 int ret;
140
141 vmidi = container_of(work, struct snd_virmidi, output_work);
142 substream = vmidi->substream;
143
144 /* discard the outputs in dispatch mode unless subscribed */
145 if (vmidi->seq_mode == SNDRV_VIRMIDI_SEQ_DISPATCH &&
146 !(vmidi->rdev->flags & SNDRV_VIRMIDI_SUBSCRIBE)) {
147 snd_rawmidi_proceed(substream);
148 return;
149 }
150
151 while (READ_ONCE(vmidi->trigger)) {
152 if (snd_rawmidi_transmit(substream, &input, 1) != 1)
153 break;
154 if (!snd_midi_event_encode_byte(vmidi->parser, input,
155 &vmidi->event))
156 continue;
157 if (vmidi->event.type != SNDRV_SEQ_EVENT_NONE) {
158 ret = snd_seq_kernel_client_dispatch(vmidi->client,
159 &vmidi->event,
160 false, 0);
161 vmidi->event.type = SNDRV_SEQ_EVENT_NONE;
162 if (ret < 0)
163 break;
164 }
165 /* rawmidi input might be huge, allow to have a break */
166 cond_resched();
167 }
168 }
169
170 /*
171 * trigger rawmidi stream for output
172 */
snd_virmidi_output_trigger(struct snd_rawmidi_substream * substream,int up)173 static void snd_virmidi_output_trigger(struct snd_rawmidi_substream *substream, int up)
174 {
175 struct snd_virmidi *vmidi = substream->runtime->private_data;
176
177 WRITE_ONCE(vmidi->trigger, !!up);
178 if (up)
179 queue_work(system_highpri_wq, &vmidi->output_work);
180 }
181
182 /*
183 * open rawmidi handle for input
184 */
snd_virmidi_input_open(struct snd_rawmidi_substream * substream)185 static int snd_virmidi_input_open(struct snd_rawmidi_substream *substream)
186 {
187 struct snd_virmidi_dev *rdev = substream->rmidi->private_data;
188 struct snd_rawmidi_runtime *runtime = substream->runtime;
189 struct snd_virmidi *vmidi;
190
191 vmidi = kzalloc_obj(*vmidi);
192 if (vmidi == NULL)
193 return -ENOMEM;
194 vmidi->substream = substream;
195 if (snd_midi_event_new(0, &vmidi->parser) < 0) {
196 kfree(vmidi);
197 return -ENOMEM;
198 }
199 vmidi->seq_mode = rdev->seq_mode;
200 vmidi->client = rdev->client;
201 vmidi->port = rdev->port;
202 runtime->private_data = vmidi;
203 scoped_guard(rwsem_write, &rdev->filelist_sem) {
204 list_add_tail_rcu(&vmidi->list, &rdev->filelist);
205 }
206 vmidi->rdev = rdev;
207 return 0;
208 }
209
210 /*
211 * open rawmidi handle for output
212 */
snd_virmidi_output_open(struct snd_rawmidi_substream * substream)213 static int snd_virmidi_output_open(struct snd_rawmidi_substream *substream)
214 {
215 struct snd_virmidi_dev *rdev = substream->rmidi->private_data;
216 struct snd_rawmidi_runtime *runtime = substream->runtime;
217 struct snd_virmidi *vmidi;
218
219 vmidi = kzalloc_obj(*vmidi);
220 if (vmidi == NULL)
221 return -ENOMEM;
222 vmidi->substream = substream;
223 if (snd_midi_event_new(MAX_MIDI_EVENT_BUF, &vmidi->parser) < 0) {
224 kfree(vmidi);
225 return -ENOMEM;
226 }
227 vmidi->seq_mode = rdev->seq_mode;
228 vmidi->client = rdev->client;
229 vmidi->port = rdev->port;
230 snd_virmidi_init_event(vmidi, &vmidi->event);
231 vmidi->rdev = rdev;
232 INIT_WORK(&vmidi->output_work, snd_vmidi_output_work);
233 runtime->private_data = vmidi;
234 return 0;
235 }
236
237 /*
238 * close rawmidi handle for input
239 */
snd_virmidi_input_close(struct snd_rawmidi_substream * substream)240 static int snd_virmidi_input_close(struct snd_rawmidi_substream *substream)
241 {
242 struct snd_virmidi_dev *rdev = substream->rmidi->private_data;
243 struct snd_virmidi *vmidi = substream->runtime->private_data;
244
245 scoped_guard(rwsem_write, &rdev->filelist_sem) {
246 list_del_rcu(&vmidi->list);
247 }
248 /* wait for a grace period so that lockless readers in the atomic
249 * delivery path (snd_virmidi_dev_receive_event()) are no longer
250 * traversing this entry before its parser and memory are freed
251 */
252 synchronize_rcu();
253 snd_midi_event_free(vmidi->parser);
254 substream->runtime->private_data = NULL;
255 kfree(vmidi);
256 return 0;
257 }
258
259 /*
260 * close rawmidi handle for output
261 */
snd_virmidi_output_close(struct snd_rawmidi_substream * substream)262 static int snd_virmidi_output_close(struct snd_rawmidi_substream *substream)
263 {
264 struct snd_virmidi *vmidi = substream->runtime->private_data;
265
266 WRITE_ONCE(vmidi->trigger, false); /* to be sure */
267 cancel_work_sync(&vmidi->output_work);
268 snd_midi_event_free(vmidi->parser);
269 substream->runtime->private_data = NULL;
270 kfree(vmidi);
271 return 0;
272 }
273
274 /*
275 * drain output work queue
276 */
snd_virmidi_output_drain(struct snd_rawmidi_substream * substream)277 static void snd_virmidi_output_drain(struct snd_rawmidi_substream *substream)
278 {
279 struct snd_virmidi *vmidi = substream->runtime->private_data;
280
281 flush_work(&vmidi->output_work);
282 }
283
284 /*
285 * subscribe callback - allow output to rawmidi device
286 */
snd_virmidi_subscribe(void * private_data,struct snd_seq_port_subscribe * info)287 static int snd_virmidi_subscribe(void *private_data,
288 struct snd_seq_port_subscribe *info)
289 {
290 struct snd_virmidi_dev *rdev;
291
292 rdev = private_data;
293 if (!try_module_get(rdev->card->module))
294 return -EFAULT;
295 rdev->flags |= SNDRV_VIRMIDI_SUBSCRIBE;
296 return 0;
297 }
298
299 /*
300 * unsubscribe callback - disallow output to rawmidi device
301 */
snd_virmidi_unsubscribe(void * private_data,struct snd_seq_port_subscribe * info)302 static int snd_virmidi_unsubscribe(void *private_data,
303 struct snd_seq_port_subscribe *info)
304 {
305 struct snd_virmidi_dev *rdev;
306
307 rdev = private_data;
308 rdev->flags &= ~SNDRV_VIRMIDI_SUBSCRIBE;
309 module_put(rdev->card->module);
310 return 0;
311 }
312
313
314 /*
315 * use callback - allow input to rawmidi device
316 */
snd_virmidi_use(void * private_data,struct snd_seq_port_subscribe * info)317 static int snd_virmidi_use(void *private_data,
318 struct snd_seq_port_subscribe *info)
319 {
320 struct snd_virmidi_dev *rdev;
321
322 rdev = private_data;
323 if (!try_module_get(rdev->card->module))
324 return -EFAULT;
325 rdev->flags |= SNDRV_VIRMIDI_USE;
326 return 0;
327 }
328
329 /*
330 * unuse callback - disallow input to rawmidi device
331 */
snd_virmidi_unuse(void * private_data,struct snd_seq_port_subscribe * info)332 static int snd_virmidi_unuse(void *private_data,
333 struct snd_seq_port_subscribe *info)
334 {
335 struct snd_virmidi_dev *rdev;
336
337 rdev = private_data;
338 rdev->flags &= ~SNDRV_VIRMIDI_USE;
339 module_put(rdev->card->module);
340 return 0;
341 }
342
343
344 /*
345 * Register functions
346 */
347
348 static const struct snd_rawmidi_ops snd_virmidi_input_ops = {
349 .open = snd_virmidi_input_open,
350 .close = snd_virmidi_input_close,
351 .trigger = snd_virmidi_input_trigger,
352 };
353
354 static const struct snd_rawmidi_ops snd_virmidi_output_ops = {
355 .open = snd_virmidi_output_open,
356 .close = snd_virmidi_output_close,
357 .trigger = snd_virmidi_output_trigger,
358 .drain = snd_virmidi_output_drain,
359 };
360
361 /*
362 * create a sequencer client and a port
363 */
snd_virmidi_dev_attach_seq(struct snd_virmidi_dev * rdev)364 static int snd_virmidi_dev_attach_seq(struct snd_virmidi_dev *rdev)
365 {
366 int client;
367 struct snd_seq_port_callback pcallbacks;
368 int err;
369
370 if (rdev->client >= 0)
371 return 0;
372
373 struct snd_seq_port_info *pinfo __free(kfree) =
374 kzalloc_obj(*pinfo);
375 if (!pinfo)
376 return -ENOMEM;
377
378 client = snd_seq_create_kernel_client(rdev->card, rdev->device,
379 "%s %d-%d", rdev->rmidi->name,
380 rdev->card->number,
381 rdev->device);
382 if (client < 0)
383 return client;
384 rdev->client = client;
385
386 /* create a port */
387 pinfo->addr.client = client;
388 sprintf(pinfo->name, "VirMIDI %d-%d", rdev->card->number, rdev->device);
389 /* set all capabilities */
390 pinfo->capability |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SYNC_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE;
391 pinfo->capability |= SNDRV_SEQ_PORT_CAP_READ | SNDRV_SEQ_PORT_CAP_SYNC_READ | SNDRV_SEQ_PORT_CAP_SUBS_READ;
392 pinfo->capability |= SNDRV_SEQ_PORT_CAP_DUPLEX;
393 pinfo->direction = SNDRV_SEQ_PORT_DIR_BIDIRECTION;
394 pinfo->type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC
395 | SNDRV_SEQ_PORT_TYPE_SOFTWARE
396 | SNDRV_SEQ_PORT_TYPE_PORT;
397 pinfo->midi_channels = 16;
398 memset(&pcallbacks, 0, sizeof(pcallbacks));
399 pcallbacks.owner = THIS_MODULE;
400 pcallbacks.private_data = rdev;
401 pcallbacks.subscribe = snd_virmidi_subscribe;
402 pcallbacks.unsubscribe = snd_virmidi_unsubscribe;
403 pcallbacks.use = snd_virmidi_use;
404 pcallbacks.unuse = snd_virmidi_unuse;
405 pcallbacks.event_input = snd_virmidi_event_input;
406 pinfo->kernel = &pcallbacks;
407 err = snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_CREATE_PORT, pinfo);
408 if (err < 0) {
409 snd_seq_delete_kernel_client(client);
410 rdev->client = -1;
411 return err;
412 }
413
414 rdev->port = pinfo->addr.port;
415 return 0; /* success */
416 }
417
418
419 /*
420 * release the sequencer client
421 */
snd_virmidi_dev_detach_seq(struct snd_virmidi_dev * rdev)422 static void snd_virmidi_dev_detach_seq(struct snd_virmidi_dev *rdev)
423 {
424 if (rdev->client >= 0) {
425 snd_seq_delete_kernel_client(rdev->client);
426 rdev->client = -1;
427 }
428 }
429
430 /*
431 * register the device
432 */
snd_virmidi_dev_register(struct snd_rawmidi * rmidi)433 static int snd_virmidi_dev_register(struct snd_rawmidi *rmidi)
434 {
435 struct snd_virmidi_dev *rdev = rmidi->private_data;
436 int err;
437
438 switch (rdev->seq_mode) {
439 case SNDRV_VIRMIDI_SEQ_DISPATCH:
440 err = snd_virmidi_dev_attach_seq(rdev);
441 if (err < 0)
442 return err;
443 break;
444 case SNDRV_VIRMIDI_SEQ_ATTACH:
445 if (rdev->client == 0)
446 return -EINVAL;
447 /* should check presence of port more strictly.. */
448 break;
449 default:
450 pr_err("ALSA: seq_virmidi: seq_mode is not set: %d\n", rdev->seq_mode);
451 return -EINVAL;
452 }
453 return 0;
454 }
455
456
457 /*
458 * unregister the device
459 */
snd_virmidi_dev_unregister(struct snd_rawmidi * rmidi)460 static int snd_virmidi_dev_unregister(struct snd_rawmidi *rmidi)
461 {
462 struct snd_virmidi_dev *rdev = rmidi->private_data;
463
464 if (rdev->seq_mode == SNDRV_VIRMIDI_SEQ_DISPATCH)
465 snd_virmidi_dev_detach_seq(rdev);
466 return 0;
467 }
468
469 /*
470 *
471 */
472 static const struct snd_rawmidi_global_ops snd_virmidi_global_ops = {
473 .dev_register = snd_virmidi_dev_register,
474 .dev_unregister = snd_virmidi_dev_unregister,
475 };
476
477 /*
478 * free device
479 */
snd_virmidi_free(struct snd_rawmidi * rmidi)480 static void snd_virmidi_free(struct snd_rawmidi *rmidi)
481 {
482 struct snd_virmidi_dev *rdev = rmidi->private_data;
483 kfree(rdev);
484 }
485
486 /*
487 * create a new device
488 *
489 */
490 /* exported */
snd_virmidi_new(struct snd_card * card,int device,struct snd_rawmidi ** rrmidi)491 int snd_virmidi_new(struct snd_card *card, int device, struct snd_rawmidi **rrmidi)
492 {
493 struct snd_rawmidi *rmidi;
494 struct snd_virmidi_dev *rdev;
495 int err;
496
497 *rrmidi = NULL;
498 err = snd_rawmidi_new(card, "VirMidi", device,
499 16, /* may be configurable */
500 16, /* may be configurable */
501 &rmidi);
502 if (err < 0)
503 return err;
504 strscpy(rmidi->name, rmidi->id);
505 rdev = kzalloc_obj(*rdev);
506 if (rdev == NULL) {
507 snd_device_free(card, rmidi);
508 return -ENOMEM;
509 }
510 rdev->card = card;
511 rdev->rmidi = rmidi;
512 rdev->device = device;
513 rdev->client = -1;
514 init_rwsem(&rdev->filelist_sem);
515 INIT_LIST_HEAD(&rdev->filelist);
516 rdev->seq_mode = SNDRV_VIRMIDI_SEQ_DISPATCH;
517 rmidi->private_data = rdev;
518 rmidi->private_free = snd_virmidi_free;
519 rmidi->ops = &snd_virmidi_global_ops;
520 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_virmidi_input_ops);
521 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_virmidi_output_ops);
522 rmidi->info_flags = SNDRV_RAWMIDI_INFO_INPUT |
523 SNDRV_RAWMIDI_INFO_OUTPUT |
524 SNDRV_RAWMIDI_INFO_DUPLEX;
525 *rrmidi = rmidi;
526 return 0;
527 }
528 EXPORT_SYMBOL(snd_virmidi_new);
529