open() 함수 사용시, Invalid argument 에러 발생
글쓴이: dlatjrwo / 작성시간: 수, 2013/07/10 - 3:56오후
사운드카드 디바이스를 통한 wav 파일 재생 프로그램 실행 중,
open() 함수을 통하여 장치를 접근하려고 할 때, Invalid argument 에러가 발생합니다.
이 소스코드를 컴파일 환경에서 gcc(Ubuntu 4.4.3-4ubuntu5.1)4.4.3을 통하여 컴파일했을 경우,
문제없이 장치를 사용하였습니다. 헌데, 컴파일 환경에서 arm-Linux-gcc(gcc version 4.3.1)을 통하여
컴파일하고,(컴파일은 문제없이 되었습니다.) 테스트 보드로 실행파일을 옮겨 실행하면 앞서 언급한,
Invalid argument 에러가 발생합니다.
/dev/폴더에서 dsp장치가 인식된 것은 확인하였습니다.
장치에 접근을 못하는 건지, 아니면, 관련 소스에 문제가 있는 것인지, 어떤 문제인지 도통 감이 잡히지 않네요.
도움을 부탁드립니다.
컴파일 환경
- Linux 2.6.32-45-generic #103-Ubuntu SMP i686 GNU/Linux
테스트 보드 실행 환경
- Linux 3.0.15 #4 SMP PREEMPT armv7l GNU/Linux
소스코드
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <sys/ioctl.h>
#include <linux/soundcard.h>
#include <errno.h>
#define SCERR_NO_PROC_DEVICE -1 // Thers's no /proc/device
#define SCERR_DRIVER_NO_FIND -2 // Cannot find driver in /proc/device
#define SCERR_NO_SOUNDCARD -3 // There's no Sound Card
#define SCERR_NO_MIXER -4 // There's no Mixer
#define SCERR_OPEN_SOUNDCARD -5 // Fail to open Sound Card
#define SCERR_OPEN_MIXER -6 // Fail to open Mixer
#define SCERR_PRIVILEGE_SOUNDCARD -7 // No permission using Sound Card
#define SCERR_PRIVILEGE_MIXER -8 // No permission using Mixer
#define SCERR_NO_FILE -10 // There's no file
#define SCERR_NOT_OPEN -11 // Cannot open the file
#define SCERR_NOT_WAV_FILE -12 // Is not the WAV file
#define SCERR_NO_wav_info -13 // There's no forman information of WAV
#define BUFF_SIZE 1024
#define DSP_DEVICE_NAME "/dev/dsp" // interface for excution of AU sound file in sound card
//#define DSP_DEVICE_NAME "/dev/audio" // interface for excution of AU sound file in sound card
#define MIXER_DEVICE_NAME "/dev/mixer"
#define TRUE 1
typedef struct
{
unsigned char chunk_id[4];
unsigned long size;
unsigned short tag;
unsigned short channels;
unsigned long rate;
unsigned long avr_samples;
unsigned short align;
unsigned short data_bit;
} wav_info_t;
static int fd_soundcard = -1;
static int fd_mixer = -1; // descriptor for volume control
static unsigned long data_offset = 0; // offset for wav play
//------------------------------------------------------------------------------
// Description: Program Close after print the Msg
// Factor: format : print string format ex) "%s%d"
// ... : factor to need format
//------------------------------------------------------------------------------
void printx( const char *_format, ...)
{
char *bar = "-------------------------------";
va_list parg;
int count;
printf( "%s:ERRORn", bar);
va_start( parg,_format);
count = vprintf(_format, parg);
va_end( parg);
printf( "n%sn", bar);
exit( -1);
}
//------------------------------------------------------------------------------
// Description: get the buffer size for sound output
// Return: buffer size for sound output
//------------------------------------------------------------------------------
int soundcard_get_buff_size( void)
{
int size = 1024;
if ( 0 <= fd_soundcard)
{
ioctl( fd_soundcard, SNDCTL_DSP_GETBLKSIZE, &size);
if ( size < 1024 )
size = 1024;
}
return size;
}
//------------------------------------------------------------------------------
// Desciption: set output of sound card as stereo
// Factor: _enable - 1 : stereo
// 0 : mono
//------------------------------------------------------------------------------
void soundcard_set_stereo( int _enable)
{
if ( 0 <= fd_soundcard) ioctl( fd_soundcard, SNDCTL_DSP_STEREO, &_enable);
}
//------------------------------------------------------------------------------
// Description: set bit rate of output sound
// Factor : _rate - bit rate value
//------------------------------------------------------------------------------
void soundcard_set_bit_rate( int _rate)
{
if ( 0 <= fd_soundcard) ioctl( fd_soundcard, SNDCTL_DSP_SPEED, &_rate );
}
//------------------------------------------------------------------------------
// Description: set bit size of output sound
// Factor: _size - bit size of sound data
//------------------------------------------------------------------------------
void soundcard_set_data_bit_size( int _size)
{
if ( 0 <= fd_soundcard) ioctl( fd_soundcard, SNDCTL_DSP_SAMPLESIZE, &_size);
}
//------------------------------------------------------------------------------
// Description: set sound card volume
// Factor: _channel - the chennel number
// Headphone volume : SOUND_MIXER_WRITE_VOLUME
// PCM volume : SOUND_MIXER_WRITE_PCM
// Speaker volume : SOUND_MIXER_WRITE_SPEAKER
// Line volume : SOUND_MIXER_WRITE_LINE
// Mic volume : SOUND_MIXER_WRITE_MIC
// CD volume : SOUND_MIXER_WRITE_CD
// PCM2 volume : SOUND_MIXER_WRITE_ALTPCM main) Speaker volume of ESP-MMI
// IGain volume : SOUND_MIXER_WRITE_IGAIN
// Line 1 volume : SOUND_MIXER_WRITE_LINE1
// _left : left or low value of volume
// _right: right or high value of volume
//------------------------------------------------------------------------------
void soundcard_set_volume( int _channel, int _left, int _right )
{
int volume;
if ( 120 < _left ) _left = 120;
if ( 120 < _right ) _right = 120;
volume = 256 *_right +_left;
ioctl( fd_mixer, _channel, &volume );
}
//--------------------------------------------------------------------
// Description: Open for play the wav file
// Detail: Possible only wav file
// Factor: _filename : Name of wav file
// Return: 0 < Success in file open
// 0 > Fail to file open & Error code
//--------------------------------------------------------------------
int soundcard_open_file( char *_filename)
{
int fd_wavfile;
int read_size;
unsigned char buff[BUFF_SIZE+5];
wav_info_t *p_wav_info;
wav_info_t wav_info;
unsigned char *ptr;
if ( 0 != access(_filename, R_OK ) ) // No file
return SCERR_NO_FILE;
fd_wavfile = open(_filename, O_RDONLY );
if ( 0 > fd_wavfile) // Fail to file open
return SCERR_NOT_OPEN;
// Header processing
memset( buff, 0 , BUFF_SIZE);
read_size = read( fd_wavfile, buff, BUFF_SIZE);
if ( 0 == memmem( buff, BUFF_SIZE, "RIFF", 4 )) // examine whether "RIFF" string is.
return SCERR_NOT_WAV_FILE;
if ( 0 == memmem( buff, BUFF_SIZE, "WAVE", 4 )) // examine whether "WAVE" string is.
return SCERR_NOT_WAV_FILE;
p_wav_info = (wav_info_t *)memmem( buff, BUFF_SIZE, "fmt ", 4 ); // get the format information
if ( NULL == p_wav_info)
return SCERR_NO_wav_info;
memcpy( &wav_info, p_wav_info, sizeof(wav_info_t) );
// printf( "CHANNEL = %dn", (int) wav_info.channels );
// printf( "DATA BITS = %dn", (int) wav_info.data_bit);
// printf( "RATE = %dn", (int) wav_info.rate);
ptr = (unsigned char *)memmem( buff, BUFF_SIZE, "data", 4 );
ptr += 8;
data_offset = (unsigned long)( ptr - buff );
lseek( fd_wavfile, data_offset , SEEK_SET ); // move to data offset file read offset
soundcard_set_stereo ( wav_info.channels >= 2 ? 1 : 0); // enable sound춖tereo mode
soundcard_set_data_bit_size( wav_info.data_bit ); // set sound data size
soundcard_set_bit_rate ( wav_info.rate ); // set sound bit rate
return fd_wavfile;
}
//--------------------------------------------------------------------
// Description: Close for quit to use sound card
//--------------------------------------------------------------------
void soundcard_close( void)
{
close( fd_soundcard);
close( fd_mixer );
}
//--------------------------------------------------------------------
// Description: Open for using Sound Card
// Factor: _mode - PLAYER : Private Play
// Factor: _mode - RECORDER : Private Recorder
// Factor: _mode - AUDIO : Play and Record
// Return: Sound Card file descriptor
//--------------------------------------------------------------------
int soundcard_open(int _mode)
{
char *dsp_devname = DSP_DEVICE_NAME;
char *mixer_devname = MIXER_DEVICE_NAME;
// Open Sound Card device
if ( 0 != access( dsp_devname, W_OK ) )
return SCERR_PRIVILEGE_SOUNDCARD;
printf(" dsp_devname : %s \n", dsp_devname);
printf(" _mode : %d\n", _mode);
fd_soundcard = open( dsp_devname, _mode );
if ( 0 > fd_soundcard ) {
printf("\n***** Error : %d ********\n", fd_soundcard);
perror("file open error:");
return SCERR_OPEN_SOUNDCARD;
}
// Open MIXER
if ( 0 != access( mixer_devname, W_OK ) )
return SCERR_PRIVILEGE_MIXER;
fd_mixer = open( mixer_devname, O_RDWR|O_NDELAY );
if ( 0 > fd_soundcard)
return SCERR_OPEN_MIXER;
return fd_soundcard;
}
//--------------------------------------------------------------------
// Description: Save to "test.wav" recoarded during 10sec using sound card
//--------------------------------------------------------------------
int main( int argc, char **argv )
{
int fd_soundcard;
int fd_wav_file;
char *sound_buff; // buffer for sound output
int sound_buff_size;
int read_size;
if ( 2 > argc)
printx( "usage: ./exe [wave file name]");
fd_soundcard = soundcard_open( O_WRONLY);
printf("\n***** fd_soundcard : %d ********\n", fd_soundcard);
printf("\n***** Error : %s ********\n", strerror(errno));
switch( fd_soundcard)
{
case SCERR_NO_PROC_DEVICE : printx( "Do not have /proc/device");
case SCERR_NO_SOUNDCARD : printx( "Do not have Sound Card");
case SCERR_NO_MIXER : printx( "Do not have Mixer");
case SCERR_PRIVILEGE_SOUNDCARD : printx( "No permission using Sound Card");
case SCERR_PRIVILEGE_MIXER : printx( "No permission using Mixer device");
case SCERR_OPEN_SOUNDCARD : printx( "Cannot open Sound Card");
case SCERR_OPEN_MIXER : printx( "Cnanot open Mixer device");
}
soundcard_set_volume( SOUND_MIXER_WRITE_ALTPCM, 100, 100);
soundcard_set_volume( SOUND_MIXER_WRITE_MIC , 80, 80);
soundcard_set_volume( SOUND_MIXER_WRITE_IGAIN , 60, 60);
sound_buff_size = soundcard_get_buff_size();
sound_buff = ( char *)malloc( sound_buff_size);
fd_wav_file = soundcard_open_file( argv[1]); // open the wave file to output
switch( fd_wav_file)
{
case SCERR_NO_FILE : printx( "There's no WAV file");
case SCERR_NOT_OPEN : printx( "Cannot open WAV file");
case SCERR_NOT_WAV_FILE : printx( "It's not WAV file");
case SCERR_NO_wav_info : printx( "There's no WAV Information");
}
while( 1)
{
read_size = read( fd_wav_file, &sound_buff[0], soundcard_get_buff_size());
if( 0 < read_size)
{
write( fd_soundcard, &sound_buff[0], read_size );
}
else
break;
}
close( fd_wav_file);
soundcard_close();
return 0;
}Forums:


ioctl() 호출에 사용한 argument 가
ioctl() 호출에 사용한 argument 가 커널단 안에서는 구현이 안되어 있는 상태인 것 같습니다.
타겟 보드의 커널 소스나 드라이버 소스를 확인하셔서 사용하신 cmd 를 지원하는지 확인해 보십시요.
========================
조직 : E.L.D(Embedded Linux Developer/Designer)
블로그 : poplinux@tistory.com
카페 : cafe.naver.com/poplinux
임베디드 리눅스 관련 프리렌서 지향
댓글 달기