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 if (call_ctl(SNDRV_SEQ_IOCTL_CREATE_PORT, port) >= 0) { 98 struct snd_seq_port_subscribe subs; 99 100 system_port = port->addr.port; 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 rc = call_ctl(SNDRV_SEQ_IOCTL_CREATE_QUEUE, &qinfo); 358 if (rc < 0) 359 return rc; 360 dp->queue = qinfo.queue; 361 return 0; 362 } 363 364 /* 365 * release queue 366 */ 367 static int 368 delete_seq_queue(int queue) 369 { 370 struct snd_seq_queue_info qinfo; 371 int rc; 372 373 if (queue < 0) 374 return 0; 375 memset(&qinfo, 0, sizeof(qinfo)); 376 qinfo.queue = queue; 377 rc = call_ctl(SNDRV_SEQ_IOCTL_DELETE_QUEUE, &qinfo); 378 if (rc < 0) 379 pr_err("ALSA: seq_oss: unable to delete queue %d (%d)\n", queue, rc); 380 return rc; 381 } 382 383 384 /* 385 * free device informations - private_free callback of port 386 */ 387 static void 388 free_devinfo(void *private) 389 { 390 struct seq_oss_devinfo *dp = (struct seq_oss_devinfo *)private; 391 392 snd_seq_oss_timer_delete(dp->timer); 393 394 snd_seq_oss_writeq_delete(dp->writeq); 395 396 snd_seq_oss_readq_delete(dp->readq); 397 398 kfree(dp); 399 } 400 401 402 /* 403 * close sequencer device 404 */ 405 void 406 snd_seq_oss_release(struct seq_oss_devinfo *dp) 407 { 408 int queue; 409 410 client_table[dp->index] = NULL; 411 num_clients--; 412 413 snd_seq_oss_reset(dp); 414 415 snd_seq_oss_synth_cleanup(dp); 416 snd_seq_oss_midi_cleanup(dp); 417 418 /* clear slot */ 419 queue = dp->queue; 420 if (dp->port >= 0) 421 delete_port(dp); 422 delete_seq_queue(queue); 423 } 424 425 426 /* 427 * reset sequencer devices 428 */ 429 void 430 snd_seq_oss_reset(struct seq_oss_devinfo *dp) 431 { 432 int i; 433 434 /* reset all synth devices */ 435 for (i = 0; i < dp->max_synthdev; i++) 436 snd_seq_oss_synth_reset(dp, i); 437 438 /* reset all midi devices */ 439 if (dp->seq_mode != SNDRV_SEQ_OSS_MODE_MUSIC) { 440 for (i = 0; i < dp->max_mididev; i++) 441 snd_seq_oss_midi_reset(dp, i); 442 } 443 444 /* remove queues */ 445 if (dp->readq) 446 snd_seq_oss_readq_clear(dp->readq); 447 if (dp->writeq) 448 snd_seq_oss_writeq_clear(dp->writeq); 449 450 /* reset timer */ 451 snd_seq_oss_timer_stop(dp->timer); 452 } 453 454 #ifdef CONFIG_SND_PROC_FS 455 /* 456 * misc. functions for proc interface 457 */ 458 char * 459 enabled_str(int bool) 460 { 461 return bool ? "enabled" : "disabled"; 462 } 463 464 static const char * 465 filemode_str(int val) 466 { 467 static const char * const str[] = { 468 "none", "read", "write", "read/write", 469 }; 470 return str[val & SNDRV_SEQ_OSS_FILE_ACMODE]; 471 } 472 473 474 /* 475 * proc interface 476 */ 477 void 478 snd_seq_oss_system_info_read(struct snd_info_buffer *buf) 479 { 480 int i; 481 struct seq_oss_devinfo *dp; 482 483 snd_iprintf(buf, "ALSA client number %d\n", system_client); 484 snd_iprintf(buf, "ALSA receiver port %d\n", system_port); 485 486 snd_iprintf(buf, "\nNumber of applications: %d\n", num_clients); 487 for (i = 0; i < num_clients; i++) { 488 snd_iprintf(buf, "\nApplication %d: ", i); 489 dp = client_table[i]; 490 if (!dp) { 491 snd_iprintf(buf, "*empty*\n"); 492 continue; 493 } 494 snd_iprintf(buf, "port %d : queue %d\n", dp->port, dp->queue); 495 snd_iprintf(buf, " sequencer mode = %s : file open mode = %s\n", 496 (dp->seq_mode ? "music" : "synth"), 497 filemode_str(dp->file_mode)); 498 if (dp->seq_mode) 499 snd_iprintf(buf, " timer tempo = %d, timebase = %d\n", 500 dp->timer->oss_tempo, dp->timer->oss_timebase); 501 snd_iprintf(buf, " max queue length %d\n", maxqlen); 502 if (is_read_mode(dp->file_mode) && dp->readq) 503 snd_seq_oss_readq_info_read(dp->readq, buf); 504 } 505 } 506 #endif /* CONFIG_SND_PROC_FS */ 507