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); }
/* 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); }
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); } }
/* 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); } }
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); }
/* 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); }
/* * 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); }
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); } }
/* * 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); }