📄 caiaq-midi.c
字号:
/* * Copyright (c) 2006,2007 Daniel Mack * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/#include <linux/init.h>#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/interrupt.h>#include <linux/usb.h>#include <linux/input.h>#include <linux/spinlock.h>#include <sound/driver.h>#include <sound/core.h>#include <sound/rawmidi.h>#include <sound/pcm.h>#include "caiaq-device.h"#include "caiaq-midi.h"static int snd_usb_caiaq_midi_input_open(struct snd_rawmidi_substream *substream){ return 0;}static int snd_usb_caiaq_midi_input_close(struct snd_rawmidi_substream *substream){ return 0;}static void snd_usb_caiaq_midi_input_trigger(struct snd_rawmidi_substream *substream, int up){ struct snd_usb_caiaqdev *dev = substream->rmidi->private_data; if (!dev) return; dev->midi_receive_substream = up ? substream : NULL;}static int snd_usb_caiaq_midi_output_open(struct snd_rawmidi_substream *substream){ return 0;}static int snd_usb_caiaq_midi_output_close(struct snd_rawmidi_substream *substream){ return 0;}static void snd_usb_caiaq_midi_send(struct snd_usb_caiaqdev *dev, struct snd_rawmidi_substream *substream){ int len, ret; dev->midi_out_buf[0] = EP1_CMD_MIDI_WRITE; dev->midi_out_buf[1] = 0; /* port */ len = snd_rawmidi_transmit_peek(substream, dev->midi_out_buf+3, EP1_BUFSIZE-3); if (len <= 0) return; dev->midi_out_buf[2] = len; dev->midi_out_urb.transfer_buffer_length = len+3; ret = usb_submit_urb(&dev->midi_out_urb, GFP_ATOMIC); if (ret < 0) log("snd_usb_caiaq_midi_send(%p): usb_submit_urb() failed, %d\n", substream, ret);}static void snd_usb_caiaq_midi_output_trigger(struct snd_rawmidi_substream *substream, int up){ struct snd_usb_caiaqdev *dev = substream->rmidi->private_data; if (dev->midi_out_substream != NULL) return; if (!up) { dev->midi_out_substream = NULL; return; } dev->midi_out_substream = substream; snd_usb_caiaq_midi_send(dev, substream);}static struct snd_rawmidi_ops snd_usb_caiaq_midi_output ={ .open = snd_usb_caiaq_midi_output_open, .close = snd_usb_caiaq_midi_output_close, .trigger = snd_usb_caiaq_midi_output_trigger,};static struct snd_rawmidi_ops snd_usb_caiaq_midi_input ={ .open = snd_usb_caiaq_midi_input_open, .close = snd_usb_caiaq_midi_input_close, .trigger = snd_usb_caiaq_midi_input_trigger,};void snd_usb_caiaq_midi_handle_input(struct snd_usb_caiaqdev *dev, int port, const char *buf, int len){ if (!dev->midi_receive_substream) return; snd_rawmidi_receive(dev->midi_receive_substream, buf, len);}int __devinit snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *device){ int ret; struct snd_rawmidi *rmidi; ret = snd_rawmidi_new(device->chip.card, device->product_name, 0, device->spec.num_midi_out, device->spec.num_midi_in, &rmidi); if (ret < 0) return ret; strcpy(rmidi->name, device->product_name); rmidi->info_flags = SNDRV_RAWMIDI_INFO_DUPLEX; rmidi->private_data = device; if (device->spec.num_midi_out > 0) { rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT; snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_usb_caiaq_midi_output); } if (device->spec.num_midi_in > 0) { rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT; snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_usb_caiaq_midi_input); } device->rmidi = rmidi; return 0;}void snd_usb_caiaq_midi_output_done(struct urb* urb){ struct snd_usb_caiaqdev *dev = urb->context; char *buf = urb->transfer_buffer; if (urb->status != 0) return; if (!dev->midi_out_substream) return; snd_rawmidi_transmit_ack(dev->midi_out_substream, buf[2]); dev->midi_out_substream = NULL; snd_usb_caiaq_midi_send(dev, dev->midi_out_substream);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -