示例#1
0
文件: lib.c 项目: 020gzh/linux
static void async_midi_port_callback(struct fw_card *card, int rcode,
				     void *data, size_t length,
				     void *callback_data)
{
	struct snd_fw_async_midi_port *port = callback_data;
	struct snd_rawmidi_substream *substream = ACCESS_ONCE(port->substream);

	/* This port is closed. */
	if (substream == NULL)
		return;

	if (rcode == RCODE_COMPLETE)
		snd_rawmidi_transmit_ack(substream, port->consume_bytes);
	else if (!rcode_is_permanent_error(rcode))
		/* To start next transaction immediately for recovery. */
		port->next_ktime = ktime_set(0, 0);
	else
		/* Don't continue processing. */
		port->error = true;

	port->idling = true;

	if (!snd_rawmidi_transmit_empty(substream))
		schedule_work(&port->work);
}
示例#2
0
/*
	Read data from MIDI buffer and transmit them via USB.
*/
static void line6_midi_transmit(struct snd_rawmidi_substream *substream)
{
	struct usb_line6 *line6 =
	    line6_rawmidi_substream_midi(substream)->line6;
	struct snd_line6_midi *line6midi = line6->line6midi;
	struct MidiBuffer *mb = &line6midi->midibuf_out;
	unsigned long flags;
	unsigned char chunk[line6->max_packet_size];
	int req, done;

	spin_lock_irqsave(&line6->line6midi->midi_transmit_lock, flags);

	for (;;) {
		req = min(line6_midibuf_bytes_free(mb), line6->max_packet_size);
		done = snd_rawmidi_transmit_peek(substream, chunk, req);

		if (done == 0)
			break;

		line6_midibuf_write(mb, chunk, done);
		snd_rawmidi_transmit_ack(substream, done);
	}

	for (;;) {
		done = line6_midibuf_read(mb, chunk, line6->max_packet_size);

		if (done == 0)
			break;

		send_midi_async(line6, chunk, done);
	}

	spin_unlock_irqrestore(&line6->line6midi->midi_transmit_lock, flags);
}
示例#3
0
static void snd_sb8dsp_midi_output_write(struct snd_rawmidi_substream *substream)
{
	unsigned long flags;
	struct snd_sb *chip;
	char byte;
	int max = 32;

	/* how big is Tx FIFO? */
	chip = substream->rmidi->private_data;
	while (max-- > 0) {
		spin_lock_irqsave(&chip->open_lock, flags);
		if (snd_rawmidi_transmit_peek(substream, &byte, 1) != 1) {
			chip->open &= ~SB_OPEN_MIDI_OUTPUT_TRIGGER;
			del_timer(&chip->midi_timer);
			spin_unlock_irqrestore(&chip->open_lock, flags);
			break;
		}
		if (chip->hardware >= SB_HW_20) {
			int timeout = 8;
			while ((inb(SBP(chip, STATUS)) & 0x80) != 0 && --timeout > 0)
				;
			if (timeout == 0) {
				/* Tx FIFO full - try again later */
				spin_unlock_irqrestore(&chip->open_lock, flags);
				break;
			}
			outb(byte, SBP(chip, WRITE));
		} else {
			snd_sbdsp_command(chip, SB_DSP_MIDI_OUTPUT);
			snd_sbdsp_command(chip, byte);
		}
		snd_rawmidi_transmit_ack(substream, 1);
		spin_unlock_irqrestore(&chip->open_lock, flags);
	}
}
示例#4
0
文件: midi.c 项目: 020gzh/linux
/*
	Read data from MIDI buffer and transmit them via USB.
*/
static void line6_midi_transmit(struct snd_rawmidi_substream *substream)
{
	struct usb_line6 *line6 =
	    line6_rawmidi_substream_midi(substream)->line6;
	struct snd_line6_midi *line6midi = line6->line6midi;
	struct midi_buffer *mb = &line6midi->midibuf_out;
	unsigned char chunk[LINE6_FALLBACK_MAXPACKETSIZE];
	int req, done;

	for (;;) {
		req = min(line6_midibuf_bytes_free(mb), line6->max_packet_size);
		done = snd_rawmidi_transmit_peek(substream, chunk, req);

		if (done == 0)
			break;

		line6_midibuf_write(mb, chunk, done);
		snd_rawmidi_transmit_ack(substream, done);
	}

	for (;;) {
		done = line6_midibuf_read(mb, chunk,
					  LINE6_FALLBACK_MAXPACKETSIZE);

		if (done == 0)
			break;

		send_midi_async(line6, chunk, done);
	}
}
示例#5
0
文件: midi.c 项目: 3null/linux
static void snd_echo_midi_output_write(unsigned long data)
{
	struct echoaudio *chip = (struct echoaudio *)data;
	unsigned long flags;
	int bytes, sent, time;
	unsigned char buf[MIDI_OUT_BUFFER_SIZE - 1];

	DE_MID(("snd_echo_midi_output_write\n"));
	/* No interrupts are involved: we have to check at regular intervals
	if the card's output buffer has room for new data. */
	sent = bytes = 0;
	spin_lock_irqsave(&chip->lock, flags);
	chip->midi_full = 0;
	if (!snd_rawmidi_transmit_empty(chip->midi_out)) {
		bytes = snd_rawmidi_transmit_peek(chip->midi_out, buf,
						  MIDI_OUT_BUFFER_SIZE - 1);
		DE_MID(("Try to send %d bytes...\n", bytes));
		sent = write_midi(chip, buf, bytes);
		if (sent < 0) {
			dev_err(chip->card->dev,
				"write_midi() error %d\n", sent);
			/* retry later */
			sent = 9000;
			chip->midi_full = 1;
		} else if (sent > 0) {
			DE_MID(("%d bytes sent\n", sent));
			snd_rawmidi_transmit_ack(chip->midi_out, sent);
		} else {
			/* Buffer is full. DSP's internal buffer is 64 (128 ?)
			bytes long. Let's wait until half of them are sent */
			DE_MID(("Full\n"));
			sent = 32;
			chip->midi_full = 1;
		}
	}

	/* We restart the timer only if there is some data left to send */
	if (!snd_rawmidi_transmit_empty(chip->midi_out) && chip->tinuse) {
		/* The timer will expire slightly after the data has been
		   sent */
		time = (sent << 3) / 25 + 1;	/* 8/25=0.32ms to send a byte */
		mod_timer(&chip->timer, jiffies + (time * HZ + 999) / 1000);
		DE_MID(("Timer armed(%d)\n", ((time * HZ + 999) / 1000)));
	}
	spin_unlock_irqrestore(&chip->lock, flags);
}
static void snd_mpu401_uart_output_write(struct snd_mpu401 * mpu)
{
	unsigned char byte;
	int max = 256;

	do {
		if (snd_rawmidi_transmit_peek(mpu->substream_output,
					      &byte, 1) == 1) {
			if (!snd_mpu401_output_ready(mpu) &&
			    !snd_mpu401_output_ready(mpu))
				break;	
			mpu->write(mpu, byte, MPU401D(mpu));
			snd_rawmidi_transmit_ack(mpu->substream_output, 1);
		} else {
			snd_mpu401_uart_remove_timer (mpu, 0);
			break;	
		}
	} while (--max > 0);
}
示例#7
0
文件: midi.c 项目: CSCLOG/beaglebone
/*
	Read data from MIDI buffer and transmit them via USB.
*/
static void line6_midi_transmit(struct snd_rawmidi_substream *substream)
{
	struct usb_line6 *line6 =
	    line6_rawmidi_substream_midi(substream)->line6;
	struct snd_line6_midi *line6midi = line6->line6midi;
	struct MidiBuffer *mb = &line6midi->midibuf_out;
	unsigned long flags;
	unsigned char chunk[line6->max_packet_size];
	int req, done;

	spin_lock_irqsave(&line6->line6midi->midi_transmit_lock, flags);

	for (;;) {
		req = min(line6_midibuf_bytes_free(mb), line6->max_packet_size);
		done = snd_rawmidi_transmit_peek(substream, chunk, req);

		if (done == 0)
			break;

#ifdef CONFIG_LINE6_USB_DUMP_MIDI
		line6_write_hexdump(line6, 's', chunk, done);
#endif
		line6_midibuf_write(mb, chunk, done);
		snd_rawmidi_transmit_ack(substream, done);
	}

	for (;;) {
		done = line6_midibuf_read(mb, chunk, line6->max_packet_size);

		if (done == 0)
			break;

		if (line6_midibuf_skip_message
		    (mb, line6midi->midi_mask_transmit))
			continue;

		send_midi_async(line6, chunk, done);
	}

	spin_unlock_irqrestore(&line6->line6midi->midi_transmit_lock, flags);
}
示例#8
0
/*
 * write output pending bytes
 * call with output_lock spinlock held
 */
static void snd_mpu401_uart_output_write(mpu401_t * mpu)
{
	unsigned char byte;
	int max = 256, timeout;

	do {
		if (snd_rawmidi_transmit_peek(mpu->substream_output, &byte, 1) == 1) {
			for (timeout = 100; timeout > 0; timeout--) {
				if (snd_mpu401_output_ready(mpu)) {
					mpu->write(mpu, byte, MPU401D(mpu));
					snd_rawmidi_transmit_ack(mpu->substream_output, 1);
					break;
				}
			}
			if (timeout == 0)
				break;	/* Tx FIFO full - try again later */
		} else {
			snd_mpu401_uart_remove_timer (mpu, 0);
			break;	/* no other data - leave the tx loop */
		}
	} while (--max > 0);
}
示例#9
0
文件: midirender.c 项目: bkero/hdjmod
void snd_hdjmidi_output_trigger(snd_rawmidi_substream_t *substream, int up_param)
#endif
{
	struct hdjmidi_out_port* port = (struct hdjmidi_out_port*)substream->runtime->private_data;
	
#ifdef RENDER_DATA_PRINTK
	snd_printk(KERN_INFO"%s(): up:%d\n",__FUNCTION__,up_param);
#endif
	port->active = up_param;
	if (up_param) {
		if (atomic_read(&port->ep->umidi->chip->shutdown)==1) {
			/* gobble up remaining bytes to prevent wait in
			 * snd_rawmidi_drain_output */
			while (!snd_rawmidi_transmit_empty(substream))
				snd_rawmidi_transmit_ack(substream, 1);
			return;
		}
		if (atomic_read(&port->ep->umidi->chip->no_urb_submission)!=0) {
			return;
		}
		tasklet_hi_schedule(&port->ep->tasklet);
	}
}
示例#10
0
/*
 * write output pending bytes
 * call with output_lock spinlock held
 */
static void snd_mpu401_uart_output_write(struct snd_mpu401 * mpu)
{
	unsigned char byte;
	int max = 256;

	do {
		if (snd_rawmidi_transmit_peek(mpu->substream_output,
					      &byte, 1) == 1) {
			/*
			 * Try twice because there is hardware that insists on
			 * setting the output busy bit after each write.
			 */
			if (!snd_mpu401_output_ready(mpu) &&
			    !snd_mpu401_output_ready(mpu))
				break;	/* Tx FIFO full - try again later */
			mpu->write(mpu, byte, MPU401D(mpu));
			snd_rawmidi_transmit_ack(mpu->substream_output, 1);
		} else {
			snd_mpu401_uart_remove_timer (mpu, 0);
			break;	/* no other data - leave the tx loop */
		}
	} while (--max > 0);
}
static void snd_uart16550_output_write(snd_rawmidi_substream_t * substream)
{
	unsigned long flags;
	unsigned char midi_byte, addr_byte;
	snd_uart16550_t *uart = snd_magic_cast(snd_uart16550_t, substream->rmidi->private_data, return);
	char first;
	static unsigned long lasttime=0;
	
	/* Interupts are disabled during the updating of the tx_buff,
	 * since it is 'bad' to have two processes updating the same
	 * variables (ie buff_in & buff_out)
	 */

	spin_lock_irqsave(&uart->open_lock, flags);

	if (uart->irq < 0)	//polling
		snd_uart16550_io_loop(uart);

	if (uart->adaptor == SNDRV_SERIAL_MS124W_MB) {
		while (1) {
			/* buffer full? */
			/* in this mode we need two bytes of space */
			if (uart->buff_in_count > TX_BUFF_SIZE - 2)
				break;
			if (snd_rawmidi_transmit(substream, &midi_byte, 1) != 1)
				break;
#ifdef SNDRV_SERIAL_MS124W_MB_NOCOMBO
			/* select exactly one of the four ports */
			addr_byte = (1 << (substream->number + 4)) | 0x08;
#else
			/* select any combination of the four ports */
			addr_byte = (substream->number << 4) | 0x08;
			/* ...except none */
			if (addr_byte == 0x08) addr_byte = 0xf8;
#endif
			snd_uart16550_output_byte(uart, substream, addr_byte);
			/* send midi byte */
			snd_uart16550_output_byte(uart, substream, midi_byte);
		}
	} else {
		first = 0;
		while( 1 == snd_rawmidi_transmit_peek(substream, &midi_byte, 1) ) {
			/* Also send F5 after 3 seconds with no data to handle device disconnect */
			if (first == 0 && (uart->adaptor == SNDRV_SERIAL_SOUNDCANVAS ||
				uart->adaptor == SNDRV_SERIAL_GENERIC) &&
			   (uart->prev_out != substream->number || jiffies-lasttime > 3*HZ)) {

				if( snd_uart16550_buffer_can_write( uart, 3 ) ) {
					/* Roland Soundcanvas part selection */
					/* If this substream of the data is different previous
					   substream in this uart, send the change part event */
					uart->prev_out = substream->number;
					/* change part */
					snd_uart16550_output_byte(uart, substream, 0xf5);
					/* data */
					snd_uart16550_output_byte(uart, substream, uart->prev_out + 1);
					/* If midi_byte is a data byte, send the previous status byte */
					if ((midi_byte < 0x80) && (uart->adaptor == SNDRV_SERIAL_SOUNDCANVAS))
						snd_uart16550_output_byte(uart, substream, uart->prev_status[uart->prev_out]);
				} else if( !uart->drop_on_full )
					break;

			}

			/* send midi byte */
			if( !snd_uart16550_output_byte(uart, substream, midi_byte) && !uart->drop_on_full )
				break;

			if (midi_byte >= 0x80 && midi_byte < 0xf0)
				uart->prev_status[uart->prev_out] = midi_byte;
			first = 1;

			snd_rawmidi_transmit_ack( substream, 1 );
		}
		lasttime = jiffies;
	}
	spin_unlock_irqrestore(&uart->open_lock, flags);
}