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
임베디드 리눅스 관련 프리렌서 지향
댓글 달기