Ejemplo n.º 1
0
Archivo: lib.c Proyecto: 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);
}
Ejemplo n.º 2
0
Archivo: midi.c Proyecto: 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);
}
Ejemplo n.º 3
0
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);
	}
}
Ejemplo n.º 4
0
Archivo: lib.c Proyecto: 020gzh/linux
static void midi_port_work(struct work_struct *work)
{
	struct snd_fw_async_midi_port *port =
			container_of(work, struct snd_fw_async_midi_port, work);
	struct snd_rawmidi_substream *substream = ACCESS_ONCE(port->substream);
	int generation;
	int type;

	/* Under transacting or error state. */
	if (!port->idling || port->error)
		return;

	/* Nothing to do. */
	if (substream == NULL || snd_rawmidi_transmit_empty(substream))
		return;

	/* Do it in next chance. */
	if (ktime_after(port->next_ktime, ktime_get())) {
		schedule_work(&port->work);
		return;
	}

	/*
	 * Fill the buffer. The callee must use snd_rawmidi_transmit_peek().
	 * Later, snd_rawmidi_transmit_ack() is called.
	 */
	memset(port->buf, 0, port->len);
	port->consume_bytes = port->fill(substream, port->buf);
	if (port->consume_bytes <= 0) {
		/* Do it in next chance, immediately. */
		if (port->consume_bytes == 0) {
			port->next_ktime = ktime_set(0, 0);
			schedule_work(&port->work);
		} else {
			/* Fatal error. */
			port->error = true;
		}
		return;
	}

	/* Calculate type of transaction. */
	if (port->len == 4)
		type = TCODE_WRITE_QUADLET_REQUEST;
	else
		type = TCODE_WRITE_BLOCK_REQUEST;

	/* Set interval to next transaction. */
	port->next_ktime = ktime_add_ns(ktime_get(),
				port->consume_bytes * 8 * NSEC_PER_SEC / 31250);

	/* Start this transaction. */
	port->idling = false;

	/*
	 * In Linux FireWire core, when generation is updated with memory
	 * barrier, node id has already been updated. In this module, After
	 * this smp_rmb(), load/store instructions to memory are completed.
	 * Thus, both of generation and node id are available with recent
	 * values. This is a light-serialization solution to handle bus reset
	 * events on IEEE 1394 bus.
	 */
	generation = port->parent->generation;
	smp_rmb();

	fw_send_request(port->parent->card, &port->transaction, type,
			port->parent->node_id, generation,
			port->parent->max_speed, port->addr,
			port->buf, port->len, async_midi_port_callback,
			port);
}