1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * OSS compatible sequencer driver 4 * 5 * open/close and reset interface 6 * 7 * Copyright (C) 1998-1999 Takashi Iwai <tiwai@suse.de> 8 */ 9 10 #include "seq_oss_device.h" 11 #include "seq_oss_synth.h" 12 #include "seq_oss_midi.h" 13 #include "seq_oss_writeq.h" 14 #include "seq_oss_readq.h" 15 #include "seq_oss_timer.h" 16 #include "seq_oss_event.h" 17 #include <linux/init.h> 18 #include <linux/export.h> 19 #include <linux/moduleparam.h> 20 #include <linux/slab.h> 21 #include <linux/workqueue.h> 22 23 /* 24 * common variables 25 */ 26 static int maxqlen = SNDRV_SEQ_OSS_MAX_QLEN; 27 module_param(maxqlen, int, 0444); 28 MODULE_PARM_DESC(maxqlen, "maximum queue length"); 29 30 static int system_client = -1; /* ALSA sequencer client number */ 31 static int system_port = -1; 32 33 static int num_clients; 34 static struct seq_oss_devinfo *client_table[SNDRV_SEQ_OSS_MAX_CLIENTS]; 35 36 37 /* 38 * prototypes 39 */ 40 static int receive_announce(struct snd_seq_event *ev, int direct, void *private, int atomic, int hop); 41 static int translate_mode(struct file *file); 42 static int create_port(struct seq_oss_devinfo *dp); 43 static int delete_port(struct seq_oss_devinfo *dp); 44 static int alloc_seq_queue(struct seq_oss_devinfo *dp); 45 static int delete_seq_queue(int queue); 46 static void free_devinfo(void *private); 47 48 #define call_ctl(type,rec) snd_seq_kernel_client_ctl(system_client, type, rec) 49 50 51 /* call snd_seq_oss_midi_lookup_ports() asynchronously */ 52 static void async_call_lookup_ports(struct work_struct *work) 53 { 54 snd_seq_oss_midi_lookup_ports(system_client); 55 } 56 57 static DECLARE_WORK(async_lookup_work, async_call_lookup_ports); 58 59 /* 60 * create sequencer client for OSS sequencer 61 */ 62 int __init 63 snd_seq_oss_create_client(void) 64 { 65 int rc; 66 struct snd_seq_port_info *port; 67 struct snd_seq_port_callback port_callback; 68 69 port = kzalloc(sizeof(*port), GFP_KERNEL); 70 if (!port) { 71 rc = -ENOMEM; 72 goto __error; 73 } 74 75 /* create ALSA client */ 76 rc = snd_seq_create_kernel_client(NULL, SNDRV_SEQ_CLIENT_OSS, 77 "OSS sequencer"); 78 if (rc < 0) 79 goto __error; 80 81 system_client = rc; 82 83 /* create announcement receiver port */ 84 strcpy(port->name, "Receiver"); 85 port->addr.client = system_client; 86 port->capability = SNDRV_SEQ_PORT_CAP_WRITE; /* receive only */ 87 port->type = 0; 88 89 memset(&port_callback, 0, sizeof(port_callback)); 90 /* don't set port_callback.owner here. otherwise the module counter 91 * is incremented and we can no longer release the module.. 92 */ 93 port_callback.event_input = receive_announce; 94 port->kernel = &port_callback; 95 96 if (call_ctl(SNDRV_SEQ_IOCTL_CREATE_PORT, port) >= 0) { 97 struct snd_seq_port_subscribe subs; 98 99 system_port = port->addr.port; 100 memset(&subs, 0, sizeof(subs)); 101 subs.sender.client = SNDRV_SEQ_CLIENT_SYSTEM; 102 subs.sender.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE; 103 subs.dest.client = system_client; 104 subs.dest.port = system_port; 105 call_ctl(SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, &subs); 106 } 107 rc = 0; 108 109 /* look up midi devices */ 110 schedule_work(&async_lookup_work); 111 112 __error: 113 kfree(port); 114 return rc; 115 } 116 117 118 /* 119 * receive annoucement from system port, and check the midi device 120 */ 121 static int 122 receive_announce(struct snd_seq_event *ev, int direct, void *private, int atomic, int hop) 123 { 124 struct snd_seq_port_info pinfo; 125 126 if (atomic) 127 return 0; /* it must not happen */ 128 129 switch (ev->type) { 130 case SNDRV_SEQ_EVENT_PORT_START: 131 case SNDRV_SEQ_EVENT_PORT_CHANGE: 132 if (ev->data.addr.client == system_client) 133 break; /* ignore myself */ 134 memset(&pinfo, 0, sizeof(pinfo)); 135 pinfo.addr = ev->data.addr; 136 if (call_ctl(SNDRV_SEQ_IOCTL_GET_PORT_INFO, &pinfo) >= 0) 137 snd_seq_oss_midi_check_new_port(&pinfo); 138 break; 139 140 case SNDRV_SEQ_EVENT_PORT_EXIT: 141 if (ev->data.addr.client == system_client) 142 break; /* ignore myself */ 143 snd_seq_oss_midi_check_exit_port(ev->data.addr.client, 144 ev->data.addr.port); 145 break; 146 } 147 return 0; 148 } 149 150 151 /* 152 * delete OSS sequencer client 153 */ 154 int 155 snd_seq_oss_delete_client(void) 156 { 157 cancel_work_sync(&async_lookup_work); 158 if (system_client >= 0) 159 snd_seq_delete_kernel_client(system_client); 160 161 snd_seq_oss_midi_clear_all(); 162 163 return 0; 164 } 165 166 167 /* 168 * open sequencer device 169 */ 170 int 171 snd_seq_oss_open(struct file *file, int level) 172 { 173 int i, rc; 174 struct seq_oss_devinfo *dp; 175 176 dp = kzalloc(sizeof(*dp), GFP_KERNEL); 177 if (!dp) 178 return -ENOMEM; 179 180 dp->cseq = system_client; 181 dp->port = -1; 182 dp->queue = -1; 183 184 for (i = 0; i < SNDRV_SEQ_OSS_MAX_CLIENTS; i++) { 185 if (client_table[i] == NULL) 186 break; 187 } 188 189 dp->index = i; 190 if (i >= SNDRV_SEQ_OSS_MAX_CLIENTS) { 191 pr_debug("ALSA: seq_oss: too many applications\n"); 192 rc = -ENOMEM; 193 goto _error; 194 } 195 196 /* look up synth and midi devices */ 197 snd_seq_oss_synth_setup(dp); 198 snd_seq_oss_midi_setup(dp); 199 200 if (dp->synth_opened == 0 && dp->max_mididev == 0) { 201 /* pr_err("ALSA: seq_oss: no device found\n"); */ 202 rc = -ENODEV; 203 goto _error; 204 } 205 206 /* create port */ 207 rc = create_port(dp); 208 if (rc < 0) { 209 pr_err("ALSA: seq_oss: can't create port\n"); 210 goto _error; 211 } 212 213 /* allocate queue */ 214 rc = alloc_seq_queue(dp); 215 if (rc < 0) 216 goto _error; 217 218 /* set address */ 219 dp->addr.client = dp->cseq; 220 dp->addr.port = dp->port; 221 /*dp->addr.queue = dp->queue;*/ 222 /*dp->addr.channel = 0;*/ 223 224 dp->seq_mode = level; 225 226 /* set up file mode */ 227 dp->file_mode = translate_mode(file); 228 229 /* initialize read queue */ 230 if (is_read_mode(dp->file_mode)) { 231 dp->readq = snd_seq_oss_readq_new(dp, maxqlen); 232 if (!dp->readq) { 233 rc = -ENOMEM; 234 goto _error; 235 } 236 } 237 238 /* initialize write queue */ 239 if (is_write_mode(dp->file_mode)) { 240 dp->writeq = snd_seq_oss_writeq_new(dp, maxqlen); 241 if (!dp->writeq) { 242 rc = -ENOMEM; 243 goto _error; 244 } 245 } 246 247 /* initialize timer */ 248 dp->timer = snd_seq_oss_timer_new(dp); 249 if (!dp->timer) { 250 pr_err("ALSA: seq_oss: can't alloc timer\n"); 251 rc = -ENOMEM; 252 goto _error; 253 } 254 255 /* set private data pointer */ 256 file->private_data = dp; 257 258 /* set up for mode2 */ 259 if (level == SNDRV_SEQ_OSS_MODE_MUSIC) 260 snd_seq_oss_synth_setup_midi(dp); 261 else if (is_read_mode(dp->file_mode)) 262 snd_seq_oss_midi_open_all(dp, SNDRV_SEQ_OSS_FILE_READ); 263 264 client_table[dp->index] = dp; 265 num_clients++; 266 267 return 0; 268 269 _error: 270 snd_seq_oss_synth_cleanup(dp); 271 snd_seq_oss_midi_cleanup(dp); 272 delete_seq_queue(dp->queue); 273 delete_port(dp); 274 275 return rc; 276 } 277 278 /* 279 * translate file flags to private mode 280 */ 281 static int 282 translate_mode(struct file *file) 283 { 284 int file_mode = 0; 285 if ((file->f_flags & O_ACCMODE) != O_RDONLY) 286 file_mode |= SNDRV_SEQ_OSS_FILE_WRITE; 287 if ((file->f_flags & O_ACCMODE) != O_WRONLY) 288 file_mode |= SNDRV_SEQ_OSS_FILE_READ; 289 if (file->f_flags & O_NONBLOCK) 290 file_mode |= SNDRV_SEQ_OSS_FILE_NONBLOCK; 291 return file_mode; 292 } 293 294 295 /* 296 * create sequencer port 297 */ 298 static int 299 create_port(struct seq_oss_devinfo *dp) 300 { 301 int rc; 302 struct snd_seq_port_info port; 303 struct snd_seq_port_callback callback; 304 305 memset(&port, 0, sizeof(port)); 306 port.addr.client = dp->cseq; 307 sprintf(port.name, "Sequencer-%d", dp->index); 308 port.capability = SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_WRITE; /* no subscription */ 309 port.type = SNDRV_SEQ_PORT_TYPE_SPECIFIC; 310 port.midi_channels = 128; 311 port.synth_voices = 128; 312 313 memset(&callback, 0, sizeof(callback)); 314 callback.owner = THIS_MODULE; 315 callback.private_data = dp; 316 callback.event_input = snd_seq_oss_event_input; 317 callback.private_free = free_devinfo; 318 port.kernel = &callback; 319 320 rc = call_ctl(SNDRV_SEQ_IOCTL_CREATE_PORT, &port); 321 if (rc < 0) 322 return rc; 323 324 dp->port = port.addr.port; 325 326 return 0; 327 } 328 329 /* 330 * delete ALSA port 331 */ 332 static int 333 delete_port(struct seq_oss_devinfo *dp) 334 { 335 if (dp->port < 0) { 336 kfree(dp); 337 return 0; 338 } 339 340 return snd_seq_event_port_detach(dp->cseq, dp->port); 341 } 342 343 /* 344 * allocate a queue 345 */ 346 static int 347 alloc_seq_queue(struct seq_oss_devinfo *dp) 348 { 349 struct snd_seq_queue_info qinfo; 350 int rc; 351 352 memset(&qinfo, 0, sizeof(qinfo)); 353 qinfo.owner = system_client; 354 qinfo.locked = 1; 355 strcpy(qinfo.name, "OSS Sequencer Emulation"); 356 rc = call_ctl(SNDRV_SEQ_IOCTL_CREATE_QUEUE, &qinfo); 357 if (rc < 0) 358 return rc; 359 dp->queue = qinfo.queue; 360 return 0; 361 } 362 363 /* 364 * release queue 365 */ 366 static int 367 delete_seq_queue(int queue) 368 { 369 struct snd_seq_queue_info qinfo; 370 int rc; 371 372 if (queue < 0) 373 return 0; 374 memset(&qinfo, 0, sizeof(qinfo)); 375 qinfo.queue = queue; 376 rc = call_ctl(SNDRV_SEQ_IOCTL_DELETE_QUEUE, &qinfo); 377 if (rc < 0) 378 pr_err("ALSA: seq_oss: unable to delete queue %d (%d)\n", queue, rc); 379 return rc; 380 } 381 382 383 /* 384 * free device informations - private_free callback of port 385 */ 386 static void 387 free_devinfo(void *private) 388 { 389 struct seq_oss_devinfo *dp = (struct seq_oss_devinfo *)private; 390 391 snd_seq_oss_timer_delete(dp->timer); 392 393 snd_seq_oss_writeq_delete(dp->writeq); 394 395 snd_seq_oss_readq_delete(dp->readq); 396 397 kfree(dp); 398 } 399 400 401 /* 402 * close sequencer device 403 */ 404 void 405 snd_seq_oss_release(struct seq_oss_devinfo *dp) 406 { 407 int queue; 408 409 client_table[dp->index] = NULL; 410 num_clients--; 411 412 snd_seq_oss_reset(dp); 413 414 snd_seq_oss_synth_cleanup(dp); 415 snd_seq_oss_midi_cleanup(dp); 416 417 /* clear slot */ 418 queue = dp->queue; 419 if (dp->port >= 0) 420 delete_port(dp); 421 delete_seq_queue(queue); 422 } 423 424 425 /* 426 * reset sequencer devices 427 */ 428 void 429 snd_seq_oss_reset(struct seq_oss_devinfo *dp) 430 { 431 int i; 432 433 /* reset all synth devices */ 434 for (i = 0; i < dp->max_synthdev; i++) 435 snd_seq_oss_synth_reset(dp, i); 436 437 /* reset all midi devices */ 438 if (dp->seq_mode != SNDRV_SEQ_OSS_MODE_MUSIC) { 439 for (i = 0; i < dp->max_mididev; i++) 440 snd_seq_oss_midi_reset(dp, i); 441 } 442 443 /* remove queues */ 444 if (dp->readq) 445 snd_seq_oss_readq_clear(dp->readq); 446 if (dp->writeq) 447 snd_seq_oss_writeq_clear(dp->writeq); 448 449 /* reset timer */ 450 snd_seq_oss_timer_stop(dp->timer); 451 } 452 453 #ifdef CONFIG_SND_PROC_FS 454 /* 455 * misc. functions for proc interface 456 */ 457 char * 458 enabled_str(int bool) 459 { 460 return bool ? "enabled" : "disabled"; 461 } 462 463 static const char * 464 filemode_str(int val) 465 { 466 static const char * const str[] = { 467 "none", "read", "write", "read/write", 468 }; 469 return str[val & SNDRV_SEQ_OSS_FILE_ACMODE]; 470 } 471 472 473 /* 474 * proc interface 475 */ 476 void 477 snd_seq_oss_system_info_read(struct snd_info_buffer *buf) 478 { 479 int i; 480 struct seq_oss_devinfo *dp; 481 482 snd_iprintf(buf, "ALSA client number %d\n", system_client); 483 snd_iprintf(buf, "ALSA receiver port %d\n", system_port); 484 485 snd_iprintf(buf, "\nNumber of applications: %d\n", num_clients); 486 for (i = 0; i < num_clients; i++) { 487 snd_iprintf(buf, "\nApplication %d: ", i); 488 dp = client_table[i]; 489 if (!dp) { 490 snd_iprintf(buf, "*empty*\n"); 491 continue; 492 } 493 snd_iprintf(buf, "port %d : queue %d\n", dp->port, dp->queue); 494 snd_iprintf(buf, " sequencer mode = %s : file open mode = %s\n", 495 (dp->seq_mode ? "music" : "synth"), 496 filemode_str(dp->file_mode)); 497 if (dp->seq_mode) 498 snd_iprintf(buf, " timer tempo = %d, timebase = %d\n", 499 dp->timer->oss_tempo, dp->timer->oss_timebase); 500 snd_iprintf(buf, " max queue length %d\n", maxqlen); 501 if (is_read_mode(dp->file_mode) && dp->readq) 502 snd_seq_oss_readq_info_read(dp->readq, buf); 503 } 504 } 505 #endif /* CONFIG_SND_PROC_FS */ 506