source: GPL/lib32/soundmidi.c@ 18

Last change on this file since 18 was 18, checked in by vladest, 20 years ago

initial import

File size: 12.6 KB
Line 
1/* $Id: soundmidi.c,v 1.1.1.1 2003/07/02 13:57:02 eleph Exp $ */
2/*
3 * MMPM/2 to OSS interface translation layer
4 *
5 * (C) 2000-2002 InnoTek Systemberatung GmbH
6 * (C) 2000-2001 Sander van Leeuwen (sandervl@xs4all.nl)
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public
19 * License along with this program; if not, write to the Free
20 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
21 * USA.
22 *
23 */
24
25#include <sound/driver.h>
26#include <sound/control.h>
27#include <sound/info.h>
28#include <sound/pcm.h>
29#include <sound/pcm_params.h>
30#include <sound/minors.h>
31#include <sound/asequencer.h>
32#include <sound/seqmid.h>
33#include <linux/file.h>
34#include <linux/soundcard.h>
35
36#define LINUX
37#include <ossidc32.h>
38#include <stacktoflat.h>
39#include <stdlib.h>
40#include "soundoss.h"
41
42int midi_port = 0;
43
44//******************************************************************************
45//******************************************************************************
46OSSRET OSS32_MidiOpen(ULONG deviceid, ULONG streamtype, OSSSTREAMID *pStreamId)
47{
48 midihandle *pHandle;
49 int ret, i;
50 struct sndrv_seq_port_subscribe subs;
51 struct sndrv_seq_client_info clientinfo;
52 struct sndrv_seq_port_info portinfo;
53
54 *pStreamId = 0;
55
56 if(alsa_fops == NULL) {
57 DebugInt3();
58 return OSSERR_NO_DEVICE_AVAILABLE;
59 }
60
61 pHandle = kmalloc(sizeof(midihandle), GFP_KERNEL);
62 if(pHandle == NULL) {
63 DebugInt3();
64 return OSSERR_OUT_OF_MEMORY;
65 }
66 memset(pHandle, 0, sizeof(midihandle));
67
68 //set operation to non-blocking
69 pHandle->file.f_flags = O_NONBLOCK;
70
71 //setup pointers in file structure (used internally by ALSA)
72 pHandle->file.f_dentry = &pHandle->d_entry;
73 pHandle->file.f_dentry->d_inode = &pHandle->inode;
74
75 switch(streamtype) {
76 case OSS32_STREAM_MPU401_MIDIOUT:
77 dprintf(("OSS32_STREAM_MPU401_MIDIOUT"));
78 pHandle->file.f_mode = FMODE_WRITE;
79 pHandle->inode.i_rdev = SNDRV_MINOR(deviceid, SNDRV_MINOR_RAWMIDI);
80 pHandle->inode.i_rdev |= (CONFIG_SND_MAJOR << 8);
81 break;
82 case OSS32_STREAM_MPU401_MIDIIN:
83 dprintf(("OSS32_STREAM_MPU401_MIDIIN"));
84 pHandle->file.f_mode = FMODE_READ;
85 pHandle->inode.i_rdev = SNDRV_MINOR(deviceid, SNDRV_MINOR_RAWMIDI);
86 pHandle->inode.i_rdev |= (CONFIG_SND_MAJOR << 8);
87 break;
88 case OSS32_STREAM_FM_MIDIOUT:
89 dprintf(("OSS32_STREAM_FM_MIDIOUT"));
90 pHandle->file.f_mode = FMODE_WRITE;
91 pHandle->inode.i_rdev = SNDRV_MINOR(deviceid, SNDRV_MINOR_SEQUENCER);
92 break;
93 case OSS32_STREAM_WAVETABLE_MIDIOUT:
94 dprintf(("OSS32_STREAM_WAVETABLE_MIDIOUT: TODO"));
95 pHandle->file.f_mode = FMODE_WRITE;
96 pHandle->inode.i_rdev = SNDRV_MINOR(deviceid, SNDRV_MINOR_SEQUENCER);
97 kfree(pHandle);
98 return OSSERR_INVALID_PARAMETER;
99 break;
100 default:
101 DebugInt3();
102 kfree(pHandle);
103 return OSSERR_INVALID_PARAMETER;
104 }
105#if 1
106
107 ret = alsa_fops->open(&pHandle->inode, &pHandle->file);
108 if(ret) {
109 dprintf(("Midi Open %d failed with error %d", streamtype, ret));
110 kfree(pHandle);
111 return UNIXToOSSError(ret);
112 }
113 pHandle->magic = MAGIC_MIDI_ALSA32;
114 *pStreamId = (ULONG)pHandle;
115
116 pHandle->state |= MIDISTATE_OPENED;
117 printk("Opened MIDI %x\n",(ULONG)pHandle);
118 if(streamtype == OSS32_STREAM_FM_MIDIOUT)
119 {
120 //get the client id
121 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_SEQ_IOCTL_CLIENT_ID, (ULONG)&pHandle->clientid);
122 if(ret) {
123 dprintf(("Get client id failed with error %d", ret));
124 kfree(pHandle);
125 return UNIXToOSSError(ret);
126 }
127
128 //find the FM device
129 for(i=64;i<64+((deviceid+1)<<3);i++)
130 {
131 memset((PVOID)__Stack32ToFlat(&clientinfo), 0, sizeof(clientinfo));
132 clientinfo.client = i;
133 clientinfo.type = KERNEL_CLIENT;
134 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_SEQ_IOCTL_GET_CLIENT_INFO, (ULONG)__Stack32ToFlat(&clientinfo));
135 if(ret) {
136 continue;
137 }
138 if(!strcmp(clientinfo.name, "OPL3 FM synth")) {
139 //found the FM synth device
140 break;
141 }
142 }
143 if(i == 64+((deviceid+1)<<3)) {
144 dprintf(("Couldn't find OPL3 device"));
145 ret = pHandle->file.f_op->release(&pHandle->inode, &pHandle->file);
146 kfree(pHandle);
147 *pStreamId = 0;
148 return OSSERR_NO_DEVICE_AVAILABLE;
149 }
150 pHandle->destclient = i;
151 pHandle->destport = 0;
152
153 //create client port
154 memset(&portinfo, 0, sizeof(portinfo));
155 strcpy(portinfo.name, "Unamed port");
156 portinfo.addr.client = pHandle->clientid;
157 portinfo.flags = SNDRV_SEQ_PORT_TYPE_APPLICATION;
158 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_SEQ_IOCTL_CREATE_PORT, (ULONG)__Stack32ToFlat(&portinfo));
159 if(ret) {
160 dprintf(("subscribe error %d", ret));
161 kfree(pHandle);
162 return UNIXToOSSError(ret);
163 }
164 pHandle->clientport = portinfo.addr.port;
165 pHandle->state |= MIDISTATE_PORTCREATED;
166
167 //subscribe to FM device port
168 memset(&subs, 0, sizeof(subs));
169 subs.dest.client = pHandle->destclient;
170 subs.dest.port = pHandle->destport;
171 subs.sender.client = pHandle->clientid;
172 subs.sender.port = pHandle->clientport;
173 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, (ULONG)__Stack32ToFlat(&subs));
174 if(ret) {
175 dprintf(("subscribe error %d", ret));
176 kfree(pHandle);
177 return UNIXToOSSError(ret);
178 }
179 pHandle->state |= MIDISTATE_SUBSCRIBED;
180
181 //Load FM instruments (only done once)
182 OSS32_FMMidiLoadInstruments((ULONG)pHandle);
183
184 }//if FM
185#endif
186 return OSSERR_SUCCESS;
187}
188//******************************************************************************
189//******************************************************************************
190OSSRET OSS32_MidiClose(OSSSTREAMID streamid)
191{
192 midihandle *pHandle = (midihandle *)streamid;
193 int ret;
194
195 if(pHandle == NULL || pHandle->magic != MAGIC_MIDI_ALSA32) {
196 DebugInt3();
197 return OSSERR_INVALID_STREAMID;
198 }
199 printk("Closing MIDI %x\n",(ULONG)streamid);
200
201 //set operation to non-blocking
202 pHandle->file.f_flags = O_NONBLOCK;
203 //unsubscribe
204 if(pHandle->state & MIDISTATE_SUBSCRIBED) {
205 struct sndrv_seq_port_subscribe subs;
206
207 memset(&subs, 0, sizeof(subs));
208 subs.dest.client = pHandle->destclient;
209 subs.dest.port = pHandle->destport;
210 subs.sender.client = pHandle->clientid;
211 subs.sender.port = pHandle->clientport;
212 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT, (ULONG)__Stack32ToFlat(&subs));
213 if(ret) {
214 dprintf(("unsubscribe error %d", ret));
215 DebugInt3();
216 }
217 }
218
219 //delete port
220 if(pHandle->state & MIDISTATE_SUBSCRIBED) {
221 struct sndrv_seq_port_info portinfo;
222
223 memset(&portinfo, 0, sizeof(portinfo));
224 strcpy(portinfo.name, "Unamed port");
225 portinfo.addr.client = pHandle->clientid;
226 portinfo.addr.port = pHandle->clientport;
227 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_SEQ_IOCTL_DELETE_PORT, (ULONG)__Stack32ToFlat(&portinfo));
228 if(ret) {
229 dprintf(("delete port error %d", ret));
230 DebugInt3();
231 }
232 }
233 //and release device
234 ret = pHandle->file.f_op->release(&pHandle->inode, &pHandle->file);
235 kfree(pHandle); //free handle data
236
237 if(ret) {
238 DebugInt3();
239 return UNIXToOSSError(ret);
240 }
241
242 return OSSERR_SUCCESS;
243}
244//******************************************************************************
245//******************************************************************************
246OSSRET OSS32_MidiWrite(OSSSTREAMID streamid, ULONG midiByte)
247{
248 printk("MIDI write %x\n",(ULONG)streamid);
249 return OSSERR_INVALID_STREAMID;
250}
251//******************************************************************************
252//******************************************************************************
253OSSRET OSS32_MidiRead(OSSSTREAMID streamid, char *buffer, ULONG bufsize, ULONG *pTransferred)
254{
255 midihandle *pHandle = (midihandle *)streamid;
256 int ret;
257
258 if(pHandle == NULL || pHandle->magic != MAGIC_MIDI_ALSA32) {
259 DebugInt3();
260 return OSSERR_INVALID_STREAMID;
261 }
262 //set operation to non-blocking
263 pHandle->file.f_flags = O_NONBLOCK;
264 //and release device
265 ret = pHandle->file.f_op->read(&pHandle->file,(char*)buffer, bufsize, &pHandle->file.f_pos);
266 kfree(pHandle); //free handle data
267 if (ret > 0)
268 {
269 printk("MIDI read %i bytes from %x. first byte is: %x\n",ret, (ULONG)streamid, (char*)buffer[0]);
270 *pTransferred = ret;
271 return OSSERR_SUCCESS;
272 }
273 return UNIXToOSSError(ret);
274}
275//******************************************************************************
276//******************************************************************************
277OSSRET OSS32_MidiQueryCaps(OSSSTREAMID streamid, POSS32_MIDICAPS pCaps)
278{
279 printk("MIDI query caps %x\n",(ULONG)streamid);
280 return OSSERR_INVALID_STREAMID;
281}
282//******************************************************************************
283//******************************************************************************
284OSSRET OSS32_MidiCommand(OSSSTREAMID streamid, ULONG Cmd, BYTE channel, BYTE param1, BYTE param2)
285{
286 midihandle *pHandle = (midihandle *)streamid;
287 int ret;
288 LONG transferred;
289 struct sndrv_seq_event fmevent;
290
291 if(pHandle == NULL || pHandle->magic != MAGIC_MIDI_ALSA32) {
292 DebugInt3();
293 return OSSERR_INVALID_STREAMID;
294 }
295 printk("MIDI command %x\n",(ULONG)streamid);
296
297 //set operation to non-blocking
298 pHandle->file.f_flags = O_NONBLOCK;
299
300 memset((PVOID)__Stack32ToFlat(&fmevent), 0, sizeof(fmevent));
301 switch(Cmd) {
302 case IDC32_MIDI_NOTEON:
303 snd_seq_ev_set_noteon((&fmevent), channel, param1, param2);
304 break;
305 case IDC32_MIDI_NOTEOFF:
306 snd_seq_ev_set_noteoff((&fmevent), channel, param1, param2);
307 break;
308 case IDC32_MIDI_KEY_PRESSURE:
309 snd_seq_ev_set_keypress((&fmevent), channel, param1, param2);
310 break;
311 case IDC32_MIDI_CONTROL_CHANGE:
312 snd_seq_ev_set_controller((&fmevent), channel, param1, param2);
313 break;
314 case IDC32_MIDI_PROGRAM_CHANGE:
315 snd_seq_ev_set_pgmchange((&fmevent), channel, param1);
316 break;
317 case IDC32_MIDI_CHANNEL_PRESSURE:
318 snd_seq_ev_set_chanpress((&fmevent), channel, param1);
319 break;
320 case IDC32_MIDI_PITCH_BEND:
321 snd_seq_ev_set_pitchbend((&fmevent), channel, param1);
322 break;
323 }
324 fmevent.tag = 0;
325 fmevent.queue = SNDRV_SEQ_QUEUE_DIRECT;
326 fmevent.source.client = pHandle->clientid;
327 fmevent.source.port = pHandle->clientport;
328 fmevent.dest.client = pHandle->destclient;
329 fmevent.dest.port = pHandle->destport;
330
331 transferred = pHandle->file.f_op->write(&pHandle->file, (char *)__Stack32ToFlat(&fmevent), sizeof(fmevent), &pHandle->file.f_pos);
332
333 if(transferred < 0) {
334 dprintf(("OSS32_MidiNoteOn failed!!"));
335 DebugInt3();
336 return UNIXToOSSError(transferred);
337 }
338 return OSSERR_SUCCESS;
339}
340//******************************************************************************
341//******************************************************************************
342
Note: See TracBrowser for help on using the repository browser.