~ubuntu-branches/ubuntu/saucy/linux-n900/saucy

« back to all changes in this revision

Viewing changes to sound/usb/caiaq/midi.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathieu Poirier
  • Date: 2011-02-18 09:43:31 UTC
  • Revision ID: james.westby@ubuntu.com-20110218094331-eyubsja4f9k0yhmq
Tags: 2.6.35-1.1
Initial release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *   Copyright (c) 2006,2007 Daniel Mack
 
3
 *
 
4
 *   This program is free software; you can redistribute it and/or modify
 
5
 *   it under the terms of the GNU General Public License as published by
 
6
 *   the Free Software Foundation; either version 2 of the License, or
 
7
 *   (at your option) any later version.
 
8
 *
 
9
 *   This program is distributed in the hope that it will be useful,
 
10
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 *   GNU General Public License for more details.
 
13
 *
 
14
 *   You should have received a copy of the GNU General Public License
 
15
 *   along with this program; if not, write to the Free Software
 
16
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 
17
*/
 
18
 
 
19
#include <linux/usb.h>
 
20
#include <linux/gfp.h>
 
21
#include <sound/rawmidi.h>
 
22
#include <sound/core.h>
 
23
#include <sound/pcm.h>
 
24
 
 
25
#include "device.h"
 
26
#include "midi.h"
 
27
 
 
28
static int snd_usb_caiaq_midi_input_open(struct snd_rawmidi_substream *substream)
 
29
{
 
30
        return 0;
 
31
}
 
32
 
 
33
static int snd_usb_caiaq_midi_input_close(struct snd_rawmidi_substream *substream)
 
34
{
 
35
        return 0;
 
36
}
 
37
 
 
38
static void snd_usb_caiaq_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
 
39
{
 
40
        struct snd_usb_caiaqdev *dev = substream->rmidi->private_data;
 
41
 
 
42
        if (!dev)
 
43
                return;
 
44
 
 
45
        dev->midi_receive_substream = up ? substream : NULL;
 
46
}
 
47
 
 
48
 
 
49
static int snd_usb_caiaq_midi_output_open(struct snd_rawmidi_substream *substream)
 
50
{
 
51
        return 0;
 
52
}
 
53
 
 
54
static int snd_usb_caiaq_midi_output_close(struct snd_rawmidi_substream *substream)
 
55
{
 
56
        struct snd_usb_caiaqdev *dev = substream->rmidi->private_data;
 
57
        if (dev->midi_out_active) {
 
58
                usb_kill_urb(&dev->midi_out_urb);
 
59
                dev->midi_out_active = 0;
 
60
        }
 
61
        return 0;
 
62
}
 
63
 
 
64
static void snd_usb_caiaq_midi_send(struct snd_usb_caiaqdev *dev,
 
65
                                    struct snd_rawmidi_substream *substream)
 
66
{
 
67
        int len, ret;
 
68
 
 
69
        dev->midi_out_buf[0] = EP1_CMD_MIDI_WRITE;
 
70
        dev->midi_out_buf[1] = 0; /* port */
 
71
        len = snd_rawmidi_transmit(substream, dev->midi_out_buf + 3,
 
72
                                   EP1_BUFSIZE - 3);
 
73
 
 
74
        if (len <= 0)
 
75
                return;
 
76
 
 
77
        dev->midi_out_buf[2] = len;
 
78
        dev->midi_out_urb.transfer_buffer_length = len+3;
 
79
 
 
80
        ret = usb_submit_urb(&dev->midi_out_urb, GFP_ATOMIC);
 
81
        if (ret < 0)
 
82
                log("snd_usb_caiaq_midi_send(%p): usb_submit_urb() failed,"
 
83
                    "ret=%d, len=%d\n",
 
84
                    substream, ret, len);
 
85
        else
 
86
                dev->midi_out_active = 1;
 
87
}
 
88
 
 
89
static void snd_usb_caiaq_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
 
90
{
 
91
        struct snd_usb_caiaqdev *dev = substream->rmidi->private_data;
 
92
 
 
93
        if (up) {
 
94
                dev->midi_out_substream = substream;
 
95
                if (!dev->midi_out_active)
 
96
                        snd_usb_caiaq_midi_send(dev, substream);
 
97
        } else {
 
98
                dev->midi_out_substream = NULL;
 
99
        }
 
100
}
 
101
 
 
102
 
 
103
static struct snd_rawmidi_ops snd_usb_caiaq_midi_output =
 
104
{
 
105
        .open =         snd_usb_caiaq_midi_output_open,
 
106
        .close =        snd_usb_caiaq_midi_output_close,
 
107
        .trigger =      snd_usb_caiaq_midi_output_trigger,
 
108
};
 
109
 
 
110
static struct snd_rawmidi_ops snd_usb_caiaq_midi_input =
 
111
{
 
112
        .open =         snd_usb_caiaq_midi_input_open,
 
113
        .close =        snd_usb_caiaq_midi_input_close,
 
114
        .trigger =      snd_usb_caiaq_midi_input_trigger,
 
115
};
 
116
 
 
117
void snd_usb_caiaq_midi_handle_input(struct snd_usb_caiaqdev *dev,
 
118
                                     int port, const char *buf, int len)
 
119
{
 
120
        if (!dev->midi_receive_substream)
 
121
                return;
 
122
 
 
123
        snd_rawmidi_receive(dev->midi_receive_substream, buf, len);
 
124
}
 
125
 
 
126
int snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *device)
 
127
{
 
128
        int ret;
 
129
        struct snd_rawmidi *rmidi;
 
130
 
 
131
        ret = snd_rawmidi_new(device->chip.card, device->product_name, 0,
 
132
                                        device->spec.num_midi_out,
 
133
                                        device->spec.num_midi_in,
 
134
                                        &rmidi);
 
135
 
 
136
        if (ret < 0)
 
137
                return ret;
 
138
 
 
139
        strcpy(rmidi->name, device->product_name);
 
140
 
 
141
        rmidi->info_flags = SNDRV_RAWMIDI_INFO_DUPLEX;
 
142
        rmidi->private_data = device;
 
143
 
 
144
        if (device->spec.num_midi_out > 0) {
 
145
                rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
 
146
                snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
 
147
                                    &snd_usb_caiaq_midi_output);
 
148
        }
 
149
 
 
150
        if (device->spec.num_midi_in > 0) {
 
151
                rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
 
152
                snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
 
153
                                    &snd_usb_caiaq_midi_input);
 
154
        }
 
155
 
 
156
        device->rmidi = rmidi;
 
157
 
 
158
        return 0;
 
159
}
 
160
 
 
161
void snd_usb_caiaq_midi_output_done(struct urb* urb)
 
162
{
 
163
        struct snd_usb_caiaqdev *dev = urb->context;
 
164
 
 
165
        dev->midi_out_active = 0;
 
166
        if (urb->status != 0)
 
167
                return;
 
168
 
 
169
        if (!dev->midi_out_substream)
 
170
                return;
 
171
 
 
172
        snd_usb_caiaq_midi_send(dev, dev->midi_out_substream);
 
173
}
 
174