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 = kmalloc(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 annoucement receiver port */ 84 memset(port, 0, sizeof(*port)); 85 strcpy(port->name, "Receiver"); 86 port->addr.client = system_client; 87 port->capability = SNDRV_SEQ_PORT_CAP_WRITE; /* receive only */ 88 port->type = 0; 89 90 memset(&port_callback, 0, sizeof(port_callback)); 91 /* don't set port_callback.owner here. otherwise the module counter 92 * is incremented and we can no longer release the module.. 93 */ 94 port_callback.event_input = receive_announce; 95 port->kernel = &port_callback; 96 97 call_ctl(SNDRV_SEQ_IOCTL_CREATE_PORT, port); 98 if ((system_port = port->addr.port) >= 0) { 99 struct snd_seq_port_subscribe subs; 100 101 memset(&subs, 0, sizeof(subs)); 102 subs.sender.client = SNDRV_SEQ_CLIENT_SYSTEM; 103 subs.sender.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE; 104 subs.dest.client = system_client; 105 subs.dest.port = system_port; 106 call_ctl(SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, &subs); 107 } 108 rc = 0; 109 110 /* look up midi devices */ 111 schedule_work(&async_lookup_work); 112 113 __error: 114 kfree(port); 115 return rc; 116 } 117 118 119 /* 120 * receive annoucement from system port, and check the midi device 121 */ 122 static int 123 receive_announce(struct snd_seq_event *ev, int direct, void *private, int atomic, int hop) 124 { 125 struct snd_seq_port_info pinfo; 126 127 if (atomic) 128 return 0; /* it must not happen */ 129 130 switch (ev->type) { 131 case SNDRV_SEQ_EVENT_PORT_START: 132 case SNDRV_SEQ_EVENT_PORT_CHANGE: 133 if (ev->data.addr.client == system_client) 134 break; /* ignore myself */ 135 memset(&pinfo, 0, sizeof(pinfo)); 136 pinfo.addr = ev->data.addr; 137 if (call_ctl(SNDRV_SEQ_IOCTL_GET_PORT_INFO, &pinfo) >= 0) 138 snd_seq_oss_midi_check_new_port(&pinfo); 139 break; 140 141 case SNDRV_SEQ_EVENT_PORT_EXIT: 142 if (ev->data.addr.client == system_client) 143 break; /* ignore myself */ 144 snd_seq_oss_midi_check_exit_port(ev->data.addr.client, 145 ev->data.addr.port); 146 break; 147 } 148 return 0; 149 } 150 151 152 /* 153 * delete OSS sequencer client 154 */ 155 int 156 snd_seq_oss_delete_client(void) 157 { 158 cancel_work_sync(&async_lookup_work); 159 if (system_client >= 0) 160 snd_seq_delete_kernel_client(system_client); 161 162 snd_seq_oss_midi_clear_all(); 163 164 return 0; 165 } 166 167 168 /* 169 * open sequencer device 170 */ 171 int 172 snd_seq_oss_open(struct file *file, int level) 173 { 174 int i, rc; 175 struct seq_oss_devinfo *dp; 176 177 dp = kzalloc(sizeof(*dp), GFP_KERNEL); 178 if (!dp) 179 return -ENOMEM; 180 181 dp->cseq = system_client; 182 dp->port = -1; 183 dp->queue = -1; 184 185 for (i = 0; i < SNDRV_SEQ_OSS_MAX_CLIENTS; i++) { 186 if (client_table[i] == NULL) 187 break; 188 } 189 190 dp->index = i; 191 if (i >= SNDRV_SEQ_OSS_MAX_CLIENTS) { 192 pr_debug("ALSA: seq_oss: too many applications\n"); 193 rc = -ENOMEM; 194 goto _error; 195 } 196 197 /* look up synth and midi devices */ 198 snd_seq_oss_synth_setup(dp); 199 snd_seq_oss_midi_setup(dp); 200 201 if (dp->synth_opened == 0 && dp->max_mididev == 0) { 202 /* pr_err("ALSA: seq_oss: no device found\n"); */ 203 rc = -ENODEV; 204 goto _error; 205 } 206 207 /* create port */ 208 rc = create_port(dp); 209 if (rc < 0) { 210 pr_err("ALSA: seq_oss: can't create port\n"); 211 goto _error; 212 } 213 214 /* allocate queue */ 215 rc = alloc_seq_queue(dp); 216 if (rc < 0) 217 goto _error; 218 219 /* set address */ 220 dp->addr.client = dp->cseq; 221 dp->addr.port = dp->port; 222 /*dp->addr.queue = dp->queue;*/ 223 /*dp->addr.channel = 0;*/ 224 225 dp->seq_mode = level; 226 227 /* set up file mode */ 228 dp->file_mode = translate_mode(file); 229 230 /* initialize read queue */ 231 if (is_read_mode(dp->file_mode)) { 232 dp->readq = snd_seq_oss_readq_new(dp, maxqlen); 233 if (!dp->readq) { 234 rc = -ENOMEM; 235 goto _error; 236 } 237 } 238 239 /* initialize write queue */ 240 if (is_write_mode(dp->file_mode)) { 241 dp->writeq = snd_seq_oss_writeq_new(dp, maxqlen); 242 if (!dp->writeq) { 243 rc = -ENOMEM; 244 goto _error; 245 } 246 } 247 248 /* initialize timer */ 249 dp->timer = snd_seq_oss_timer_new(dp); 250 if (!dp->timer) { 251 pr_err("ALSA: seq_oss: can't alloc timer\n"); 252 rc = -ENOMEM; 253 goto _error; 254 } 255 256 /* set private data pointer */ 257 file->private_data = dp; 258 259 /* set up for mode2 */ 260 if (level == SNDRV_SEQ_OSS_MODE_MUSIC) 261 snd_seq_oss_synth_setup_midi(dp); 262 else if (is_read_mode(dp->file_mode)) 263 snd_seq_oss_midi_open_all(dp, SNDRV_SEQ_OSS_FILE_READ); 264 265 client_table[dp->index] = dp; 266 num_clients++; 267 268 return 0; 269 270 _error: 271 snd_seq_oss_synth_cleanup(dp); 272 snd_seq_oss_midi_cleanup(dp); 273 delete_seq_queue(dp->queue); 274 delete_port(dp); 275 276 return rc; 277 } 278 279 /* 280 * translate file flags to private mode 281 */ 282 static int 283 translate_mode(struct file *file) 284 { 285 int file_mode = 0; 286 if ((file->f_flags & O_ACCMODE) != O_RDONLY) 287 file_mode |= SNDRV_SEQ_OSS_FILE_WRITE; 288 if ((file->f_flags & O_ACCMODE) != O_WRONLY) 289 file_mode |= SNDRV_SEQ_OSS_FILE_READ; 290 if (file->f_flags & O_NONBLOCK) 291 file_mode |= SNDRV_SEQ_OSS_FILE_NONBLOCK; 292 return file_mode; 293 } 294 295 296 /* 297 * create sequencer port 298 */ 299 static int 300 create_port(struct seq_oss_devinfo *dp) 301 { 302 int rc; 303 struct snd_seq_port_info port; 304 struct snd_seq_port_callback callback; 305 306 memset(&port, 0, sizeof(port)); 307 port.addr.client = dp->cseq; 308 sprintf(port.name, "Sequencer-%d", dp->index); 309 port.capability = SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_WRITE; /* no subscription */ 310 port.type = SNDRV_SEQ_PORT_TYPE_SPECIFIC; 311 port.midi_channels = 128; 312 port.synth_voices = 128; 313 314 memset(&callback, 0, sizeof(callback)); 315 callback.owner = THIS_MODULE; 316 callback.private_data = dp; 317 callback.event_input = snd_seq_oss_event_input; 318 callback.private_free = free_devinfo; 319 port.kernel = &callback; 320 321 rc = call_ctl(SNDRV_SEQ_IOCTL_CREATE_PORT, &port); 322 if (rc < 0) 323 return rc; 324 325 dp->port = port.addr.port; 326 327 return 0; 328 } 329 330 /* 331 * delete ALSA port 332 */ 333 static int 334 delete_port(struct seq_oss_devinfo *dp) 335 { 336 if (dp->port < 0) { 337 kfree(dp); 338 return 0; 339 } 340 341 return snd_seq_event_port_detach(dp->cseq, dp->port); 342 } 343 344 /* 345 * allocate a queue 346 */ 347 static int 348 alloc_seq_queue(struct seq_oss_devinfo *dp) 349 { 350 struct snd_seq_queue_info qinfo; 351 int rc; 352 353 memset(&qinfo, 0, sizeof(qinfo)); 354 qinfo.owner = system_client; 355 qinfo.locked = 1; 356 strcpy(qinfo.name, "OSS Sequencer Emulation"); 357 if ((rc = call_ctl(SNDRV_SEQ_IOCTL_CREATE_QUEUE, &qinfo)) < 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 if ((dp = client_table[i]) == NULL) { 489 snd_iprintf(buf, "*empty*\n"); 490 continue; 491 } 492 snd_iprintf(buf, "port %d : queue %d\n", dp->port, dp->queue); 493 snd_iprintf(buf, " sequencer mode = %s : file open mode = %s\n", 494 (dp->seq_mode ? "music" : "synth"), 495 filemode_str(dp->file_mode)); 496 if (dp->seq_mode) 497 snd_iprintf(buf, " timer tempo = %d, timebase = %d\n", 498 dp->timer->oss_tempo, dp->timer->oss_timebase); 499 snd_iprintf(buf, " max queue length %d\n", maxqlen); 500 if (is_read_mode(dp->file_mode) && dp->readq) 501 snd_seq_oss_readq_info_read(dp->readq, buf); 502 } 503 } 504 #endif /* CONFIG_SND_PROC_FS */ 505