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

Last change on this file since 86 was 86, checked in by vladest, 19 years ago

Added missed files
Applied latest modifications of ALSA
Reworked sharing strategy between MMOS2 and UNIAUD API

File size: 52.8 KB
Line 
1/* $Id: sound.c,v 1.2 2003/08/08 15:09:03 vladest Exp $ */
2/*
3 * MMPM/2 to OSS interface translation layer
4 *
5 * (C) 2000-2002 InnoTek Systemberatung GmbH
6 * (C) 2000-2001 Sander van Leeuwen (sandervl@xs4all.nl)
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public
19 * License along with this program; if not, write to the Free
20 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
21 * USA.
22 *
23 */
24
25#include <sound/driver.h>
26#include <sound/control.h>
27#include <sound/info.h>
28#include <sound/pcm.h>
29#include <sound/pcm_params.h>
30#include <sound/minors.h>
31#include <linux/file.h>
32#include <linux/soundcard.h>
33
34#define LINUX
35#include <ossidc32.h>
36#include <osspci.h>
37#include <stacktoflat.h>
38#include <stdlib.h>
39#include "soundoss.h"
40
41#undef samples_to_bytes
42#undef bytes_to_samples
43#define samples_to_bytes(a) ((a*pHandle->doublesamplesize)/2)
44#define bytes_to_samples(a) (pHandle->doublesamplesize ? ((a*2)/pHandle->doublesamplesize) : a)
45
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;
54int pcm_instances = 0;
55
56OpenedHandles opened_handles[8 * 256] = {0};
57
58//OSS32 to ALSA datatype conversion table
59static 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 if(fuRates & SNDRV_PCM_RATE_5512) {
258 fuOSSRates |= OSS32_CAPS_PCM_RATE_5512;
259 }
260 if(fuRates & SNDRV_PCM_RATE_8000) {
261 fuOSSRates |= OSS32_CAPS_PCM_RATE_8000;
262 }
263 if(fuRates & SNDRV_PCM_RATE_11025) {
264 fuOSSRates |= OSS32_CAPS_PCM_RATE_11025;
265 }
266 if(fuRates & SNDRV_PCM_RATE_16000) {
267 fuOSSRates |= OSS32_CAPS_PCM_RATE_16000;
268 }
269 if(fuRates & SNDRV_PCM_RATE_22050) {
270 fuOSSRates |= OSS32_CAPS_PCM_RATE_22050;
271 }
272 if(fuRates & SNDRV_PCM_RATE_32000) {
273 fuOSSRates |= OSS32_CAPS_PCM_RATE_32000;
274 }
275 if(fuRates & SNDRV_PCM_RATE_44100) {
276 fuOSSRates |= OSS32_CAPS_PCM_RATE_44100;
277 }
278 if(fuRates & SNDRV_PCM_RATE_48000) {
279 fuOSSRates |= OSS32_CAPS_PCM_RATE_48000;
280 }
281#if 0
282 if(fuRates & SNDRV_PCM_RATE_64000) {
283 fuOSSRates |= OSS32_CAPS_PCM_RATE_64000;
284 }
285 if(fuRates & SNDRV_PCM_RATE_88200) {
286 fuOSSRates |= OSS32_CAPS_PCM_RATE_88200;
287 }
288 if(fuRates & SNDRV_PCM_RATE_96000) {
289 fuOSSRates |= OSS32_CAPS_PCM_RATE_96000;
290 }
291 if(fuRates & SNDRV_PCM_RATE_176400) {
292 fuOSSRates |= OSS32_CAPS_PCM_RATE_176400;
293 }
294 if(fuRates & SNDRV_PCM_RATE_192000) {
295 fuOSSRates |= OSS32_CAPS_PCM_RATE_192000;
296 }
297#endif
298 if(fuRates & SNDRV_PCM_RATE_CONTINUOUS) {
299 fuOSSRates |= OSS32_CAPS_PCM_RATE_CONTINUOUS;
300 }
301
302 //TODO:
303 if(fuRates & SNDRV_PCM_RATE_KNOT) {
304 DebugInt3();
305 }
306//#define OSS32_CAPS_PCM_RATE_KNOT (1<<31) /* supports more non-continuos rates */
307
308 return fuOSSRates;
309}
310//******************************************************************************
311//******************************************************************************
312OSSRET OSS32_QueryDevCaps(ULONG deviceid, POSS32_DEVCAPS pDevCaps)
313{
314 OSSSTREAMID streamid = 0;
315 soundhandle *pHandle;
316 snd_pcm_info_t *pcminfo = NULL;
317 snd_pcm_hw_params_t *params;
318 int ret, fmt, i;
319 ULONG format_mask;
320 snd_mask_t *mask;
321 int max_ch;
322
323#ifdef DEBUG
324 dprintf(("OSS32_QueryDevCaps"));
325#endif
326// max_ch = GetMaxChannels(deviceid, OSS32_CAPS_WAVE_PLAYBACK);
327
328 //these structures are too big to put on the stack
329 pcminfo = (snd_pcm_info_t *)kmalloc(sizeof(snd_pcm_info_t)+sizeof(snd_pcm_hw_params_t), GFP_KERNEL);
330 if(pcminfo == NULL) {
331 DebugInt3();
332 printk("OSS32_QueryDevCaps: out of memory\n");
333 return OSSERR_OUT_OF_MEMORY;
334 }
335 params = (snd_pcm_hw_params_t *)(pcminfo+1);
336
337// printk("Number of cards: %i\n",nrCardsDetected);
338// printk("dev id: %i\n",deviceid);
339 pDevCaps->nrDevices = 1;//nrCardsDetected;
340 pDevCaps->ulCaps = OSS32_CAPS_WAVE_PLAYBACK | OSS32_CAPS_WAVE_CAPTURE;
341
342 //query wave in & out caps
343 for(i=0;i<2;i++)
344 {
345 PWAVE_CAPS pWaveCaps = (i == 0) ? &pDevCaps->waveOutCaps : &pDevCaps->waveInCaps;
346
347 ret = OSS32_WaveOpen(deviceid, (i == 0) ? OSS32_STREAM_WAVEOUT : OSS32_STREAM_WAVEIN, &streamid, 0, 0);
348 if(ret != OSSERR_SUCCESS)
349 {
350 printk("OSS32_QueryDevCaps: wave open error %i\n", ret);
351 DebugInt3();
352 goto fail;
353 }
354 pHandle = (soundhandle *)streamid;
355 if(pHandle == NULL || pHandle->magic != MAGIC_WAVE_ALSA32) {
356 printk("OSS32_QueryDevCaps: invalid stream id \n");
357 ret = OSSERR_INVALID_STREAMID;
358 goto fail;
359 }
360 //set operation to non-blocking
361 pHandle->file.f_flags = O_NONBLOCK;
362
363 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_INFO, (ULONG)pcminfo);
364 if(ret != 0) {
365 printk("OSS32_QueryDevCaps: SNDRV_PCM_IOCTL_INFO error %i\n", ret);
366 ret = UNIXToOSSError(ret);
367 goto fail;
368 }
369 if(i == 0) {//only need to do this once
370 if(pcminfo->name[0]) {
371 strncpy(pDevCaps->szDeviceName, pcminfo->name, sizeof(pDevCaps->szDeviceName));
372 }
373 else strncpy(pDevCaps->szDeviceName, pcminfo->id, sizeof(pDevCaps->szDeviceName));
374 }
375 printk("Device name: %s\n", pDevCaps->szDeviceName);
376 pWaveCaps->nrStreams = pcminfo->subdevices_count;
377
378 //get all hardware parameters
379 _snd_pcm_hw_params_any(params);
380 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_HW_REFINE, (ULONG)params);
381 if(ret != 0) {
382 printk("OSS32_QueryDevCaps: SNDRV_PCM_IOCTL_HW_REFINE error %i\n", ret);
383 ret = UNIXToOSSError(ret);
384 goto fail;
385 }
386
387 pWaveCaps->ulMinChannels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS)->min;
388 pWaveCaps->ulMaxChannels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS)->max;
389 pWaveCaps->ulChanFlags = 0;
390 if(pWaveCaps->ulMinChannels == 1) {
391 pWaveCaps->ulChanFlags |= OSS32_CAPS_PCM_CHAN_MONO;
392 }
393 if(pWaveCaps->ulMaxChannels >= 2) {
394 pWaveCaps->ulChanFlags |= OSS32_CAPS_PCM_CHAN_STEREO;
395 }
396 if(pWaveCaps->ulMaxChannels >= 4) {
397 pWaveCaps->ulChanFlags |= OSS32_CAPS_PCM_CHAN_QUAD;
398 }
399 if(pWaveCaps->ulMaxChannels >= 6) {
400 pWaveCaps->ulChanFlags |= OSS32_CAPS_PCM_CHAN_5_1;
401 }
402
403 pWaveCaps->ulMinRate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->min;
404 pWaveCaps->ulMaxRate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->max;
405
406 mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_RATE_MASK);
407 pWaveCaps->ulRateFlags = mask->bits[0];
408
409 pWaveCaps->ulRateFlags = ALSAToOSSRateFlags(pWaveCaps->ulRateFlags);
410
411 printk("rate flags: %X\n", pWaveCaps->ulRateFlags);
412
413 pWaveCaps->ulDataFormats = 0;
414
415 mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
416 format_mask = mask->bits[0];
417 for(fmt=0;fmt<32;fmt++)
418 {
419 if(format_mask & (1 << fmt))
420 {
421 int f = ALSAToOSSDataType(fmt);
422 if (f >= 0)
423 pWaveCaps->ulDataFormats |= f;
424 }
425 }
426
427 OSS32_WaveClose(streamid);
428 streamid = 0;
429
430 }
431 //Check support for MPU401, FM & Wavetable MIDI
432 if(OSS32_MidiOpen(deviceid, OSS32_STREAM_MPU401_MIDIOUT, &streamid) == OSSERR_SUCCESS)
433 {
434 pDevCaps->ulCaps |= OSS32_CAPS_MPU401_PLAYBACK;
435 OSS32_MidiClose(streamid);
436 streamid = 0;
437 }
438 if(OSS32_MidiOpen(deviceid, OSS32_STREAM_MPU401_MIDIIN, &streamid) == OSSERR_SUCCESS)
439 {
440 pDevCaps->ulCaps |= OSS32_CAPS_MPU401_CAPTURE;
441 OSS32_MidiClose(streamid);
442 streamid = 0;
443 }
444 if(OSS32_MidiOpen(deviceid, OSS32_STREAM_FM_MIDIOUT, &streamid) == OSSERR_SUCCESS)
445 {
446 pDevCaps->ulCaps |= OSS32_CAPS_FMSYNTH_PLAYBACK;
447 OSS32_MidiClose(streamid);
448 streamid = 0;
449 }
450 if(OSS32_MidiOpen(deviceid, OSS32_STREAM_WAVETABLE_MIDIOUT, &streamid) == OSSERR_SUCCESS)
451 {
452 pDevCaps->ulCaps |= OSS32_CAPS_WAVETABLE_PLAYBACK;
453 OSS32_MidiClose(streamid);
454 streamid = 0;
455 }
456 if(OSS32_MixQueryName(deviceid, &pDevCaps->szMixerName, sizeof(pDevCaps->szMixerName)) != OSSERR_SUCCESS) {
457 DebugInt3();
458 printk("OSS32_QueryDevCaps: OSS32_MixQueryName error\n");
459 goto fail;
460 }
461// printk("OSS32_QueryDevCaps: devname: [%s]\n", pDevCaps->szDeviceName);
462 kfree(pcminfo);
463 streamid = 0;
464
465
466 return OSSERR_SUCCESS;
467
468fail:
469 printk("OSS32_QueryDevCaps failed\n");
470 DebugInt3();
471 if(streamid) OSS32_WaveClose(streamid);
472 if(pcminfo) kfree(pcminfo);
473
474 return ret;
475}
476//******************************************************************************
477//******************************************************************************
478OSSRET OSS32_WaveOpen(ULONG deviceid, ULONG streamtype, OSSSTREAMID *pStreamId, int pcm, USHORT fileid)
479{
480 soundhandle *pHandle;
481 int ret,i;
482
483 if (pStreamId)
484 *pStreamId = 0;
485 else
486 {
487 printk("ERROR: invalid stream id pointer passed\n");
488 return OSSERR_OUT_OF_MEMORY;
489 }
490
491 if(alsa_fops == NULL) {
492 DebugInt3();
493#ifdef DEBUG
494 dprintf(("OSS32_WaveOpen: no devices"));
495#endif
496 printk("OSS32_WaveOpen: no devices\n");
497
498 return OSSERR_NO_DEVICE_AVAILABLE;
499 }
500
501// printk("dev id: %i\n",deviceid);
502
503 pHandle = kmalloc(sizeof(soundhandle), GFP_KERNEL);
504 if(pHandle == NULL) {
505 DebugInt3();
506 printk("OSS32_WaveOpen: out of memory\n");
507 return OSSERR_OUT_OF_MEMORY;
508 }
509 memset(pHandle, 0, sizeof(soundhandle));
510
511 //set operation to non-blocking
512 pHandle->file.f_flags = O_NONBLOCK;
513
514 //setup pointers in file structure (used internally by ALSA)
515 pHandle->file.f_dentry = &pHandle->d_entry;
516 pHandle->file.f_dentry->d_inode = &pHandle->inode;
517
518 switch(streamtype) {
519 case OSS32_STREAM_WAVEOUT:
520 pHandle->file.f_mode = FMODE_WRITE;
521 pHandle->inode.i_rdev = SNDRV_MINOR(deviceid, SNDRV_MINOR_PCM_PLAYBACK) + pcm;
522 break;
523 case OSS32_STREAM_WAVEIN:
524 pHandle->file.f_mode = FMODE_READ;
525 pHandle->inode.i_rdev = SNDRV_MINOR(deviceid, SNDRV_MINOR_PCM_CAPTURE) + pcm;
526 break;
527 default:
528 DebugInt3();
529 kfree(pHandle);
530 printk("OSS32_WaveOpen: invalid parameter\n");
531 return OSSERR_INVALID_PARAMETER;
532 }
533
534 ret = alsa_fops->open(&pHandle->inode, &pHandle->file);
535 //printk("OSS32_WaveOpen. ret: %i\n", ret);
536 /* check if PCM already opened (stupid uniaud16.sys doesnt closes it) */
537 if (ret == -16)
538 {
539 for (i=0; i < 8*256; i++)
540 {
541 if (opened_handles[i].handle != 0)
542 {
543 ret = 0;
544 if (pStreamId)
545 *pStreamId = (ULONG)opened_handles[i].handle;
546 opened_handles[i].reuse = 1; /* try to reuse */
547 if (OSS32_WaveClose((OSSSTREAMID)opened_handles[i].handle) == 0)
548 {
549 if (!opened_handles[i].reuse)
550 {
551 //opened_handles[i].handle = 0;
552 kfree(opened_handles[i].handle); //free handle data
553 ret = alsa_fops->open(&pHandle->inode, &pHandle->file);
554 printk("OSS32_WaveOpen. Reopen ret: %i\n", ret);
555 }
556 else
557 {
558 kfree(pHandle);
559 pHandle = opened_handles[i].handle;
560 }
561 break;
562 }
563 }
564 }
565 }
566 else if (ret == 0)
567 {
568 for (i=0; i < 8*256; i++)
569 {
570 if (opened_handles[i].handle == 0)
571 {
572 opened_handles[i].handle = pHandle;
573 opened_handles[i].FileId = fileid;
574 break;
575 }
576 }
577 }
578
579 if(ret) {
580 kfree(pHandle);
581 DebugInt3();
582 printk("OSS32_WaveOpen: open error: %i\n",ret);
583 return UNIXToOSSError(ret);
584 }
585 pHandle->magic = MAGIC_WAVE_ALSA32;
586 if (pStreamId)
587 *pStreamId = (ULONG)pHandle;
588 // filling opened handles table
589 printk("OSS32_WaveOpen. streamid %X\n",(ULONG)pHandle);
590 return OSSERR_SUCCESS;
591}
592//******************************************************************************
593//******************************************************************************
594OSSRET OSS32_WaveClose(OSSSTREAMID streamid)
595{
596 soundhandle *pHandle = (soundhandle *)streamid;
597 int ret = 0, i;
598
599 if(pHandle == NULL || pHandle->magic != MAGIC_WAVE_ALSA32) {
600 DebugInt3();
601 printk("OSS32_WaveClose. invalid streamid %X\n",(ULONG)pHandle);
602 return OSSERR_INVALID_STREAMID;
603 }
604
605 //set operation to non-blocking
606 pHandle->file.f_flags = O_NONBLOCK;
607
608 for (i=0; i < 8*256; i++)
609 {
610 if (opened_handles[i].handle == pHandle)
611 {
612 printk("Found phandle for closing: %x reuse flag: %i\n", pHandle, opened_handles[i].reuse);
613 if (!opened_handles[i].reuse)
614 {
615 ret = pHandle->file.f_op->release(&pHandle->inode, &pHandle->file);
616 opened_handles[i].handle = 0;
617 kfree(pHandle); //free handle data
618 OSS32_CloseUNI16(); /* say to UNIAUD16 that we closing now */
619 } else
620 {
621 /* prepare for reuse */
622 pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_RESET, 0);
623 pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_PREPARE, 0);
624 }
625 break;
626 }
627 }
628
629 if (i >= 8*256)
630 {
631 //all already closed
632 printk("phandle %x not found\n", pHandle);
633// return OSSERR_SUCCESS;
634 }
635
636
637 if(ret) {
638 printk("Error closing wave. rc = %i\n", ret);
639 DebugInt3();
640 return UNIXToOSSError(ret);
641 }
642 printk("OSS32_WaveClose. streamid %X\n",(ULONG)pHandle);
643 return OSSERR_SUCCESS;
644}
645//******************************************************************************
646//******************************************************************************
647OSSRET OSS32_WavePrepare(OSSSTREAMID streamid)
648{
649 soundhandle *pHandle = (soundhandle *)streamid;
650 int ret;
651
652#ifdef DEBUG
653 dprintf(("OSS32_WavePrepare"));
654#endif
655
656 if(pHandle == NULL || pHandle->magic != MAGIC_WAVE_ALSA32) {
657 DebugInt3();
658//#ifdef DEBUG
659 printk("vladest: OSS32_WavePrepare: invalid streamID\n");
660//#endif
661
662 return OSSERR_INVALID_STREAMID;
663 }
664 //set operation to non-blocking
665 pHandle->file.f_flags = O_NONBLOCK;
666
667 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_PREPARE, 0);
668 if (ret)
669 printk("Wave prepare ret = %i, streamid %X\n",ret,(ULONG)pHandle);
670
671 return UNIXToOSSError(ret);;
672}
673//******************************************************************************
674//******************************************************************************
675OSSRET OSS32_WaveStart(OSSSTREAMID streamid)
676{
677 soundhandle *pHandle = (soundhandle *)streamid;
678 int ret;
679
680 if(pHandle == NULL || pHandle->magic != MAGIC_WAVE_ALSA32) {
681 DebugInt3();
682 return OSSERR_INVALID_STREAMID;
683 }
684 //set operation to non-blocking
685 pHandle->file.f_flags = O_NONBLOCK;
686
687 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_START, 0);
688 if (ret)
689 printk("Wave start ret = %i, streamid %X\n",ret,(ULONG)pHandle);
690
691 return UNIXToOSSError(ret);;
692}
693//******************************************************************************
694//******************************************************************************
695OSSRET OSS32_WaveStop(OSSSTREAMID streamid)
696{
697 soundhandle *pHandle = (soundhandle *)streamid;
698 int ret;
699
700 if(pHandle == NULL || pHandle->magic != MAGIC_WAVE_ALSA32) {
701 DebugInt3();
702 return OSSERR_INVALID_STREAMID;
703 }
704 //set operation to non-blocking
705 pHandle->file.f_flags = O_NONBLOCK;
706
707 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_DROP, 0);
708 if (ret)
709 printk("Wave stop ret = %i. streamid %X\n",ret,(ULONG)pHandle);
710
711 return UNIXToOSSError(ret);;
712}
713//******************************************************************************
714//******************************************************************************
715OSSRET OSS32_WavePause(OSSSTREAMID streamid)
716{
717 soundhandle *pHandle = (soundhandle *)streamid;
718 int ret;
719
720 if(pHandle == NULL || pHandle->magic != MAGIC_WAVE_ALSA32) {
721 DebugInt3();
722 return OSSERR_INVALID_STREAMID;
723 }
724 //set operation to non-blocking
725 pHandle->file.f_flags = O_NONBLOCK;
726
727 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_PAUSE, 0);
728 if (ret)
729 printk("Wave pause ret = %i, streamid %X\n",ret,(ULONG)pHandle);
730
731 return UNIXToOSSError(ret);;
732}
733//******************************************************************************
734//******************************************************************************
735OSSRET OSS32_WaveResume(OSSSTREAMID streamid)
736{
737 soundhandle *pHandle = (soundhandle *)streamid;
738 int ret;
739
740 if(pHandle == NULL || pHandle->magic != MAGIC_WAVE_ALSA32) {
741 DebugInt3();
742 return OSSERR_INVALID_STREAMID;
743 }
744 //set operation to non-blocking
745 pHandle->file.f_flags = O_NONBLOCK;
746
747 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_PAUSE, 1);
748 if (ret)
749 printk("Wave resume ret = %i, streamid %X\n",ret,(ULONG)pHandle);
750
751 return UNIXToOSSError(ret);;
752}
753
754static unsigned rates[] = {
755 /* ATTENTION: these values depend on the definition in pcm.h! */
756 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000,
757 64000, 88200, 96000, 176400, 192000
758};
759
760//******************************************************************************
761//******************************************************************************
762OSSRET OSS32_WaveSetHwParams(OSSSTREAMID streamid, OSS32_HWPARAMS *pHwParams)
763{
764 soundhandle *pHandle = (soundhandle *)streamid;
765 snd_pcm_hw_params_t params;
766 snd_pcm_status_t status;
767 snd_pcm_sw_params_t swparams;
768 int ret, ret1, nrperiods, minnrperiods, maxnrperiods, samplesize, i;
769 ULONG bufsize, periodsize, minperiodsize, maxperiodsize;
770 ULONG periodbytes, minperiodbytes, maxperiodbytes;
771 BOOL fTryAgain = FALSE;
772 ULONG ulMinRate, ulMaxRate;
773
774#ifdef DEBUG
775 dprintf(("OSS32_WaveSetHwParams"));
776#endif
777 if(pHandle == NULL || pHandle->magic != MAGIC_WAVE_ALSA32) {
778 printk("OSS32_WaveSetHwParams error. Invalid handle: %x\n", pHandle);
779 DebugInt3();
780 return OSSERR_INVALID_STREAMID;
781 }
782 if(pHwParams == NULL) {
783 printk("OSS32_WaveSetHwParams error. params = NULL\n");
784 DebugInt3();
785 return OSSERR_INVALID_PARAMETER;
786 }
787 if(pHwParams->ulDataType >= OSS32_PCM_MAX_FORMATS) {
788 printk("OSS32_WaveSetHwParams error. Too high PCM format\n");
789 DebugInt3();
790 return OSSERR_INVALID_PARAMETER;
791 }
792 if ((int)pHwParams->ulNumChannels <= 0) {
793 printk("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 //size of two samples (adpcm sample can be as small as 4 bits (mono), so take two)
801 samplesize = snd_pcm_format_size(OSSToALSADataType[pHwParams->ulDataType], 1);
802 pHandle->doublesamplesize = samplesize * 2;
803 pHandle->doublesamplesize *= pHwParams->ulNumChannels;
804 periodbytes = pHwParams->ulPeriodSize;
805 periodsize = bytes_to_samples(periodbytes);
806 // checking number of channels
807
808 printk("channels: %i, period size: %i\n",pHwParams->ulNumChannels, periodbytes);
809 _snd_pcm_hw_params_any(&params);
810 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_HW_REFINE, (ULONG)__Stack32ToFlat(&params));
811 ulMinRate = hw_param_interval(&params, SNDRV_PCM_HW_PARAM_RATE)->min;
812 ulMaxRate = hw_param_interval(&params, SNDRV_PCM_HW_PARAM_RATE)->max;
813
814 _snd_pcm_hw_params_any(&params);
815 do {
816 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_ACCESS,
817 SNDRV_PCM_ACCESS_RW_INTERLEAVED, 0);
818 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_CHANNELS,
819 pHwParams->ulNumChannels, 0);
820 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_HW_REFINE, (ULONG)__Stack32ToFlat(&params));
821 if (ret == 0) break;
822 pHwParams->ulNumChannels--;
823 } while(ret < 0 && pHwParams->ulNumChannels > 1);
824
825 printk("channels selected: %i\n",pHwParams->ulNumChannels);
826
827 //get all hardware parameters
828 _snd_pcm_hw_params_any(&params);
829 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_ACCESS,
830 SNDRV_PCM_ACCESS_RW_INTERLEAVED, 0);
831 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_FORMAT,
832 OSSToALSADataType[pHwParams->ulDataType], 0);
833 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_HW_REFINE, (ULONG)__Stack32ToFlat(&params));
834 if(ret != 0) {
835 printk("invalid format %i\n", OSSToALSADataType[pHwParams->ulDataType]);
836 return UNIXToOSSError(ret);
837 }
838 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
839 pHwParams->ulBitsPerSample, 0);
840 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_HW_REFINE, (ULONG)__Stack32ToFlat(&params));
841 if(ret != 0) {
842 printk("invalid number of sample bits %i\n", pHwParams->ulBitsPerSample);
843 return UNIXToOSSError(ret);
844 }
845 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_FRAME_BITS,
846 pHwParams->ulBitsPerSample*pHwParams->ulNumChannels, 0);
847 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_HW_REFINE, (ULONG)__Stack32ToFlat(&params));
848 if(ret != 0) {
849 printk("invalid number of frame bits %i\n", pHwParams->ulBitsPerSample*pHwParams->ulNumChannels);
850 return UNIXToOSSError(ret);
851 }
852
853 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
854 pHwParams->ulBitsPerSample, 0);
855 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_FRAME_BITS,
856 pHwParams->ulBitsPerSample*pHwParams->ulNumChannels, 0);
857 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_FORMAT,
858 OSSToALSADataType[pHwParams->ulDataType], 0);
859 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_CHANNELS,
860 pHwParams->ulNumChannels, 0);
861 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_RATE,
862 pHwParams->ulSampleRate, 0);
863
864 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_HW_REFINE, (ULONG)__Stack32ToFlat(&params));
865 if(ret != 0) {
866 printk("OSS32_WaveSetHwParams (first pass) error %i\n", ret);
867 printk("bps: %i\n",pHwParams->ulBitsPerSample);
868 printk("format: %i\n",OSSToALSADataType[pHwParams->ulDataType]);
869 printk("channels: %i\n",pHwParams->ulNumChannels);
870 printk("sample rate: %i\n",pHwParams->ulSampleRate);
871
872// printk("OSS32_WaveSetHwParams invalid sample rate %i\n", pHwParams->ulSampleRate);
873 // printk("will set to nearest\n");
874 _snd_pcm_hw_params_any(&params);
875 for (i=0; i<(sizeof(rates)/sizeof(unsigned))-1;i++)
876 {
877 if (pHwParams->ulSampleRate >= rates[i] &&
878 pHwParams->ulSampleRate <= rates[i+1])
879 {
880 pHwParams->ulSampleRate = rates[i];
881 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_RATE,
882 pHwParams->ulSampleRate, 0);
883 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_HW_REFINE, (ULONG)__Stack32ToFlat(&params));
884 if(ret == 0)
885 {
886 _snd_pcm_hw_params_any(&params);
887 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
888 pHwParams->ulBitsPerSample, 0);
889 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_FRAME_BITS,
890 pHwParams->ulBitsPerSample*pHwParams->ulNumChannels, 0);
891 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_FORMAT,
892 OSSToALSADataType[pHwParams->ulDataType], 0);
893 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_CHANNELS,
894 pHwParams->ulNumChannels, 0);
895 _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_RATE,
896 pHwParams->ulSampleRate, 0);
897 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_HW_REFINE, (ULONG)__Stack32ToFlat(&params));
898 goto __next;
899 }
900 }
901 }
902
903// ret1 = pHandle->file.f_op->release(&pHandle->inode, &pHandle->file);
904 DebugInt3();
905 return UNIXToOSSError(ret);
906 }
907__next:
908
909 printk("sample rate: %i\n",pHwParams->ulSampleRate);
910
911 //check period size against lower and upper boundaries
912 minperiodbytes = hw_param_interval((&params), SNDRV_PCM_HW_PARAM_PERIOD_BYTES)->min;
913 maxperiodbytes = hw_param_interval((&params), SNDRV_PCM_HW_PARAM_PERIOD_BYTES)->max;
914 if(periodbytes < minperiodbytes) {
915 periodbytes = minperiodbytes;
916 }
917 else
918 if(periodbytes > maxperiodbytes) {
919 periodbytes = maxperiodbytes;
920 }
921
922 minperiodsize = hw_param_interval((&params), SNDRV_PCM_HW_PARAM_PERIOD_SIZE)->min;
923 maxperiodsize = hw_param_interval((&params), SNDRV_PCM_HW_PARAM_PERIOD_SIZE)->max;
924 if(periodsize < minperiodsize) {
925 periodsize = minperiodsize;
926 }
927 else
928 if(periodsize > maxperiodsize) {
929 periodsize = maxperiodsize;
930 }
931
932 if(samples_to_bytes(periodsize) < periodbytes) {
933 periodbytes = samples_to_bytes(periodsize);
934 }
935 else
936 if(bytes_to_samples(periodbytes) < periodsize) {
937 periodsize = bytes_to_samples(periodbytes);
938 }
939
940 //make sure period size is a whole fraction of the buffer size
941 bufsize = hw_param_interval((&params), SNDRV_PCM_HW_PARAM_BUFFER_BYTES)->max;
942 if(periodsize) {
943 nrperiods = bufsize/periodbytes;
944 }
945 else {
946 printk("OSS32_WaveSetHwParams error. Invalid periodsize (=0). closing file\n");
947// ret1 = pHandle->file.f_op->release(&pHandle->inode, &pHandle->file);
948 DebugInt3();
949 return OSSERR_INVALID_PARAMETER;
950 }
951 //check nr of periods against lower and upper boundaries
952 minnrperiods = hw_param_interval((&params), SNDRV_PCM_HW_PARAM_PERIODS)->min;
953 maxnrperiods = hw_param_interval((&params), SNDRV_PCM_HW_PARAM_PERIODS)->max;
954 if(nrperiods < minnrperiods) {
955 nrperiods = minnrperiods;
956 }
957 else
958 if(nrperiods > maxnrperiods) {
959 nrperiods = maxnrperiods;
960 }
961 //an odd nr of periods is not always a good thing (CMedia -> clicks during 8 bps playback),
962 //so we make sure it's an even number.
963 if(nrperiods == 1) {
964 DebugInt3();
965 printk("OSS32_WaveSetHwParams error. Invalid number of periods(=1). closing file\n");
966// ret1 = pHandle->file.f_op->release(&pHandle->inode, &pHandle->file);
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//tryagain:
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//#ifdef DEBUG_PK
998 printk("Hardware parameters: sample rate %i, data type %i, channels %i, period size %i, periods %i\n",
999 pHwParams->ulSampleRate, pHwParams->ulDataType, pHwParams->ulNumChannels, periodsize, nrperiods);
1000//#endif
1001 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_HW_PARAMS, (ULONG)__Stack32ToFlat(&params));
1002 if (ret == -77 && fTryAgain == FALSE)
1003 {
1004 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_PREPARE, 0);
1005 fTryAgain = TRUE;
1006 goto tryagain;
1007 }
1008 if(ret) {
1009 if(fTryAgain == FALSE) {
1010 minperiodsize = hw_param_interval((&params), SNDRV_PCM_HW_PARAM_PERIOD_SIZE)->min;
1011 maxperiodsize = hw_param_interval((&params), SNDRV_PCM_HW_PARAM_PERIOD_SIZE)->max;
1012 if(minperiodsize > maxperiodsize) {
1013 //ALSA doesn't like the period size; try suggested one
1014 periodsize = maxperiodsize;
1015 periodbytes = samples_to_bytes(periodsize);
1016 fTryAgain = TRUE;
1017 goto tryagain;
1018 }
1019 }
1020 printk("OSS32_WaveSetHwParams (second pass) error %i\n", ret);
1021 printk("bps: %i\n",pHwParams->ulBitsPerSample);
1022 printk("format: %i\n",OSSToALSADataType[pHwParams->ulDataType]);
1023 printk("channels: %i\n",pHwParams->ulNumChannels);
1024 printk("sample rate: %i\n",pHwParams->ulSampleRate);
1025 printk("periodsize: %i\n",periodsize);
1026 printk("periodbytes: %i\n",periodbytes);
1027 printk("periods: %i\n",nrperiods);
1028// ret1 = pHandle->file.f_op->release(&pHandle->inode, &pHandle->file);
1029 return UNIXToOSSError(ret);
1030 }
1031
1032 //set silence threshold (all sizes in frames) (only needed for playback)
1033 if(pHandle->file.f_mode == FMODE_WRITE)
1034 {
1035 swparams.avail_min = periodsize;
1036 swparams.period_step = 1;
1037 if(nrperiods <= 2) {
1038 swparams.silence_size = (periodsize/2);
1039 }
1040 else {
1041 swparams.silence_size = periodsize;
1042 }
1043 swparams.silence_threshold = swparams.silence_size;
1044 swparams.sleep_min = 0;
1045 swparams.start_threshold = 1;
1046 swparams.stop_threshold = periodsize*nrperiods;
1047 swparams.tstamp_mode = SNDRV_PCM_TSTAMP_NONE;
1048 swparams.xfer_align = periodsize;
1049
1050 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_SW_PARAMS, (ULONG)__Stack32ToFlat(&swparams));
1051 }
1052 total = 0;
1053 per_bytes = periodbytes;
1054 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_STATUS, (ULONG)__Stack32ToFlat(&status));
1055 if ( ((status.state != SNDRV_PCM_STATE_PREPARED) &&
1056 (status.state != SNDRV_PCM_STATE_RUNNING) &&
1057 (status.state != SNDRV_PCM_STATE_DRAINING))) {
1058 printk("Device is not in proper state: %i. Calling prepare\n", status.state);
1059 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_PREPARE, 0);
1060 }
1061 printk("OSS32_WaveSetHwParams return %d after SNDRV_PCM_IOCTL_SW_PARAMS ioctl, streamid %X", ret,(ULONG)pHandle);
1062 return UNIXToOSSError(ret);
1063}
1064
1065//******************************************************************************
1066//******************************************************************************
1067OSSRET OSS32_WaveAddBuffer(OSSSTREAMID streamid, ULONG buffer, ULONG size, ULONG *pTransferred, int pcm)
1068{
1069 soundhandle *pHandle = (soundhandle *)streamid;
1070 snd_pcm_status_t status;
1071 int ret, align, size1, ret1;
1072 LONG transferred;
1073 ULONG position;
1074 char *buf;
1075 int toret = 0;
1076
1077// return OSSERR_SUCCESS;
1078
1079 if(pHandle == NULL || pHandle->magic != MAGIC_WAVE_ALSA32) {
1080 DebugInt3();
1081 return OSSERR_INVALID_STREAMID;
1082 }
1083 if(pTransferred == NULL || buffer == 0 || size == 0) {
1084 DebugInt3();
1085 return OSSERR_INVALID_PARAMETER;
1086 }
1087
1088 //set operation to non-blocking
1089 pHandle->file.f_flags = O_NONBLOCK;
1090
1091 //first check how much room is left in the circular dma buffer
1092 //this is done to make sure we don't block inside ALSA while trying to write
1093 //more data than fits in the internal dma buffer.
1094 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_STATUS, (ULONG)__Stack32ToFlat(&status));
1095
1096 if(ret) {
1097 DebugInt3();
1098 return UNIXToOSSError(ret);
1099 }
1100
1101 size1 = size;
1102
1103 size = min(size, samples_to_bytes(status.avail));
1104 if (size1 != size)
1105 printk("requested size [%i] less then available [%i]\n", size1, size);
1106#if 0
1107 if (size < per_bytes)
1108 { /*HACK!!!*/
1109 printk("HACK avoid buffer overrun: requested buffer [%i] less than period [%i]. prev size: %i\n", size, per_bytes, prev_size);
1110 *pTransferred = size;
1111 prev_size = size;
1112 ret1 = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_PREPARE, 0);
1113 return OSSERR_SUCCESS;
1114 }
1115#endif
1116// size = per_bytes * (size / per_bytes);
1117
1118#ifdef DEBUG_PK
1119 printk("OSS32_WaveAddBuffer hw %i app %i avail %i, orig size: %i, size %i align %i\n", samples_to_bytes(status.hw_ptr), samples_to_bytes(status.appl_ptr), samples_to_bytes(status.avail), size1, size, per_bytes);
1120#endif
1121
1122 if(size == 0) {
1123#ifdef DEBUG_PK
1124 printk("OSS32_WaveAddBuffer: no room left in hardware buffer!!\n");
1125 printk("state = %i\n",status.state);
1126 printk("avail = %i\n",status.avail);
1127 printk("size req = %i\n",size1);
1128#endif
1129 *pTransferred = 0;
1130 return OSSERR_BUFFER_FULL;
1131 }
1132
1133 transferred = 0;
1134 switch(SNDRV_MINOR_DEVICE(MINOR(pHandle->inode.i_rdev-pcm)))
1135 {
1136 case SNDRV_MINOR_PCM_PLAYBACK:
1137 // size should be aligned to channels number * samplesize
1138
1139 while(TRUE) {
1140 again:
1141 ret = pHandle->file.f_op->write(&pHandle->file, (char *)buffer, size, &pHandle->file.f_pos);
1142 if(ret < 0) {
1143 // check EAGAIN
1144 if (ret == -EPIPE)
1145 {
1146 ret1 = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_PREPARE, 0);
1147// if (ret1 == 0) continue;
1148// printk("prepare rc %i\n",ret);
1149 }
1150
1151 if(transferred > 0) {
1152 printk("OSS32_WaveAddBuffer failed on partial transfer %x %i; ret = %i\n", buffer, size, ret);
1153 *pTransferred = transferred;
1154 if (toret)
1155 return OSSERR_SUCCESS; /* avoid infinite loop */
1156 toret = 1;
1157 goto again;
1158 }
1159
1160 ret1 = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_STATUS, (ULONG)__Stack32ToFlat(&status));
1161
1162 if ( ((status.state != SNDRV_PCM_STATE_PREPARED) &&
1163 (status.state != SNDRV_PCM_STATE_RUNNING) &&
1164 (status.state != SNDRV_PCM_STATE_DRAINING)) || ret == -32 ) {
1165 ret1 = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_PREPARE, 0);
1166 printk("OSS32_WaveAddBuffer buffer overrun: size %i, ret %i, trans %i, prev sz %i per sz %i total %i\n", size, ret, transferred, prev_size, per_bytes, total);
1167 //ret = size;
1168 //transferred = size;
1169 if (toret) break; /* avoid infinite loop */
1170 toret = 1;
1171 goto again;
1172 }
1173 else {
1174 printk("OSS32_WaveAddBuffer failed when SNDRV_MINOR_PCM_PLAYBACK. rc = %i\n",ret);
1175 printk("hw %i app %i avail %i, size %i\n", samples_to_bytes(status.hw_ptr), samples_to_bytes(status.appl_ptr), samples_to_bytes(status.avail), size);
1176 printk("total = %i\n",total);
1177 printk("state = %i\n",status.state);
1178 printk("avail = %i\n",status.avail);
1179 printk("size req = %i\n",size1);
1180 DebugInt3();
1181 return UNIXToOSSError(transferred);
1182 }
1183 }
1184 if(ret == 0) {
1185 break;
1186 }
1187 toret = 0;
1188 transferred += ret;
1189// printk("written: now: %i, buffer: %i, total: %i\n", ret, transferred, total);
1190 buffer += ret;
1191 size -= ret;
1192 if((int)size <= 0) {
1193 break;
1194 }
1195 }
1196 break;
1197 case SNDRV_MINOR_PCM_CAPTURE:
1198 transferred = pHandle->file.f_op->read(&pHandle->file, (char *)buffer, size, &pHandle->file.f_pos);
1199// printk("readed %i bytes\n", transferred);
1200 break;
1201 default:
1202 DebugInt3();
1203 return OSSERR_INVALID_PARAMETER;
1204 }
1205 if(ret < 0) {
1206 dprintf(("OSS32_WaveAddBuffer failed"));
1207 DebugInt3();
1208 return UNIXToOSSError(transferred);
1209 }
1210
1211 total+=transferred;
1212 *pTransferred = transferred;
1213 prev_size = transferred;
1214 if (transferred < size)
1215 {
1216 printk("warning: transferred [%i] less than requested [%i]\n", transferred, size);
1217 ret1 = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_PREPARE, 0);
1218 }
1219
1220 return OSSERR_SUCCESS;
1221}
1222//******************************************************************************
1223//******************************************************************************
1224OSSRET OSS32_WaveGetPosition(ULONG streamid, ULONG *pPosition)
1225{
1226 soundhandle *pHandle = (soundhandle *)streamid;
1227 snd_pcm_status_t status;
1228 int ret;
1229 ULONG delta;
1230
1231 if(pHandle == NULL || pHandle->magic != MAGIC_WAVE_ALSA32) {
1232 DebugInt3();
1233 return OSSERR_INVALID_STREAMID;
1234 }
1235 if(pPosition == NULL) {
1236 DebugInt3();
1237 return OSSERR_INVALID_PARAMETER;
1238 }
1239
1240 //set operation to non-blocking
1241 pHandle->file.f_flags = O_NONBLOCK;
1242
1243 //Get the status of the stream
1244 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_STATUS, (ULONG)__Stack32ToFlat(&status));
1245
1246 if(ret) {
1247 DebugInt3();
1248 return UNIXToOSSError(ret);
1249 }
1250
1251 dprintf2(("OSS32_WaveGetPosition: hardware %x application %x", samples_to_bytes(status.hw_ptr), samples_to_bytes(status.appl_ptr)));
1252 *pPosition = samples_to_bytes(status.hw_ptr); //return new hardware position
1253 return OSSERR_SUCCESS;
1254}
1255//******************************************************************************
1256//******************************************************************************
1257OSSRET OSS32_WaveGetSpace(ULONG streamid, ULONG *pBytesAvail)
1258{
1259 soundhandle *pHandle = (soundhandle *)streamid;
1260 snd_pcm_status_t status;
1261 int ret;
1262
1263 if(pHandle == NULL || pHandle->magic != MAGIC_WAVE_ALSA32) {
1264 DebugInt3();
1265 return OSSERR_INVALID_STREAMID;
1266 }
1267 if(pBytesAvail == NULL) {
1268 DebugInt3();
1269 return OSSERR_INVALID_PARAMETER;
1270 }
1271
1272 //set operation to non-blocking
1273 pHandle->file.f_flags = O_NONBLOCK;
1274
1275 //Get the nr of bytes left in the audio buffer
1276 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_STATUS, (ULONG)__Stack32ToFlat(&status));
1277
1278 if(ret) {
1279 DebugInt3();
1280 return UNIXToOSSError(ret);
1281 }
1282 *pBytesAvail = samples_to_bytes(status.avail);
1283 return OSSERR_SUCCESS;
1284}
1285//******************************************************************************
1286//******************************************************************************
1287OSSRET OSS32_WaveSetVolume(OSSSTREAMID streamid, ULONG volume)
1288{
1289 soundhandle *pHandle = (soundhandle *)streamid;
1290 int ret;
1291 int leftvol, rightvol;
1292 struct snd_pcm_volume pcm_volume;
1293
1294 if(pHandle == NULL || pHandle->magic != MAGIC_WAVE_ALSA32) {
1295 DebugInt3();
1296 return OSSERR_INVALID_STREAMID;
1297 }
1298 //set operation to non-blocking
1299 pHandle->file.f_flags = O_NONBLOCK;
1300
1301 leftvol = GET_VOLUME_L(volume);
1302 rightvol = GET_VOLUME_R(volume);
1303
1304 pcm_volume.nrchannels = 4;
1305 pcm_volume.volume[SNDRV_PCM_VOL_FRONT_LEFT] = leftvol;
1306 pcm_volume.volume[SNDRV_PCM_VOL_FRONT_RIGHT] = rightvol;
1307 pcm_volume.volume[SNDRV_PCM_VOL_REAR_LEFT] = leftvol;
1308 pcm_volume.volume[SNDRV_PCM_VOL_REAR_RIGHT] = rightvol;
1309
1310 dprintf(("OSS32_WaveSetVolume %x to (%d,%d)", streamid, leftvol, rightvol));
1311 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_PCM_IOCTL_SETVOLUME, (ULONG)__Stack32ToFlat(&pcm_volume));
1312 return UNIXToOSSError(ret);
1313}
1314//******************************************************************************
1315//******************************************************************************
1316
Note: See TracBrowser for help on using the repository browser.