source: GPL/trunk/lib32/sound.c@ 475

Last change on this file since 475 was 475, checked in by Paul Smedley, 16 years ago

Buffer fix from Pasha to reserv more space for playback

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