source: GPL/branches/uniaud32-2.1.x/lib32/soundmidi.c@ 519

Last change on this file since 519 was 519, checked in by David Azarewicz, 15 years ago

Changes to PCI bus scan, malloc, cleanup all warnings, misc other changes

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/core.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 <sound/seq_kernel.h>
34#include <linux/file.h>
35#include <linux/soundcard.h>
36
37#define LINUX
38#include <ossidc32.h>
39#include <stacktoflat.h>
40#include <stdlib.h>
41#include "soundoss.h"
42
43int midi_port = 0;
44
45//******************************************************************************
46//******************************************************************************
47OSSRET OSS32_MidiOpen(ULONG deviceid, ULONG streamtype, OSSSTREAMID *pStreamId)
48{
49 midihandle *pHandle;
50 int ret, i;
51 struct snd_seq_port_subscribe subs;
52 struct snd_seq_client_info clientinfo;
53 struct snd_seq_port_info portinfo;
54
55 *pStreamId = 0;
56
57 if(alsa_fops == NULL) {
58 DebugInt3();
59 return OSSERR_NO_DEVICE_AVAILABLE;
60 }
61
62 pHandle = kmalloc(sizeof(midihandle), GFP_KERNEL);
63 if(pHandle == NULL) {
64 DebugInt3();
65 return OSSERR_OUT_OF_MEMORY;
66 }
67 memset(pHandle, 0, sizeof(midihandle));
68
69 //set operation to non-blocking
70 pHandle->file.f_flags = O_NONBLOCK;
71
72 //setup pointers in file structure (used internally by ALSA)
73 pHandle->file.f_dentry = &pHandle->d_entry;
74 pHandle->file.f_dentry->d_inode = &pHandle->inode;
75
76 switch(streamtype) {
77 case OSS32_STREAM_MPU401_MIDIOUT:
78 dprintf(("OSS32_STREAM_MPU401_MIDIOUT"));
79 pHandle->file.f_mode = FMODE_WRITE;
80 pHandle->inode.i_rdev = SNDRV_MINOR(deviceid, SNDRV_MINOR_RAWMIDI);
81 pHandle->inode.i_rdev |= (CONFIG_SND_MAJOR << 8);
82 break;
83 case OSS32_STREAM_MPU401_MIDIIN:
84 dprintf(("OSS32_STREAM_MPU401_MIDIIN"));
85 pHandle->file.f_mode = FMODE_READ;
86 pHandle->inode.i_rdev = SNDRV_MINOR(deviceid, SNDRV_MINOR_RAWMIDI);
87 pHandle->inode.i_rdev |= (CONFIG_SND_MAJOR << 8);
88 break;
89 case OSS32_STREAM_FM_MIDIOUT:
90 dprintf(("OSS32_STREAM_FM_MIDIOUT"));
91 pHandle->file.f_mode = FMODE_WRITE;
92 pHandle->inode.i_rdev = SNDRV_MINOR(deviceid, SNDRV_MINOR_SEQUENCER);
93 break;
94 case OSS32_STREAM_WAVETABLE_MIDIOUT:
95 dprintf(("OSS32_STREAM_WAVETABLE_MIDIOUT: TODO"));
96 pHandle->file.f_mode = FMODE_WRITE;
97 pHandle->inode.i_rdev = SNDRV_MINOR(deviceid, SNDRV_MINOR_SEQUENCER);
98 kfree(pHandle);
99 return OSSERR_INVALID_PARAMETER;
100 break;
101 default:
102 DebugInt3();
103 kfree(pHandle);
104 return OSSERR_INVALID_PARAMETER;
105 }
106#if 1
107
108 ret = alsa_fops->open(&pHandle->inode, &pHandle->file);
109 if(ret) {
110 rprintf(("Midi Open %d failed with error %d", streamtype, ret));
111 kfree(pHandle);
112 return UNIXToOSSError(ret);
113 }
114 pHandle->magic = MAGIC_MIDI_ALSA32;
115 *pStreamId = (ULONG)pHandle;
116
117 pHandle->state |= MIDISTATE_OPENED;
118 dprintf(("Opened MIDI %x\n",(ULONG)pHandle));
119 if(streamtype == OSS32_STREAM_FM_MIDIOUT)
120 {
121 //get the client id
122 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_SEQ_IOCTL_CLIENT_ID, (ULONG)&pHandle->clientid);
123 if(ret) {
124 rprintf(("Get client id failed with error %d", ret));
125 kfree(pHandle);
126 return UNIXToOSSError(ret);
127 }
128
129 //find the FM device
130 for(i=64;i<64+((deviceid+1)<<3);i++)
131 {
132 memset((PVOID)__Stack32ToFlat(&clientinfo), 0, sizeof(clientinfo));
133 clientinfo.client = i;
134 clientinfo.type = KERNEL_CLIENT;
135 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_SEQ_IOCTL_GET_CLIENT_INFO, (ULONG)__Stack32ToFlat(&clientinfo));
136 if(ret) {
137 continue;
138 }
139 if(!strcmp(clientinfo.name, "OPL3 FM synth")) {
140 //found the FM synth device
141 break;
142 }
143 }
144 if(i == 64+((deviceid+1)<<3)) {
145 rprintf(("Couldn't find OPL3 device"));
146 ret = pHandle->file.f_op->release(&pHandle->inode, &pHandle->file);
147 kfree(pHandle);
148 *pStreamId = 0;
149 return OSSERR_NO_DEVICE_AVAILABLE;
150 }
151 pHandle->destclient = i;
152 pHandle->destport = 0;
153
154 //create client port
155 memset(&portinfo, 0, sizeof(portinfo));
156 strcpy(portinfo.name, "Unamed port");
157 portinfo.addr.client = pHandle->clientid;
158 portinfo.flags = SNDRV_SEQ_PORT_TYPE_APPLICATION;
159 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_SEQ_IOCTL_CREATE_PORT, (ULONG)__Stack32ToFlat(&portinfo));
160 if(ret) {
161 rprintf(("subscribe error %d", ret));
162 kfree(pHandle);
163 return UNIXToOSSError(ret);
164 }
165 pHandle->clientport = portinfo.addr.port;
166 pHandle->state |= MIDISTATE_PORTCREATED;
167
168 //subscribe to FM device port
169 memset(&subs, 0, sizeof(subs));
170 subs.dest.client = pHandle->destclient;
171 subs.dest.port = pHandle->destport;
172 subs.sender.client = pHandle->clientid;
173 subs.sender.port = pHandle->clientport;
174 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, (ULONG)__Stack32ToFlat(&subs));
175 if(ret) {
176 rprintf(("subscribe error %d", ret));
177 kfree(pHandle);
178 return UNIXToOSSError(ret);
179 }
180 pHandle->state |= MIDISTATE_SUBSCRIBED;
181
182#if 0
183 //Load FM instruments (only done once)
184 OSS32_FMMidiLoadInstruments((ULONG)pHandle);
185#endif
186
187 }//if FM
188#endif
189 return OSSERR_SUCCESS;
190}
191//******************************************************************************
192//******************************************************************************
193OSSRET OSS32_MidiClose(OSSSTREAMID streamid)
194{
195 midihandle *pHandle = (midihandle *)streamid;
196 int ret;
197
198 if(pHandle == NULL || pHandle->magic != MAGIC_MIDI_ALSA32) {
199 DebugInt3();
200 return OSSERR_INVALID_STREAMID;
201 }
202 dprintf(("Closing MIDI %x\n",(ULONG)streamid));
203
204 //set operation to non-blocking
205 pHandle->file.f_flags = O_NONBLOCK;
206 //unsubscribe
207 if(pHandle->state & MIDISTATE_SUBSCRIBED) {
208 struct snd_seq_port_subscribe subs;
209 memset(&subs, 0, sizeof(subs));
210 subs.dest.client = pHandle->destclient;
211 subs.dest.port = pHandle->destport;
212 subs.sender.client = pHandle->clientid;
213 subs.sender.port = pHandle->clientport;
214 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT, (ULONG)__Stack32ToFlat(&subs));
215 if(ret) {
216 rprintf(("unsubscribe error %d", ret));
217 DebugInt3();
218 }
219 }
220
221 //delete port
222 if(pHandle->state & MIDISTATE_SUBSCRIBED) {
223 struct snd_seq_port_info portinfo;
224
225 memset(&portinfo, 0, sizeof(portinfo));
226 strcpy(portinfo.name, "Unamed port");
227 portinfo.addr.client = pHandle->clientid;
228 portinfo.addr.port = pHandle->clientport;
229 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_SEQ_IOCTL_DELETE_PORT, (ULONG)__Stack32ToFlat(&portinfo));
230 if(ret) {
231 dprintf(("delete port error %d", ret));
232 DebugInt3();
233 }
234 }
235 //and release device
236 ret = pHandle->file.f_op->release(&pHandle->inode, &pHandle->file);
237 kfree(pHandle); //free handle data
238
239 if(ret) {
240 DebugInt3();
241 return UNIXToOSSError(ret);
242 }
243
244 return OSSERR_SUCCESS;
245}
246//******************************************************************************
247//******************************************************************************
248OSSRET OSS32_MidiWrite(OSSSTREAMID streamid, ULONG midiByte)
249{
250 dprintf(("MIDI write %x\n",(ULONG)streamid));
251 return OSSERR_INVALID_STREAMID;
252}
253//******************************************************************************
254//******************************************************************************
255OSSRET OSS32_MidiRead(OSSSTREAMID streamid, char *buffer, ULONG bufsize, ULONG *pTransferred)
256{
257 midihandle *pHandle = (midihandle *)streamid;
258 int ret;
259
260 if(pHandle == NULL || pHandle->magic != MAGIC_MIDI_ALSA32) {
261 DebugInt3();
262 return OSSERR_INVALID_STREAMID;
263 }
264 //set operation to non-blocking
265 pHandle->file.f_flags = O_NONBLOCK;
266 //and release device
267 ret = pHandle->file.f_op->read(&pHandle->file,(char*)buffer, bufsize, &pHandle->file.f_pos);
268 kfree(pHandle); //free handle data
269 if (ret > 0)
270 {
271 dprintf(("MIDI read %i bytes from %x. first byte is: %x\n",ret, (ULONG)streamid, (char*)buffer[0]));
272 *pTransferred = ret;
273 return OSSERR_SUCCESS;
274 }
275 return UNIXToOSSError(ret);
276}
277//******************************************************************************
278//******************************************************************************
279OSSRET OSS32_MidiQueryCaps(OSSSTREAMID streamid, POSS32_MIDICAPS pCaps)
280{
281 dprintf(("MIDI query caps %x\n",(ULONG)streamid));
282 return OSSERR_INVALID_STREAMID;
283}
284//******************************************************************************
285//******************************************************************************
286OSSRET OSS32_MidiCommand(OSSSTREAMID streamid, ULONG Cmd, BYTE channel, BYTE param1, BYTE param2)
287{
288 midihandle *pHandle = (midihandle *)streamid;
289 int ret;
290 LONG transferred;
291 struct snd_seq_event fmevent;
292
293 if(pHandle == NULL || pHandle->magic != MAGIC_MIDI_ALSA32) {
294 DebugInt3();
295 return OSSERR_INVALID_STREAMID;
296 }
297 dprintf(("MIDI command %x\n",(ULONG)streamid));
298
299 //set operation to non-blocking
300 pHandle->file.f_flags = O_NONBLOCK;
301
302 memset((PVOID)__Stack32ToFlat(&fmevent), 0, sizeof(fmevent));
303 switch(Cmd) {
304 case IDC32_MIDI_NOTEON:
305 snd_seq_ev_set_noteon((&fmevent), channel, param1, param2);
306 break;
307 case IDC32_MIDI_NOTEOFF:
308 snd_seq_ev_set_noteoff((&fmevent), channel, param1, param2);
309 break;
310 case IDC32_MIDI_KEY_PRESSURE:
311 snd_seq_ev_set_keypress((&fmevent), channel, param1, param2);
312 break;
313 case IDC32_MIDI_CONTROL_CHANGE:
314 snd_seq_ev_set_controller((&fmevent), channel, param1, param2);
315 break;
316 case IDC32_MIDI_PROGRAM_CHANGE:
317 snd_seq_ev_set_pgmchange((&fmevent), channel, param1);
318 break;
319 case IDC32_MIDI_CHANNEL_PRESSURE:
320 snd_seq_ev_set_chanpress((&fmevent), channel, param1);
321 break;
322 case IDC32_MIDI_PITCH_BEND:
323 snd_seq_ev_set_pitchbend((&fmevent), channel, param1);
324 break;
325 }
326 fmevent.tag = 0;
327 fmevent.queue = SNDRV_SEQ_QUEUE_DIRECT;
328 fmevent.source.client = pHandle->clientid;
329 fmevent.source.port = pHandle->clientport;
330 fmevent.dest.client = pHandle->destclient;
331 fmevent.dest.port = pHandle->destport;
332
333 transferred = pHandle->file.f_op->write(&pHandle->file, (char *)__Stack32ToFlat(&fmevent), sizeof(fmevent), &pHandle->file.f_pos);
334
335 if(transferred < 0) {
336 rprintf(("OSS32_MidiNoteOn failed!!"));
337 DebugInt3();
338 return UNIXToOSSError(transferred);
339 }
340 return OSSERR_SUCCESS;
341}
342//******************************************************************************
343//******************************************************************************
344
Note: See TracBrowser for help on using the repository browser.