/*
 *  Copyright (c) 1994/95 by Jaroslav Kysela (Perex soft)
 *  Information about gus driver
 */

#include "gus_dev.h"

#ifdef PROC_SUPPORT

#include <linux/proc_fs.h>

static int gus_proc_get_text( char *buffer, char **start, off_t offset, int length );

static struct proc_module_entry gus_proc_entry = {
  NULL,
  NULL,
  PROC_ENTRY_ROOT,
  PROC_ENTRY_ONE,
  0,
  0,
  0,
  0,
  { 0, 3, "gus" },
  gus_proc_get_text,
  NULL
};

#endif

typedef int (* type_get_info_fcns)( char * );

static short info_open_flag = 0;
static type_get_info_fcns get_info_fcns[] = {
  get_info_init,
  NULL
};

#ifdef PROC_SUPPORT

static int gus_proc_get_text( char *buffer, char **start, off_t offset, int length )
{
  off_t pos;
  int index, size;

  pos = 0;
  index = size = 0;
  while ( pos <= offset && get_info_fcns[ index ] )
    {
      size = get_info_fcns[ index ]( buffer );
      pos += size;
      index++;
    }
  if ( pos <= offset ) return 0;
  *start = buffer + ( offset - ( pos - size ) );
  return size > length ? length : size;
}

void gus_proc_file_init()
{
  if ( proc_entry_insert( &gus_proc_entry ) < 0 )
    PRINTK( "gus: problem with register /proc/gus file\n" );
   else
    info_open_flag++;
}

void gus_proc_file_done()
{
  if ( info_open_flag && proc_entry_delete( &gus_proc_entry ) < 0 )
    PRINTK( "gus: problem with unregister /proc/gus file\n" );
  info_open_flag = 0;
}

#else /* !PROC_SUPPORT */

#define INFO_BUFFER_SIZE	( ( 4 * 1024 ) - 64 )

static char *info_buf = NULL;

int gus_read_info( char *buf, off_t *offset, int count )
{
  off_t pos;
  int index, size;

  pos = 0;
  index = size = 0;
  while ( pos <= *offset && get_info_fcns[ index ] )
    {
      size = get_info_fcns[ index ]( info_buf );
      pos += size;
      index++;
    }
  if ( pos <= *offset ) return 0;
  pos = *offset - ( pos - size );
  if ( size > count ) size = count;
  MEMCPY_TOFS( buf, info_buf + pos, size );
  *offset += size;
  return size;
}

int gus_open_info( void )
{
  if ( !info_open_flag )
    {
      if ( ( info_buf = (char *)VMALLOC( INFO_BUFFER_SIZE ) ) == NULL )
        return -ENOMEM;
      info_open_flag++;
      MOD_INC_USE_COUNT;
      return 0;
    }
  return -EBUSY;
}

void gus_release_info( void )
{
  if ( info_buf ) VFREE( info_buf );
  info_open_flag = 0;
  MOD_DEC_USE_COUNT;
}

#endif /* PROC_SUPPORT */

int gus_read_sndstat( char *buf, off_t *offset, int count )
{
  char *s = SNDSTAT_STRING;
  int size;

  size = strlen( s ) + 1;
  if ( *offset >= size || count < size - *offset )
    return 0;
  size -= *offset;
  MEMCPY_TOFS( buf, s + *offset, size );
  *offset += size;
  return size;
}

int gus_open_sndstat( void )
{
  MOD_INC_USE_COUNT;
  return 0;
}

void gus_release_sndstat( void )
{
  MOD_DEC_USE_COUNT;
}
