source: GPL/branches/uniaud32-2.1.x/lib32/sound.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: 48.2 KB
Line 
1/*
2 * MMPM/2 to OSS interface translation layer
3 *
4 * (C) 2000-2002 InnoTek Systemberatung GmbH
5 * (C) 2000-2001 Sander van Leeuwen (sandervl@xs4all.nl)
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public
18 * License along with this program; if not, write to the Free
19 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
20 * USA.
21 *
22 */
23
24#include <sound/core.h>
25#include <sound/control.h>
26#include <sound/info.h>
27#include <sound/pcm.h>
28#include <sound/pcm_params.h>
29#include <sound/minors.h>
30#include <linux/file.h>
31#include <linux/soundcard.h>
32
33#define LINUX
34#include <ossidc32.h>
35#include <osspci.h>
36#include <stacktoflat.h>
37#include <stdlib.h>
38#include <proto.h>
39//#include <dbgos2.h>
40#include "soundoss.h"
41
42#undef samples_to_bytes
43#undef bytes_to_samples
44#define samples_to_bytes(a) ((a*pHandle->doublesamplesize)/2)
45#define bytes_to_samples(a) (pHandle->doublesamplesize ? ((a*2)/pHandle->doublesamplesize) : a)
46int GetMaxChannels(ULONG deviceid, int type);
47
48struct file_operations oss_devices[OSS32_MAX_DEVICES] = {0};
49struct file_operations *alsa_fops = NULL;
50int per_bytes = 0;
51int prev_size = 0;
52int pcm_device = 0;
53int total = 0;
54// int pcm_instances = 0; //PS+++ !!!!!!! what is it!!!! see pcm.lib
55
56OpenedHandles opened_handles[8 * 256] = {0};
57
58//OSS32 to ALSA datatype conversion table
59static int OSSToALSADataType[OSS32_PCM_MAX_FORMATS] = {
60/* OSS32_PCM_FORMAT_S8 */ SNDRV_PCM_FORMAT_S8, //signed 8 bits sample
61/* OSS32_PCM_FORMAT_U8 */ SNDRV_PCM_FORMAT_U8, //unsigned 8 bits sample
62/* OSS32_PCM_FORMAT_S16_LE */ SNDRV_PCM_FORMAT_S16_LE, //signed 16 bits sample (little endian/Intel)
63/* OSS32_PCM_FORMAT_S16_BE */ SNDRV_PCM_FORMAT_S16_BE, //signed 16 bits sample (big endian/Motorola)
64/* OSS32_PCM_FORMAT_U16_LE */ SNDRV_PCM_FORMAT_U16_LE, //unsigned 16 bits sample (little endian/Intel)
65/* OSS32_PCM_FORMAT_U16_BE */ SNDRV_PCM_FORMAT_U16_BE, //unsigned 16 bits sample (big endian/Motorola)
66/* OSS32_PCM_FORMAT_S24_LE */ SNDRV_PCM_FORMAT_S24_LE, //signed 24 bits sample (little endian/Intel)
67/* OSS32_PCM_FORMAT_S24_BE */ SNDRV_PCM_FORMAT_S24_BE, //signed 24 bits sample (big endian/Motorola)
68/* OSS32_PCM_FORMAT_U24_LE */ SNDRV_PCM_FORMAT_U24_LE, //unsigned 24 bits sample (little endian/Intel)
69/* OSS32_PCM_FORMAT_U24_BE */ SNDRV_PCM_FORMAT_U24_BE, //unsigned 24 bits sample (big endian/Motorola)
70/* OSS32_PCM_FORMAT_S32_LE */ SNDRV_PCM_FORMAT_S32_LE, //signed 32 bits sample (little endian/Intel)
71/* OSS32_PCM_FORMAT_S32_BE */ SNDRV_PCM_FORMAT_S32_BE, //signed 32 bits sample (big endian/Motorola)
72/* OSS32_PCM_FORMAT_U32_LE */ SNDRV_PCM_FORMAT_U32_LE, //unsigned 32 bits sample (little endian/Intel)
73/* OSS32_PCM_FORMAT_U32_BE */ SNDRV_PCM_FORMAT_U32_BE, //unsigned 32 bits sample (big endian/Motorola)
74/* OSS32_PCM_FORMAT_MULAW */ SNDRV_PCM_FORMAT_MU_LAW, //8 bps (compressed 16 bits sample)
75/* OSS32_PCM_FORMAT_ALAW */ SNDRV_PCM_FORMAT_A_LAW, //8 bps (compressed 16 bits sample)
76/* OSS32_PCM_FORMAT_ADPCM */ SNDRV_PCM_FORMAT_IMA_ADPCM, //4 bps (compressed 16 bits sample)
77/* OSS32_PCM_FORMAT_MPEG */ SNDRV_PCM_FORMAT_MPEG, //AC3?
78};
79
80//******************************************************************************
81//******************************************************************************
82int register_chrdev(unsigned int version, const char *name, struct file_operations *fsop)
83{
84 if(!strcmp(name, "alsa")) {
85 alsa_fops = fsop;
86 }
87 return 0;
88}
89//******************************************************************************
90//******************************************************************************
91int unregister_chrdev(unsigned int version, const char *name)
92{
93 if(!strcmp(name, "alsa")) {
94 alsa_fops = NULL;
95 }
96 return 0;
97}
98//******************************************************************************
99//******************************************************************************
100int register_sound_special(struct file_operations *fops, int unit)
101{
102 if(fops == NULL) return -1;
103
104 memcpy(&oss_devices[OSS32_SPECIALID], fops, sizeof(struct file_operations));
105 return OSS32_SPECIALID;
106}
107//******************************************************************************
108//******************************************************************************
109int register_sound_mixer(struct file_operations *fops, int dev)
110{
111 if(fops == NULL) return -1;
112
113 memcpy(&oss_devices[OSS32_MIXERID], fops, sizeof(struct file_operations));
114 return OSS32_MIXERID;
115}
116//******************************************************************************
117//******************************************************************************
118int register_sound_midi(struct file_operations *fops, int dev)
119{
120 if(fops == NULL) return -1;
121
122 memcpy(&oss_devices[OSS32_MIDIID], fops, sizeof(struct file_operations));
123 return OSS32_MIDIID;
124}
125//******************************************************************************
126//******************************************************************************
127int register_sound_dsp(struct file_operations *fops, int dev)
128{
129 if(fops == NULL) return -1;
130
131 memcpy(&oss_devices[OSS32_DSPID], fops, sizeof(struct file_operations));
132 return OSS32_DSPID;
133}
134//******************************************************************************
135//******************************************************************************
136int register_sound_synth(struct file_operations *fops, int dev)
137{
138 if(fops == NULL) return -1;
139
140 memcpy(&oss_devices[OSS32_SYNTHID], fops, sizeof(struct file_operations));
141 return OSS32_SYNTHID;
142}
143//******************************************************************************
144//******************************************************************************
145void unregister_sound_special(int unit)
146{
147 memset(&oss_devices[OSS32_SPECIALID], 0, sizeof(struct file_operations));
148}
149//******************************************************************************
150//******************************************************************************
151void unregister_sound_mixer(int unit)
152{
153 memset(&oss_devices[OSS32_MIXERID], 0, sizeof(struct file_operations));
154}
155//******************************************************************************
156//******************************************************************************
157void unregister_sound_midi(int unit)
158{
159 memset(&oss_devices[OSS32_MIDIID], 0, sizeof(struct file_operations));
160}
161//******************************************************************************
162//******************************************************************************
163void unregister_sound_dsp(int unit)
164{
165 memset(&oss_devices[OSS32_DSPID], 0, sizeof(struct file_operations));
166}
167//******************************************************************************
168//******************************************************************************
169void unregister_sound_synth(int unit)
170{
171 memset(&oss_devices[OSS32_SYNTHID], 0, sizeof(struct file_operations));
172}
173//******************************************************************************
174//******************************************************************************
175OSSRET UNIXToOSSError(int unixerror)
176{
177 switch(unixerror) {
178 case 0:
179 return OSSERR_SUCCESS;
180 case -ENOMEM:
181 return OSSERR_OUT_OF_MEMORY;
182 case -ENODEV:
183 return OSSERR_NO_DEVICE_AVAILABLE;
184 case -ENOTTY:
185 case -EINVAL:
186 return OSSERR_INVALID_PARAMETER;
187 case -EAGAIN:
188 return OSSERR_AGAIN; //????
189 case -ENXIO:
190 return OSSERR_IO_ERROR;
191 case -EBUSY:
192 return OSSERR_BUSY;
193 case -EPERM:
194 return OSSERR_ACCESS_DENIED; //??
195 case -EPIPE:
196 case -EBADFD:
197 return OSSERR_ACCESS_DENIED; //??
198 default:
199 dprintf(("Unknown error %d", (unixerror > 0) ? unixerror : -unixerror));
200 return OSSERR_UNKNOWN;
201 }
202}
203//******************************************************************************
204//ALSA to OSS32 datatype conversion
205//******************************************************************************
206int ALSAToOSSDataType(ULONG ALSADataType)
207{
208 switch(ALSADataType)
209 {
210 case SNDRV_PCM_FORMAT_S8:
211 return OSS32_CAPS_PCM_FORMAT_S8; //signed 8 bits sample
212 case SNDRV_PCM_FORMAT_U8:
213 return OSS32_CAPS_PCM_FORMAT_U8; //unsigned 8 bits sample
214 case SNDRV_PCM_FORMAT_S16_LE:
215 return OSS32_CAPS_PCM_FORMAT_S16_LE; //signed 16 bits sample (little endian/Intel)
216 case SNDRV_PCM_FORMAT_S16_BE:
217 return OSS32_CAPS_PCM_FORMAT_S16_BE; //signed 16 bits sample (big endian/Motorola)
218 case SNDRV_PCM_FORMAT_U16_LE:
219 return OSS32_CAPS_PCM_FORMAT_U16_LE; //unsigned 16 bits sample (little endian/Intel)
220 case SNDRV_PCM_FORMAT_U16_BE:
221 return OSS32_CAPS_PCM_FORMAT_U16_BE; //unsigned 16 bits sample (big endian/Motorola)
222 case SNDRV_PCM_FORMAT_S24_LE:
223 return OSS32_CAPS_PCM_FORMAT_S24_LE; //signed 24 bits sample (little endian/Intel)
224 case SNDRV_PCM_FORMAT_S24_BE:
225 return OSS32_CAPS_PCM_FORMAT_S24_BE; //signed 24 bits sample (big endian/Motorola)
226 case SNDRV_PCM_FORMAT_U24_LE:
227 return OSS32_CAPS_PCM_FORMAT_U24_LE; //unsigned 24 bits sample (little endian/Intel)
228 case SNDRV_PCM_FORMAT_U24_BE:
229 return OSS32_CAPS_PCM_FORMAT_U24_BE; //unsigned 16 bits sample (big endian/Motorola)
230 case SNDRV_PCM_FORMAT_S32_LE:
231 return OSS32_CAPS_PCM_FORMAT_S32_LE; //signed 32 bits sample (little endian/Intel)
232 case SNDRV_PCM_FORMAT_S32_BE:
233 return OSS32_CAPS_PCM_FORMAT_S32_BE; //signed 32 bits sample (big endian/Motorola)
234 case SNDRV_PCM_FORMAT_U32_LE:
235 return OSS32_CAPS_PCM_FORMAT_U32_LE; //unsigned 32 bits sample (little endian/Intel)
236 case SNDRV_PCM_FORMAT_U32_BE:
237 return OSS32_CAPS_PCM_FORMAT_U32_BE; //unsigned 32 bits sample (big endian/Motorola)
238 case SNDRV_PCM_FORMAT_MU_LAW:
239 return OSS32_CAPS_PCM_FORMAT_MULAW; //8 bps (compressed 16 bits sample)
240 case SNDRV_PCM_FORMAT_A_LAW:
241 return OSS32_CAPS_PCM_FORMAT_ALAW; //8 bps (compressed 16 bits sample)
242 case SNDRV_PCM_FORMAT_IMA_ADPCM:
243 return OSS32_CAPS_PCM_FORMAT_ADPCM; //4 bps (compressed 16 bits sample)
244 case SNDRV_PCM_FORMAT_MPEG:
245 return OSS32_CAPS_PCM_FORMAT_MPEG; //AC3?
246 default:
247 DebugInt3();
248 return -1;
249 }
250}
251//******************************************************************************
252//******************************************************************************
253ULONG ALSAToOSSRateFlags(ULONG fuRates)
254{
255 ULONG fuOSSRates = 0;
256
257 char szMixerName[64];
258 char szDeviceName[128];
259 OSS32_QueryNames(OSS32_DEFAULT_DEVICE, szDeviceName,
260 sizeof(szDeviceName),szMixerName,
261 sizeof(szMixerName), TRUE);
262 if (strncmp(szDeviceName,"HDA",3) != 0){
263 /* non-HDA audio - support 5512 - 32000 Hz sample rates */
264 if(fuRates & SNDRV_PCM_RATE_5512) {
265 fuOSSRates |= OSS32_CAPS_PCM_RATE_5512;
266 }
267 if(fuRates & SNDRV_PCM_RATE_8000) {
268 fuOSSRates |= OSS32_CAPS_PCM_RATE_8000;
269 }
270 if(fuRates & SNDRV_PCM_RATE_11025) {
271 fuOSSRates |= OSS32_CAPS_PCM_RATE_11025;
272 }
273 if(fuRates & SNDRV_PCM_RATE_16000) {
274 fuOSSRates |= OSS32_CAPS_PCM_RATE_16000;
275 }
276 if(fuRates & SNDRV_PCM_RATE_22050) {
277 fuOSSRates |= OSS32_CAPS_PCM_RATE_22050;
278 }
279 if(fuRates & SNDRV_PCM_RATE_32000) {
280 fuOSSRates |= OSS32_CAPS_PCM_RATE_32000;
281 }
282 } else {
283 dprintf(("HDA audio detected - don't support 5512 - 32000 Hz audio sample rates\n"));
284 }
285 if(fuRates & SNDRV_PCM_RATE_44100) {
286 fuOSSRates |= OSS32_CAPS_PCM_RATE_44100;
287 }
288 if(fuRates & SNDRV_PCM_RATE_48000) {
289 fuOSSRates |= OSS32_CAPS_PCM_RATE_48000;
290 }
291#if 0
292 if(fuRates & SNDRV_PCM_RATE_64000) {
293 fuOSSRates |= OSS32_CAPS_PCM_RATE_64000;
294 }
295 if(fuRates & SNDRV_PCM_RATE_88200) {
296 fuOSSRates |= OSS32_CAPS_PCM_RATE_88200;
297 }
298 if(fuRates & SNDRV_PCM_RATE_96000) {
299 fuOSSRates |= OSS32_CAPS_PCM_RATE_96000;
300 }
301 if(fuRates & SNDRV_PCM_RATE_176400) {
302 fuOSSRates |= OSS32_CAPS_PCM_RATE_176400;
303 }
304 if(fuRates & SNDRV_PCM_RATE_192000) {
305 fuOSSRates |= OSS32_CAPS_PCM_RATE_192000;
306 }
307#endif
308 if(fuRates & SNDRV_PCM_RATE_CONTINUOUS) {
309 fuOSSRates |= OSS32_CAPS_PCM_RATE_CONTINUOUS;
310 }
311
312 //TODO:
313 if(fuRates & SNDRV_PCM_RATE_KNOT) {
314 DebugInt3();
315 }
316//#define OSS32_CAPS_PCM_RATE_KNOT (1<<31) /* supports more non-continuos rates */
317
318 return fuOSSRates;
319}
320//******************************************************************************
321//******************************************************************************
322OSSRET OSS32_QueryDevCaps(ULONG deviceid, POSS32_DEVCAPS pDevCaps)
323{
324 OSSSTREAMID streamid = 0;
325 soundhandle *pHandle;
326 struct snd_pcm_info *pcminfo = NULL;
327 struct snd_pcm_hw_params *params;
328 int ret, fmt, i;
329 ULONG format_mask;
330 struct snd_mask *mask;
331 int max_ch;
332
333 dprintf(("OSS32_QueryDevCaps"));
334// max_ch = GetMaxChannels(deviceid, OSS32_CAPS_WAVE_PLAYBACK);
335
336 //these structures are too big to put on the stack
337 pcminfo = (struct snd_pcm_info *)kmalloc(sizeof(struct snd_pcm_info)+sizeof(struct snd_pcm_hw_params), GFP_KERNEL);
338 if(pcminfo == NULL) {
339 DebugInt3();
340 rprintf(("OSS32_QueryDevCaps: out of memory\n"));
341 return OSSERR_OUT_OF_MEMORY;
342 }
343 params = (struct snd_pcm_hw_params *)(pcminfo+1);
344
345 dprintf(("Number of cards=%i dev id=%i", nrCardsDetected, deviceid));
346 pDevCaps->nrDevices = 1;//nrCardsDetected;
347// pDevCaps->nrDevices = nrCardsDetected;
348 pDevCaps->ulCaps = OSS32_CAPS_WAVE_PLAYBACK | OSS32_CAPS_WAVE_CAPTURE;
349
350 //query wave in & out caps
351 for(i=0;i<2;i++)
352 {
353 PWAVE_CAPS pWaveCaps = (i == 0) ? &pDevCaps->waveOutCaps : &pDevCaps->waveInCaps;
354
355 ret = OSS32_WaveOpen(deviceid, (i == 0) ? OSS32_STREAM_WAVEOUT : OSS32_STREAM_WAVEIN, &streamid, 0, 0);
356 if(ret != OSSERR_SUCCESS)
357 {
358 rprintf(("OSS32_QueryDevCaps: wave open error %i\n", ret));
359 DebugInt3();
360 goto fail;
361 }
362 pHandle = (soundhandle *)streamid;
363 if(pHandle == NULL || pHandle->magic != MAGIC_WAVE_ALSA32) {
364 rprintf(("OSS32_QueryDevCaps: invalid stream id \n"));
365 ret = OSSERR_INVALID_STREAMID;
366 goto fail;
367 }
368 //set operation to non-blocking
369 pHandle->file.f_flags = O_NONBLOCK;
370
371 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_INFO, (ULONG)pcminfo);
372 if(ret != 0) {
373 rprintf(("OSS32_QueryDevCaps: SNDRV_PCM_IOCTL_INFO error %i\n", ret));
374 ret = UNIXToOSSError(ret);
375 goto fail;
376 }
377 if(i == 0) {//only need to do this once
378 if(pcminfo->name[0]) {
379 strncpy(pDevCaps->szDeviceName, pcminfo->name, sizeof(pDevCaps->szDeviceName));
380 }
381 else strncpy(pDevCaps->szDeviceName, pcminfo->id, sizeof(pDevCaps->szDeviceName));
382 }
383 dprintf(("Device name: %s", pDevCaps->szDeviceName));
384 pWaveCaps->nrStreams = pcminfo->subdevices_count;
385
386 //get all hardware parameters
387 _snd_pcm_hw_params_any(params);
388 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_HW_REFINE, (ULONG)params);
389 if(ret != 0) {
390 rprintf(("OSS32_QueryDevCaps: SNDRV_PCM_IOCTL_HW_REFINE error %i\n", ret));
391 ret = UNIXToOSSError(ret);
392 goto fail;
393 }
394
395 pWaveCaps->ulMinChannels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS)->min;
396 pWaveCaps->ulMaxChannels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS)->max;
397 pWaveCaps->ulChanFlags = 0;
398 if(pWaveCaps->ulMinChannels == 1) {
399 pWaveCaps->ulChanFlags |= OSS32_CAPS_PCM_CHAN_MONO;
400 }
401 if(pWaveCaps->ulMaxChannels >= 2) {
402 pWaveCaps->ulChanFlags |= OSS32_CAPS_PCM_CHAN_STEREO;
403 }
404 if(pWaveCaps->ulMaxChannels >= 4) {
405 pWaveCaps->ulChanFlags |= OSS32_CAPS_PCM_CHAN_QUAD;
406 }
407 if(pWaveCaps->ulMaxChannels >= 6) {
408 pWaveCaps->ulChanFlags |= OSS32_CAPS_PCM_CHAN_5_1;
409 }
410
411 pWaveCaps->ulMinRate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->min;
412 pWaveCaps->ulMaxRate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->max;
413
414 mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_RATE_MASK);
415
416 pWaveCaps->ulRateFlags = mask->bits[0];
417
418 pWaveCaps->ulRateFlags = ALSAToOSSRateFlags(pWaveCaps->ulRateFlags);
419
420 pWaveCaps->ulDataFormats = 0;
421
422 mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
423 format_mask = mask->bits[0];
424 for(fmt=0;fmt<32;fmt++)
425 {
426 if(format_mask & (1 << fmt))
427 {
428 int f = ALSAToOSSDataType(fmt);
429 if (f >= 0)
430 pWaveCaps->ulDataFormats |= f;
431 }
432 }
433
434 OSS32_WaveClose(streamid);
435 streamid = 0;
436
437 }
438
439 //Check support for MPU401, FM & Wavetable MIDI
440 if(OSS32_MidiOpen(deviceid, OSS32_STREAM_MPU401_MIDIOUT, &streamid) == OSSERR_SUCCESS)
441 {
442 pDevCaps->ulCaps |= OSS32_CAPS_MPU401_PLAYBACK;
443 OSS32_MidiClose(streamid);
444 streamid = 0;
445 }
446 if(OSS32_MidiOpen(deviceid, OSS32_STREAM_MPU401_MIDIIN, &streamid) == OSSERR_SUCCESS)
447 {
448 pDevCaps->ulCaps |= OSS32_CAPS_MPU401_CAPTURE;
449 OSS32_MidiClose(streamid);
450 streamid = 0;
451 }
452 if(OSS32_MidiOpen(deviceid, OSS32_STREAM_FM_MIDIOUT, &streamid) == OSSERR_SUCCESS)
453 {
454 pDevCaps->ulCaps |= OSS32_CAPS_FMSYNTH_PLAYBACK;
455 OSS32_MidiClose(streamid);
456 streamid = 0;
457 }
458 if(OSS32_MidiOpen(deviceid, OSS32_STREAM_WAVETABLE_MIDIOUT, &streamid) == OSSERR_SUCCESS)
459 {
460 pDevCaps->ulCaps |= OSS32_CAPS_WAVETABLE_PLAYBACK;
461 OSS32_MidiClose(streamid);
462 streamid = 0;
463 }
464
465 if(OSS32_MixQueryName(deviceid, &pDevCaps->szMixerName, sizeof(pDevCaps->szMixerName)) != OSSERR_SUCCESS) {
466 DebugInt3();
467 rprintf(("OSS32_QueryDevCaps: OSS32_MixQueryName error\n"));
468 goto fail;
469 }
470 dprintf(("OSS32_QueryDevCaps: devname: [%s]\n", pDevCaps->szDeviceName));
471 kfree(pcminfo);
472 streamid = 0;
473
474
475 return OSSERR_SUCCESS;
476
477fail:
478 rprintf(("OSS32_QueryDevCaps failed\n"));
479 DebugInt3();
480 if(streamid) OSS32_WaveClose(streamid);
481 if(pcminfo) kfree(pcminfo);
482
483 return ret;
484}
485//******************************************************************************
486//******************************************************************************
487OSSRET OSS32_WaveOpen(ULONG deviceid, ULONG streamtype, OSSSTREAMID *pStreamId, int pcm, USHORT fileid)
488{
489 soundhandle *pHandle;
490 int ret,i;
491
492 if (pStreamId)
493 *pStreamId = 0;
494 else
495 {
496 rprintf(("ERROR: invalid stream id pointer\n"));
497 return OSSERR_OUT_OF_MEMORY;
498 }
499
500 if(alsa_fops == NULL) {
501 DebugInt3();
502 rprintf(("OSS32_WaveOpen: no devices"));
503
504 return OSSERR_NO_DEVICE_AVAILABLE;
505 }
506
507 //dprintf(("dev id: %i\n",deviceid));
508
509 pHandle = kmalloc(sizeof(soundhandle), GFP_KERNEL);
510 if(pHandle == NULL) {
511 DebugInt3();
512 rprintf(("OSS32_WaveOpen: out of memory\n"));
513 return OSSERR_OUT_OF_MEMORY;
514 }
515 memset(pHandle, 0, sizeof(soundhandle));
516
517 //set operation to non-blocking
518 pHandle->file.f_flags = O_NONBLOCK;
519
520 //setup pointers in file structure (used internally by ALSA)
521 pHandle->file.f_dentry = &pHandle->d_entry;
522 pHandle->file.f_dentry->d_inode = &pHandle->inode;
523
524 switch(streamtype) {
525 case OSS32_STREAM_WAVEOUT:
526 pHandle->file.f_mode = FMODE_WRITE;
527 pHandle->inode.i_rdev = SNDRV_MINOR(deviceid, SNDRV_MINOR_PCM_PLAYBACK) + pcm;
528 break;
529 case OSS32_STREAM_WAVEIN:
530 pHandle->file.f_mode = FMODE_READ;
531 pHandle->inode.i_rdev = SNDRV_MINOR(deviceid, SNDRV_MINOR_PCM_CAPTURE) + pcm;
532 break;
533 default:
534 DebugInt3();
535 kfree(pHandle);
536 rprintf(("OSS32_WaveOpen: invalid parameter\n"));
537 return OSSERR_INVALID_PARAMETER;
538 }
539
540 ret = alsa_fops->open(&pHandle->inode, &pHandle->file);
541 //dprintf(("OSS32_WaveOpen. ret: %i\n", ret));
542 /* check if PCM already opened (stupid uniaud16.sys doesnt closes it) */
543 if (ret == -16)
544 {
545 for (i=0; i < 8*256; i++)
546 {
547 if (opened_handles[i].handle != 0)
548 {
549 ret = 0;
550 if (pStreamId)
551 *pStreamId = (ULONG)opened_handles[i].handle;
552 opened_handles[i].reuse = 1; /* try to reuse */
553 if (OSS32_WaveClose((OSSSTREAMID)opened_handles[i].handle) == 0)
554 {
555 if (!opened_handles[i].reuse)
556 {
557 //opened_handles[i].handle = 0;
558 kfree(opened_handles[i].handle); //free handle data
559 ret = alsa_fops->open(&pHandle->inode, &pHandle->file);
560 dprintf(("OSS32_WaveOpen. Reopen ret: %i\n", ret));
561 }
562 else
563 {
564 kfree(pHandle);
565 pHandle = opened_handles[i].handle;
566 }
567 break;
568 }
569 }
570 }
571 }
572 else if (ret == 0)
573 {
574 for (i=0; i < 8*256; i++)
575 {
576 if (opened_handles[i].handle == 0)
577 {
578 opened_handles[i].handle = pHandle;
579 opened_handles[i].FileId = fileid;
580 break;
581 }
582 }
583 }
584
585 if(ret) {
586 kfree(pHandle);
587 DebugInt3();
588 rprintf(("OSS32_WaveOpen: open error: %i\n",ret));
589 return UNIXToOSSError(ret);
590 }
591 pHandle->magic = MAGIC_WAVE_ALSA32;
592 if (pStreamId)
593 *pStreamId = (ULONG)pHandle;
594 // filling opened handles table
595 dprintf(("OSS32_WaveOpen. streamid %X\n",(ULONG)pHandle));
596 return OSSERR_SUCCESS;
597}
598//******************************************************************************
599//******************************************************************************
600
601OSSRET OSS32_WaveClose(OSSSTREAMID streamid)
602{
603 soundhandle *pHandle = (soundhandle *)streamid;
604 int ret = 0, i;
605
606 if(pHandle == NULL || pHandle->magic != MAGIC_WAVE_ALSA32) {
607 DebugInt3();
608 rprintf(("OSS32_WaveClose. invalid streamid %X\n",(ULONG)pHandle));
609 return OSSERR_INVALID_STREAMID;
610 }
611
612 //set operation to non-blocking
613 pHandle->file.f_flags = O_NONBLOCK;
614
615 for (i=0; i < 8*256; i++)
616 {
617 if (opened_handles[i].handle == pHandle)
618 {
619 dprintf(("Found phandle for closing: %x reuse flag: %i\n", pHandle, opened_handles[i].reuse));
620 if (!opened_handles[i].reuse)
621 {
622 ret = pHandle->file.f_op->release(&pHandle->inode, &pHandle->file);
623 opened_handles[i].handle = 0;
624 kfree(pHandle); //free handle data
625 OSS32_CloseUNI16(); /* say to UNIAUD16 that we closing now */
626 } else
627 {
628 /* prepare for reuse */
629 pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_RESET, 0);
630 pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_PREPARE, 0);
631 }
632 break;
633 }
634 }
635
636 if (i >= 8*256)
637 {
638 //all already closed
639 dprintf(("phandle %x not found\n", pHandle));
640// return OSSERR_SUCCESS;
641 }
642
643
644 if(ret) {
645 dprintf(("Error closing wave. rc = %i\n", ret));
646 DebugInt3();
647 return UNIXToOSSError(ret);
648 }
649 dprintf(("OSS32_WaveClose. streamid %X\n", (ULONG)pHandle));
650 return OSSERR_SUCCESS;
651}
652//******************************************************************************
653//******************************************************************************
654OSSRET OSS32_WavePrepare(OSSSTREAMID streamid)
655{
656 soundhandle *pHandle = (soundhandle *)streamid;
657 int ret;
658
659 dprintf(("OSS32_WavePrepare"));
660
661 if(pHandle == NULL || pHandle->magic != MAGIC_WAVE_ALSA32) {
662 DebugInt3();
663 rprintf(("vladest: OSS32_WavePrepare: invalid streamID\n"));
664
665 return OSSERR_INVALID_STREAMID;
666 }
667 //set operation to non-blocking
668 pHandle->file.f_flags = O_NONBLOCK;
669
670 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_PREPARE, 0);
671 if (ret)
672 rprintf(("Wave prepare ret = %i, streamid %X\n",ret,(ULONG)pHandle));
673
674 return UNIXToOSSError(ret);;
675}
676//******************************************************************************
677//******************************************************************************
678OSSRET OSS32_WaveStart(OSSSTREAMID streamid)
679{
680 soundhandle *pHandle = (soundhandle *)streamid;
681 int ret;
682
683 if(pHandle == NULL || pHandle->magic != MAGIC_WAVE_ALSA32) {
684 DebugInt3();
685 return OSSERR_INVALID_STREAMID;
686 }
687 //set operation to non-blocking
688 pHandle->file.f_flags = O_NONBLOCK;
689 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_START, 0);
690 if (ret)
691 rprintf(("Wave start ret = %i, streamid %X\n",ret,(ULONG)pHandle));
692
693 return UNIXToOSSError(ret);;
694}
695//******************************************************************************
696//******************************************************************************
697OSSRET OSS32_WaveStop(OSSSTREAMID streamid)
698{
699 soundhandle *pHandle = (soundhandle *)streamid;
700 int ret;
701
702 if(pHandle == NULL || pHandle->magic != MAGIC_WAVE_ALSA32) {
703 DebugInt3();
704 return OSSERR_INVALID_STREAMID;
705 }
706 //set operation to non-blocking
707 pHandle->file.f_flags = O_NONBLOCK;
708
709 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_DROP, 0);
710 if (ret)
711 rprintf(("Wave stop ret = %i. streamid %X\n",ret,(ULONG)pHandle));
712
713 return UNIXToOSSError(ret);;
714}
715//******************************************************************************
716//******************************************************************************
717OSSRET OSS32_WavePause(OSSSTREAMID streamid)
718{
719 soundhandle *pHandle = (soundhandle *)streamid;
720 int ret;
721
722 if(pHandle == NULL || pHandle->magic != MAGIC_WAVE_ALSA32) {
723 DebugInt3();
724 return OSSERR_INVALID_STREAMID;
725 }
726 //set operation to non-blocking
727 pHandle->file.f_flags = O_NONBLOCK;
728
729 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_PAUSE, 0);
730 if (ret)
731 rprintf(("Wave pause ret = %i, streamid %X\n",ret,(ULONG)pHandle));
732
733 return UNIXToOSSError(ret);;
734}
735//******************************************************************************
736//******************************************************************************
737OSSRET OSS32_WaveResume(OSSSTREAMID streamid)
738{
739 soundhandle *pHandle = (soundhandle *)streamid;
740 int ret;
741
742 if(pHandle == NULL || pHandle->magic != MAGIC_WAVE_ALSA32) {
743 DebugInt3();
744 return OSSERR_INVALID_STREAMID;
745 }
746 //set operation to non-blocking
747 pHandle->file.f_flags = O_NONBLOCK;
748
749 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_PAUSE, 1);
750 if (ret)
751 rprintf(("Wave resume ret = %i, streamid %X\n",ret,(ULONG)pHandle));
752
753 return UNIXToOSSError(ret);;
754}
755
756static unsigned rates[] = {
757 /* ATTENTION: these values depend on the definition in pcm.h! */
758 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000,
759 64000, 88200, 96000, 176400, 192000
760};
761
762//******************************************************************************
763//******************************************************************************
764OSSRET OSS32_WaveSetHwParams(OSSSTREAMID streamid, OSS32_HWPARAMS *pHwParams)
765{
766 soundhandle *pHandle = (soundhandle *)streamid;
767 struct snd_pcm_hw_params params;
768 struct snd_pcm_sw_params swparams;
769 struct snd_pcm_status status;
770
771 int ret, nrperiods, minnrperiods, maxnrperiods, samplesize,i;
772 ULONG bufsize, periodsize, minperiodsize, maxperiodsize;
773 ULONG periodbytes, minperiodbytes, maxperiodbytes;
774 BOOL fTryAgain = FALSE;
775 ULONG ulMinRate, ulMaxRate;
776
777 if(pHandle == NULL || pHandle->magic != MAGIC_WAVE_ALSA32) {
778
779 DebugInt3();
780 return OSSERR_INVALID_STREAMID;
781 }
782 if(pHwParams == NULL) {
783
784 DebugInt3();
785 return OSSERR_INVALID_PARAMETER;
786 }
787 if(pHwParams->ulDataType >= OSS32_PCM_MAX_FORMATS) {
788
789 DebugInt3();
790 return OSSERR_INVALID_PARAMETER;
791 }
792 if ((int)pHwParams->ulNumChannels <= 0) {
793 rprintf(("OSS32_WaveSetHwParams error. Invalid number of channels: %i\n", pHwParams->ulNumChannels));
794 DebugInt3();
795 return OSSERR_INVALID_PARAMETER;
796 }
797tryagain:
798 //set operation to non-blocking
799 pHandle->file.f_flags = O_NONBLOCK;
800
801 //size of two samples (adpcm sample can be as small as 4 bits (mono), so take two)
802 samplesize = snd_pcm_format_size(OSSToALSADataType[pHwParams->ulDataType], 1);
803 pHandle->doublesamplesize = samplesize * 2;
804 pHandle->doublesamplesize *= pHwParams->ulNumChannels;
805 periodbytes = pHwParams->ulPeriodSize;
806 periodsize = bytes_to_samples(periodbytes);
807 // checking number of channels
808
809 dprintf(("channels: %ld, period size: %lx",pHwParams->ulNumChannels, periodbytes));
810
811 _snd_pcm_hw_params_any(&params);
812 do {
813 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_ACCESS,
814 SNDRV_PCM_ACCESS_RW_INTERLEAVED, 0);
815 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_CHANNELS,
816 pHwParams->ulNumChannels, 0);
817 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_HW_REFINE, (ULONG)__Stack32ToFlat(&params));
818 if (ret == 0) break;
819 pHwParams->ulNumChannels--;
820 } while(ret < 0 && pHwParams->ulNumChannels > 1);
821
822 dprintf(("channels selected: %d",pHwParams->ulNumChannels));
823
824 //get all hardware parameters
825 _snd_pcm_hw_params_any(&params);
826 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_ACCESS,
827 SNDRV_PCM_ACCESS_RW_INTERLEAVED, 0);
828 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_FORMAT,
829 OSSToALSADataType[pHwParams->ulDataType], 0);
830 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_HW_REFINE, (ULONG)__Stack32ToFlat(&params));
831 if(ret != 0) {
832 rprintf(("invalid format %lx\n", OSSToALSADataType[pHwParams->ulDataType]));
833 return UNIXToOSSError(ret);
834 }
835 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
836 pHwParams->ulBitsPerSample, 0);
837 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_HW_REFINE, (ULONG)__Stack32ToFlat(&params));
838 if(ret != 0) {
839 rprintf(("invalid number of sample bits %d\n", pHwParams->ulBitsPerSample));
840 return UNIXToOSSError(ret);
841 }
842 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_FRAME_BITS,
843 pHwParams->ulBitsPerSample*pHwParams->ulNumChannels, 0);
844 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_HW_REFINE, (ULONG)__Stack32ToFlat(&params));
845 if(ret != 0) {
846 rprintf(("invalid number of frame bits %d\n", pHwParams->ulBitsPerSample*pHwParams->ulNumChannels));
847 return UNIXToOSSError(ret);
848 }
849
850 //_snd_pcm_hw_params_any(&params);
851 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
852 pHwParams->ulBitsPerSample, 0);
853 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_FRAME_BITS,
854 pHwParams->ulBitsPerSample*pHwParams->ulNumChannels, 0);
855 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_FORMAT,
856 OSSToALSADataType[pHwParams->ulDataType], 0);
857 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_CHANNELS,
858 pHwParams->ulNumChannels, 0);
859 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_RATE,
860 pHwParams->ulSampleRate, 0);
861 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_HW_REFINE, (ULONG)__Stack32ToFlat(&params));
862 if(ret != 0) {
863 rprintf(("32_WSetHwPms (first pass) error %d bps:%d fmt: %d ch: %d sr: %d\n",
864 ret,
865 pHwParams->ulBitsPerSample,
866 OSSToALSADataType[pHwParams->ulDataType],
867 pHwParams->ulNumChannels,
868 pHwParams->ulSampleRate));
869 //printk("OSS32_WaveSetHwParams invalid sample rate %i\n", pHwParams->ulSampleRate);
870 // printk("will set to nearest\n");
871 _snd_pcm_hw_params_any(&params);
872 for (i=0; i<(sizeof(rates)/sizeof(unsigned))-1;i++)
873 {
874 if (pHwParams->ulSampleRate >= rates[i] &&
875 pHwParams->ulSampleRate <= rates[i+1])
876 {
877 pHwParams->ulSampleRate = rates[i];
878 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_RATE,
879 pHwParams->ulSampleRate, 0);
880 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_HW_REFINE, (ULONG)__Stack32ToFlat(&params));
881 if(ret == 0)
882 {
883 _snd_pcm_hw_params_any(&params);
884 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
885 pHwParams->ulBitsPerSample, 0);
886 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_FRAME_BITS,
887 pHwParams->ulBitsPerSample*pHwParams->ulNumChannels, 0);
888 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_FORMAT,
889 OSSToALSADataType[pHwParams->ulDataType], 0);
890 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_CHANNELS,
891 pHwParams->ulNumChannels, 0);
892 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_RATE,
893 pHwParams->ulSampleRate, 0);
894 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_HW_REFINE, (ULONG)__Stack32ToFlat(&params));
895 goto __next;
896 }
897 }
898 }
899 DebugInt3();
900 return UNIXToOSSError(ret);
901 }
902 __next:
903
904 //check period size against lower and upper boundaries
905 minperiodbytes = hw_param_interval((&params), SNDRV_PCM_HW_PARAM_PERIOD_BYTES)->min;
906 maxperiodbytes = hw_param_interval((&params), SNDRV_PCM_HW_PARAM_PERIOD_BYTES)->max;
907 if(periodbytes < minperiodbytes) {
908 periodbytes = minperiodbytes;
909 }
910 else
911 if(periodbytes > maxperiodbytes) {
912 periodbytes = maxperiodbytes;
913 }
914
915 minperiodsize = hw_param_interval((&params), SNDRV_PCM_HW_PARAM_PERIOD_SIZE)->min;
916 maxperiodsize = hw_param_interval((&params), SNDRV_PCM_HW_PARAM_PERIOD_SIZE)->max;
917 if(periodsize < minperiodsize) {
918 periodsize = minperiodsize;
919 }
920 else
921 if(periodsize > maxperiodsize) {
922 periodsize = maxperiodsize;
923 }
924
925 if(samples_to_bytes(periodsize) < periodbytes) {
926 periodbytes = samples_to_bytes(periodsize);
927 }
928 else
929 if(bytes_to_samples(periodbytes) < periodsize) {
930 periodsize = bytes_to_samples(periodbytes);
931 }
932
933 //make sure period size is a whole fraction of the buffer size
934 bufsize = hw_param_interval((&params), SNDRV_PCM_HW_PARAM_BUFFER_BYTES)->max;
935 if(periodsize) {
936 nrperiods = bufsize/periodbytes;
937 }
938 else {
939 rprintf(("32_WSHwPrms error. Invalid periodsize (=0). closing file\n"));
940 DebugInt3();
941 return OSSERR_INVALID_PARAMETER;
942 }
943 //check nr of periods against lower and upper boundaries
944 minnrperiods = hw_param_interval((&params), SNDRV_PCM_HW_PARAM_PERIODS)->min;
945 maxnrperiods = hw_param_interval((&params), SNDRV_PCM_HW_PARAM_PERIODS)->max;
946 if(nrperiods < minnrperiods) {
947 nrperiods = minnrperiods;
948 }
949 else
950 if(nrperiods > maxnrperiods) {
951 nrperiods = maxnrperiods;
952 }
953 //an odd nr of periods is not always a good thing (CMedia -> clicks during 8 bps playback),
954 //so we make sure it's an even number.
955 if(nrperiods == 1) {
956 rprintf(("32_WSHwPrms error. Invalid Num periods(=1). closing file\n"));
957 DebugInt3();
958 return OSSERR_INVALID_PARAMETER;
959 }
960 nrperiods &= ~1;
961
962 //initialize parameter block & set sample rate, nr of channels and sample format, nr of periods,
963 //period size and buffer size
964
965 _snd_pcm_hw_params_any(&params);
966 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_ACCESS,
967 SNDRV_PCM_ACCESS_RW_INTERLEAVED, 0);
968 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
969 pHwParams->ulBitsPerSample, 0);
970 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_FRAME_BITS,
971 pHwParams->ulBitsPerSample*pHwParams->ulNumChannels, 0);
972 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_FORMAT,
973 OSSToALSADataType[pHwParams->ulDataType], 0);
974 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_CHANNELS,
975 pHwParams->ulNumChannels, 0);
976 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_RATE,
977 pHwParams->ulSampleRate, 0);
978 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
979 periodsize, 0);
980 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
981 periodbytes, 0);
982 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_PERIODS,
983 nrperiods, 0);
984 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
985 periodsize*nrperiods, 0);
986 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
987 periodbytes*nrperiods, 0);
988
989
990 dprintf(("HWP: SR rate %ld, BPS %ld, CH %ld, PRSZ %lx, periods %lx",
991 pHwParams->ulSampleRate, pHwParams->ulBitsPerSample, pHwParams->ulNumChannels, periodsize, nrperiods));
992
993 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_HW_PARAMS, (ULONG)__Stack32ToFlat(&params));
994 if (ret == -77 && fTryAgain == FALSE)
995 {
996 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_PREPARE, 0);
997 fTryAgain = TRUE;
998 rprintf((" Error -77 from first IOCTL HW Parms"));
999 goto tryagain;
1000 }
1001
1002 if(ret) {
1003 if(fTryAgain == FALSE) {
1004 minperiodsize = hw_param_interval((&params), SNDRV_PCM_HW_PARAM_PERIOD_SIZE)->min;
1005 maxperiodsize = hw_param_interval((&params), SNDRV_PCM_HW_PARAM_PERIOD_SIZE)->max;
1006 dprintf(("Period size min=%lx max=%lx", minperiodsize, maxperiodsize));
1007 if(minperiodsize > maxperiodsize) {
1008 //ALSA doesn't like the period size; try suggested one
1009 periodsize = maxperiodsize;
1010 periodbytes = samples_to_bytes(periodsize);
1011 dprintf((" Peroid size error IOCTL HW Parms"));
1012 fTryAgain = TRUE;
1013 goto tryagain;
1014 }
1015 }
1016 rprintf(("Error %ld second time.. Bailing", ret));
1017 return UNIXToOSSError(ret);
1018 }
1019
1020 //set silence threshold (all sizes in frames) (only needed for playback)
1021 if(pHandle->file.f_mode == FMODE_WRITE)
1022 {
1023 swparams.avail_min = periodsize;
1024 swparams.period_step = 1;
1025 if(nrperiods <= 2) {
1026 swparams.silence_size = (periodsize/2);
1027 }
1028 else {
1029 swparams.silence_size = periodsize;
1030 }
1031 swparams.silence_threshold = swparams.silence_size;
1032 swparams.sleep_min = 0;
1033 swparams.start_threshold = 1;
1034 swparams.stop_threshold = periodsize*nrperiods;
1035 swparams.tstamp_mode = SNDRV_PCM_TSTAMP_NONE;
1036 swparams.xfer_align = periodsize;
1037
1038 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_SW_PARAMS, (ULONG)__Stack32ToFlat(&swparams));
1039 }
1040
1041 total = 0;
1042 per_bytes = periodbytes;
1043 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_STATUS, (ULONG)__Stack32ToFlat(&status));
1044 if ( ((status.state != SNDRV_PCM_STATE_PREPARED) &&
1045 (status.state != SNDRV_PCM_STATE_SETUP) &&
1046 (status.state != SNDRV_PCM_STATE_RUNNING) &&
1047 (status.state != SNDRV_PCM_STATE_DRAINING))) {
1048 rprintf(("Device is not in proper state: %lx. Calling prepare\n", status.state));
1049 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_PREPARE, 0);
1050 }
1051 return UNIXToOSSError(ret);
1052}
1053
1054
1055//******************************************************************************
1056ULONG CountWv=0;
1057ULONG LockAdd=0;
1058extern ULONG xchg( ULONG *p, ULONG x);
1059#pragma aux xchg = "xchg [esi],eax" parm [ESI][EAX] value [EAX];
1060//******************************************************************************
1061OSSRET OSS32_WaveAddBuffer(OSSSTREAMID streamid, ULONG ulBuffer, ULONG ulReqSize, ULONG *pulTransferred, int pcm)
1062{
1063 soundhandle *pHandle = (soundhandle *)streamid;
1064 struct snd_pcm_status status;
1065 int iRet, align, iRet1;
1066 LONG ulTransferred;
1067 ULONG ulPosition, ulI, ulJ, ulSize;
1068 char *buf;
1069
1070// return OSSERR_SUCCESS;
1071
1072 if(pHandle == NULL || pHandle->magic != MAGIC_WAVE_ALSA32) {
1073 DebugInt3();
1074 return OSSERR_INVALID_STREAMID;
1075 }
1076 if(pulTransferred == NULL || ulBuffer == 0 || ulReqSize == 0) {
1077 DebugInt3();
1078 return OSSERR_INVALID_PARAMETER;
1079 }
1080
1081 //set operation to non-blocking
1082 pHandle->file.f_flags = O_NONBLOCK;
1083
1084 /* get the status of the circular dma buffer */
1085 iRet = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_STATUS, (ULONG)__Stack32ToFlat(&status));
1086
1087 if(iRet) {
1088 DebugInt3();
1089 return UNIXToOSSError(iRet);
1090 }
1091
1092 CountWv++;
1093 ulTransferred = 0;
1094 *pulTransferred = 0;
1095 switch(SNDRV_MINOR_DEVICE(MINOR(pHandle->inode.i_rdev-pcm)))
1096 {
1097 case SNDRV_MINOR_PCM_PLAYBACK:
1098
1099#if 1
1100 //first check how much room is left in the circular dma buffer
1101 //this is done to make sure we don't block inside ALSA while trying to write
1102 //more data than fits in the internal dma buffer.
1103 ulSize = min(ulReqSize, samples_to_bytes(status.avail));
1104
1105 if (ulSize == 0) {
1106 rprintf(("OSS32_WaveAddBuffer: no room left in hardware buffer!!\n"));
1107 rprintf(("state=%x avail=%x ReqSize=%x\n", status.state, status.avail, ulReqSize));
1108 *pulTransferred = 0;
1109 return OSSERR_BUFFER_FULL;
1110 }
1111
1112 if (status.state == SNDRV_PCM_STATE_XRUN) {
1113 rprintf(("Internal Error: Xrun\n"));
1114 }
1115
1116 iRet = pHandle->file.f_op->write(&pHandle->file, (char *)ulBuffer, ulSize, &pHandle->file.f_pos);
1117
1118 if (iRet < 0 ) break;
1119 ulTransferred = iRet;
1120#else
1121 //first check how much room is left in the circular dma buffer
1122 //this is done to make sure we don't block inside ALSA while trying to write
1123 //more data than fits in the internal dma buffer.
1124 ulSize = min(ulReqSize, samples_to_bytes(status.avail));
1125
1126 //printk("OSS32_WaveAddBuffer N:%d hw=%x app=%x avail=%x req size=%x size=%x\n",
1127 // CountWv, samples_to_bytes(status.hw_ptr), samples_to_bytes(status.appl_ptr), samples_to_bytes(status.avail), ulSize, ulReqSize);
1128
1129 if (ulSize == 0) {
1130 rprintf(("OSS32_WaveAddBuffer: no room left in hardware buffer!!\n"));
1131 rprintf(("state=%x avail=%x SizeReq=%x\n", status.state, status.avail, ulReqSize));
1132 *pulTransferred = 0;
1133 return OSSERR_BUFFER_FULL;
1134 }
1135
1136 // size should be aligned to channels number * samplesize //PS+++ what is it and why?!?!?!
1137 ulJ = 10; // 10 try if error
1138 iRet = -11;
1139 while (ulSize && ulJ && iRet)
1140 {
1141 for (ulI=0; ulI < 1000; ulI++)
1142 {
1143 iRet1 = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_STATUS, (ULONG)__Stack32ToFlat(&status));
1144 // If here any state and have free buffer to any byte
1145 if ((status.state != SNDRV_PCM_STATE_XRUN ) && samples_to_bytes(status.avail) ) break;
1146 if (status.state == SNDRV_PCM_STATE_XRUN) {
1147 rprintf(("Internal Error: Xrun\n"));
1148 }
1149 if (ulI > 998) {
1150 // printk("timeout stat %x avail:%d hw:%d app:%d\n",status.state,samples_to_bytes(status.avail),samples_to_bytes(status.hw_ptr), samples_to_bytes(status.appl_ptr));
1151 iRet1 = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_PREPARE, 0);
1152 }
1153 }
1154
1155 if (iRet1 < 0) {
1156 // printk("Status Error iRet1:%i trans: %i need %d tot:%d\n",iRet1,ulTransferred, ulReqSize,ulSize);
1157 break; // We have any global error, don't try more
1158 }
1159
1160 iRet = pHandle->file.f_op->write(&pHandle->file, (char *)ulBuffer, ulSize, &pHandle->file.f_pos);
1161
1162 if (iRet < 0 ) { // We have any error, don't try more
1163 ulJ--;
1164 if ( iRet != -11 )
1165 iRet1 = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_PREPARE, 0);
1166 // printk("Error ret:%i ret1:%i trans: %d need %d tot:%d\n",iRet,iRet1,ulTransferred, ulReqSize,ulSize);
1167 continue;
1168 }
1169 if (iRet == 0) continue;
1170 ulTransferred += iRet;
1171 // printk("written: now: %d, trans: %d need %d tot:%d\n", iRet, ulTransferred, ulReqSize,ulSize);
1172 ulBuffer += iRet;
1173 if (ulSize > iRet) ulSize -= iRet;
1174 else ulSize = 0;
1175 }
1176#endif
1177 break;
1178 case SNDRV_MINOR_PCM_CAPTURE:
1179 //printk("OSS32_WaveAddBuffer N:%d state=%x hw=%x app=%x avail=%x size=%x\n",
1180 // CountWv, status.state, samples_to_bytes(status.hw_ptr), samples_to_bytes(status.appl_ptr), samples_to_bytes(status.avail), ulReqSize);
1181// Need to handle overrun condition when reading
1182// if (status.state == SNDRV_PCM_STATE_XRUN) {
1183// *pulTransferred = 0;
1184// return OSSERR_BUFFER_FULL;
1185// }
1186 iRet = pHandle->file.f_op->read(&pHandle->file, (char *)ulBuffer, ulReqSize, &pHandle->file.f_pos);
1187 if (iRet < 0) {
1188 *pulTransferred = 0;
1189 return OSSERR_BUFFER_FULL;
1190 }
1191 ulTransferred = iRet;
1192 break;
1193 default:
1194 DebugInt3();
1195 return OSSERR_INVALID_PARAMETER;
1196 }
1197
1198 total += ulTransferred;
1199 *pulTransferred = ulTransferred;
1200 prev_size = ulTransferred;
1201// if (*pulTransferred < ulSize)
1202// {
1203// printk("warning: ulTransferred [%d] less than requested [%d]\n", *pulTransferred, ulSize);
1204// iRet1 = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_PREPARE, 0);
1205// }
1206
1207 return OSSERR_SUCCESS;
1208}
1209//******************************************************************************
1210//******************************************************************************
1211OSSRET OSS32_WaveGetPosition(ULONG streamid, ULONG *pPosition)
1212{
1213 soundhandle *pHandle = (soundhandle *)streamid;
1214 struct snd_pcm_status status;
1215 int ret;
1216
1217 if(pHandle == NULL || pHandle->magic != MAGIC_WAVE_ALSA32) {
1218 DebugInt3();
1219 return OSSERR_INVALID_STREAMID;
1220 }
1221 if(pPosition == NULL) {
1222 DebugInt3();
1223 return OSSERR_INVALID_PARAMETER;
1224 }
1225
1226 //set operation to non-blocking
1227 pHandle->file.f_flags = O_NONBLOCK;
1228
1229 //Get the status of the stream
1230 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_STATUS, (ULONG)__Stack32ToFlat(&status));
1231
1232 if(ret) {
1233 DebugInt3();
1234 return UNIXToOSSError(ret);
1235 }
1236
1237 dprintf2(("OSS32_WaveGetPosition: hardware %x application %x", samples_to_bytes(status.hw_ptr), samples_to_bytes(status.appl_ptr)));
1238 *pPosition = samples_to_bytes(status.hw_ptr); //return new hardware position
1239 return OSSERR_SUCCESS;
1240}
1241//******************************************************************************
1242//******************************************************************************
1243OSSRET OSS32_WaveGetSpace(ULONG streamid, ULONG *pBytesAvail)
1244{
1245 soundhandle *pHandle = (soundhandle *)streamid;
1246 struct snd_pcm_status status;
1247 int ret;
1248
1249 if(pHandle == NULL || pHandle->magic != MAGIC_WAVE_ALSA32) {
1250 DebugInt3();
1251 return OSSERR_INVALID_STREAMID;
1252 }
1253 if(pBytesAvail == NULL) {
1254 DebugInt3();
1255 return OSSERR_INVALID_PARAMETER;
1256 }
1257
1258 //set operation to non-blocking
1259 pHandle->file.f_flags = O_NONBLOCK;
1260
1261 //Get the nr of bytes left in the audio buffer
1262 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_STATUS, (ULONG)__Stack32ToFlat(&status));
1263
1264 if(ret) {
1265 DebugInt3();
1266 return UNIXToOSSError(ret);
1267 }
1268 ret = samples_to_bytes(status.avail);
1269
1270 *pBytesAvail = ret;
1271 return OSSERR_SUCCESS;
1272}
1273//******************************************************************************
1274//******************************************************************************
1275OSSRET OSS32_WaveGetHwPtr(ULONG streamid, ULONG *pPosition)
1276{
1277 soundhandle *pHandle = (soundhandle *)streamid;
1278 struct snd_pcm_status status;
1279 int ret;
1280
1281 if(pHandle == NULL || pHandle->magic != MAGIC_WAVE_ALSA32) {
1282 DebugInt3();
1283 return OSSERR_INVALID_STREAMID;
1284 }
1285 if(pPosition == NULL) {
1286 DebugInt3();
1287 return OSSERR_INVALID_PARAMETER;
1288 }
1289
1290 //set operation to non-blocking
1291 pHandle->file.f_flags = O_NONBLOCK;
1292
1293 //Get the status of the stream
1294 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_STATUS, (ULONG)__Stack32ToFlat(&status));
1295
1296 if(ret) {
1297 DebugInt3();
1298 return UNIXToOSSError(ret);
1299 }
1300
1301 *pPosition = samples_to_bytes(status.appl_ptr); //return new hardware position
1302 return OSSERR_SUCCESS;
1303}
1304//******************************************************************************
1305//******************************************************************************
1306OSSRET OSS32_WaveGetStatus(ULONG streamid, ULONG *pStatus)
1307{
1308 soundhandle *pHandle = (soundhandle *)streamid;
1309 struct snd_pcm_status status;
1310 int ret;
1311
1312 if(pHandle == NULL || pHandle->magic != MAGIC_WAVE_ALSA32) {
1313 DebugInt3();
1314 return OSSERR_INVALID_STREAMID;
1315 }
1316 if(pStatus == NULL) {
1317 DebugInt3();
1318 return OSSERR_INVALID_PARAMETER;
1319 }
1320
1321 //set operation to non-blocking
1322 pHandle->file.f_flags = O_NONBLOCK;
1323
1324 //Get the status of the stream
1325 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_STATUS, (ULONG)__Stack32ToFlat(&status));
1326
1327 if(ret) {
1328 DebugInt3();
1329 return UNIXToOSSError(ret);
1330 }
1331
1332 *pStatus = status.state;
1333 return OSSERR_SUCCESS;
1334}
1335//******************************************************************************
1336//******************************************************************************
1337OSSRET OSS32_WaveSetVolume(OSSSTREAMID streamid, ULONG volume)
1338{
1339 soundhandle *pHandle = (soundhandle *)streamid;
1340 int ret;
1341 int leftvol, rightvol;
1342 struct snd_pcm_volume pcm_volume;
1343
1344 if(pHandle == NULL || pHandle->magic != MAGIC_WAVE_ALSA32) {
1345 DebugInt3();
1346 return OSSERR_INVALID_STREAMID;
1347 }
1348 //set operation to non-blocking
1349 pHandle->file.f_flags = O_NONBLOCK;
1350
1351 leftvol = GET_VOLUME_L(volume);
1352 rightvol = GET_VOLUME_R(volume);
1353
1354 pcm_volume.nrchannels = 4;
1355 pcm_volume.volume[SNDRV_PCM_VOL_FRONT_LEFT] = leftvol;
1356 pcm_volume.volume[SNDRV_PCM_VOL_FRONT_RIGHT] = rightvol;
1357 pcm_volume.volume[SNDRV_PCM_VOL_REAR_LEFT] = leftvol;
1358 pcm_volume.volume[SNDRV_PCM_VOL_REAR_RIGHT] = rightvol;
1359
1360 dprintf(("OSS32_WaveSetVolume %x to (%d,%d)", streamid, leftvol, rightvol));
1361 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_SETVOLUME, (ULONG)__Stack32ToFlat(&pcm_volume));
1362 return UNIXToOSSError(ret);
1363}
1364//******************************************************************************
1365
Note: See TracBrowser for help on using the repository browser.