Re: Sound driver and xquake problem (the solution)

Hannu Savolainen (hannu@voxware.pp.fi)
Fri, 12 Jul 1996 15:21:33 +0300 (EET DST)


On Wed, 10 Jul 1996, Hallow wrote:

> According to ddt (the gentleman who wrote the linux port),
> the kernel in 1.3.8x returns a 2 for stereo sound. This
> number is used internally by xquake for a couple of different
> things. As you can see above 2.0.x kernels are returning 0,
> that's why you get an FPE - it's trying to divide by 0,
> and everyone knows you can't do that.
This explains why the program fails the bug is actually in xquake and
sound driver versions earlier than Linux 2.0.1.

There are two similar ioctl calls. SNDCTL_DSP_STEREO (used by xquake)
accepts 0 (mono) or 1 (stereo) as it's argument and returns 0 or 1
depending on if the device was set into stereo mode or not. The another
call is SNDCTL_DSP_CHANNELS (which should have been used in Quake) is
similar but it accepts the actual number of channels (1 or 2) as the
argument.

There is some difference in handling of SNDCTL_DSP_STEREO between Linux
2.0.1 and earlier. In older driver versions value of 2..N was taken as 1.
Current driver doesn't accept this value but just returns the current
setting. I will change the driver to return EINVAL in future versions if
the argument is anything else than 0 or 1.

Enclosed is a patch which makes the driver to work with current xquake.
It's not an official patch and it will not be included in future driver
versions. The file to be patched is linux/drivers/sound/dmabuf.c.

Best regards,

Hannu
-----------------------------
Hannu Savolainen (hannu@voxware.pp.fi, hannu@4front-tech.com)
http://personal.eunet.fi/pp/voxware/hannu.html (my home page)
http://www.4Front-Tech.com/uss.html (UNIX Sound System (USS))
http://personal.eunet.fi/pp/voxware (USS Lite/TASD/VoxWare)
---------------- cut here ---------------
*** dmabuf.c.old Fri Jul 12 15:00:41 1996
--- dmabuf.c Fri Jul 12 15:06:02 1996
***************
*** 778,784 ****
case SNDCTL_DSP_STEREO:
if (local)
return audio_devs[dev]->d->set_channels (dev, (int) arg + 1) - 1;
! return snd_ioctl_return ((int *) arg, audio_devs[dev]->d->set_channels (dev, get_fs_long ((long *) arg) + 1) - 1);

case SOUND_PCM_WRITE_CHANNELS:
if (local)
--- 778,796 ----
case SNDCTL_DSP_STEREO:
if (local)
return audio_devs[dev]->d->set_channels (dev, (int) arg + 1) - 1;
!
! {
! int n;
!
! n = get_fs_long ((long *) arg);
!
! if (n>1) /* The program is trying to set number of channels */
! return snd_ioctl_return ((int *) arg,
! audio_devs[dev]->d->set_channels (dev, n));
!
! return snd_ioctl_return ((int *) arg,
! audio_devs[dev]->d->set_channels (dev, n + 1) - 1);
! }

case SOUND_PCM_WRITE_CHANNELS:
if (local)