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