source: sbliveos2/trunk/lib32/sound.c@ 143

Last change on this file since 143 was 142, checked in by ktk, 25 years ago

Import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.3 KB
Line 
1/* $Id: sound.c 142 2000-04-23 14:55:46Z ktk $ */
2
3//******************************************************************************
4// MMPM/2 to OSS interface translation layer
5//
6// Copyright 2000 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//Note: Opening and closing the mixer device for each mixer command might
25// not be a good idea if the SB Live code changes. (right now it hardly
26// matters)
27#include "hwaccess.h"
28#include <linux/init.h>
29#include <linux/poll.h>
30#include <asm/uaccess.h>
31#include <asm/hardirq.h>
32
33#define LINUX
34#include <ossidc.h>
35#include <stacktoflat.h>
36
37struct file_operations oss_devices[OSS_MAX_DEVICES] = {0};
38
39//******************************************************************************
40//******************************************************************************
41int register_sound_special(struct file_operations *fops, int unit)
42{
43 memcpy(&oss_devices[OSS_SPECIALID], fops, sizeof(struct file_operations));
44 return OSS_SPECIALID;
45}
46//******************************************************************************
47//******************************************************************************
48int register_sound_mixer(struct file_operations *fops, int dev)
49{
50 memcpy(&oss_devices[OSS_MIXERID], fops, sizeof(struct file_operations));
51 return OSS_MIXERID;
52}
53//******************************************************************************
54//******************************************************************************
55int register_sound_midi(struct file_operations *fops, int dev)
56{
57 memcpy(&oss_devices[OSS_MIDIID], fops, sizeof(struct file_operations));
58 return OSS_MIDIID;
59}
60//******************************************************************************
61//******************************************************************************
62int register_sound_dsp(struct file_operations *fops, int dev)
63{
64 memcpy(&oss_devices[OSS_DSPID], fops, sizeof(struct file_operations));
65 return OSS_DSPID;
66}
67//******************************************************************************
68//******************************************************************************
69int register_sound_synth(struct file_operations *fops, int dev)
70{
71 memcpy(&oss_devices[OSS_SYNTHID], fops, sizeof(struct file_operations));
72 return OSS_SYNTHID;
73}
74//******************************************************************************
75//******************************************************************************
76void unregister_sound_special(int unit)
77{
78 memset(&oss_devices[OSS_SPECIALID], 0, sizeof(struct file_operations));
79}
80//******************************************************************************
81//******************************************************************************
82void unregister_sound_mixer(int unit)
83{
84 memset(&oss_devices[OSS_MIXERID], 0, sizeof(struct file_operations));
85}
86//******************************************************************************
87//******************************************************************************
88void unregister_sound_midi(int unit)
89{
90 memset(&oss_devices[OSS_MIDIID], 0, sizeof(struct file_operations));
91}
92//******************************************************************************
93//******************************************************************************
94void unregister_sound_dsp(int unit)
95{
96 memset(&oss_devices[OSS_DSPID], 0, sizeof(struct file_operations));
97}
98//******************************************************************************
99//******************************************************************************
100void unregister_sound_synth(int unit)
101{
102 memset(&oss_devices[OSS_SYNTHID], 0, sizeof(struct file_operations));
103}
104//******************************************************************************
105//******************************************************************************
106ULONG OSS32_StreamOpen(ULONG streamtype)
107{
108struct inode ossinode;
109struct file ossfile;
110ULONG ossid = streamtype & OSS_IDMASK;
111
112 ossinode.i_rdev = ossid;
113 ossfile.f_flags = 0;
114
115 switch(streamtype) {
116 case OSS_STREAM_WAVEOUT:
117 ossfile.f_mode = FMODE_WRITE;
118 break;
119 case OSS_STREAM_WAVEIN:
120 ossfile.f_mode = FMODE_READ;
121 break;
122 case OSS_STREAM_MIDIOUT:
123 ossfile.f_mode = FMODE_WRITE;
124 break;
125 case OSS_STREAM_MIDIIN:
126 ossfile.f_mode = FMODE_READ;
127 break;
128 }
129
130 if(!oss_devices[ossid].open) {
131 return 0;
132 }
133 if(oss_devices[ossid].open(&ossinode, &ossfile)) {
134 DebugInt3();
135 return 0;
136 }
137 return (ULONG)ossfile.private_data;
138}
139//******************************************************************************
140//******************************************************************************
141ULONG OSS32_StreamClose(ULONG streamtype, ULONG streamid)
142{
143struct inode ossinode;
144struct file ossfile;
145ULONG ossid = streamtype & OSS_IDMASK;
146
147 ossinode.i_rdev = ossid;
148 ossfile.private_data = (void *)streamid;
149 ossfile.f_flags = 0;
150
151 switch(streamtype) {
152 case OSS_STREAM_WAVEOUT:
153 ossfile.f_mode = FMODE_WRITE;
154 break;
155 case OSS_STREAM_WAVEIN:
156 ossfile.f_mode = FMODE_READ;
157 break;
158 case OSS_STREAM_MIDIOUT:
159 ossfile.f_mode = FMODE_WRITE;
160 break;
161 case OSS_STREAM_MIDIIN:
162 ossfile.f_mode = FMODE_READ;
163 break;
164 }
165 if(!oss_devices[ossid].release) {
166 return 0;
167 }
168 if(oss_devices[ossid].release(&ossinode, &ossfile)) {
169 DebugInt3();
170 return 0;
171 }
172 return 0;
173}
174//******************************************************************************
175//******************************************************************************
176ULONG OSS32_StreamIOCtl(ULONG streamtype, ULONG streamid, ULONG cmd, char NEAR *buffer)
177{
178 struct inode ossinode;
179 struct file ossfile;
180 ULONG ossid = streamtype & OSS_IDMASK, newcmd = -1, fraginfo;
181 count_info cinfo;
182 char NEAR *tmpbuf;
183
184 ossinode.i_rdev = ossid;
185 ossfile.private_data = (void *)streamid;
186 ossfile.f_flags = 0;
187
188 switch(streamtype) {
189 case OSS_STREAM_WAVEOUT:
190 ossfile.f_mode = FMODE_WRITE;
191 break;
192 case OSS_STREAM_WAVEIN:
193 ossfile.f_mode = FMODE_READ;
194 break;
195 case OSS_STREAM_MIDIOUT:
196 ossfile.f_mode = FMODE_WRITE;
197 break;
198 case OSS_STREAM_MIDIIN:
199 ossfile.f_mode = FMODE_READ;
200 break;
201 }
202
203 if(!oss_devices[ossid].ioctl) {
204 return 0;
205 }
206 switch(cmd) {
207 case IOCTL_GETPOS:
208 if(streamtype == OSS_STREAM_WAVEOUT) {
209 newcmd = SNDCTL_DSP_GETOPTR;
210 }
211 else newcmd = SNDCTL_DSP_GETIPTR;
212#ifdef KEE
213 tmpbuf = (char NEAR *)&cinfo;
214#else
215 tmpbuf = (char NEAR *)__StackToFlat((ULONG)&cinfo);
216#endif
217 break;
218
219 case IOCTL_SETFRAGMENT:
220 {
221 ULONG fragsize;
222
223 newcmd = SNDCTL_DSP_SETFRAGMENT;
224
225 fragsize = *(ULONG NEAR *)buffer; //fragsize
226 fraginfo = 0;
227 while(fragsize) {
228 fragsize >>= 1;
229 fraginfo++;
230 }
231 fraginfo--;
232
233#ifdef KEE
234 tmpbuf = (char NEAR *)&fraginfo;
235#else
236 tmpbuf = (char NEAR *)__StackToFlat((ULONG)&fraginfo);
237#endif
238 break;
239 }
240 default:
241 DebugInt3();
242 return 0;
243 }
244 if(oss_devices[ossid].ioctl(&ossinode, &ossfile, newcmd, (ULONG)tmpbuf)) {
245 return 0;
246 }
247 switch(cmd) {
248 case IOCTL_GETPOS:
249 *(ULONG NEAR *)buffer = cinfo.bytes;
250 break;
251 }
252 return 1;
253}
254//******************************************************************************
255//******************************************************************************
256ULONG OSS32_StreamSetFormat(ULONG streamtype, ULONG streamid, ULONG cmd, FORMAT_INFO NEAR *pFormatInfo)
257{
258 struct inode ossinode;
259 struct file ossfile;
260 ULONG ossid = streamtype & OSS_IDMASK;
261
262 ossinode.i_rdev = ossid;
263 ossfile.private_data = (void *)streamid;
264 ossfile.f_flags = 0;
265
266 switch(streamtype) {
267 case OSS_STREAM_WAVEOUT:
268 ossfile.f_mode = FMODE_WRITE;
269 break;
270 case OSS_STREAM_WAVEIN:
271 ossfile.f_mode = FMODE_READ;
272 break;
273 case OSS_STREAM_MIDIOUT:
274 ossfile.f_mode = FMODE_WRITE;
275 break;
276 case OSS_STREAM_MIDIIN:
277 ossfile.f_mode = FMODE_READ;
278 break;
279 }
280
281 if(!oss_devices[ossid].ioctl) {
282 return 0;
283 }
284 if(oss_devices[ossid].ioctl(&ossinode, &ossfile, SNDCTL_DSP_SPEED, (ULONG)&pFormatInfo->ulSampleRate)) {
285 return 0;
286 }
287 if(oss_devices[ossid].ioctl(&ossinode, &ossfile, SNDCTL_DSP_CHANNELS, (ULONG)&pFormatInfo->ulNumChannels)) {
288 return 0;
289 }
290 if(oss_devices[ossid].ioctl(&ossinode, &ossfile, SNDCTL_DSP_SETFMT, (ULONG)&pFormatInfo->ulBitsPerSample)) {
291 return 0;
292 }
293
294 return 1;
295}
296//******************************************************************************
297//******************************************************************************
298ULONG OSS32_StreamTrigger(ULONG streamtype, ULONG streamid, ULONG NEAR *fStart)
299{
300 struct inode ossinode;
301 struct file ossfile;
302 ULONG ossid = streamtype & OSS_IDMASK;
303 ULONG cmd;
304
305 ossinode.i_rdev = ossid;
306 ossfile.private_data = (void *)streamid;
307 ossfile.f_flags = 0;
308
309 switch(streamtype) {
310 case OSS_STREAM_WAVEOUT:
311 ossfile.f_mode = FMODE_WRITE;
312 *fStart = (*fStart) ? PCM_ENABLE_OUTPUT : 0;
313 cmd = SNDCTL_DSP_SETTRIGGER;
314 break;
315 case OSS_STREAM_WAVEIN:
316 ossfile.f_mode = FMODE_READ;
317 *fStart = (*fStart) ? PCM_ENABLE_INPUT : 0;
318 cmd = SNDCTL_DSP_SETTRIGGER;
319 break;
320 case OSS_STREAM_MIDIOUT:
321 ossfile.f_mode = FMODE_WRITE;
322 break;
323 case OSS_STREAM_MIDIIN:
324 ossfile.f_mode = FMODE_READ;
325 break;
326 }
327
328 if(!oss_devices[ossid].ioctl) {
329 return 0;
330 }
331 if(oss_devices[ossid].ioctl(&ossinode, &ossfile, cmd, (ULONG)fStart)) {
332 return 0;
333 }
334 return 1;
335}
336//******************************************************************************
337//******************************************************************************
338ULONG OSS32_StreamReset(ULONG streamtype, ULONG streamid)
339{
340 struct inode ossinode;
341 struct file ossfile;
342 ULONG ossid = streamtype & OSS_IDMASK;
343 ULONG cmd;
344
345 ossinode.i_rdev = ossid;
346 ossfile.private_data = (void *)streamid;
347 ossfile.f_flags = 0;
348
349 switch(streamtype) {
350 case OSS_STREAM_WAVEOUT:
351 ossfile.f_mode = FMODE_WRITE;
352 cmd = SNDCTL_DSP_RESET;
353 break;
354 case OSS_STREAM_WAVEIN:
355 ossfile.f_mode = FMODE_READ;
356 cmd = SNDCTL_DSP_RESET;
357 break;
358 case OSS_STREAM_MIDIOUT:
359 ossfile.f_mode = FMODE_WRITE;
360 break;
361 case OSS_STREAM_MIDIIN:
362 ossfile.f_mode = FMODE_READ;
363 break;
364 }
365
366 if(!oss_devices[ossid].ioctl) {
367 return 0;
368 }
369 if(oss_devices[ossid].ioctl(&ossinode, &ossfile, cmd, 0)) {
370 return 0;
371 }
372 return 1;
373}
374//******************************************************************************
375//******************************************************************************
376ULONG OSS32_StreamAddBuffer(ULONG streamtype, ULONG streamid, ULONG buffer, ULONG size)
377{
378 struct inode ossinode;
379 struct file ossfile;
380 struct dentry ossdentry;
381 ULONG ossid = streamtype & OSS_IDMASK;
382 audio_buf_info info;
383 char NEAR *tmpbuf;
384 ULONG cmd;
385 int transferred;
386
387 ossinode.i_rdev = ossid;
388 ossfile.private_data = (void *)streamid;
389 ossfile.f_flags = 0;
390 ossfile.f_dentry = &ossdentry;
391 ossdentry.d_inode = &ossinode;
392
393 switch(streamtype) {
394 case OSS_STREAM_WAVEOUT:
395 ossfile.f_mode = FMODE_WRITE;
396 cmd = SNDCTL_DSP_GETOSPACE;
397 break;
398 case OSS_STREAM_WAVEIN:
399 ossfile.f_mode = FMODE_READ;
400 cmd = SNDCTL_DSP_GETISPACE;
401 break;
402 case OSS_STREAM_MIDIOUT:
403 ossfile.f_mode = FMODE_WRITE;
404 break;
405 case OSS_STREAM_MIDIIN:
406 ossfile.f_mode = FMODE_READ;
407 break;
408 }
409
410 if(!oss_devices[ossid].write || !oss_devices[ossid].read || !oss_devices[ossid].ioctl) {
411 return 0;
412 }
413 //check how much room is left in the circular dma buffer
414#ifdef KEE
415 tmpbuf = (char NEAR *)&info;
416#else
417 tmpbuf = (char NEAR *)__StackToFlat((ULONG)&info);
418#endif
419 if(oss_devices[ossid].ioctl(&ossinode, &ossfile, cmd, (ULONG)tmpbuf)) {
420 return 0;
421 }
422 size = min(size, info.bytes);
423
424 if(size == 0) {
425 return 0; //no room left, fail
426 }
427
428 if(streamtype == OSS_STREAM_WAVEIN) {
429 transferred = oss_devices[ossid].read(&ossfile, (char *)buffer, size, &ossfile.f_pos);
430 }
431 else transferred = oss_devices[ossid].write(&ossfile, (char *)buffer, size, &ossfile.f_pos);
432 if(transferred < 0) {
433 return 0;
434 }
435 return transferred;
436}
437//******************************************************************************
438//******************************************************************************
439ULONG OSS32_SetVolume(ULONG streamtype, ULONG streamid, ULONG cmd, ULONG volume)
440{
441 struct inode ossinode;
442 struct file ossfile;
443 struct dentry ossdentry;
444 ULONG ossid = streamtype & OSS_IDMASK;
445 char NEAR *tmpbuf;
446 ULONG ioctl;
447
448 ossinode.i_rdev = OSS_MIXERID;
449 ossfile.private_data = (void *)streamid;
450 ossfile.f_flags = 0;
451 ossfile.f_dentry = &ossdentry;
452 ossfile.f_mode = FMODE_WRITE;
453 ossdentry.d_inode = &ossinode;
454
455 switch(cmd) {
456 case MIX_SETMASTERVOL:
457 ioctl = SOUND_MIXER_WRITE_VOLUME;
458 break;
459 case MIX_SETWAVEVOL:
460 ioctl = SOUND_MIXER_WRITE_PCM;
461 // channel volume ranges from 0 to 0x7FFFFFFF (linear)
462 volume = volume >> 16;
463 volume = (volume*100)/0x7FFF;
464 volume = (volume << 8) | volume; //l&r
465 break;
466 case MIX_SETMIDIVOL:
467// ioctl =
468 break;
469 case MIX_SETINPUTSRC:
470 ioctl = SOUND_MIXER_WRITE_RECSRC; //todo
471 switch(volume)
472 {
473 case MIX_RECSRC_MIC:
474 volume = SOUND_MASK_MIC;
475 break;
476 case MIX_RECSRC_CD:
477 volume = SOUND_MASK_CD;
478 break;
479 case MIX_RECSRC_LINE:
480 volume = SOUND_MASK_LINE;
481 break;
482 case MIX_RECSRC_VIDEO:
483 volume = SOUND_MASK_VIDEO;
484 break;
485 case MIX_RECSRC_MIXER:
486 volume = SOUND_MASK_MONITOR;
487 break;
488 case MIX_RECSRC_AUX:
489 volume = SOUND_MASK_LINE1;
490 break;
491 default:
492 DebugInt3();
493 break;
494 }
495 break;
496 case MIX_SETINPUTGAIN:
497 ioctl = SOUND_MIXER_WRITE_IGAIN;
498 break;
499 case MIX_SETLINEINVOL:
500 ioctl = SOUND_MIXER_WRITE_LINE;
501 break;
502 case MIX_SETLINEINMUTE:
503 ioctl = SOUND_MIXER_WRITE_LINE;
504 break;
505 case MIX_SETMICVOL:
506 ioctl = SOUND_MIXER_WRITE_MIC;
507 break;
508 case MIX_SETMICMUTE:
509 ioctl = SOUND_MIXER_WRITE_MIC;
510 break;
511 case MIX_SETCDVOL:
512 ioctl = SOUND_MIXER_WRITE_CD;
513 break;
514 case MIX_SETCDMUTE:
515 ioctl = SOUND_MIXER_WRITE_CD;
516 break;
517 case MIX_SETVIDEOVOL:
518//// ioctl = SOUND_MIXER_WRITE_VIDEO;
519 break;
520 case MIX_SETAUXVOL:
521 ioctl = SOUND_MIXER_LINE1;
522 break;
523 case MIX_SETBASS:
524 ioctl = SOUND_MIXER_WRITE_BASS;
525 break;
526 case MIX_SETTREBLE:
527 ioctl = SOUND_MIXER_WRITE_TREBLE;
528 break;
529 case MIX_SETSPDIFVOL:
530// ioctl =
531 break;
532 case MIX_SETSPDIFMUTE:
533// ioctl =
534 break;
535 }
536 if(!oss_devices[OSS_MIXERID].ioctl || !oss_devices[OSS_MIXERID].open || !oss_devices[OSS_MIXERID].release) {
537 return 0;
538 }
539
540 if(oss_devices[OSS_MIXERID].open(&ossinode, &ossfile)) {
541 return 0;
542 }
543
544#ifdef KEE
545 tmpbuf = (char NEAR *)&volume;
546#else
547 tmpbuf = (char NEAR *)__StackToFlat((ULONG)&volume);
548#endif
549 if(oss_devices[OSS_MIXERID].ioctl(&ossinode, &ossfile, ioctl, (ULONG)tmpbuf)) {
550 oss_devices[OSS_MIXERID].release(&ossinode, &ossfile);
551 return 0;
552 }
553 oss_devices[OSS_MIXERID].release(&ossinode, &ossfile);
554 return 1;
555}
556//******************************************************************************
557//******************************************************************************
Note: See TracBrowser for help on using the repository browser.