[alsa-devel] snd_ctl_elem_write fails -EPERM if snd_pcm is open
Bouterse, Bob
bob.bouterse at dm-holdings-na.com
Tue Apr 15 19:33:33 CEST 2008
I am trying to sent IEC958 status bits on a VT1708A HAD-INTEL codec
while audio is being output.
snd_ctl_elem_write returns -EPERM from
linux-2.6.24.3/sound/core/control.c:769 .
Is there some way I can do this?
FYI using iecset will also give you an:
# iecset copywrite on
snd_ctl_elem_write: Operation not permitted
I am using alsa-lib-1.0.14a
$uname -a
Linux vision-vs 2.6.24.3 #1 SMP Fri Mar 28 09:35:45 EDT 2008 i686
unknown
$ gcc -v
Target: x86_64-linux-gnu
Configured with: ../src/configure -v
--enable-languages=c,c++,fortran,objc,obj-c++,treelang --prefix=/usr
--enable-shared --with-system-zlib --libexecdir=/usr/lib
--without-included-gettext --enable-threads=posix --enable-nls
--with-gxx-include-dir=/usr/include/c++/4.2 --program-suffix=-4.2
--enable-clocale=gnu --enable-libstdcxx-debug --enable-mpfr
--enable-checking=release --build=x86_64-linux-gnu
--host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.2.3 20071123 (prerelease) (Debian 4.2.2-4)
If it helps, here is the code I am using to set the bits. I modeled this
after the iecset.c code. Everything opens fine, it is the final call to
"snd_ctl_elem_write(this->ctl_handle, cval))" that fails.
static int ao_alsa_set_spdif_status(ao_driver_t *this_gen,
snd_aes_iec958_t* iec958)
{
alsa_driver_t *this = (alsa_driver_t *) this_gen;
config_values_t *config = this->class->xine->config;
char *pcm_device;
snd_ctl_card_info_t *hw_info;
int err;
snd_pcm_info_t *pcm_info;
int card;
char card_name[20];
snd_ctl_elem_list_t *clist;
snd_ctl_elem_id_t *cid;
snd_ctl_elem_value_t *cval;
unsigned int controls, cidx;
const char *spdif_str = SND_CTL_NAME_IEC958("", PLAYBACK, DEFAULT);
int opened_audio=0;
llprintf(LOG_TRACE_ENTER, "Entered\n");
if(!this->ctl_handle) {
if (!this->audio_fd) {
pcm_device =
config->lookup_entry(config,
"audio.device.alsa_passthrough_device")->str_value;
llprintf(LOG_MIXER,"Calling
local_snd_pcm_open(%s)\n", pcm_device);
err=local_snd_pcm_open(&this->audio_fd, pcm_device,
SND_PCM_STREAM_PLAYBACK, 1); /* NON-BLOCK mode */
if ( err <0 )
{
xine_log
(this->class->xine, XINE_LOG_MSG,
_("local_snd_pcm_open() failed:%d:%s\n"), err, snd_strerror(err));
return -1;
}
opened_audio = 1;
}
snd_pcm_info_alloca(&pcm_info);
snd_pcm_info(this->audio_fd, pcm_info);
card = snd_pcm_info_get_card(pcm_info);
llprintf(LOG_MIXER,"snd_pcm_info_get_card()
returned %d\n", card);
if(card < 0){
sprintf(card_name, "default");
}
else{
sprintf(card_name, "hw:CARD=%i",
card);
}
if (opened_audio && this->audio_fd) {
snd_pcm_close(this->audio_fd);
this->audio_fd = NULL;
opened_audio = 0;
}
llprintf(LOG_MIXER,"Calling snd_ctl_open(%s)\n",
card_name);
if ( (err = snd_ctl_open (&this->ctl_handle,
card_name, 0)) < 0 )
{
xprintf (this->class->xine,
XINE_VERBOSITY_DEBUG, "%s: snd_ctl_open(): %s\n", LOG_MODULE,
snd_strerror(err));
return -1;
}
}
snd_ctl_card_info_alloca(&hw_info);
if ( (err = snd_ctl_card_info (this->ctl_handle, hw_info)) < 0 )
{
xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
"%s: snd_ctl_card_info(): %s\n", LOG_MODULE,
snd_strerror(err));
snd_ctl_close(this->ctl_handle);
this->ctl_handle = 0;
return -1;
}
/* set the spdif status bits */
snd_ctl_elem_list_alloca(&clist);
if ((err = snd_ctl_elem_list(this->ctl_handle, clist)) < 0) {
xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
"snd_ctl_elem_list(): %s\n", snd_strerror(err));
snd_ctl_close(this->ctl_handle);
this->ctl_handle = 0;
return -1;
}
if ((err = snd_ctl_elem_list_alloc_space(clist,
snd_ctl_elem_list_get_count(clist))) < 0) {
xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
"snd_ctl_elem_list_alloc_space(): %s\n", snd_strerror(err));
snd_ctl_close(this->ctl_handle);
return -1;
}
if ((err = snd_ctl_elem_list(this->ctl_handle, clist)) < 0) {
xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
"snd_ctl_elem_list(): %s\n", snd_strerror(err));
snd_ctl_close(this->ctl_handle);
this->ctl_handle = 0;
return -1;
}
controls = snd_ctl_elem_list_get_used(clist);
for (cidx = 0; cidx < controls; cidx++) {
if (!strcmp(snd_ctl_elem_list_get_name(clist, cidx), spdif_str))
break;
}
if (cidx >= controls) {
fprintf(stderr, "control \"%s\" not found\n", spdif_str);
snd_ctl_close(this->ctl_handle);
this->ctl_handle = 0;
return -1;
}
snd_ctl_elem_id_alloca(&cid);
snd_ctl_elem_list_get_id(clist, cidx, cid);
snd_ctl_elem_value_alloca(&cval);
snd_ctl_elem_value_set_id(cval, cid);
llprintf(LOG_MIXER,"Writing
AES0=0x%02x,AES1=0x%02x,AES2=0x%02x,AES3=0x%02x\n",
iec958->status[0], iec958->status[1], iec958->status[2],
iec958->status[3]);
/* store the values */
snd_ctl_elem_value_set_iec958(cval, iec958);
if ((err = snd_ctl_elem_write(this->ctl_handle, cval)) < 0) {
xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
"snd_ctl_elem_write(): %s\n", snd_strerror(err));
snd_ctl_close(this->ctl_handle);
this->ctl_handle = 0;
}
llprintf(LOG_MIXER,"snd_ctl_elem_write() returrned %d\n",err);
/*-------------------------------------------------------*/
/*snd_ctl_close (this->ctl_handle);*/
return 0;
}
----------------------------------------------------
Bob Bouterse
Sr. Software Engineer
D&M Holdings Inc.
More information about the Alsa-devel
mailing list