lkml.org 
[lkml]   [2004]   [May]   [11]   [last100]   RSS Feed
Views: [more markup]  [less markup]  [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
DateTue, 11 May 2004 13:06:56 -0400
FromGary Wong <>
Subject[PATCH] Re: Segmentation fault in i810_audio.c:__i810_update_lvi
On Tue, May 11, 2004 at 12:27:28AM -0700, Andrew Morton wrote:
> Gary Wong <gtw@cs.bu.edu> wrote:
> > I believe that one of two fixes should be applied: either the
> >  SNDCTL_DSP_SETTRIGGER ioctl handling should not enable the
> >  PCM_ENABLE_{IN,OUT}PUT bits unless file->f_mode is compatible,
> >  or i810_release() should ignore the PCM_ENABLE_* bits without
> >  the corresponding FMODE_*.
> 
> The first option sounds more appropriate but I wonder if it could break
> existing applications?  Probably not, if it oopses.

I agree; I had a look at a few other drivers at random (audio, esssolo1,
trident) and they all silently ignore inappropriate PCM_ENABLE_* bits.

> Let's try option #1, please.

OK, a patch is attached.  It seems to fix the problem on a 2.6.3 system
with Herbert Xu's patches from Jeff Garzik applied.

break-i810.c is a small test case which hopefully demonstrates the
problem.

Cheers,
Gary.
-- 
     Gary Wong          gtw@cs.bu.edu          http://cs-people.bu.edu/gtw/
--- i810_audio.c.herbert	2004-05-11 12:36:05.674715334 -0400
+++ i810_audio.c	2004-05-11 12:41:50.101624990 -0400
@@ -2186,6 +2186,10 @@
 #if defined(DEBUG) || defined(DEBUG_MMAP)
 		printk("SNDCTL_DSP_SETTRIGGER 0x%x\n", val);
 #endif
+		if (!(file->f_mode & FMODE_READ ))
+			val &= ~PCM_ENABLE_INPUT;
+		if (!(file->f_mode & FMODE_WRITE ))
+			val &= ~PCM_ENABLE_OUTPUT;
 		if((file->f_mode & FMODE_READ) && !(val & PCM_ENABLE_INPUT) && dmabuf->enable == ADC_RUNNING) {
 			stop_adc(state);
 		}
@@ -2193,7 +2197,7 @@
 			stop_dac(state);
 		}
 		dmabuf->trigger = val;
-		if((file->f_mode & FMODE_WRITE) && (val & PCM_ENABLE_OUTPUT) && !(dmabuf->enable & DAC_RUNNING)) {
+		if((val & PCM_ENABLE_OUTPUT) && !(dmabuf->enable & DAC_RUNNING)) {
 			if (!dmabuf->write_channel) {
 				dmabuf->ready = 0;
 				dmabuf->write_channel = state->card->alloc_pcm_channel(state->card);
@@ -2214,7 +2218,7 @@
 			i810_update_lvi(state, 0);
 			start_dac(state);
 		}
-		if((file->f_mode & FMODE_READ) && (val & PCM_ENABLE_INPUT) && !(dmabuf->enable & ADC_RUNNING)) {
+		if((val & PCM_ENABLE_INPUT) && !(dmabuf->enable & ADC_RUNNING)) {
 			if (!dmabuf->read_channel) {
 				dmabuf->ready = 0;
 				dmabuf->read_channel = state->card->alloc_rec_pcm_channel(state->card);#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

extern int main( void ) {
#define DSP "/dev/dsp"

    int f = open( DSP, O_RDONLY );
    int i, n;
    fd_set fds;

    if( f < 0 ) {
	perror( DSP );
	return EXIT_FAILURE;
    }
    n = 0;
    if( ioctl( f, SNDCTL_DSP_SETTRIGGER, &n ) < 0 ) {
	perror( "SNDCTL_DSP_SETTRIGGER" );
	return EXIT_FAILURE;
    }
    n = PCM_ENABLE_INPUT | PCM_ENABLE_OUTPUT;
    if( ioctl( f, SNDCTL_DSP_SETTRIGGER, &n ) < 0 ) {
	perror( "SNDCTL_DSP_SETTRIGGER" );
	return EXIT_FAILURE;
    }
    for( i = 0; i < 10; i++ ) {
	char a[ 1024 ];
	FD_ZERO( &fds );
	FD_SET( f, &fds );

	if( select( f + 1, &fds, NULL, NULL, NULL ) < 0 )
	    perror( "select" );
	if( read( f, a, 1024 ) < 0 )
	    perror( "read" );
    }
    close( f );

    return EXIT_SUCCESS;
}
\
 
 \ /
  Last update: 2005-03-22 13:03    [from the cache]
©2003-2008