ALSA學習筆記 (4)Control

1. 如何創建一個control

1.1 定義一個snd_kcontrol_new結構體

static struct snd_kcontrol_new my_control __devinitdata = {
	.face = SNDRV_CTL_ELEM_IFACE_MIXER,
	.name = “PCM Playback Switch”,
	.index = 0,
	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
	.private_value = 0xffff,
	.info = my_control_info,
	.get = my_control_get,
	.put = my_control_put
};

iface 表示control的類型,用SNDRV_CTL_ELEM_IFACE_XXX來定義。例如: CARD, MIXER, PCM等
name 表示control的名字,用戶層可以通過這個名字訪問這個control
index 存放這個 control 的索引號
access 訪問權限的控制,READ,WRITE,READWRITE等
private_value 特定control的私有數據,例如可以存放寄存器地址信息

1.2 回調函數

1.2.1 info 函數

用於得到對應control的詳細信息,需要把信息存入snd_ctl_elem_info 對象中。

struct snd_ctl_elem_info {
	struct snd_ctl_elem_id id;	/* W: element ID */
	snd_ctl_elem_type_t type;	/* R: value type - SNDRV_CTL_ELEM_TYPE_* */
	unsigned int access;		/* R: value access (bitmask) - SNDRV_CTL_ELEM_ACCESS_* */
	unsigned int count;		/* count of values */
	__kernel_pid_t owner;		/* owner's PID of this control */
	union {
		struct {
			long min;		/* R: minimum value */
			long max;		/* R: maximum value */
			long step;		/* R: step (0 variable) */
		} integer;
		struct {
			long long min;		/* R: minimum value */
			long long max;		/* R: maximum value */
			long long step;		/* R: step (0 variable) */
		} integer64;
		struct {
			unsigned int items;	/* R: number of items */
			unsigned int item;	/* W: item number */
			char name[64];		/* R: value name */
			__u64 names_ptr;	/* W: names list (ELEM_ADD only) */
			unsigned int names_length;
		} enumerated;
		unsigned char reserved[128];
	} value;
	union {
		unsigned short d[4];		/* dimensions */
		unsigned short *d_ptr;		/* indirect - obsoleted */
	} dimen;
	unsigned char reserved[64-4*sizeof(unsigned short)];
};

其中value的值是一個共用體,根據control的類型,確定值的類型:
包括BOOLEAN,INTEGER,ENUMERATED,BYTES等類型,下面以BOOLEAN和ENUMRATED爲例定義info回調函數。

static int snd_myctl_info(struct snd_kcontrol *kcontrol,
							struct snd_ctl_elem_info *uinfo)
{
	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
	uinfo->count = 1;
	uinfo->value.integer.min = 0;
	uinfo->value.integer.max = 1;
	return 0;
}

Static int snd_myctl_info(struct snd_kcontrol *kcontrol,
							struct snd_ctl_elem_info *uinfo)
{
	static char *texts[4] ={
		“First”,“Second”,“Third”,“Fourth”
	};

	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMRATED;
	uinfo->count = 1;
	uinfo->value.enumerated.item = 3;
	strcpy(uinfo->value.enumerated.name,texts[uinfo->value.enumerated.item]);

	return 0;
}

1.2.2 get 函數

這個函數用來讀取當前 control 的值並返回到用戶空間
需要把值放在snd_ctl_elem_value結構體中,與info結構體類似,value字段是一個共用體,與類型相關。
如果value的cont大於1, 需要把值全部放入到 value[]數組中。

static int snd_myctl_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct mychip *chip = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = get_some_value(chip);
return 0;
}

1.2.3 put 函數

主要是從用戶空間寫一個值

static int snd_myctrl_put(struct snd_kcontrol *kcontrol,
							struct snd_ctl_elem_value *ucontrol)
{
	struct mychip *chip = snd_kcontrol_chip(kcontrol);
	int changed = 0;

	if (chip->current_value != ucontrol->value.integer.value[0]){
		change_current_value(chip,ucontrol->value.integer.value[0]);
		changed = 1;
	}

	return changed;
}

1.3 創建並添加一個 snd_kcontrol

snd_ctl_new1用於分配一個snd_kcontrol實例,把snd_kcontrol_new中的成員賦值給snd_kcontrol實例,另外需要傳入private_data 的指針
snd_ctl_add 把給定的 control 組件添加到 card 裏面

if ((err = snd_ctl_add(card, snd_ctl_new1(&my_control, chip))) < 0)
	return err;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章