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

Last change on this file since 149 was 147, checked in by sandervl, 25 years ago

Fixed wave volume, recording gain + wave recording

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.4 KB
Line 
1/* $Id: sound.c 147 2000-04-24 19:45:21Z sandervl $ */
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(ossfile.f_mode == FMODE_READ && *fStart == PCM_ENABLE_INPUT) {
332 //need to call poll to really start the stream
333 int rc;
334 struct poll_table_struct poll = {0};
335
336 rc = oss_devices[ossid].poll(&ossfile, &poll);
337 if(rc & POLLERR)
338 return 0;
339 return 1;
340 }
341 else
342 if(oss_devices[ossid].ioctl(&ossinode, &ossfile, cmd, (ULONG)fStart)) {
343 return 0;
344 }
345 return 1;
346}
347//******************************************************************************
348//******************************************************************************
349ULONG OSS32_StreamReset(ULONG streamtype, ULONG streamid)
350{
351 struct inode ossinode;
352 struct file ossfile;
353 ULONG ossid = streamtype & OSS_IDMASK;
354 ULONG cmd;
355
356 ossinode.i_rdev = ossid;
357 ossfile.private_data = (void *)streamid;
358 ossfile.f_flags = 0;
359
360 switch(streamtype) {
361 case OSS_STREAM_WAVEOUT:
362 ossfile.f_mode = FMODE_WRITE;
363 cmd = SNDCTL_DSP_RESET;
364 break;
365 case OSS_STREAM_WAVEIN:
366 ossfile.f_mode = FMODE_READ;
367 cmd = SNDCTL_DSP_RESET;
368 break;
369 case OSS_STREAM_MIDIOUT:
370 ossfile.f_mode = FMODE_WRITE;
371 break;
372 case OSS_STREAM_MIDIIN:
373 ossfile.f_mode = FMODE_READ;
374 break;
375 }
376
377 if(!oss_devices[ossid].ioctl) {
378 return 0;
379 }
380 if(oss_devices[ossid].ioctl(&ossinode, &ossfile, cmd, 0)) {
381 return 0;
382 }
383 return 1;
384}
385//******************************************************************************
386//******************************************************************************
387ULONG OSS32_StreamAddBuffer(ULONG streamtype, ULONG streamid, ULONG buffer, ULONG size)
388{
389 struct inode ossinode;
390 struct file ossfile;
391 struct dentry ossdentry;
392 ULONG ossid = streamtype & OSS_IDMASK;
393 audio_buf_info info;
394 char NEAR *tmpbuf;
395 ULONG cmd;
396 int transferred;
397
398 ossinode.i_rdev = ossid;
399 ossfile.private_data = (void *)streamid;
400 ossfile.f_flags = 0;
401 ossfile.f_dentry = &ossdentry;
402 ossdentry.d_inode = &ossinode;
403
404 switch(streamtype) {
405 case OSS_STREAM_WAVEOUT:
406 ossfile.f_mode = FMODE_WRITE;
407 cmd = SNDCTL_DSP_GETOSPACE;
408 break;
409 case OSS_STREAM_WAVEIN:
410 ossfile.f_mode = FMODE_READ;
411 cmd = SNDCTL_DSP_GETISPACE;
412 break;
413 case OSS_STREAM_MIDIOUT:
414 ossfile.f_mode = FMODE_WRITE;
415 break;
416 case OSS_STREAM_MIDIIN:
417 ossfile.f_mode = FMODE_READ;
418 break;
419 }
420
421 if(!oss_devices[ossid].write || !oss_devices[ossid].read || !oss_devices[ossid].ioctl) {
422 return 0;
423 }
424 //check how much room is left in the circular dma buffer
425#ifdef KEE
426 tmpbuf = (char NEAR *)&info;
427#else
428 tmpbuf = (char NEAR *)__StackToFlat((ULONG)&info);
429#endif
430 if(oss_devices[ossid].ioctl(&ossinode, &ossfile, cmd, (ULONG)tmpbuf)) {
431 return 0;
432 }
433 size = min(size, info.bytes);
434
435 if(size == 0) {
436 return 0; //no room left, fail
437 }
438
439 if(streamtype == OSS_STREAM_WAVEIN) {
440 transferred = oss_devices[ossid].read(&ossfile, (char *)buffer, size, &ossfile.f_pos);
441 }
442 else transferred = oss_devices[ossid].write(&ossfile, (char *)buffer, size, &ossfile.f_pos);
443 if(transferred < 0) {
444 return 0;
445 }
446 return transferred;
447}
448//******************************************************************************
449//******************************************************************************
450ULONG OSS32_SetVolume(ULONG streamtype, ULONG streamid, ULONG cmd, ULONG volume)
451{
452 struct inode ossinode;
453 struct file ossfile;
454 struct dentry ossdentry;
455 ULONG ossid = streamtype & OSS_IDMASK;
456 char NEAR *tmpbuf;
457 ULONG ioctl;
458
459 ossinode.i_rdev = OSS_MIXERID;
460 ossfile.private_data = (void *)streamid;
461 ossfile.f_flags = 0;
462 ossfile.f_dentry = &ossdentry;
463 ossfile.f_mode = FMODE_WRITE;
464 ossdentry.d_inode = &ossinode;
465
466 switch(cmd) {
467 case MIX_SETMASTERVOL:
468 ioctl = SOUND_MIXER_WRITE_VOLUME;
469 break;
470 case MIX_SETWAVEVOL:
471 ioctl = SOUND_MIXER_WRITE_PCM;
472 break;
473 case MIX_SETMIDIVOL:
474// ioctl =
475 break;
476 case MIX_SETINPUTSRC:
477 ioctl = SOUND_MIXER_WRITE_RECSRC; //todo
478 switch(volume)
479 {
480 case MIX_RECSRC_MIC:
481 volume = SOUND_MASK_MIC;
482 break;
483 case MIX_RECSRC_CD:
484 volume = SOUND_MASK_CD;
485 break;
486 case MIX_RECSRC_LINE:
487 volume = SOUND_MASK_LINE;
488 break;
489 case MIX_RECSRC_VIDEO:
490 volume = SOUND_MASK_VIDEO;
491 break;
492 case MIX_RECSRC_MIXER:
493 volume = SOUND_MASK_MONITOR;
494 break;
495 case MIX_RECSRC_AUX:
496 volume = SOUND_MASK_LINE1;
497 break;
498 default:
499 DebugInt3();
500 break;
501 }
502 break;
503 case MIX_SETINPUTGAIN:
504 ioctl = SOUND_MIXER_WRITE_RECLEV;
505 break;
506 case MIX_SETLINEINVOL:
507 ioctl = SOUND_MIXER_WRITE_LINE;
508 break;
509 case MIX_SETLINEINMUTE:
510 ioctl = SOUND_MIXER_WRITE_LINE;
511 break;
512 case MIX_SETMICVOL:
513 ioctl = SOUND_MIXER_WRITE_MIC;
514 break;
515 case MIX_SETMICMUTE:
516 ioctl = SOUND_MIXER_WRITE_MIC;
517 break;
518 case MIX_SETCDVOL:
519 ioctl = SOUND_MIXER_WRITE_CD;
520 break;
521 case MIX_SETCDMUTE:
522 ioctl = SOUND_MIXER_WRITE_CD;
523 break;
524 case MIX_SETVIDEOVOL:
525//// ioctl = SOUND_MIXER_WRITE_VIDEO;
526 break;
527 case MIX_SETAUXVOL:
528 ioctl = SOUND_MIXER_LINE1;
529 break;
530 case MIX_SETBASS:
531 ioctl = SOUND_MIXER_WRITE_BASS;
532 break;
533 case MIX_SETTREBLE:
534 ioctl = SOUND_MIXER_WRITE_TREBLE;
535 break;
536 case MIX_SETSPDIFVOL:
537// ioctl =
538 break;
539 case MIX_SETSPDIFMUTE:
540// ioctl =
541 break;
542 }
543 if(!oss_devices[OSS_MIXERID].ioctl || !oss_devices[OSS_MIXERID].open || !oss_devices[OSS_MIXERID].release) {
544 return 0;
545 }
546
547 if(oss_devices[OSS_MIXERID].open(&ossinode, &ossfile)) {
548 return 0;
549 }
550
551#ifdef KEE
552 tmpbuf = (char NEAR *)&volume;
553#else
554 tmpbuf = (char NEAR *)__StackToFlat((ULONG)&volume);
555#endif
556 if(oss_devices[OSS_MIXERID].ioctl(&ossinode, &ossfile, ioctl, (ULONG)tmpbuf)) {
557 oss_devices[OSS_MIXERID].release(&ossinode, &ossfile);
558 return 0;
559 }
560 oss_devices[OSS_MIXERID].release(&ossinode, &ossfile);
561 return 1;
562}
563//******************************************************************************
564//******************************************************************************
Note: See TracBrowser for help on using the repository browser.