當在我們的device端,可以使用命令 "amixer -c0 set i2s_clock on" 來開啟 i2s_clock
也可以使用命令 "amixer -c0 set i2s_clock off" 來關閉 i2s_clock
這表示我們的device 底層,已經有建立 "i2s_clock" 這個kcontrol,因此我們使用amixer 命令,才可以順利的再取呼叫到kcontrol所定義好的 function,進而做到function裡面所實作好的行為
簡單的kcontrol,大概如下圖所示: (此範例為MTK mt6880 audio card)
*註 SOC_SINGLE_EXT 是Linux底下的巨集,想知道定義可以去kernel底下 include/sound/soc.h 查看
以上簡單描述一下kcontrol,接下來進入本文章的主題,如何使用ALSA API來實作一個API,讓別人呼叫此API,就達到跟 amixer command 一樣的行為,底下是一個簡單的實作範例
#include <stdio.h>
#include <alsa/asoundlib.h>
int set_mixer_onoff(const char *control_name,
int option)
{
const char *device = "hw:0"; // 音訊設備的名稱或識別符號
//const char *control_name = "i2s_clock"; // 控制元素的名稱, 由API參數帶入
snd_ctl_t *handle;
snd_ctl_elem_id_t *elem_id;
snd_ctl_elem_value_t *elem_value;
int err;
// 打開音訊設備的控制界面
err = snd_ctl_open(&handle, device, 0);
if (err < 0) {
printf(":Cannot open device interface: %s\n", snd_strerror(err)); //無法打開音訊設備的控制界面
return err;
}
// 分配並初始化 snd_ctl_elem_id_t 結構
snd_ctl_elem_id_alloca(&elem_id);
snd_ctl_elem_id_set_name(elem_id, control_name);
// 獲取控制元素的索引
snd_ctl_elem_id_set_interface(elem_id, SND_CTL_ELEM_IFACE_MIXER);
// 獲取控制元素的數值
snd_ctl_elem_value_alloca(&elem_value);
snd_ctl_elem_value_set_id(elem_value, elem_id);
snd_ctl_elem_value_set_boolean(elem_value, 0, option); // 設置boolean值為1,由API參數帶入
// 設置控制元素的數值
err = snd_ctl_elem_write(handle, elem_value);
if (err < 0) {
printf("Cannot set value: %s\n", snd_strerror(err)); //無法設置控制元素的數值
snd_ctl_close(handle);
return err;
}
// 關閉音訊設備的控制界面
snd_ctl_close(handle);
printf("Setting %s %d success\n", control_name, option); //已成功設置 i2s_clock 為 on
return 0;
}
最後,編譯成為Library之後,提供對方 library 以及 xxx.h 裡面有包含此API宣告
int set_mixer_onoff(const char *control_name, int option);
對方就可以使用了!