static void ca_midi_interrupt(struct snd_ca_midi *midi, unsigned int status) { unsigned char byte; if (midi->rmidi == NULL) { midi->interrupt_disable(midi,midi->tx_enable | midi->rx_enable); return; } spin_lock(&midi->input_lock); if ((status & midi->ipr_rx) && ca_midi_input_avail(midi)) { if (!(midi->midi_mode & CA_MIDI_MODE_INPUT)) { ca_midi_clear_rx(midi); } else { byte = ca_midi_read_data(midi); if(midi->substream_input) snd_rawmidi_receive(midi->substream_input, &byte, 1); } } spin_unlock(&midi->input_lock); spin_lock(&midi->output_lock); if ((status & midi->ipr_tx) && ca_midi_output_ready(midi)) { if (midi->substream_output && snd_rawmidi_transmit(midi->substream_output, &byte, 1) == 1) { ca_midi_write_data(midi, byte); } else { midi->interrupt_disable(midi,midi->tx_enable); } } spin_unlock(&midi->output_lock); }
static void do_emu10k1_midi_interrupt(struct snd_emu10k1 *emu, struct snd_emu10k1_midi *midi, unsigned int status) { unsigned char byte; if (midi->rmidi == NULL) { snd_emu10k1_intr_disable(emu, midi->tx_enable | midi->rx_enable); return; } spin_lock(&midi->input_lock); if ((status & midi->ipr_rx) && mpu401_input_avail(emu, midi)) { if (!(midi->midi_mode & EMU10K1_MIDI_MODE_INPUT)) { mpu401_clear_rx(emu, midi); } else { byte = mpu401_read_data(emu, midi); if (midi->substream_input) snd_rawmidi_receive(midi->substream_input, &byte, 1); } } spin_unlock(&midi->input_lock); spin_lock(&midi->output_lock); if ((status & midi->ipr_tx) && mpu401_output_ready(emu, midi)) { if (midi->substream_output && snd_rawmidi_transmit(midi->substream_output, &byte, 1) == 1) { mpu401_write_data(emu, midi, byte); } else { snd_emu10k1_intr_disable(emu, midi->tx_enable); } } spin_unlock(&midi->output_lock); }
static void write_midi_messages(struct amdtp_stream *s, __be32 *buffer, unsigned int frames) { struct amdtp_am824 *p = s->protocol; unsigned int f, port; u8 *b; for (f = 0; f < frames; f++) { b = (u8 *)&buffer[p->midi_position]; port = (s->data_block_counter + f) % 8; if (f < MAX_MIDI_RX_BLOCKS && midi_ratelimit_per_packet(s, port) && p->midi[port] != NULL && snd_rawmidi_transmit(p->midi[port], &b[1], 1) == 1) { midi_rate_use_one_byte(s, port); b[0] = 0x81; } else { b[0] = 0x80; b[1] = 0; } b[2] = 0; b[3] = 0; buffer += s->data_block_quadlets; } }
static void snd_emu10k1_midi_output_trigger(snd_rawmidi_substream_t * substream, int up) { emu10k1_t *emu; emu10k1_midi_t *midi = (emu10k1_midi_t *)substream->rmidi->private_data; unsigned long flags; emu = midi->emu; snd_assert(emu, return); if (up) { int max = 4; unsigned char byte; /* try to send some amount of bytes here before interrupts */ spin_lock_irqsave(&midi->output_lock, flags); while (max > 0) { if (mpu401_output_ready(emu, midi)) { if (!(midi->midi_mode & EMU10K1_MIDI_MODE_OUTPUT) || snd_rawmidi_transmit(substream, &byte, 1) != 1) { /* no more data */ spin_unlock_irqrestore(&midi->output_lock, flags); return; } mpu401_write_data(emu, midi, byte); max--; } else { break; } } spin_unlock_irqrestore(&midi->output_lock, flags); snd_emu10k1_intr_enable(emu, midi->tx_enable); } else { snd_emu10k1_intr_disable(emu, midi->tx_enable); } }
static void usb6fire_midi_out_trigger( struct snd_rawmidi_substream *alsa_sub, int up) { struct midi_runtime *rt = alsa_sub->rmidi->private_data; struct urb *urb = &rt->out_urb; __s8 ret; unsigned long flags; spin_lock_irqsave(&rt->out_lock, flags); if (up) { /* start transfer */ if (rt->out) { /* we are already transmitting so just return */ spin_unlock_irqrestore(&rt->out_lock, flags); return; } ret = snd_rawmidi_transmit(alsa_sub, rt->out_buffer + 4, MIDI_BUFSIZE - 4); if (ret > 0) { rt->out_buffer[1] = ret + 2; rt->out_buffer[3] = rt->out_serial++; urb->transfer_buffer_length = ret + 4; ret = usb_submit_urb(urb, GFP_ATOMIC); if (ret < 0) // snd_printk(KERN_ERR PREFIX "midi out urb " ; else rt->out = alsa_sub; } } else if (rt->out == alsa_sub) rt->out = NULL; spin_unlock_irqrestore(&rt->out_lock, flags); }
static void usb6fire_midi_out_handler(struct urb *urb) { struct midi_runtime *rt = urb->context; int ret; unsigned long flags; spin_lock_irqsave(&rt->out_lock, flags); if (rt->out) { ret = snd_rawmidi_transmit(rt->out, rt->out_buffer + 4, MIDI_BUFSIZE - 4); if (ret > 0) { /* more data available, send next packet */ rt->out_buffer[1] = ret + 2; rt->out_buffer[3] = rt->out_serial++; urb->transfer_buffer_length = ret + 4; ret = usb_submit_urb(urb, GFP_ATOMIC); if (ret < 0) // snd_printk(KERN_ERR PREFIX "midi out urb " ; } else /* no more data to transmit */ rt->out = NULL; } spin_unlock_irqrestore(&rt->out_lock, flags); }
static void snd_usb_caiaq_midi_send(struct snd_usb_caiaqdev *cdev, struct snd_rawmidi_substream *substream) { int len, ret; struct device *dev = caiaqdev_to_dev(cdev); cdev->midi_out_buf[0] = EP1_CMD_MIDI_WRITE; cdev->midi_out_buf[1] = 0; /* port */ len = snd_rawmidi_transmit(substream, cdev->midi_out_buf + 3, EP1_BUFSIZE - 3); if (len <= 0) return; cdev->midi_out_buf[2] = len; cdev->midi_out_urb.transfer_buffer_length = len+3; ret = usb_submit_urb(&cdev->midi_out_urb, GFP_ATOMIC); if (ret < 0) dev_err(dev, "snd_usb_caiaq_midi_send(%p): usb_submit_urb() failed," "ret=%d, len=%d\n", substream, ret, len); else cdev->midi_out_active = 1; }
static void bcd2000_midi_send(struct bcd2000 *bcd2k) { int len, ret; struct snd_rawmidi_substream *midi_out_substream; BUILD_BUG_ON(sizeof(device_cmd_prefix) >= BUFSIZE); midi_out_substream = ACCESS_ONCE(bcd2k->midi_out_substream); if (!midi_out_substream) return; /* copy command prefix bytes */ memcpy(bcd2k->midi_out_buf, device_cmd_prefix, sizeof(device_cmd_prefix)); /* * get MIDI packet and leave space for command prefix * and payload length */ len = snd_rawmidi_transmit(midi_out_substream, bcd2k->midi_out_buf + 3, BUFSIZE - 3); if (len < 0) dev_err(&bcd2k->dev->dev, "%s: snd_rawmidi_transmit error %d\n", __func__, len); if (len <= 0) return; /* set payload length */ bcd2k->midi_out_buf[2] = len; bcd2k->midi_out_urb->transfer_buffer_length = BUFSIZE; bcd2000_dump_buffer(PREFIX "sending to device: ", bcd2k->midi_out_buf, len+3); /* send packet to the BCD2000 */ ret = usb_submit_urb(bcd2k->midi_out_urb, GFP_ATOMIC); if (ret < 0) dev_err(&bcd2k->dev->dev, PREFIX "%s (%p): usb_submit_urb() failed, ret=%d, len=%d\n", __func__, midi_out_substream, ret, len); else bcd2k->midi_out_active = 1; }
static void snd_gf1_interrupt_midi_out(snd_gus_card_t * gus) { char byte; unsigned long flags; /* try unlock output */ if (snd_gf1_uart_stat(gus) & 0x01) snd_gf1_interrupt_midi_in(gus); spin_lock_irqsave(&gus->uart_cmd_lock, flags); if (snd_gf1_uart_stat(gus) & 0x02) { /* Tx FIFO free? */ if (snd_rawmidi_transmit(gus->midi_substream_output, &byte, 1) != 1) { /* no other bytes or error */ snd_gf1_uart_cmd(gus, gus->gf1.uart_cmd & ~0x20); /* disable Tx interrupt */ } else { snd_gf1_uart_put(gus, byte); } } spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); }
/* call this with spin lock held */ static void snd_mtpav_output_port_write(mtpav_port_t *port, snd_rawmidi_substream_t *substream) { u8 outbyte; // send port change command if necessary if (port->hwport != mtp_card->outmidihwport) { mtp_card->outmidihwport = port->hwport; snd_mtpav_send_byte(mtp_card, 0xf5); snd_mtpav_send_byte(mtp_card, port->hwport); //snd_printk("new outport: 0x%x\n", (unsigned int) port->hwport); } // send data while (snd_rawmidi_transmit(substream, &outbyte, 1) == 1) snd_mtpav_send_byte(mtp_card, outbyte); }
static void snd_gf1_uart_output_trigger(snd_rawmidi_substream_t * substream, int up) { unsigned long flags; snd_gus_card_t *gus; char byte; int timeout; gus = snd_magic_cast(snd_gus_card_t, substream->rmidi->private_data, return); spin_lock_irqsave(&gus->uart_cmd_lock, flags); if (up) { if ((gus->gf1.uart_cmd & 0x20) == 0) { spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); /* wait for empty Rx - Tx is probably unlocked */ timeout = 10000; while (timeout-- > 0 && snd_gf1_uart_stat(gus) & 0x01); /* Tx FIFO free? */ spin_lock_irqsave(&gus->uart_cmd_lock, flags); if (gus->gf1.uart_cmd & 0x20) { spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); return; } if (snd_gf1_uart_stat(gus) & 0x02) { if (snd_rawmidi_transmit(substream, &byte, 1) != 1) { spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); return; } snd_gf1_uart_put(gus, byte); } snd_gf1_uart_cmd(gus, gus->gf1.uart_cmd | 0x20); /* enable Tx interrupt */ } } else { if (gus->gf1.uart_cmd & 0x20) snd_gf1_uart_cmd(gus, gus->gf1.uart_cmd & ~0x20); } spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); }
static void ca_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) { struct snd_ca_midi *midi = substream->rmidi->private_data; unsigned long flags; if (snd_BUG_ON(!midi->dev_id)) return; if (up) { int max = 4; unsigned char byte; spin_lock_irqsave(&midi->output_lock, flags); /* try to send some amount of bytes here before interrupts */ while (max > 0) { if (ca_midi_output_ready(midi)) { if (!(midi->midi_mode & CA_MIDI_MODE_OUTPUT) || snd_rawmidi_transmit(substream, &byte, 1) != 1) { /* no more data */ spin_unlock_irqrestore(&midi->output_lock, flags); return; } ca_midi_write_data(midi, byte); max--; } else { break; } } spin_unlock_irqrestore(&midi->output_lock, flags); midi->interrupt_enable(midi,midi->tx_enable); } else { midi->interrupt_disable(midi,midi->tx_enable); } }
void snd_hdjmidi_standard_output(struct snd_hdjmidi_out_endpoint* ep) { struct urb* urb = ep->urb; int p; /* Note: Hercules DJ products only have one output port thus far, so this is not urgent. * The only exception is the DJ Console "Mac Ed.", which is USBMIDI, and so is managed by * system modules and not us. */ /* FIXME: lower-numbered ports can starve higher-numbered ports */ for (p = 0; p < 0x10; ++p) { struct hdjmidi_out_port* port = &ep->ports[p]; if (!port->active) continue; while (urb->transfer_buffer_length + 3 < ep->max_transfer) { uint8_t b; if (snd_rawmidi_transmit(port->substream, &b, 1) != 1) { port->active = 0; break; } snd_hdjmidi_transmit_byte(port, b, urb, ep); } } }
static void snd_emu10k1_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) { struct snd_emu10k1 *emu; struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data; unsigned long flags; emu = midi->emu; if (snd_BUG_ON(!emu)) return; if (up) { int max = 4; unsigned char byte; /* */ spin_lock_irqsave(&midi->output_lock, flags); while (max > 0) { if (mpu401_output_ready(emu, midi)) { if (!(midi->midi_mode & EMU10K1_MIDI_MODE_OUTPUT) || snd_rawmidi_transmit(substream, &byte, 1) != 1) { /* */ spin_unlock_irqrestore(&midi->output_lock, flags); return; } mpu401_write_data(emu, midi, byte); max--; } else { break; } } spin_unlock_irqrestore(&midi->output_lock, flags); snd_emu10k1_intr_enable(emu, midi->tx_enable); } else { snd_emu10k1_intr_disable(emu, midi->tx_enable); } }
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; /* 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; #if 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) { /* buffer full? */ if (uart->buff_in_count >= TX_BUFF_SIZE) break; if (snd_rawmidi_transmit(substream, &midi_byte, 1) != 1) break; if (first == 0 && uart->adaptor == SNDRV_SERIAL_SOUNDCANVAS && uart->prev_out != substream->number) { /* 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) snd_uart16550_output_byte(uart, substream, uart->prev_status[uart->prev_out]); } /* send midi byte */ snd_uart16550_output_byte(uart, substream, midi_byte); if (midi_byte >= 0x80 && midi_byte < 0xf0) uart->prev_status[uart->prev_out] = midi_byte; first = 1; } } spin_unlock_irqrestore(&uart->open_lock, flags); }