cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

seq_midi_emul.c (19290B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *  GM/GS/XG midi module.
      4 *
      5 *  Copyright (C) 1999 Steve Ratcliffe
      6 *
      7 *  Based on awe_wave.c by Takashi Iwai
      8 */
      9/*
     10 * This module is used to keep track of the current midi state.
     11 * It can be used for drivers that are required to emulate midi when
     12 * the hardware doesn't.
     13 *
     14 * It was written for a AWE64 driver, but there should be no AWE specific
     15 * code in here.  If there is it should be reported as a bug.
     16 */
     17
     18#include <linux/init.h>
     19#include <linux/slab.h>
     20#include <linux/string.h>
     21#include <linux/module.h>
     22#include <sound/core.h>
     23#include <sound/seq_kernel.h>
     24#include <sound/seq_midi_emul.h>
     25#include <sound/initval.h>
     26#include <sound/asoundef.h>
     27
     28MODULE_AUTHOR("Takashi Iwai / Steve Ratcliffe");
     29MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer MIDI emulation.");
     30MODULE_LICENSE("GPL");
     31
     32/* Prototypes for static functions */
     33static void note_off(const struct snd_midi_op *ops, void *drv,
     34		     struct snd_midi_channel *chan,
     35		     int note, int vel);
     36static void do_control(const struct snd_midi_op *ops, void *private,
     37		       struct snd_midi_channel_set *chset,
     38		       struct snd_midi_channel *chan,
     39		       int control, int value);
     40static void rpn(const struct snd_midi_op *ops, void *drv,
     41		struct snd_midi_channel *chan,
     42		struct snd_midi_channel_set *chset);
     43static void nrpn(const struct snd_midi_op *ops, void *drv,
     44		 struct snd_midi_channel *chan,
     45		 struct snd_midi_channel_set *chset);
     46static void sysex(const struct snd_midi_op *ops, void *private,
     47		  unsigned char *sysex,
     48		  int len, struct snd_midi_channel_set *chset);
     49static void all_sounds_off(const struct snd_midi_op *ops, void *private,
     50			   struct snd_midi_channel *chan);
     51static void all_notes_off(const struct snd_midi_op *ops, void *private,
     52			  struct snd_midi_channel *chan);
     53static void snd_midi_reset_controllers(struct snd_midi_channel *chan);
     54static void reset_all_channels(struct snd_midi_channel_set *chset);
     55
     56
     57/*
     58 * Process an event in a driver independent way.  This means dealing
     59 * with RPN, NRPN, SysEx etc that are defined for common midi applications
     60 * such as GM, GS and XG.
     61 * There modes that this module will run in are:
     62 *   Generic MIDI - no interpretation at all, it will just save current values
     63 *                  of controllers etc.
     64 *   GM - You can use all gm_ prefixed elements of chan.  Controls, RPN, NRPN,
     65 *        SysEx will be interpreded as defined in General Midi.
     66 *   GS - You can use all gs_ prefixed elements of chan. Codes for GS will be
     67 *        interpreted.
     68 *   XG - You can use all xg_ prefixed elements of chan.  Codes for XG will
     69 *        be interpreted.
     70 */
     71void
     72snd_midi_process_event(const struct snd_midi_op *ops,
     73		       struct snd_seq_event *ev,
     74		       struct snd_midi_channel_set *chanset)
     75{
     76	struct snd_midi_channel *chan;
     77	void *drv;
     78	int dest_channel = 0;
     79
     80	if (ev == NULL || chanset == NULL) {
     81		pr_debug("ALSA: seq_midi_emul: ev or chanbase NULL (snd_midi_process_event)\n");
     82		return;
     83	}
     84	if (chanset->channels == NULL)
     85		return;
     86
     87	if (snd_seq_ev_is_channel_type(ev)) {
     88		dest_channel = ev->data.note.channel;
     89		if (dest_channel >= chanset->max_channels) {
     90			pr_debug("ALSA: seq_midi_emul: dest channel is %d, max is %d\n",
     91				   dest_channel, chanset->max_channels);
     92			return;
     93		}
     94	}
     95
     96	chan = chanset->channels + dest_channel;
     97	drv  = chanset->private_data;
     98
     99	/* EVENT_NOTE should be processed before queued */
    100	if (ev->type == SNDRV_SEQ_EVENT_NOTE)
    101		return;
    102
    103	/* Make sure that we don't have a note on that should really be
    104	 * a note off */
    105	if (ev->type == SNDRV_SEQ_EVENT_NOTEON && ev->data.note.velocity == 0)
    106		ev->type = SNDRV_SEQ_EVENT_NOTEOFF;
    107
    108	/* Make sure the note is within array range */
    109	if (ev->type == SNDRV_SEQ_EVENT_NOTEON ||
    110	    ev->type == SNDRV_SEQ_EVENT_NOTEOFF ||
    111	    ev->type == SNDRV_SEQ_EVENT_KEYPRESS) {
    112		if (ev->data.note.note >= 128)
    113			return;
    114	}
    115
    116	switch (ev->type) {
    117	case SNDRV_SEQ_EVENT_NOTEON:
    118		if (chan->note[ev->data.note.note] & SNDRV_MIDI_NOTE_ON) {
    119			if (ops->note_off)
    120				ops->note_off(drv, ev->data.note.note, 0, chan);
    121		}
    122		chan->note[ev->data.note.note] = SNDRV_MIDI_NOTE_ON;
    123		if (ops->note_on)
    124			ops->note_on(drv, ev->data.note.note, ev->data.note.velocity, chan);
    125		break;
    126	case SNDRV_SEQ_EVENT_NOTEOFF:
    127		if (! (chan->note[ev->data.note.note] & SNDRV_MIDI_NOTE_ON))
    128			break;
    129		if (ops->note_off)
    130			note_off(ops, drv, chan, ev->data.note.note, ev->data.note.velocity);
    131		break;
    132	case SNDRV_SEQ_EVENT_KEYPRESS:
    133		if (ops->key_press)
    134			ops->key_press(drv, ev->data.note.note, ev->data.note.velocity, chan);
    135		break;
    136	case SNDRV_SEQ_EVENT_CONTROLLER:
    137		do_control(ops, drv, chanset, chan,
    138			   ev->data.control.param, ev->data.control.value);
    139		break;
    140	case SNDRV_SEQ_EVENT_PGMCHANGE:
    141		chan->midi_program = ev->data.control.value;
    142		break;
    143	case SNDRV_SEQ_EVENT_PITCHBEND:
    144		chan->midi_pitchbend = ev->data.control.value;
    145		if (ops->control)
    146			ops->control(drv, MIDI_CTL_PITCHBEND, chan);
    147		break;
    148	case SNDRV_SEQ_EVENT_CHANPRESS:
    149		chan->midi_pressure = ev->data.control.value;
    150		if (ops->control)
    151			ops->control(drv, MIDI_CTL_CHAN_PRESSURE, chan);
    152		break;
    153	case SNDRV_SEQ_EVENT_CONTROL14:
    154		/* Best guess is that this is any of the 14 bit controller values */
    155		if (ev->data.control.param < 32) {
    156			/* set low part first */
    157			chan->control[ev->data.control.param + 32] =
    158				ev->data.control.value & 0x7f;
    159			do_control(ops, drv, chanset, chan,
    160				   ev->data.control.param,
    161				   ((ev->data.control.value>>7) & 0x7f));
    162		} else
    163			do_control(ops, drv, chanset, chan,
    164				   ev->data.control.param,
    165				   ev->data.control.value);
    166		break;
    167	case SNDRV_SEQ_EVENT_NONREGPARAM:
    168		/* Break it back into its controller values */
    169		chan->param_type = SNDRV_MIDI_PARAM_TYPE_NONREGISTERED;
    170		chan->control[MIDI_CTL_MSB_DATA_ENTRY]
    171			= (ev->data.control.value >> 7) & 0x7f;
    172		chan->control[MIDI_CTL_LSB_DATA_ENTRY]
    173			= ev->data.control.value & 0x7f;
    174		chan->control[MIDI_CTL_NONREG_PARM_NUM_MSB]
    175			= (ev->data.control.param >> 7) & 0x7f;
    176		chan->control[MIDI_CTL_NONREG_PARM_NUM_LSB]
    177			= ev->data.control.param & 0x7f;
    178		nrpn(ops, drv, chan, chanset);
    179		break;
    180	case SNDRV_SEQ_EVENT_REGPARAM:
    181		/* Break it back into its controller values */
    182		chan->param_type = SNDRV_MIDI_PARAM_TYPE_REGISTERED;
    183		chan->control[MIDI_CTL_MSB_DATA_ENTRY]
    184			= (ev->data.control.value >> 7) & 0x7f;
    185		chan->control[MIDI_CTL_LSB_DATA_ENTRY]
    186			= ev->data.control.value & 0x7f;
    187		chan->control[MIDI_CTL_REGIST_PARM_NUM_MSB]
    188			= (ev->data.control.param >> 7) & 0x7f;
    189		chan->control[MIDI_CTL_REGIST_PARM_NUM_LSB]
    190			= ev->data.control.param & 0x7f;
    191		rpn(ops, drv, chan, chanset);
    192		break;
    193	case SNDRV_SEQ_EVENT_SYSEX:
    194		if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) == SNDRV_SEQ_EVENT_LENGTH_VARIABLE) {
    195			unsigned char sysexbuf[64];
    196			int len;
    197			len = snd_seq_expand_var_event(ev, sizeof(sysexbuf), sysexbuf, 1, 0);
    198			if (len > 0)
    199				sysex(ops, drv, sysexbuf, len, chanset);
    200		}
    201		break;
    202	case SNDRV_SEQ_EVENT_SONGPOS:
    203	case SNDRV_SEQ_EVENT_SONGSEL:
    204	case SNDRV_SEQ_EVENT_CLOCK:
    205	case SNDRV_SEQ_EVENT_START:
    206	case SNDRV_SEQ_EVENT_CONTINUE:
    207	case SNDRV_SEQ_EVENT_STOP:
    208	case SNDRV_SEQ_EVENT_QFRAME:
    209	case SNDRV_SEQ_EVENT_TEMPO:
    210	case SNDRV_SEQ_EVENT_TIMESIGN:
    211	case SNDRV_SEQ_EVENT_KEYSIGN:
    212		goto not_yet;
    213	case SNDRV_SEQ_EVENT_SENSING:
    214		break;
    215	case SNDRV_SEQ_EVENT_CLIENT_START:
    216	case SNDRV_SEQ_EVENT_CLIENT_EXIT:
    217	case SNDRV_SEQ_EVENT_CLIENT_CHANGE:
    218	case SNDRV_SEQ_EVENT_PORT_START:
    219	case SNDRV_SEQ_EVENT_PORT_EXIT:
    220	case SNDRV_SEQ_EVENT_PORT_CHANGE:
    221	case SNDRV_SEQ_EVENT_ECHO:
    222	not_yet:
    223	default:
    224		/*pr_debug("ALSA: seq_midi_emul: Unimplemented event %d\n", ev->type);*/
    225		break;
    226	}
    227}
    228EXPORT_SYMBOL(snd_midi_process_event);
    229
    230
    231/*
    232 * release note
    233 */
    234static void
    235note_off(const struct snd_midi_op *ops, void *drv,
    236	 struct snd_midi_channel *chan,
    237	 int note, int vel)
    238{
    239	if (chan->gm_hold) {
    240		/* Hold this note until pedal is turned off */
    241		chan->note[note] |= SNDRV_MIDI_NOTE_RELEASED;
    242	} else if (chan->note[note] & SNDRV_MIDI_NOTE_SOSTENUTO) {
    243		/* Mark this note as release; it will be turned off when sostenuto
    244		 * is turned off */
    245		chan->note[note] |= SNDRV_MIDI_NOTE_RELEASED;
    246	} else {
    247		chan->note[note] = 0;
    248		if (ops->note_off)
    249			ops->note_off(drv, note, vel, chan);
    250	}
    251}
    252
    253/*
    254 * Do all driver independent operations for this controller and pass
    255 * events that need to take place immediately to the driver.
    256 */
    257static void
    258do_control(const struct snd_midi_op *ops, void *drv,
    259	   struct snd_midi_channel_set *chset,
    260	   struct snd_midi_channel *chan, int control, int value)
    261{
    262	int  i;
    263
    264	if (control >= ARRAY_SIZE(chan->control))
    265		return;
    266
    267	/* Switches */
    268	if ((control >=64 && control <=69) || (control >= 80 && control <= 83)) {
    269		/* These are all switches; either off or on so set to 0 or 127 */
    270		value = (value >= 64)? 127: 0;
    271	}
    272	chan->control[control] = value;
    273
    274	switch (control) {
    275	case MIDI_CTL_SUSTAIN:
    276		if (value == 0) {
    277			/* Sustain has been released, turn off held notes */
    278			for (i = 0; i < 128; i++) {
    279				if (chan->note[i] & SNDRV_MIDI_NOTE_RELEASED) {
    280					chan->note[i] = SNDRV_MIDI_NOTE_OFF;
    281					if (ops->note_off)
    282						ops->note_off(drv, i, 0, chan);
    283				}
    284			}
    285		}
    286		break;
    287	case MIDI_CTL_PORTAMENTO:
    288		break;
    289	case MIDI_CTL_SOSTENUTO:
    290		if (value) {
    291			/* Mark each note that is currently held down */
    292			for (i = 0; i < 128; i++) {
    293				if (chan->note[i] & SNDRV_MIDI_NOTE_ON)
    294					chan->note[i] |= SNDRV_MIDI_NOTE_SOSTENUTO;
    295			}
    296		} else {
    297			/* release all notes that were held */
    298			for (i = 0; i < 128; i++) {
    299				if (chan->note[i] & SNDRV_MIDI_NOTE_SOSTENUTO) {
    300					chan->note[i] &= ~SNDRV_MIDI_NOTE_SOSTENUTO;
    301					if (chan->note[i] & SNDRV_MIDI_NOTE_RELEASED) {
    302						chan->note[i] = SNDRV_MIDI_NOTE_OFF;
    303						if (ops->note_off)
    304							ops->note_off(drv, i, 0, chan);
    305					}
    306				}
    307			}
    308		}
    309		break;
    310	case MIDI_CTL_MSB_DATA_ENTRY:
    311		chan->control[MIDI_CTL_LSB_DATA_ENTRY] = 0;
    312		fallthrough;
    313	case MIDI_CTL_LSB_DATA_ENTRY:
    314		if (chan->param_type == SNDRV_MIDI_PARAM_TYPE_REGISTERED)
    315			rpn(ops, drv, chan, chset);
    316		else
    317			nrpn(ops, drv, chan, chset);
    318		break;
    319	case MIDI_CTL_REGIST_PARM_NUM_LSB:
    320	case MIDI_CTL_REGIST_PARM_NUM_MSB:
    321		chan->param_type = SNDRV_MIDI_PARAM_TYPE_REGISTERED;
    322		break;
    323	case MIDI_CTL_NONREG_PARM_NUM_LSB:
    324	case MIDI_CTL_NONREG_PARM_NUM_MSB:
    325		chan->param_type = SNDRV_MIDI_PARAM_TYPE_NONREGISTERED;
    326		break;
    327
    328	case MIDI_CTL_ALL_SOUNDS_OFF:
    329		all_sounds_off(ops, drv, chan);
    330		break;
    331
    332	case MIDI_CTL_ALL_NOTES_OFF:
    333		all_notes_off(ops, drv, chan);
    334		break;
    335
    336	case MIDI_CTL_MSB_BANK:
    337		if (chset->midi_mode == SNDRV_MIDI_MODE_XG) {
    338			if (value == 127)
    339				chan->drum_channel = 1;
    340			else
    341				chan->drum_channel = 0;
    342		}
    343		break;
    344	case MIDI_CTL_LSB_BANK:
    345		break;
    346
    347	case MIDI_CTL_RESET_CONTROLLERS:
    348		snd_midi_reset_controllers(chan);
    349		break;
    350
    351	case MIDI_CTL_SOFT_PEDAL:
    352	case MIDI_CTL_LEGATO_FOOTSWITCH:
    353	case MIDI_CTL_HOLD2:
    354	case MIDI_CTL_SC1_SOUND_VARIATION:
    355	case MIDI_CTL_SC2_TIMBRE:
    356	case MIDI_CTL_SC3_RELEASE_TIME:
    357	case MIDI_CTL_SC4_ATTACK_TIME:
    358	case MIDI_CTL_SC5_BRIGHTNESS:
    359	case MIDI_CTL_E1_REVERB_DEPTH:
    360	case MIDI_CTL_E2_TREMOLO_DEPTH:
    361	case MIDI_CTL_E3_CHORUS_DEPTH:
    362	case MIDI_CTL_E4_DETUNE_DEPTH:
    363	case MIDI_CTL_E5_PHASER_DEPTH:
    364		goto notyet;
    365	notyet:
    366	default:
    367		if (ops->control)
    368			ops->control(drv, control, chan);
    369		break;
    370	}
    371}
    372
    373
    374/*
    375 * initialize the MIDI status
    376 */
    377void
    378snd_midi_channel_set_clear(struct snd_midi_channel_set *chset)
    379{
    380	int i;
    381
    382	chset->midi_mode = SNDRV_MIDI_MODE_GM;
    383	chset->gs_master_volume = 127;
    384
    385	for (i = 0; i < chset->max_channels; i++) {
    386		struct snd_midi_channel *chan = chset->channels + i;
    387		memset(chan->note, 0, sizeof(chan->note));
    388
    389		chan->midi_aftertouch = 0;
    390		chan->midi_pressure = 0;
    391		chan->midi_program = 0;
    392		chan->midi_pitchbend = 0;
    393		snd_midi_reset_controllers(chan);
    394		chan->gm_rpn_pitch_bend_range = 256; /* 2 semitones */
    395		chan->gm_rpn_fine_tuning = 0;
    396		chan->gm_rpn_coarse_tuning = 0;
    397
    398		if (i == 9)
    399			chan->drum_channel = 1;
    400		else
    401			chan->drum_channel = 0;
    402	}
    403}
    404EXPORT_SYMBOL(snd_midi_channel_set_clear);
    405
    406/*
    407 * Process a rpn message.
    408 */
    409static void
    410rpn(const struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan,
    411    struct snd_midi_channel_set *chset)
    412{
    413	int type;
    414	int val;
    415
    416	if (chset->midi_mode != SNDRV_MIDI_MODE_NONE) {
    417		type = (chan->control[MIDI_CTL_REGIST_PARM_NUM_MSB] << 8) |
    418			chan->control[MIDI_CTL_REGIST_PARM_NUM_LSB];
    419		val = (chan->control[MIDI_CTL_MSB_DATA_ENTRY] << 7) |
    420			chan->control[MIDI_CTL_LSB_DATA_ENTRY];
    421
    422		switch (type) {
    423		case 0x0000: /* Pitch bend sensitivity */
    424			/* MSB only / 1 semitone per 128 */
    425			chan->gm_rpn_pitch_bend_range = val;
    426			break;
    427					
    428		case 0x0001: /* fine tuning: */
    429			/* MSB/LSB, 8192=center, 100/8192 cent step */
    430			chan->gm_rpn_fine_tuning = val - 8192;
    431			break;
    432
    433		case 0x0002: /* coarse tuning */
    434			/* MSB only / 8192=center, 1 semitone per 128 */
    435			chan->gm_rpn_coarse_tuning = val - 8192;
    436			break;
    437
    438		case 0x7F7F: /* "lock-in" RPN */
    439			/* ignored */
    440			break;
    441		}
    442	}
    443	/* should call nrpn or rpn callback here.. */
    444}
    445
    446/*
    447 * Process an nrpn message.
    448 */
    449static void
    450nrpn(const struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan,
    451     struct snd_midi_channel_set *chset)
    452{
    453	/* parse XG NRPNs here if possible */
    454	if (ops->nrpn)
    455		ops->nrpn(drv, chan, chset);
    456}
    457
    458
    459/*
    460 * convert channel parameter in GS sysex
    461 */
    462static int
    463get_channel(unsigned char cmd)
    464{
    465	int p = cmd & 0x0f;
    466	if (p == 0)
    467		p = 9;
    468	else if (p < 10)
    469		p--;
    470	return p;
    471}
    472
    473
    474/*
    475 * Process a sysex message.
    476 */
    477static void
    478sysex(const struct snd_midi_op *ops, void *private, unsigned char *buf, int len,
    479      struct snd_midi_channel_set *chset)
    480{
    481	/* GM on */
    482	static const unsigned char gm_on_macro[] = {
    483		0x7e,0x7f,0x09,0x01,
    484	};
    485	/* XG on */
    486	static const unsigned char xg_on_macro[] = {
    487		0x43,0x10,0x4c,0x00,0x00,0x7e,0x00,
    488	};
    489	/* GS prefix
    490	 * drum channel: XX=0x1?(channel), YY=0x15, ZZ=on/off
    491	 * reverb mode: XX=0x01, YY=0x30, ZZ=0-7
    492	 * chorus mode: XX=0x01, YY=0x38, ZZ=0-7
    493	 * master vol:  XX=0x00, YY=0x04, ZZ=0-127
    494	 */
    495	static const unsigned char gs_pfx_macro[] = {
    496		0x41,0x10,0x42,0x12,0x40,/*XX,YY,ZZ*/
    497	};
    498
    499	int parsed = SNDRV_MIDI_SYSEX_NOT_PARSED;
    500
    501	if (len <= 0 || buf[0] != 0xf0)
    502		return;
    503	/* skip first byte */
    504	buf++;
    505	len--;
    506
    507	/* GM on */
    508	if (len >= (int)sizeof(gm_on_macro) &&
    509	    memcmp(buf, gm_on_macro, sizeof(gm_on_macro)) == 0) {
    510		if (chset->midi_mode != SNDRV_MIDI_MODE_GS &&
    511		    chset->midi_mode != SNDRV_MIDI_MODE_XG) {
    512			chset->midi_mode = SNDRV_MIDI_MODE_GM;
    513			reset_all_channels(chset);
    514			parsed = SNDRV_MIDI_SYSEX_GM_ON;
    515		}
    516	}
    517
    518	/* GS macros */
    519	else if (len >= 8 &&
    520		 memcmp(buf, gs_pfx_macro, sizeof(gs_pfx_macro)) == 0) {
    521		if (chset->midi_mode != SNDRV_MIDI_MODE_GS &&
    522		    chset->midi_mode != SNDRV_MIDI_MODE_XG)
    523			chset->midi_mode = SNDRV_MIDI_MODE_GS;
    524
    525		if (buf[5] == 0x00 && buf[6] == 0x7f && buf[7] == 0x00) {
    526			/* GS reset */
    527			parsed = SNDRV_MIDI_SYSEX_GS_RESET;
    528			reset_all_channels(chset);
    529		}
    530
    531		else if ((buf[5] & 0xf0) == 0x10 && buf[6] == 0x15) {
    532			/* drum pattern */
    533			int p = get_channel(buf[5]);
    534			if (p < chset->max_channels) {
    535				parsed = SNDRV_MIDI_SYSEX_GS_DRUM_CHANNEL;
    536				if (buf[7])
    537					chset->channels[p].drum_channel = 1;
    538				else
    539					chset->channels[p].drum_channel = 0;
    540			}
    541
    542		} else if ((buf[5] & 0xf0) == 0x10 && buf[6] == 0x21) {
    543			/* program */
    544			int p = get_channel(buf[5]);
    545			if (p < chset->max_channels &&
    546			    ! chset->channels[p].drum_channel) {
    547				parsed = SNDRV_MIDI_SYSEX_GS_DRUM_CHANNEL;
    548				chset->channels[p].midi_program = buf[7];
    549			}
    550
    551		} else if (buf[5] == 0x01 && buf[6] == 0x30) {
    552			/* reverb mode */
    553			parsed = SNDRV_MIDI_SYSEX_GS_REVERB_MODE;
    554			chset->gs_reverb_mode = buf[7];
    555
    556		} else if (buf[5] == 0x01 && buf[6] == 0x38) {
    557			/* chorus mode */
    558			parsed = SNDRV_MIDI_SYSEX_GS_CHORUS_MODE;
    559			chset->gs_chorus_mode = buf[7];
    560
    561		} else if (buf[5] == 0x00 && buf[6] == 0x04) {
    562			/* master volume */
    563			parsed = SNDRV_MIDI_SYSEX_GS_MASTER_VOLUME;
    564			chset->gs_master_volume = buf[7];
    565
    566		}
    567	}
    568
    569	/* XG on */
    570	else if (len >= (int)sizeof(xg_on_macro) &&
    571		 memcmp(buf, xg_on_macro, sizeof(xg_on_macro)) == 0) {
    572		int i;
    573		chset->midi_mode = SNDRV_MIDI_MODE_XG;
    574		parsed = SNDRV_MIDI_SYSEX_XG_ON;
    575		/* reset CC#0 for drums */
    576		for (i = 0; i < chset->max_channels; i++) {
    577			if (chset->channels[i].drum_channel)
    578				chset->channels[i].control[MIDI_CTL_MSB_BANK] = 127;
    579			else
    580				chset->channels[i].control[MIDI_CTL_MSB_BANK] = 0;
    581		}
    582	}
    583
    584	if (ops->sysex)
    585		ops->sysex(private, buf - 1, len + 1, parsed, chset);
    586}
    587
    588/*
    589 * all sound off
    590 */
    591static void
    592all_sounds_off(const struct snd_midi_op *ops, void *drv,
    593	       struct snd_midi_channel *chan)
    594{
    595	int n;
    596
    597	if (! ops->note_terminate)
    598		return;
    599	for (n = 0; n < 128; n++) {
    600		if (chan->note[n]) {
    601			ops->note_terminate(drv, n, chan);
    602			chan->note[n] = 0;
    603		}
    604	}
    605}
    606
    607/*
    608 * all notes off
    609 */
    610static void
    611all_notes_off(const struct snd_midi_op *ops, void *drv,
    612	      struct snd_midi_channel *chan)
    613{
    614	int n;
    615
    616	if (! ops->note_off)
    617		return;
    618	for (n = 0; n < 128; n++) {
    619		if (chan->note[n] == SNDRV_MIDI_NOTE_ON)
    620			note_off(ops, drv, chan, n, 0);
    621	}
    622}
    623
    624/*
    625 * Initialise a single midi channel control block.
    626 */
    627static void snd_midi_channel_init(struct snd_midi_channel *p, int n)
    628{
    629	if (p == NULL)
    630		return;
    631
    632	memset(p, 0, sizeof(struct snd_midi_channel));
    633	p->private = NULL;
    634	p->number = n;
    635
    636	snd_midi_reset_controllers(p);
    637	p->gm_rpn_pitch_bend_range = 256; /* 2 semitones */
    638	p->gm_rpn_fine_tuning = 0;
    639	p->gm_rpn_coarse_tuning = 0;
    640
    641	if (n == 9)
    642		p->drum_channel = 1;	/* Default ch 10 as drums */
    643}
    644
    645/*
    646 * Allocate and initialise a set of midi channel control blocks.
    647 */
    648static struct snd_midi_channel *snd_midi_channel_init_set(int n)
    649{
    650	struct snd_midi_channel *chan;
    651	int  i;
    652
    653	chan = kmalloc_array(n, sizeof(struct snd_midi_channel), GFP_KERNEL);
    654	if (chan) {
    655		for (i = 0; i < n; i++)
    656			snd_midi_channel_init(chan+i, i);
    657	}
    658
    659	return chan;
    660}
    661
    662/*
    663 * reset all midi channels
    664 */
    665static void
    666reset_all_channels(struct snd_midi_channel_set *chset)
    667{
    668	int ch;
    669	for (ch = 0; ch < chset->max_channels; ch++) {
    670		struct snd_midi_channel *chan = chset->channels + ch;
    671		snd_midi_reset_controllers(chan);
    672		chan->gm_rpn_pitch_bend_range = 256; /* 2 semitones */
    673		chan->gm_rpn_fine_tuning = 0;
    674		chan->gm_rpn_coarse_tuning = 0;
    675
    676		if (ch == 9)
    677			chan->drum_channel = 1;
    678		else
    679			chan->drum_channel = 0;
    680	}
    681}
    682
    683
    684/*
    685 * Allocate and initialise a midi channel set.
    686 */
    687struct snd_midi_channel_set *snd_midi_channel_alloc_set(int n)
    688{
    689	struct snd_midi_channel_set *chset;
    690
    691	chset = kmalloc(sizeof(*chset), GFP_KERNEL);
    692	if (chset) {
    693		chset->channels = snd_midi_channel_init_set(n);
    694		chset->private_data = NULL;
    695		chset->max_channels = n;
    696	}
    697	return chset;
    698}
    699EXPORT_SYMBOL(snd_midi_channel_alloc_set);
    700
    701/*
    702 * Reset the midi controllers on a particular channel to default values.
    703 */
    704static void snd_midi_reset_controllers(struct snd_midi_channel *chan)
    705{
    706	memset(chan->control, 0, sizeof(chan->control));
    707	chan->gm_volume = 127;
    708	chan->gm_expression = 127;
    709	chan->gm_pan = 64;
    710}
    711
    712
    713/*
    714 * Free a midi channel set.
    715 */
    716void snd_midi_channel_free_set(struct snd_midi_channel_set *chset)
    717{
    718	if (chset == NULL)
    719		return;
    720	kfree(chset->channels);
    721	kfree(chset);
    722}
    723EXPORT_SYMBOL(snd_midi_channel_free_set);