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