wavefront_midi.c

来自「鼎力推荐!本程序是基于嵌入式LUNUX系统开发的源程序代码」· C语言 代码 · 共 575 行 · 第 1/2 页

C
575
字号
	        return -EIO;	spin_lock_irqsave (&midi->open, flags);	midi->mode[mpu] &= ~MPU401_MODE_INPUT;	spin_unlock_irqrestore (&midi->open, flags);	return 0;}static int snd_wavefront_midi_output_close(snd_rawmidi_substream_t * substream){	unsigned long flags;	snd_wavefront_midi_t *midi;	snd_wavefront_mpu_id mpu;	snd_assert(substream != NULL && substream->rmidi != NULL, return -EIO);	snd_assert(substream->rmidi->private_data != NULL, return -EIO);	mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);	if ((midi = get_wavefront_midi (substream)) == NULL)	        return -EIO;	spin_lock_irqsave (&midi->open, flags);	midi->mode[mpu] &= ~MPU401_MODE_OUTPUT;	spin_unlock_irqrestore (&midi->open, flags);	return 0;}static void snd_wavefront_midi_input_trigger(snd_rawmidi_substream_t * substream, int up){	unsigned long flags;	snd_wavefront_midi_t *midi;	snd_wavefront_mpu_id mpu;	if (substream == NULL || substream->rmidi == NULL) 	        return;	if (substream->rmidi->private_data == NULL)	        return;	mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);	if ((midi = get_wavefront_midi (substream)) == NULL) {		return;	}	spin_lock_irqsave (&midi->virtual, flags);	if (up) {		midi->mode[mpu] |= MPU401_MODE_INPUT_TRIGGER;	} else {		midi->mode[mpu] &= ~MPU401_MODE_INPUT_TRIGGER;	}	spin_unlock_irqrestore (&midi->virtual, flags);}static void snd_wavefront_midi_output_timer(unsigned long data){	snd_wavefront_card_t *card = (snd_wavefront_card_t *)data;	snd_wavefront_midi_t *midi = &card->wavefront.midi;	unsigned long flags;		spin_lock_irqsave (&midi->virtual, flags);	midi->timer.expires = 1 + jiffies;	add_timer(&midi->timer);	spin_unlock_irqrestore (&midi->virtual, flags);	snd_wavefront_midi_output_write(card);}static void snd_wavefront_midi_output_trigger(snd_rawmidi_substream_t * substream, int up){	unsigned long flags;	snd_wavefront_midi_t *midi;	snd_wavefront_mpu_id mpu;	if (substream == NULL || substream->rmidi == NULL) 	        return;	if (substream->rmidi->private_data == NULL)	        return;	mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);	if ((midi = get_wavefront_midi (substream)) == NULL) {		return;	}	spin_lock_irqsave (&midi->virtual, flags);	if (up) {		if ((midi->mode[mpu] & MPU401_MODE_OUTPUT_TRIGGER) == 0) {			if (!midi->istimer) {				init_timer(&midi->timer);				midi->timer.function = snd_wavefront_midi_output_timer;				midi->timer.data = (unsigned long) substream->rmidi->card->private_data;				midi->timer.expires = 1 + jiffies;				add_timer(&midi->timer);			}			midi->istimer++;			midi->mode[mpu] |= MPU401_MODE_OUTPUT_TRIGGER;		}	} else {		midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER;	}	spin_unlock_irqrestore (&midi->virtual, flags);	if (up)		snd_wavefront_midi_output_write((snd_wavefront_card_t *)substream->rmidi->card->private_data);}voidsnd_wavefront_midi_interrupt (snd_wavefront_card_t *card){	unsigned long flags;	snd_wavefront_midi_t *midi;	static snd_rawmidi_substream_t *substream = NULL;	static int mpu = external_mpu; 	int max = 128;	unsigned char byte;	midi = &card->wavefront.midi;	if (!input_avail (midi)) { /* not for us */		snd_wavefront_midi_output_write(card);		return;	}	while (--max) {		spin_lock_irqsave (&midi->virtual, flags);		if (input_avail (midi)) {			byte = read_data (midi);			if (midi->isvirtual) {								if (byte == WF_EXTERNAL_SWITCH) {					substream = midi->substream_input[external_mpu];					mpu = external_mpu;				} else if (byte == WF_INTERNAL_SWITCH) { 					substream = midi->substream_output[internal_mpu];					mpu = internal_mpu;				} /* else just leave it as it is */			} else {				substream = midi->substream_input[internal_mpu];				mpu = internal_mpu;			}			if (substream == NULL) {				spin_unlock_irqrestore (&midi->virtual, flags);				continue;			}			if (midi->mode[mpu] & MPU401_MODE_INPUT_TRIGGER) {				spin_unlock_irqrestore (&midi->virtual, flags);				snd_rawmidi_receive(substream, &byte, 1);			} else {				spin_unlock_irqrestore (&midi->virtual, flags);			}		} else {			spin_unlock_irqrestore (&midi->virtual, flags);			break;		}	} 	snd_wavefront_midi_output_write(card);}voidsnd_wavefront_midi_enable_virtual (snd_wavefront_card_t *card){	unsigned long flags;	spin_lock_irqsave (&card->wavefront.midi.virtual, flags);	card->wavefront.midi.isvirtual = 1;	card->wavefront.midi.output_mpu = internal_mpu;	card->wavefront.midi.input_mpu = internal_mpu;	spin_unlock_irqrestore (&card->wavefront.midi.virtual, flags);}voidsnd_wavefront_midi_disable_virtual (snd_wavefront_card_t *card){	unsigned long flags;	spin_lock_irqsave (&card->wavefront.midi.virtual, flags);	// snd_wavefront_midi_input_close (card->ics2115_external_rmidi);	// snd_wavefront_midi_output_close (card->ics2115_external_rmidi);	card->wavefront.midi.isvirtual = 0;	spin_unlock_irqrestore (&card->wavefront.midi.virtual, flags);}int __initsnd_wavefront_midi_start (snd_wavefront_card_t *card){	int ok, i;	unsigned char rbuf[4], wbuf[4];	snd_wavefront_t *dev;	snd_wavefront_midi_t *midi;	dev = &card->wavefront;	midi = &dev->midi;	/* The ICS2115 MPU-401 interface doesn't do anything	   until its set into UART mode.	*/	/* XXX fix me - no hard timing loops allowed! */	for (i = 0; i < 30000 && !output_ready (midi); i++);	if (!output_ready (midi)) {		snd_printk ("MIDI interface not ready for command\n");		return -1;	}	/* Any interrupts received from now on	   are owned by the MIDI side of things.	*/	dev->interrupts_are_midi = 1;		outb (UART_MODE_ON, midi->mpu_command_port);	for (ok = 0, i = 50000; i > 0 && !ok; i--) {		if (input_avail (midi)) {			if (read_data (midi) == MPU_ACK) {				ok = 1;				break;			}		}	}	if (!ok) {		snd_printk ("cannot set UART mode for MIDI interface");		dev->interrupts_are_midi = 0;		return -1;	}	/* Route external MIDI to WaveFront synth (by default) */    	if (snd_wavefront_cmd (dev, WFC_MISYNTH_ON, rbuf, wbuf)) {		snd_printk ("can't enable MIDI-IN-2-synth routing.\n");		/* XXX error ? */	}	/* Turn on Virtual MIDI, but first *always* turn it off,	   since otherwise consectutive reloads of the driver will	   never cause the hardware to generate the initial "internal" or 	   "external" source bytes in the MIDI data stream. This	   is pretty important, since the internal hardware generally will	   be used to generate none or very little MIDI output, and	   thus the only source of MIDI data is actually external. Without	   the switch bytes, the driver will think it all comes from	   the internal interface. Duh.	*/	if (snd_wavefront_cmd (dev, WFC_VMIDI_OFF, rbuf, wbuf)) { 		snd_printk ("virtual MIDI mode not disabled\n");		return 0; /* We're OK, but missing the external MIDI dev */	}	snd_wavefront_midi_enable_virtual (card);	if (snd_wavefront_cmd (dev, WFC_VMIDI_ON, rbuf, wbuf)) {		snd_printk ("cannot enable virtual MIDI mode.\n");		snd_wavefront_midi_disable_virtual (card);	} 	return 0;}snd_rawmidi_ops_t snd_wavefront_midi_output ={	.open =		snd_wavefront_midi_output_open,	.close =	snd_wavefront_midi_output_close,	.trigger =	snd_wavefront_midi_output_trigger,};snd_rawmidi_ops_t snd_wavefront_midi_input ={	.open =		snd_wavefront_midi_input_open,	.close =	snd_wavefront_midi_input_close,	.trigger =	snd_wavefront_midi_input_trigger,};

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?