0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include "seq_oss_device.h"
0011 #include "seq_oss_synth.h"
0012 #include "seq_oss_midi.h"
0013 #include "seq_oss_writeq.h"
0014 #include "seq_oss_readq.h"
0015 #include "seq_oss_timer.h"
0016 #include "seq_oss_event.h"
0017 #include <linux/init.h>
0018 #include <linux/export.h>
0019 #include <linux/moduleparam.h>
0020 #include <linux/slab.h>
0021 #include <linux/workqueue.h>
0022
0023
0024
0025
0026 static int maxqlen = SNDRV_SEQ_OSS_MAX_QLEN;
0027 module_param(maxqlen, int, 0444);
0028 MODULE_PARM_DESC(maxqlen, "maximum queue length");
0029
0030 static int system_client = -1;
0031 static int system_port = -1;
0032
0033 static int num_clients;
0034 static struct seq_oss_devinfo *client_table[SNDRV_SEQ_OSS_MAX_CLIENTS];
0035
0036
0037
0038
0039
0040 static int receive_announce(struct snd_seq_event *ev, int direct, void *private, int atomic, int hop);
0041 static int translate_mode(struct file *file);
0042 static int create_port(struct seq_oss_devinfo *dp);
0043 static int delete_port(struct seq_oss_devinfo *dp);
0044 static int alloc_seq_queue(struct seq_oss_devinfo *dp);
0045 static int delete_seq_queue(int queue);
0046 static void free_devinfo(void *private);
0047
0048 #define call_ctl(type,rec) snd_seq_kernel_client_ctl(system_client, type, rec)
0049
0050
0051
0052 static void async_call_lookup_ports(struct work_struct *work)
0053 {
0054 snd_seq_oss_midi_lookup_ports(system_client);
0055 }
0056
0057 static DECLARE_WORK(async_lookup_work, async_call_lookup_ports);
0058
0059
0060
0061
0062 int __init
0063 snd_seq_oss_create_client(void)
0064 {
0065 int rc;
0066 struct snd_seq_port_info *port;
0067 struct snd_seq_port_callback port_callback;
0068
0069 port = kzalloc(sizeof(*port), GFP_KERNEL);
0070 if (!port) {
0071 rc = -ENOMEM;
0072 goto __error;
0073 }
0074
0075
0076 rc = snd_seq_create_kernel_client(NULL, SNDRV_SEQ_CLIENT_OSS,
0077 "OSS sequencer");
0078 if (rc < 0)
0079 goto __error;
0080
0081 system_client = rc;
0082
0083
0084 strcpy(port->name, "Receiver");
0085 port->addr.client = system_client;
0086 port->capability = SNDRV_SEQ_PORT_CAP_WRITE;
0087 port->type = 0;
0088
0089 memset(&port_callback, 0, sizeof(port_callback));
0090
0091
0092
0093 port_callback.event_input = receive_announce;
0094 port->kernel = &port_callback;
0095
0096 if (call_ctl(SNDRV_SEQ_IOCTL_CREATE_PORT, port) >= 0) {
0097 struct snd_seq_port_subscribe subs;
0098
0099 system_port = port->addr.port;
0100 memset(&subs, 0, sizeof(subs));
0101 subs.sender.client = SNDRV_SEQ_CLIENT_SYSTEM;
0102 subs.sender.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE;
0103 subs.dest.client = system_client;
0104 subs.dest.port = system_port;
0105 call_ctl(SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, &subs);
0106 }
0107 rc = 0;
0108
0109
0110 schedule_work(&async_lookup_work);
0111
0112 __error:
0113 kfree(port);
0114 return rc;
0115 }
0116
0117
0118
0119
0120
0121 static int
0122 receive_announce(struct snd_seq_event *ev, int direct, void *private, int atomic, int hop)
0123 {
0124 struct snd_seq_port_info pinfo;
0125
0126 if (atomic)
0127 return 0;
0128
0129 switch (ev->type) {
0130 case SNDRV_SEQ_EVENT_PORT_START:
0131 case SNDRV_SEQ_EVENT_PORT_CHANGE:
0132 if (ev->data.addr.client == system_client)
0133 break;
0134 memset(&pinfo, 0, sizeof(pinfo));
0135 pinfo.addr = ev->data.addr;
0136 if (call_ctl(SNDRV_SEQ_IOCTL_GET_PORT_INFO, &pinfo) >= 0)
0137 snd_seq_oss_midi_check_new_port(&pinfo);
0138 break;
0139
0140 case SNDRV_SEQ_EVENT_PORT_EXIT:
0141 if (ev->data.addr.client == system_client)
0142 break;
0143 snd_seq_oss_midi_check_exit_port(ev->data.addr.client,
0144 ev->data.addr.port);
0145 break;
0146 }
0147 return 0;
0148 }
0149
0150
0151
0152
0153
0154 int
0155 snd_seq_oss_delete_client(void)
0156 {
0157 cancel_work_sync(&async_lookup_work);
0158 if (system_client >= 0)
0159 snd_seq_delete_kernel_client(system_client);
0160
0161 snd_seq_oss_midi_clear_all();
0162
0163 return 0;
0164 }
0165
0166
0167
0168
0169
0170 int
0171 snd_seq_oss_open(struct file *file, int level)
0172 {
0173 int i, rc;
0174 struct seq_oss_devinfo *dp;
0175
0176 dp = kzalloc(sizeof(*dp), GFP_KERNEL);
0177 if (!dp)
0178 return -ENOMEM;
0179
0180 dp->cseq = system_client;
0181 dp->port = -1;
0182 dp->queue = -1;
0183
0184 for (i = 0; i < SNDRV_SEQ_OSS_MAX_CLIENTS; i++) {
0185 if (client_table[i] == NULL)
0186 break;
0187 }
0188
0189 dp->index = i;
0190 if (i >= SNDRV_SEQ_OSS_MAX_CLIENTS) {
0191 pr_debug("ALSA: seq_oss: too many applications\n");
0192 rc = -ENOMEM;
0193 goto _error;
0194 }
0195
0196
0197 snd_seq_oss_synth_setup(dp);
0198 snd_seq_oss_midi_setup(dp);
0199
0200 if (dp->synth_opened == 0 && dp->max_mididev == 0) {
0201
0202 rc = -ENODEV;
0203 goto _error;
0204 }
0205
0206
0207 rc = create_port(dp);
0208 if (rc < 0) {
0209 pr_err("ALSA: seq_oss: can't create port\n");
0210 goto _error;
0211 }
0212
0213
0214 rc = alloc_seq_queue(dp);
0215 if (rc < 0)
0216 goto _error;
0217
0218
0219 dp->addr.client = dp->cseq;
0220 dp->addr.port = dp->port;
0221
0222
0223
0224 dp->seq_mode = level;
0225
0226
0227 dp->file_mode = translate_mode(file);
0228
0229
0230 if (is_read_mode(dp->file_mode)) {
0231 dp->readq = snd_seq_oss_readq_new(dp, maxqlen);
0232 if (!dp->readq) {
0233 rc = -ENOMEM;
0234 goto _error;
0235 }
0236 }
0237
0238
0239 if (is_write_mode(dp->file_mode)) {
0240 dp->writeq = snd_seq_oss_writeq_new(dp, maxqlen);
0241 if (!dp->writeq) {
0242 rc = -ENOMEM;
0243 goto _error;
0244 }
0245 }
0246
0247
0248 dp->timer = snd_seq_oss_timer_new(dp);
0249 if (!dp->timer) {
0250 pr_err("ALSA: seq_oss: can't alloc timer\n");
0251 rc = -ENOMEM;
0252 goto _error;
0253 }
0254
0255
0256 file->private_data = dp;
0257
0258
0259 if (level == SNDRV_SEQ_OSS_MODE_MUSIC)
0260 snd_seq_oss_synth_setup_midi(dp);
0261 else if (is_read_mode(dp->file_mode))
0262 snd_seq_oss_midi_open_all(dp, SNDRV_SEQ_OSS_FILE_READ);
0263
0264 client_table[dp->index] = dp;
0265 num_clients++;
0266
0267 return 0;
0268
0269 _error:
0270 snd_seq_oss_synth_cleanup(dp);
0271 snd_seq_oss_midi_cleanup(dp);
0272 delete_seq_queue(dp->queue);
0273 delete_port(dp);
0274
0275 return rc;
0276 }
0277
0278
0279
0280
0281 static int
0282 translate_mode(struct file *file)
0283 {
0284 int file_mode = 0;
0285 if ((file->f_flags & O_ACCMODE) != O_RDONLY)
0286 file_mode |= SNDRV_SEQ_OSS_FILE_WRITE;
0287 if ((file->f_flags & O_ACCMODE) != O_WRONLY)
0288 file_mode |= SNDRV_SEQ_OSS_FILE_READ;
0289 if (file->f_flags & O_NONBLOCK)
0290 file_mode |= SNDRV_SEQ_OSS_FILE_NONBLOCK;
0291 return file_mode;
0292 }
0293
0294
0295
0296
0297
0298 static int
0299 create_port(struct seq_oss_devinfo *dp)
0300 {
0301 int rc;
0302 struct snd_seq_port_info port;
0303 struct snd_seq_port_callback callback;
0304
0305 memset(&port, 0, sizeof(port));
0306 port.addr.client = dp->cseq;
0307 sprintf(port.name, "Sequencer-%d", dp->index);
0308 port.capability = SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_WRITE;
0309 port.type = SNDRV_SEQ_PORT_TYPE_SPECIFIC;
0310 port.midi_channels = 128;
0311 port.synth_voices = 128;
0312
0313 memset(&callback, 0, sizeof(callback));
0314 callback.owner = THIS_MODULE;
0315 callback.private_data = dp;
0316 callback.event_input = snd_seq_oss_event_input;
0317 callback.private_free = free_devinfo;
0318 port.kernel = &callback;
0319
0320 rc = call_ctl(SNDRV_SEQ_IOCTL_CREATE_PORT, &port);
0321 if (rc < 0)
0322 return rc;
0323
0324 dp->port = port.addr.port;
0325
0326 return 0;
0327 }
0328
0329
0330
0331
0332 static int
0333 delete_port(struct seq_oss_devinfo *dp)
0334 {
0335 if (dp->port < 0) {
0336 kfree(dp);
0337 return 0;
0338 }
0339
0340 return snd_seq_event_port_detach(dp->cseq, dp->port);
0341 }
0342
0343
0344
0345
0346 static int
0347 alloc_seq_queue(struct seq_oss_devinfo *dp)
0348 {
0349 struct snd_seq_queue_info qinfo;
0350 int rc;
0351
0352 memset(&qinfo, 0, sizeof(qinfo));
0353 qinfo.owner = system_client;
0354 qinfo.locked = 1;
0355 strcpy(qinfo.name, "OSS Sequencer Emulation");
0356 rc = call_ctl(SNDRV_SEQ_IOCTL_CREATE_QUEUE, &qinfo);
0357 if (rc < 0)
0358 return rc;
0359 dp->queue = qinfo.queue;
0360 return 0;
0361 }
0362
0363
0364
0365
0366 static int
0367 delete_seq_queue(int queue)
0368 {
0369 struct snd_seq_queue_info qinfo;
0370 int rc;
0371
0372 if (queue < 0)
0373 return 0;
0374 memset(&qinfo, 0, sizeof(qinfo));
0375 qinfo.queue = queue;
0376 rc = call_ctl(SNDRV_SEQ_IOCTL_DELETE_QUEUE, &qinfo);
0377 if (rc < 0)
0378 pr_err("ALSA: seq_oss: unable to delete queue %d (%d)\n", queue, rc);
0379 return rc;
0380 }
0381
0382
0383
0384
0385
0386 static void
0387 free_devinfo(void *private)
0388 {
0389 struct seq_oss_devinfo *dp = (struct seq_oss_devinfo *)private;
0390
0391 snd_seq_oss_timer_delete(dp->timer);
0392
0393 snd_seq_oss_writeq_delete(dp->writeq);
0394
0395 snd_seq_oss_readq_delete(dp->readq);
0396
0397 kfree(dp);
0398 }
0399
0400
0401
0402
0403
0404 void
0405 snd_seq_oss_release(struct seq_oss_devinfo *dp)
0406 {
0407 int queue;
0408
0409 client_table[dp->index] = NULL;
0410 num_clients--;
0411
0412 snd_seq_oss_reset(dp);
0413
0414 snd_seq_oss_synth_cleanup(dp);
0415 snd_seq_oss_midi_cleanup(dp);
0416
0417
0418 queue = dp->queue;
0419 if (dp->port >= 0)
0420 delete_port(dp);
0421 delete_seq_queue(queue);
0422 }
0423
0424
0425
0426
0427
0428 void
0429 snd_seq_oss_reset(struct seq_oss_devinfo *dp)
0430 {
0431 int i;
0432
0433
0434 for (i = 0; i < dp->max_synthdev; i++)
0435 snd_seq_oss_synth_reset(dp, i);
0436
0437
0438 if (dp->seq_mode != SNDRV_SEQ_OSS_MODE_MUSIC) {
0439 for (i = 0; i < dp->max_mididev; i++)
0440 snd_seq_oss_midi_reset(dp, i);
0441 }
0442
0443
0444 if (dp->readq)
0445 snd_seq_oss_readq_clear(dp->readq);
0446 if (dp->writeq)
0447 snd_seq_oss_writeq_clear(dp->writeq);
0448
0449
0450 snd_seq_oss_timer_stop(dp->timer);
0451 }
0452
0453 #ifdef CONFIG_SND_PROC_FS
0454
0455
0456
0457 char *
0458 enabled_str(int bool)
0459 {
0460 return bool ? "enabled" : "disabled";
0461 }
0462
0463 static const char *
0464 filemode_str(int val)
0465 {
0466 static const char * const str[] = {
0467 "none", "read", "write", "read/write",
0468 };
0469 return str[val & SNDRV_SEQ_OSS_FILE_ACMODE];
0470 }
0471
0472
0473
0474
0475
0476 void
0477 snd_seq_oss_system_info_read(struct snd_info_buffer *buf)
0478 {
0479 int i;
0480 struct seq_oss_devinfo *dp;
0481
0482 snd_iprintf(buf, "ALSA client number %d\n", system_client);
0483 snd_iprintf(buf, "ALSA receiver port %d\n", system_port);
0484
0485 snd_iprintf(buf, "\nNumber of applications: %d\n", num_clients);
0486 for (i = 0; i < num_clients; i++) {
0487 snd_iprintf(buf, "\nApplication %d: ", i);
0488 dp = client_table[i];
0489 if (!dp) {
0490 snd_iprintf(buf, "*empty*\n");
0491 continue;
0492 }
0493 snd_iprintf(buf, "port %d : queue %d\n", dp->port, dp->queue);
0494 snd_iprintf(buf, " sequencer mode = %s : file open mode = %s\n",
0495 (dp->seq_mode ? "music" : "synth"),
0496 filemode_str(dp->file_mode));
0497 if (dp->seq_mode)
0498 snd_iprintf(buf, " timer tempo = %d, timebase = %d\n",
0499 dp->timer->oss_tempo, dp->timer->oss_timebase);
0500 snd_iprintf(buf, " max queue length %d\n", maxqlen);
0501 if (is_read_mode(dp->file_mode) && dp->readq)
0502 snd_seq_oss_readq_info_read(dp->readq, buf);
0503 }
0504 }
0505 #endif