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