📄 em8xxx_oss.c
字号:
if (RMFAILED(err)){ printk("Error while setting the play time\n"); return err; } EM8XXXSNDGP(pE, audio_engine, RMAudioEnginePropertyID_SampleFrequency, &sampleRate, sizeof(sampleRate)); if (RMFAILED(err)){ printk("Error while getting the sample frequency\n"); return err; } //Init command = AudioDecoder_Command_Init; EM8XXXSNDSP(pE, audio_decoder, RMAudioDecoderPropertyID_Command, &command, sizeof(command)); if (RMFAILED(err)){ RMDBGLOG((ENABLE, "Error while initializing audio decoder! \n")); return err; } timeout =0; while (timeout < 1000000) { static RMuint32 count = 0; EM8XXXSNDGP(pE, audio_decoder,RMAudioDecoderPropertyID_State, &state, sizeof(state)); if (state == AudioDecoder_State_Stopped) break; kc_interruptible_sleep_on_timeout(pE->wq,US_TO_JIFFIES(10000)); timeout += 10000; count ++; printk("count : %lu, timeout = %ld\n", count, timeout); if (signal_pending(current)) { rc=-ERESTARTSYS; break; } } if (timeout >= 1000000) { RMDBGLOG((ENABLE, "Error setting init state! \n")); return -EINVAL; } /* allows us to change audio parameters without having to close/re-open the sound device */ pS->playback_enable = FALSE; printk("audio parameters are set : samplerate = %d, nb_bits_per_sample = %d, channelcount = %d\n", sampleRate,pS->nb_bits_per_sample, channelCount); return err;}#endifstatic int process_ioctl_dsp(struct sndprivate *pS, unsigned int cmd, unsigned long arg){ struct em8xxxprivate *pE=Etable+(pS-Stable); int val, rc,closed; audio_buf_info abinfo; long timeout; RMuint32 audio_decoder = EMHWLIB_MODULE(AudioDecoder,audio_decoder_index); RMuint32 audio_engine = EMHWLIB_MODULE(AudioEngine,audio_engine_index); struct DataFIFOInfo data_info; RMstatus err; RMbool enablesync=0; // Disable AV Sync from SNDCTL_DSP_GETBLKSIZE enum AudioDecoder_State_type state; rc = 0; switch (cmd) { case OSS_GETVERSION: printk("OSS_GETVERSION\n"); val = SOUND_VERSION; rc = kc_logging_copy_to_user((int *) arg, &val, sizeof(int)); break; case SNDCTL_DSP_SYNC: printk("SND_DSP_SYNC\n"); timeout = 0; rc = 0; while (timeout < 1000000) {// 1 sec EM8XXXSNDGP(pE, audio_decoder,RMGenericPropertyID_DataFIFOInfo, &data_info, sizeof(data_info)); val = (int) data_info.Readable % data_info.Size; if (val == 0) break; timeout += 10000; if (signal_pending(current)) { rc=-ERESTARTSYS; break; } } break; case SNDCTL_DSP_SETDUPLEX: printk("SND_DSP_SETDUPLEX\n"); rc = 0; break; case SNDCTL_DSP_GETCAPS: printk("SND_DSP_GETCAPS\n"); val = DSP_CAP_DUPLEX; rc = kc_logging_copy_to_user((int *) arg, &val, sizeof(int)); break; case SNDCTL_DSP_RESET: printk("SND_DSP_RESET\n"); break; case SNDCTL_DSP_SPEED: rc = kc_logging_copy_from_user(&val, (int *) arg, sizeof(int)); if (rc != 0) break; printk("SND_DSP_SPEED %d\n", val); pS->sample_rate = val; closed=1;#ifdef RMFEATURE_HAS_AUDIO_ENGINE_1 switch(audio_engine_index){ case 0: EM8XXXSNDGP(pE,EMHWLIB_MODULE(AudioDecoder,1-audio_decoder_index),RMAudioDecoderPropertyID_State,&state,sizeof(state)); if (state != AudioDecoder_State_Closed) closed=0; break; case 1: if (audio_decoder_index==2){ EM8XXXSNDGP(pE,EMHWLIB_MODULE(AudioDecoder,3),RMAudioDecoderPropertyID_State,&state,sizeof(state)); } else EM8XXXSNDGP(pE,EMHWLIB_MODULE(AudioDecoder,2),RMAudioDecoderPropertyID_State,&state,sizeof(state)); if (state != AudioDecoder_State_Closed) closed=0; break; } #else EM8XXXSNDGP(pE,EMHWLIB_MODULE(AudioDecoder,1-audio_decoder_index),RMAudioDecoderPropertyID_State,&state,sizeof(state)); if (state != AudioDecoder_State_Closed) closed=0; #endif // RMFEATURE_HAS_AUDIO_ENGINE_1 if(closed==1){ EM8XXXSNDSP(pE, audio_engine, RMAudioEnginePropertyID_SampleFrequency, &val, sizeof(val)); if (RMFAILED(err)){ printk("Error while setting the sample frequency\n"); return err; } } else{ RMDBGLOG((ENABLE,"Impossible to change sample rate because the other decoder is in use\n")); } rc = kc_logging_copy_to_user((int *) arg, &val, sizeof(int)); break; case SNDCTL_DSP_STEREO: printk("SND_DSP_STEREO\n"); rc = kc_logging_copy_from_user(&val, (int *) arg, sizeof(int)); if (rc != 0) break; pS->channel_count = (val) ? 2 : 1; break; case SNDCTL_DSP_CHANNELS: rc = kc_logging_copy_from_user(&val, (int *) arg, sizeof(int)); if (rc != 0) break; printk("SND_DSP_CHANNELS %d\n", val); if ((val == 1) || (val == 2)) { pS->channel_count = val; rc = 0; break; } else { rc = -EINVAL; } break; case SNDCTL_DSP_GETFMTS: printk("SND_DSP_GETFMTS\n"); /* this should be only AFMT_S16_BE. But some applications don't use this flag correctly */ val = AFMT_S16_BE | AFMT_S16_LE | AFMT_U8; rc = kc_logging_copy_to_user((int *) arg, &val, sizeof(int)); break; case SNDCTL_DSP_SETFMT: rc = kc_logging_copy_from_user(&val, (int *) arg, sizeof(int)); if (rc != 0) break; printk("SND_DSP_SETFMT %d\n", val); switch (val) { case AFMT_S16_LE: pS->format = AudioDecoder_Codec_PCM; pS->nb_bits_per_sample = 16; pS->MSBFirst = FALSE; break; case AFMT_S16_BE: pS->format = AudioDecoder_Codec_PCM; pS->nb_bits_per_sample = 16; pS->MSBFirst = TRUE; break; case AFMT_U8: pS->format = AudioDecoder_Codec_PCM; pS->nb_bits_per_sample = 8; break; case AFMT_QUERY: val = (pS->format == AudioDecoder_Codec_PCM) ? AFMT_S16_BE : AFMT_S16_LE; break; default: pS->format = AudioDecoder_Codec_PCM; val = AFMT_S16_LE; pS->nb_bits_per_sample = 16; pS->MSBFirst = FALSE; break; } { // Uninit long timeout = 0; enum AudioDecoder_Command_type command = AudioDecoder_Command_Uninit; enum AudioDecoder_Codec_type codec = pS->format; struct AudioDecoder_PcmCdaParameters_type pcm_parameters; long timeout_jiffies = (unsigned long long) 100000*(unsigned long long)HZ/1000000ULL; //10^-1 sec EM8XXXSNDSP(pE,audio_decoder,RMAudioDecoderPropertyID_Command,&command,sizeof(command)); if (RMFAILED(err)){ RMDBGLOG((ENABLE, "Unable to Uninit \n")); return err; } while (timeout < 1000000) { EM8XXXSNDGP(pE, audio_decoder,RMAudioDecoderPropertyID_State, &state, sizeof(state)); if (state == AudioDecoder_State_Uninitialized) break; timeout += kc_interruptible_sleep_on_timeout(pE->wq,timeout_jiffies); if (signal_pending(current)) { rc=-ERESTARTSYS; break; } } if (timeout >= 1000000) { RMDBGLOG((ENABLE, "Error setting uninit state! \n")); return -EINVAL; } // Format EM8XXXSNDSP(pE, audio_decoder, RMAudioDecoderPropertyID_Codec, &codec, sizeof(codec)); if (RMFAILED(err)){ RMDBGLOG((ENABLE, "Error setting codec property! \n")); return err; } // PCM Parameters switch(pS->channel_count) { case 1: pcm_parameters.ChannelAssign = PcmCda1_C; break; case 2: pcm_parameters.ChannelAssign = PcmCda2_LR; break; default: pcm_parameters.ChannelAssign = PcmCda2_LR; break; } pcm_parameters.BitsPerSample = pS->nb_bits_per_sample; pcm_parameters.SamplingFrequency = pS->sample_rate; pcm_parameters.MsbFirst = pS->MSBFirst; pcm_parameters.OutputDualMode = DualMode_Stereo; pcm_parameters.OutputSpdif = OutputSpdif_Uncompressed; pcm_parameters.OutputChannels = Audio_Out_Ch_LR; pcm_parameters.OutputLfe = FALSE; pcm_parameters.SignedPCM = (pS->nb_bits_per_sample==16) ? TRUE : FALSE; pcm_parameters.BassMode = 0; EM8XXXSNDSP(pE, audio_decoder, RMAudioDecoderPropertyID_PcmCdaParameters, &pcm_parameters, sizeof(pcm_parameters)); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Error setting pcm parameters! \n")); } //Init command = AudioDecoder_Command_Init; EM8XXXSNDSP(pE, audio_decoder, RMAudioDecoderPropertyID_Command, &command, sizeof(command)); if (RMFAILED(err)){ RMDBGLOG((ENABLE, "Error while initializing audio decoder! \n")); return err; } timeout =0; while (timeout < 1000000) { RMuint32 count = 0; EM8XXXSNDGP(pE, audio_decoder,RMAudioDecoderPropertyID_State, &state, sizeof(state)); if (state == AudioDecoder_State_Stopped) break; kc_interruptible_sleep_on_timeout(pE->wq,US_TO_JIFFIES(10000)); timeout += 10000; count ++; printk("count : %lu, timeout = %ld\n", count, timeout); if (signal_pending(current)) { rc=-ERESTARTSYS; break; } } if (timeout >= 1000000) { RMDBGLOG((ENABLE, "Error setting init state! \n")); return -EINVAL; } } rc = kc_logging_copy_to_user((int *) arg, &val, sizeof(int)); break; case SOUND_PCM_READ_RATE: printk("SOUND_PCM_READ_RATE\n"); EM8XXXSNDGP(pE, audio_engine, RMAudioEnginePropertyID_SampleFrequency, &val, sizeof(val)); if (RMFAILED(err)){ printk("Error while setting the sample frequency\n"); break; } rc = kc_logging_copy_to_user((int *) arg, &val, sizeof(int)); break; case SOUND_PCM_READ_CHANNELS: printk("SOUND_PCM_READ_CHANNELS\n"); val = pS->channel_count; rc = kc_logging_copy_to_user((int *) arg, &val, sizeof(int)); break; case SOUND_PCM_READ_BITS: printk("SOUND_PCM_READ_BITS\n"); val = pS->nb_bits_per_sample; rc = kc_logging_copy_to_user((int *) arg, &val, sizeof(int)); break; case SNDCTL_DSP_GETBLKSIZE: printk("SNDCTL_DSP_GETBLKSIZE\n"); val = BLKSIZE; rc = kc_logging_copy_to_user((int *) arg, &val, sizeof(int)); //Remove AV Sync form here printk("\nDisable AV Sync....module 0x%lx ad 0x%lx\n",(RMuint32)EMHWLIB_MODULE(AudioDecoder,audio_decoder_index),(RMuint32)audio_decoder_index); EM8XXXSNDSP(pE,EMHWLIB_MODULE(AudioDecoder,audio_decoder_index),RMAudioDecoderPropertyID_SyncSTCEnable, &enablesync, sizeof(RMbool)); break; case SNDCTL_DSP_GETOSPACE: EM8XXXSNDGP(pE, audio_decoder,RMGenericPropertyID_DataFIFOInfo, &data_info, sizeof(data_info)); val = (int) ((data_info.Size + data_info.Writable - data_info.Readable) % data_info.Size); printk("SNDCTL_DSP_GETOSPACE %d\n", val); abinfo.fragsize = 1<<AUDIO_DMA_BUFFER_SIZE_LOG2; abinfo.bytes = val; abinfo.fragstotal = AUDIO_DMA_BUFFER_COUNT; abinfo.fragments = val /(1<<AUDIO_DMA_BUFFER_SIZE_LOG2); rc = kc_logging_copy_to_user((void *)arg, &abinfo, sizeof(abinfo)); break; case SNDCTL_DSP_POST: printk("SNDCTL_DSP_POST\n"); rc = 0; break; case SNDCTL_DSP_SETFRAGMENT: printk("SNDCTL_DSP_SETFRAGMENT\n"); /* this call may be ignored */ rc = 0; break; case SNDCTL_DSP_GETODELAY: EM8XXXSNDGP(pE, audio_decoder,RMGenericPropertyID_DataFIFOInfo, &data_info, sizeof(data_info)); val = (int) ((data_info.Size + data_info.Writable - data_info.Readable) % data_info.Size); printk("SNDCTL_DSP_GETODELAY %d\n", val); rc = kc_logging_copy_to_user((int *) arg, &val, sizeof(int)); break; case SNDCTL_DSP_GETTRIGGER: printk("SNDCTL_DSP_GETTRIGGER\n"); rc = -EINVAL; break; case SNDCTL_DSP_SETTRIGGER: printk("SNDCTL_DSP_SETTRIGGER\n"); rc = -EINVAL; break; case SNDCTL_DSP_GETISPACE: printk("SNDCTL_DSP_GETISPACE\n"); rc = -EINVAL; break; case SNDCTL_DSP_GETIPTR: printk("SNDCTL_DSP_GETIPTR\n"); rc = -EINVAL; break; case SNDCTL_DSP_GETOPTR: printk("SNDCTL_DSP_GETOPTR\n"); rc = -EINVAL; break; case SNDCTL_DSP_SUBDIVIDE: printk("SNDCTL_DSP_SUBDIVIDE\n"); rc = -EINVAL; break; case SOUND_PCM_WRITE_FILTER: printk("SOUND_PCM_WRITE_FILTER\n"); rc = -EINVAL; break; case SNDCTL_DSP_SETSYNCRO: printk("SNDCTL_DSP_SETSYNCRO\n"); rc = -EINVAL; break; case SOUND_PCM_READ_FILTER: printk("SOUND_PCM_READ_FILTER\n"); rc = -EINVAL; break; case SNDCTL_DSP_NONBLOCK: printk("SNDCTL_DSP_NONBLOCK\n"); rc = -EINVAL; break; default: printk("try mixer ioctl\n"); rc = process_ioctl_mixer(pE, cmd, arg); break; } return rc;}int init_module(void){ int i,enabled_count=0; printk("begun\n"); switch(audio_decoder_index){ case 0: case 1: audio_engine_index=0; break;#ifdef RMFEATURE_HAS_AUDIO_ENGINE_1 case 2: case 3: audio_engine_index=1; break;#endif // RMFEATURE_HAS_AUDIO_ENGINE_1 default: printk("invalid parameter \n"); return -EINVAL; } audio_capture_index = audio_engine_index; for (i=0 ; i<MAXLLAD ; i++) { if (&((&Etable[i])->pllad) != NULL) { if (Etable[i].pllad != NULL){ if (sndprivate_init(&Etable[i]) != 0) return -EINVAL; enabled_count++; } } } if ( ((&Etable[0])->pllad != NULL) && (enabled_count == 0)) { printk("default behavior, enabling sound on device #0\n"); if (sndprivate_init(&Etable[0]) != 0) return -EINVAL; } printk("done\n"); return 0; }void cleanup_module(void){ int i; printk("begun\n"); for (i=0 ; i<MAXLLAD ; i++) { if (Stable[i].sndprivate_active) { sndprivate_cleanup(&Etable[i]); } } printk("done\n");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -