1 /* 2 * Interface for OSS sequencer emulation 3 * 4 * Copyright (C) 1999 Takashi Iwai <tiwai@suse.de> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * 20 * Changes 21 * 19990227 Steve Ratcliffe Made separate file and merged in latest 22 * midi emulation. 23 */ 24 25 26 #ifdef CONFIG_SND_SEQUENCER_OSS 27 28 #include <linux/export.h> 29 #include <linux/uaccess.h> 30 #include <sound/core.h> 31 #include "emux_voice.h" 32 #include <sound/asoundef.h> 33 34 static int snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure); 35 static int snd_emux_close_seq_oss(struct snd_seq_oss_arg *arg); 36 static int snd_emux_ioctl_seq_oss(struct snd_seq_oss_arg *arg, unsigned int cmd, 37 unsigned long ioarg); 38 static int snd_emux_load_patch_seq_oss(struct snd_seq_oss_arg *arg, int format, 39 const char __user *buf, int offs, int count); 40 static int snd_emux_reset_seq_oss(struct snd_seq_oss_arg *arg); 41 static int snd_emux_event_oss_input(struct snd_seq_event *ev, int direct, 42 void *private, int atomic, int hop); 43 static void reset_port_mode(struct snd_emux_port *port, int midi_mode); 44 static void emuspec_control(struct snd_emux *emu, struct snd_emux_port *port, 45 int cmd, unsigned char *event, int atomic, int hop); 46 static void gusspec_control(struct snd_emux *emu, struct snd_emux_port *port, 47 int cmd, unsigned char *event, int atomic, int hop); 48 static void fake_event(struct snd_emux *emu, struct snd_emux_port *port, 49 int ch, int param, int val, int atomic, int hop); 50 51 /* operators */ 52 static struct snd_seq_oss_callback oss_callback = { 53 .owner = THIS_MODULE, 54 .open = snd_emux_open_seq_oss, 55 .close = snd_emux_close_seq_oss, 56 .ioctl = snd_emux_ioctl_seq_oss, 57 .load_patch = snd_emux_load_patch_seq_oss, 58 .reset = snd_emux_reset_seq_oss, 59 }; 60 61 62 /* 63 * register OSS synth 64 */ 65 66 void 67 snd_emux_init_seq_oss(struct snd_emux *emu) 68 { 69 struct snd_seq_oss_reg *arg; 70 struct snd_seq_device *dev; 71 72 if (snd_seq_device_new(emu->card, 0, SNDRV_SEQ_DEV_ID_OSS, 73 sizeof(struct snd_seq_oss_reg), &dev) < 0) 74 return; 75 76 emu->oss_synth = dev; 77 strcpy(dev->name, emu->name); 78 arg = SNDRV_SEQ_DEVICE_ARGPTR(dev); 79 arg->type = SYNTH_TYPE_SAMPLE; 80 arg->subtype = SAMPLE_TYPE_AWE32; 81 arg->nvoices = emu->max_voices; 82 arg->oper = oss_callback; 83 arg->private_data = emu; 84 85 /* register to OSS synth table */ 86 snd_device_register(emu->card, dev); 87 } 88 89 90 /* 91 * unregister 92 */ 93 void 94 snd_emux_detach_seq_oss(struct snd_emux *emu) 95 { 96 if (emu->oss_synth) { 97 snd_device_free(emu->card, emu->oss_synth); 98 emu->oss_synth = NULL; 99 } 100 } 101 102 103 /* use port number as a unique soundfont client number */ 104 #define SF_CLIENT_NO(p) ((p) + 0x1000) 105 106 /* 107 * open port for OSS sequencer 108 */ 109 static int 110 snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure) 111 { 112 struct snd_emux *emu; 113 struct snd_emux_port *p; 114 struct snd_seq_port_callback callback; 115 char tmpname[64]; 116 117 emu = closure; 118 if (snd_BUG_ON(!arg || !emu)) 119 return -ENXIO; 120 121 mutex_lock(&emu->register_mutex); 122 123 if (!snd_emux_inc_count(emu)) { 124 mutex_unlock(&emu->register_mutex); 125 return -EFAULT; 126 } 127 128 memset(&callback, 0, sizeof(callback)); 129 callback.owner = THIS_MODULE; 130 callback.event_input = snd_emux_event_oss_input; 131 132 sprintf(tmpname, "%s OSS Port", emu->name); 133 p = snd_emux_create_port(emu, tmpname, 32, 134 1, &callback); 135 if (p == NULL) { 136 snd_printk(KERN_ERR "can't create port\n"); 137 snd_emux_dec_count(emu); 138 mutex_unlock(&emu->register_mutex); 139 return -ENOMEM; 140 } 141 142 /* fill the argument data */ 143 arg->private_data = p; 144 arg->addr.client = p->chset.client; 145 arg->addr.port = p->chset.port; 146 p->oss_arg = arg; 147 148 reset_port_mode(p, arg->seq_mode); 149 150 snd_emux_reset_port(p); 151 152 mutex_unlock(&emu->register_mutex); 153 return 0; 154 } 155 156 157 #define DEFAULT_DRUM_FLAGS ((1<<9) | (1<<25)) 158 159 /* 160 * reset port mode 161 */ 162 static void 163 reset_port_mode(struct snd_emux_port *port, int midi_mode) 164 { 165 if (midi_mode) { 166 port->port_mode = SNDRV_EMUX_PORT_MODE_OSS_MIDI; 167 port->drum_flags = DEFAULT_DRUM_FLAGS; 168 port->volume_atten = 0; 169 port->oss_arg->event_passing = SNDRV_SEQ_OSS_PROCESS_KEYPRESS; 170 } else { 171 port->port_mode = SNDRV_EMUX_PORT_MODE_OSS_SYNTH; 172 port->drum_flags = 0; 173 port->volume_atten = 32; 174 port->oss_arg->event_passing = SNDRV_SEQ_OSS_PROCESS_EVENTS; 175 } 176 } 177 178 179 /* 180 * close port 181 */ 182 static int 183 snd_emux_close_seq_oss(struct snd_seq_oss_arg *arg) 184 { 185 struct snd_emux *emu; 186 struct snd_emux_port *p; 187 188 if (snd_BUG_ON(!arg)) 189 return -ENXIO; 190 p = arg->private_data; 191 if (snd_BUG_ON(!p)) 192 return -ENXIO; 193 194 emu = p->emu; 195 if (snd_BUG_ON(!emu)) 196 return -ENXIO; 197 198 mutex_lock(&emu->register_mutex); 199 snd_emux_sounds_off_all(p); 200 snd_soundfont_close_check(emu->sflist, SF_CLIENT_NO(p->chset.port)); 201 snd_seq_event_port_detach(p->chset.client, p->chset.port); 202 snd_emux_dec_count(emu); 203 204 mutex_unlock(&emu->register_mutex); 205 return 0; 206 } 207 208 209 /* 210 * load patch 211 */ 212 static int 213 snd_emux_load_patch_seq_oss(struct snd_seq_oss_arg *arg, int format, 214 const char __user *buf, int offs, int count) 215 { 216 struct snd_emux *emu; 217 struct snd_emux_port *p; 218 int rc; 219 220 if (snd_BUG_ON(!arg)) 221 return -ENXIO; 222 p = arg->private_data; 223 if (snd_BUG_ON(!p)) 224 return -ENXIO; 225 226 emu = p->emu; 227 if (snd_BUG_ON(!emu)) 228 return -ENXIO; 229 230 if (format == GUS_PATCH) 231 rc = snd_soundfont_load_guspatch(emu->sflist, buf, count, 232 SF_CLIENT_NO(p->chset.port)); 233 else if (format == SNDRV_OSS_SOUNDFONT_PATCH) { 234 struct soundfont_patch_info patch; 235 if (count < (int)sizeof(patch)) 236 rc = -EINVAL; 237 if (copy_from_user(&patch, buf, sizeof(patch))) 238 rc = -EFAULT; 239 if (patch.type >= SNDRV_SFNT_LOAD_INFO && 240 patch.type <= SNDRV_SFNT_PROBE_DATA) 241 rc = snd_soundfont_load(emu->sflist, buf, count, SF_CLIENT_NO(p->chset.port)); 242 else { 243 if (emu->ops.load_fx) 244 rc = emu->ops.load_fx(emu, patch.type, patch.optarg, buf, count); 245 else 246 rc = -EINVAL; 247 } 248 } else 249 rc = 0; 250 return rc; 251 } 252 253 254 /* 255 * ioctl 256 */ 257 static int 258 snd_emux_ioctl_seq_oss(struct snd_seq_oss_arg *arg, unsigned int cmd, unsigned long ioarg) 259 { 260 struct snd_emux_port *p; 261 struct snd_emux *emu; 262 263 if (snd_BUG_ON(!arg)) 264 return -ENXIO; 265 p = arg->private_data; 266 if (snd_BUG_ON(!p)) 267 return -ENXIO; 268 269 emu = p->emu; 270 if (snd_BUG_ON(!emu)) 271 return -ENXIO; 272 273 switch (cmd) { 274 case SNDCTL_SEQ_RESETSAMPLES: 275 snd_soundfont_remove_samples(emu->sflist); 276 return 0; 277 278 case SNDCTL_SYNTH_MEMAVL: 279 if (emu->memhdr) 280 return snd_util_mem_avail(emu->memhdr); 281 return 0; 282 } 283 284 return 0; 285 } 286 287 288 /* 289 * reset device 290 */ 291 static int 292 snd_emux_reset_seq_oss(struct snd_seq_oss_arg *arg) 293 { 294 struct snd_emux_port *p; 295 296 if (snd_BUG_ON(!arg)) 297 return -ENXIO; 298 p = arg->private_data; 299 if (snd_BUG_ON(!p)) 300 return -ENXIO; 301 snd_emux_reset_port(p); 302 return 0; 303 } 304 305 306 /* 307 * receive raw events: only SEQ_PRIVATE is accepted. 308 */ 309 static int 310 snd_emux_event_oss_input(struct snd_seq_event *ev, int direct, void *private_data, 311 int atomic, int hop) 312 { 313 struct snd_emux *emu; 314 struct snd_emux_port *p; 315 unsigned char cmd, *data; 316 317 p = private_data; 318 if (snd_BUG_ON(!p)) 319 return -EINVAL; 320 emu = p->emu; 321 if (snd_BUG_ON(!emu)) 322 return -EINVAL; 323 if (ev->type != SNDRV_SEQ_EVENT_OSS) 324 return snd_emux_event_input(ev, direct, private_data, atomic, hop); 325 326 data = ev->data.raw8.d; 327 /* only SEQ_PRIVATE is accepted */ 328 if (data[0] != 0xfe) 329 return 0; 330 cmd = data[2] & _EMUX_OSS_MODE_VALUE_MASK; 331 if (data[2] & _EMUX_OSS_MODE_FLAG) 332 emuspec_control(emu, p, cmd, data, atomic, hop); 333 else 334 gusspec_control(emu, p, cmd, data, atomic, hop); 335 return 0; 336 } 337 338 339 /* 340 * OSS/AWE driver specific h/w controls 341 */ 342 static void 343 emuspec_control(struct snd_emux *emu, struct snd_emux_port *port, int cmd, 344 unsigned char *event, int atomic, int hop) 345 { 346 int voice; 347 unsigned short p1; 348 short p2; 349 int i; 350 struct snd_midi_channel *chan; 351 352 voice = event[3]; 353 if (voice < 0 || voice >= port->chset.max_channels) 354 chan = NULL; 355 else 356 chan = &port->chset.channels[voice]; 357 358 p1 = *(unsigned short *) &event[4]; 359 p2 = *(short *) &event[6]; 360 361 switch (cmd) { 362 #if 0 /* don't do this atomically */ 363 case _EMUX_OSS_REMOVE_LAST_SAMPLES: 364 snd_soundfont_remove_unlocked(emu->sflist); 365 break; 366 #endif 367 case _EMUX_OSS_SEND_EFFECT: 368 if (chan) 369 snd_emux_send_effect_oss(port, chan, p1, p2); 370 break; 371 372 case _EMUX_OSS_TERMINATE_ALL: 373 snd_emux_terminate_all(emu); 374 break; 375 376 case _EMUX_OSS_TERMINATE_CHANNEL: 377 /*snd_emux_mute_channel(emu, chan);*/ 378 break; 379 case _EMUX_OSS_RESET_CHANNEL: 380 /*snd_emux_channel_init(chset, chan);*/ 381 break; 382 383 case _EMUX_OSS_RELEASE_ALL: 384 fake_event(emu, port, voice, MIDI_CTL_ALL_NOTES_OFF, 0, atomic, hop); 385 break; 386 case _EMUX_OSS_NOTEOFF_ALL: 387 fake_event(emu, port, voice, MIDI_CTL_ALL_SOUNDS_OFF, 0, atomic, hop); 388 break; 389 390 case _EMUX_OSS_INITIAL_VOLUME: 391 if (p2) { 392 port->volume_atten = (short)p1; 393 snd_emux_update_port(port, SNDRV_EMUX_UPDATE_VOLUME); 394 } 395 break; 396 397 case _EMUX_OSS_CHN_PRESSURE: 398 if (chan) { 399 chan->midi_pressure = p1; 400 snd_emux_update_channel(port, chan, SNDRV_EMUX_UPDATE_FMMOD|SNDRV_EMUX_UPDATE_FM2FRQ2); 401 } 402 break; 403 404 case _EMUX_OSS_CHANNEL_MODE: 405 reset_port_mode(port, p1); 406 snd_emux_reset_port(port); 407 break; 408 409 case _EMUX_OSS_DRUM_CHANNELS: 410 port->drum_flags = *(unsigned int*)&event[4]; 411 for (i = 0; i < port->chset.max_channels; i++) { 412 chan = &port->chset.channels[i]; 413 chan->drum_channel = ((port->drum_flags >> i) & 1) ? 1 : 0; 414 } 415 break; 416 417 case _EMUX_OSS_MISC_MODE: 418 if (p1 < EMUX_MD_END) 419 port->ctrls[p1] = p2; 420 break; 421 case _EMUX_OSS_DEBUG_MODE: 422 break; 423 424 default: 425 if (emu->ops.oss_ioctl) 426 emu->ops.oss_ioctl(emu, cmd, p1, p2); 427 break; 428 } 429 } 430 431 /* 432 * GUS specific h/w controls 433 */ 434 435 #include <linux/ultrasound.h> 436 437 static void 438 gusspec_control(struct snd_emux *emu, struct snd_emux_port *port, int cmd, 439 unsigned char *event, int atomic, int hop) 440 { 441 int voice; 442 unsigned short p1; 443 short p2; 444 int plong; 445 struct snd_midi_channel *chan; 446 447 if (port->port_mode != SNDRV_EMUX_PORT_MODE_OSS_SYNTH) 448 return; 449 if (cmd == _GUS_NUMVOICES) 450 return; 451 voice = event[3]; 452 if (voice < 0 || voice >= port->chset.max_channels) 453 return; 454 455 chan = &port->chset.channels[voice]; 456 457 p1 = *(unsigned short *) &event[4]; 458 p2 = *(short *) &event[6]; 459 plong = *(int*) &event[4]; 460 461 switch (cmd) { 462 case _GUS_VOICESAMPLE: 463 chan->midi_program = p1; 464 return; 465 466 case _GUS_VOICEBALA: 467 /* 0 to 15 --> 0 to 127 */ 468 chan->control[MIDI_CTL_MSB_PAN] = (int)p1 << 3; 469 snd_emux_update_channel(port, chan, SNDRV_EMUX_UPDATE_PAN); 470 return; 471 472 case _GUS_VOICEVOL: 473 case _GUS_VOICEVOL2: 474 /* not supported yet */ 475 return; 476 477 case _GUS_RAMPRANGE: 478 case _GUS_RAMPRATE: 479 case _GUS_RAMPMODE: 480 case _GUS_RAMPON: 481 case _GUS_RAMPOFF: 482 /* volume ramping not supported */ 483 return; 484 485 case _GUS_VOLUME_SCALE: 486 return; 487 488 case _GUS_VOICE_POS: 489 #ifdef SNDRV_EMUX_USE_RAW_EFFECT 490 snd_emux_send_effect(port, chan, EMUX_FX_SAMPLE_START, 491 (short)(plong & 0x7fff), 492 EMUX_FX_FLAG_SET); 493 snd_emux_send_effect(port, chan, EMUX_FX_COARSE_SAMPLE_START, 494 (plong >> 15) & 0xffff, 495 EMUX_FX_FLAG_SET); 496 #endif 497 return; 498 } 499 } 500 501 502 /* 503 * send an event to midi emulation 504 */ 505 static void 506 fake_event(struct snd_emux *emu, struct snd_emux_port *port, int ch, int param, int val, int atomic, int hop) 507 { 508 struct snd_seq_event ev; 509 memset(&ev, 0, sizeof(ev)); 510 ev.type = SNDRV_SEQ_EVENT_CONTROLLER; 511 ev.data.control.channel = ch; 512 ev.data.control.param = param; 513 ev.data.control.value = val; 514 snd_emux_event_input(&ev, 0, port, atomic, hop); 515 } 516 517 #endif /* CONFIG_SND_SEQUENCER_OSS */ 518