2
* OSS compatible sequencer driver
4
* open/close and reset interface
6
* Copyright (C) 1998-1999 Takashi Iwai <tiwai@suse.de>
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23
#include "seq_oss_device.h"
24
#include "seq_oss_synth.h"
25
#include "seq_oss_midi.h"
26
#include "seq_oss_writeq.h"
27
#include "seq_oss_readq.h"
28
#include "seq_oss_timer.h"
29
#include "seq_oss_event.h"
30
#include <linux/init.h>
31
#include <linux/export.h>
32
#include <linux/moduleparam.h>
33
#include <linux/slab.h>
38
static int maxqlen = SNDRV_SEQ_OSS_MAX_QLEN;
39
module_param(maxqlen, int, 0444);
40
MODULE_PARM_DESC(maxqlen, "maximum queue length");
42
static int system_client = -1; /* ALSA sequencer client number */
43
static int system_port = -1;
45
static int num_clients;
46
static struct seq_oss_devinfo *client_table[SNDRV_SEQ_OSS_MAX_CLIENTS];
52
static int receive_announce(struct snd_seq_event *ev, int direct, void *private, int atomic, int hop);
53
static int translate_mode(struct file *file);
54
static int create_port(struct seq_oss_devinfo *dp);
55
static int delete_port(struct seq_oss_devinfo *dp);
56
static int alloc_seq_queue(struct seq_oss_devinfo *dp);
57
static int delete_seq_queue(int queue);
58
static void free_devinfo(void *private);
60
#define call_ctl(type,rec) snd_seq_kernel_client_ctl(system_client, type, rec)
64
* create sequencer client for OSS sequencer
67
snd_seq_oss_create_client(void)
70
struct snd_seq_port_info *port;
71
struct snd_seq_port_callback port_callback;
73
port = kmalloc(sizeof(*port), GFP_KERNEL);
79
/* create ALSA client */
80
rc = snd_seq_create_kernel_client(NULL, SNDRV_SEQ_CLIENT_OSS,
86
debug_printk(("new client = %d\n", rc));
88
/* look up midi devices */
89
snd_seq_oss_midi_lookup_ports(system_client);
91
/* create annoucement receiver port */
92
memset(port, 0, sizeof(*port));
93
strcpy(port->name, "Receiver");
94
port->addr.client = system_client;
95
port->capability = SNDRV_SEQ_PORT_CAP_WRITE; /* receive only */
98
memset(&port_callback, 0, sizeof(port_callback));
99
/* don't set port_callback.owner here. otherwise the module counter
100
* is incremented and we can no longer release the module..
102
port_callback.event_input = receive_announce;
103
port->kernel = &port_callback;
105
call_ctl(SNDRV_SEQ_IOCTL_CREATE_PORT, port);
106
if ((system_port = port->addr.port) >= 0) {
107
struct snd_seq_port_subscribe subs;
109
memset(&subs, 0, sizeof(subs));
110
subs.sender.client = SNDRV_SEQ_CLIENT_SYSTEM;
111
subs.sender.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE;
112
subs.dest.client = system_client;
113
subs.dest.port = system_port;
114
call_ctl(SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, &subs);
125
* receive annoucement from system port, and check the midi device
128
receive_announce(struct snd_seq_event *ev, int direct, void *private, int atomic, int hop)
130
struct snd_seq_port_info pinfo;
133
return 0; /* it must not happen */
136
case SNDRV_SEQ_EVENT_PORT_START:
137
case SNDRV_SEQ_EVENT_PORT_CHANGE:
138
if (ev->data.addr.client == system_client)
139
break; /* ignore myself */
140
memset(&pinfo, 0, sizeof(pinfo));
141
pinfo.addr = ev->data.addr;
142
if (call_ctl(SNDRV_SEQ_IOCTL_GET_PORT_INFO, &pinfo) >= 0)
143
snd_seq_oss_midi_check_new_port(&pinfo);
146
case SNDRV_SEQ_EVENT_PORT_EXIT:
147
if (ev->data.addr.client == system_client)
148
break; /* ignore myself */
149
snd_seq_oss_midi_check_exit_port(ev->data.addr.client,
158
* delete OSS sequencer client
161
snd_seq_oss_delete_client(void)
163
if (system_client >= 0)
164
snd_seq_delete_kernel_client(system_client);
166
snd_seq_oss_midi_clear_all();
173
* open sequencer device
176
snd_seq_oss_open(struct file *file, int level)
179
struct seq_oss_devinfo *dp;
181
dp = kzalloc(sizeof(*dp), GFP_KERNEL);
183
snd_printk(KERN_ERR "can't malloc device info\n");
186
debug_printk(("oss_open: dp = %p\n", dp));
188
dp->cseq = system_client;
192
for (i = 0; i < SNDRV_SEQ_OSS_MAX_CLIENTS; i++) {
193
if (client_table[i] == NULL)
198
if (i >= SNDRV_SEQ_OSS_MAX_CLIENTS) {
199
snd_printk(KERN_ERR "too many applications\n");
204
/* look up synth and midi devices */
205
snd_seq_oss_synth_setup(dp);
206
snd_seq_oss_midi_setup(dp);
208
if (dp->synth_opened == 0 && dp->max_mididev == 0) {
209
/* snd_printk(KERN_ERR "no device found\n"); */
215
debug_printk(("create new port\n"));
216
rc = create_port(dp);
218
snd_printk(KERN_ERR "can't create port\n");
223
debug_printk(("allocate queue\n"));
224
rc = alloc_seq_queue(dp);
229
dp->addr.client = dp->cseq;
230
dp->addr.port = dp->port;
231
/*dp->addr.queue = dp->queue;*/
232
/*dp->addr.channel = 0;*/
234
dp->seq_mode = level;
236
/* set up file mode */
237
dp->file_mode = translate_mode(file);
239
/* initialize read queue */
240
debug_printk(("initialize read queue\n"));
241
if (is_read_mode(dp->file_mode)) {
242
dp->readq = snd_seq_oss_readq_new(dp, maxqlen);
249
/* initialize write queue */
250
debug_printk(("initialize write queue\n"));
251
if (is_write_mode(dp->file_mode)) {
252
dp->writeq = snd_seq_oss_writeq_new(dp, maxqlen);
259
/* initialize timer */
260
debug_printk(("initialize timer\n"));
261
dp->timer = snd_seq_oss_timer_new(dp);
263
snd_printk(KERN_ERR "can't alloc timer\n");
267
debug_printk(("timer initialized\n"));
269
/* set private data pointer */
270
file->private_data = dp;
272
/* set up for mode2 */
273
if (level == SNDRV_SEQ_OSS_MODE_MUSIC)
274
snd_seq_oss_synth_setup_midi(dp);
275
else if (is_read_mode(dp->file_mode))
276
snd_seq_oss_midi_open_all(dp, SNDRV_SEQ_OSS_FILE_READ);
278
client_table[dp->index] = dp;
281
debug_printk(("open done\n"));
285
snd_seq_oss_synth_cleanup(dp);
286
snd_seq_oss_midi_cleanup(dp);
287
delete_seq_queue(dp->queue);
294
* translate file flags to private mode
297
translate_mode(struct file *file)
300
if ((file->f_flags & O_ACCMODE) != O_RDONLY)
301
file_mode |= SNDRV_SEQ_OSS_FILE_WRITE;
302
if ((file->f_flags & O_ACCMODE) != O_WRONLY)
303
file_mode |= SNDRV_SEQ_OSS_FILE_READ;
304
if (file->f_flags & O_NONBLOCK)
305
file_mode |= SNDRV_SEQ_OSS_FILE_NONBLOCK;
311
* create sequencer port
314
create_port(struct seq_oss_devinfo *dp)
317
struct snd_seq_port_info port;
318
struct snd_seq_port_callback callback;
320
memset(&port, 0, sizeof(port));
321
port.addr.client = dp->cseq;
322
sprintf(port.name, "Sequencer-%d", dp->index);
323
port.capability = SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_WRITE; /* no subscription */
324
port.type = SNDRV_SEQ_PORT_TYPE_SPECIFIC;
325
port.midi_channels = 128;
326
port.synth_voices = 128;
328
memset(&callback, 0, sizeof(callback));
329
callback.owner = THIS_MODULE;
330
callback.private_data = dp;
331
callback.event_input = snd_seq_oss_event_input;
332
callback.private_free = free_devinfo;
333
port.kernel = &callback;
335
rc = call_ctl(SNDRV_SEQ_IOCTL_CREATE_PORT, &port);
339
dp->port = port.addr.port;
340
debug_printk(("new port = %d\n", port.addr.port));
349
delete_port(struct seq_oss_devinfo *dp)
356
debug_printk(("delete_port %i\n", dp->port));
357
return snd_seq_event_port_detach(dp->cseq, dp->port);
364
alloc_seq_queue(struct seq_oss_devinfo *dp)
366
struct snd_seq_queue_info qinfo;
369
memset(&qinfo, 0, sizeof(qinfo));
370
qinfo.owner = system_client;
372
strcpy(qinfo.name, "OSS Sequencer Emulation");
373
if ((rc = call_ctl(SNDRV_SEQ_IOCTL_CREATE_QUEUE, &qinfo)) < 0)
375
dp->queue = qinfo.queue;
383
delete_seq_queue(int queue)
385
struct snd_seq_queue_info qinfo;
390
memset(&qinfo, 0, sizeof(qinfo));
392
rc = call_ctl(SNDRV_SEQ_IOCTL_DELETE_QUEUE, &qinfo);
394
printk(KERN_ERR "seq-oss: unable to delete queue %d (%d)\n", queue, rc);
400
* free device informations - private_free callback of port
403
free_devinfo(void *private)
405
struct seq_oss_devinfo *dp = (struct seq_oss_devinfo *)private;
408
snd_seq_oss_timer_delete(dp->timer);
411
snd_seq_oss_writeq_delete(dp->writeq);
414
snd_seq_oss_readq_delete(dp->readq);
421
* close sequencer device
424
snd_seq_oss_release(struct seq_oss_devinfo *dp)
428
client_table[dp->index] = NULL;
431
debug_printk(("resetting..\n"));
432
snd_seq_oss_reset(dp);
434
debug_printk(("cleaning up..\n"));
435
snd_seq_oss_synth_cleanup(dp);
436
snd_seq_oss_midi_cleanup(dp);
439
debug_printk(("releasing resource..\n"));
443
delete_seq_queue(queue);
445
debug_printk(("release done\n"));
450
* Wait until the queue is empty (if we don't have nonblock)
453
snd_seq_oss_drain_write(struct seq_oss_devinfo *dp)
455
if (! dp->timer->running)
457
if (is_write_mode(dp->file_mode) && !is_nonblock_mode(dp->file_mode) &&
459
debug_printk(("syncing..\n"));
460
while (snd_seq_oss_writeq_sync(dp->writeq))
467
* reset sequencer devices
470
snd_seq_oss_reset(struct seq_oss_devinfo *dp)
474
/* reset all synth devices */
475
for (i = 0; i < dp->max_synthdev; i++)
476
snd_seq_oss_synth_reset(dp, i);
478
/* reset all midi devices */
479
if (dp->seq_mode != SNDRV_SEQ_OSS_MODE_MUSIC) {
480
for (i = 0; i < dp->max_mididev; i++)
481
snd_seq_oss_midi_reset(dp, i);
486
snd_seq_oss_readq_clear(dp->readq);
488
snd_seq_oss_writeq_clear(dp->writeq);
491
snd_seq_oss_timer_stop(dp->timer);
495
#ifdef CONFIG_PROC_FS
497
* misc. functions for proc interface
500
enabled_str(int bool)
502
return bool ? "enabled" : "disabled";
506
filemode_str(int val)
508
static char *str[] = {
509
"none", "read", "write", "read/write",
511
return str[val & SNDRV_SEQ_OSS_FILE_ACMODE];
519
snd_seq_oss_system_info_read(struct snd_info_buffer *buf)
522
struct seq_oss_devinfo *dp;
524
snd_iprintf(buf, "ALSA client number %d\n", system_client);
525
snd_iprintf(buf, "ALSA receiver port %d\n", system_port);
527
snd_iprintf(buf, "\nNumber of applications: %d\n", num_clients);
528
for (i = 0; i < num_clients; i++) {
529
snd_iprintf(buf, "\nApplication %d: ", i);
530
if ((dp = client_table[i]) == NULL) {
531
snd_iprintf(buf, "*empty*\n");
534
snd_iprintf(buf, "port %d : queue %d\n", dp->port, dp->queue);
535
snd_iprintf(buf, " sequencer mode = %s : file open mode = %s\n",
536
(dp->seq_mode ? "music" : "synth"),
537
filemode_str(dp->file_mode));
539
snd_iprintf(buf, " timer tempo = %d, timebase = %d\n",
540
dp->timer->oss_tempo, dp->timer->oss_timebase);
541
snd_iprintf(buf, " max queue length %d\n", maxqlen);
542
if (is_read_mode(dp->file_mode) && dp->readq)
543
snd_seq_oss_readq_info_read(dp->readq, buf);
546
#endif /* CONFIG_PROC_FS */