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