第一部分 alsa子系统关键结构体对象等
1.声卡设备类型定义
#define SNDRV_DEV_TOPLEVEL ((__force snd_device_type_t) 0)
#define SNDRV_DEV_CONTROL ((__force snd_device_type_t) 1)
#define SNDRV_DEV_LOWLEVEL_PRE ((__force snd_device_type_t) 2)
#define SNDRV_DEV_LOWLEVEL_NORMAL ((__force snd_device_type_t) 0x1000)
#define SNDRV_DEV_PCM ((__force snd_device_type_t) 0x1001)
#define SNDRV_DEV_RAWMIDI ((__force snd_device_type_t) 0x1002)
#define SNDRV_DEV_TIMER ((__force snd_device_type_t) 0x1003)
#define SNDRV_DEV_SEQUENCER ((__force snd_device_type_t) 0x1004)
#define SNDRV_DEV_HWDEP ((__force snd_device_type_t) 0x1005)
#define SNDRV_DEV_INFO ((__force snd_device_type_t) 0x1006)
#define SNDRV_DEV_BUS ((__force snd_device_type_t) 0x1007)
#define SNDRV_DEV_CODEC ((__force snd_device_type_t) 0x1008)
#define SNDRV_DEV_JACK ((__force snd_device_type_t) 0x1009)
#define SNDRV_DEV_LOWLEVEL ((__force snd_device_type_t) 0x2000)
一个声卡可以有多个声卡设备,alsa中用snd_card描述声卡对象,用snd_device描述声卡设备对象
2.声卡结构体
struct snd_card {
int number; //声卡索引号
char id[16]; //id识别字串
char driver[16]; //驱动名
char shortname[32]; //短名
char longname[80]; //长名
char mixername[80]; /* mixer name */
char components[128]; /* card components delimited with space */
struct module *module; //模块所有者
void *private_data; /* private data for soundcard */
void (*private_free) (struct snd_card *card); /* callback for freeing of private data */
struct list_head devices; //设备链表
unsigned int last_numid; /* last used numeric ID */
struct rw_semaphore controls_rwsem; /* controls list lock */
rwlock_t ctl_files_rwlock; /* ctl_files list lock */
int controls_count; /* count of all controls */
int user_ctl_count; /* count of all user controls */
struct list_head controls; //控制链表
struct list_head ctl_files; /* active control files */
struct snd_info_entry *proc_root; /* root for soundcard specific files */
struct snd_info_entry *proc_id; /* the card id */
struct proc_dir_entry *proc_root_link; /* number link to real id */
struct list_head files_list; /* all files associated to this card */
struct snd_shutdown_f_ops *s_f_ops; /* file operations in the shutdown state */
spinlock_t files_lock; /* lock the files for this card */
int shutdown; /* this card is going down */
int free_on_last_close; /* free in context of file_release */
wait_queue_head_t shutdown_sleep;
struct device *dev; //设备文件
struct device *card_dev; //声卡设备文件
#ifdef CONFIG_PM
unsigned int power_state; /* power state */
struct mutex power_lock; /* power lock */
wait_queue_head_t power_sleep;
#endif
#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
struct snd_mixer_oss *mixer_oss;
int mixer_oss_change_count;
#endif
};
2.1.全局变量snd_cards
在"/sound/core/init.c"
struct snd_card *snd_cards[SNDRV_CARDS];
SNDRV_CARDS为8也就是声卡最多8个
3.声卡设备结构体
struct snd_device {
struct list_head list; //链表
struct snd_card *card; //所属的声卡
snd_device_state_t state; //设备状态
snd_device_type_t type; //设备类型
void *device_data; /* device structure */
struct snd_device_ops *ops; //声卡设备操作函数集
};
3.1 设备状态的值
#define SNDRV_DEV_BUILD ((__force snd_device_state_t) 0)//创建
#define SNDRV_DEV_REGISTERED ((__force snd_device_state_t) 1)//注册
#define SNDRV_DEV_DISCONNECTED ((__force snd_device_state_t) 2)//断开连接
3.2 设备类型
也就是上面 1.声卡设备类型定义 所指定的类型
4.声卡操作函数集
struct snd_device_ops {
int (*dev_free)(struct snd_device *dev); //释放
int (*dev_register)(struct snd_device *dev); //注册
int (*dev_disconnect)(struct snd_device *dev); //断开连接
};
第二部分 声卡
1.声卡创建
传递进来的idx为负值,则系统会分配一个idx作为全局snd_cards数组的索引项值,xid字串用来区分描述声卡id,module一般为THIS_MODULE...
int snd_card_create(int idx, const char *xid,struct module *module, int extra_size,struct snd_card **card_ret)
{
struct snd_card *card;
int err, idx2;
if (snd_BUG_ON(!card_ret))
return -EINVAL;
*card_ret = NULL;
if (extra_size < 0)
extra_size = 0;
card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL); //分配声卡对象和额外空间的内存
if (!card)
return -ENOMEM;
if (xid) //若需要填充声卡id识别字串
strlcpy(card->id, xid, sizeof(card->id)); //card->id=xid 声卡id识别字串
err = 0;
mutex_lock(&snd_card_mutex); //idx为负值则交由系统选择一个值______________________<
if (idx < 0) {
for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++)
/* idx == -1 == 0xffff means: take any free slot */
if (~snd_cards_lock & idx & 1<<idx2) {
if (module_slot_match(module, idx2)) {
idx = idx2;
break;
}
}
}
if (idx < 0) {
for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++)
/* idx == -1 == 0xffff means: take any free slot */
if (~snd_cards_lock & idx & 1<<idx2) {
if (!slots[idx2] || !*slots[idx2]) {
idx = idx2;
break;
}
}
}
if (idx < 0)
err = -ENODEV;
else if (idx < snd_ecards_limit) {
if (snd_cards_lock & (1 << idx))
err = -EBUSY; /* invalid */
} else if (idx >= SNDRV_CARDS)
err = -ENODEV;
if (err < 0) {
mutex_unlock(&snd_card_mutex);
snd_printk(KERN_ERR "cannot find the slot for index %d (range 0-%i), error: %d\n",idx, snd_ecards_limit - 1, err);
goto __error;
}
snd_cards_lock |= 1 << idx; /* lock it */
if (idx >= snd_ecards_limit)
snd_ecards_limit = idx + 1; /* increase the limit */
mutex_unlock(&snd_card_mutex); //______________________>
card->number = idx; //声卡对象索引号 全局数组snd_cards的数组下标
card->module = module; //声卡对象模块所有者THIS_MODULE
INIT_LIST_HEAD(&card->devices); //初始化声卡设备链表
init_rwsem(&card->controls_rwsem); //初始化读写信号量
rwlock_init(&card->ctl_files_rwlock); //初始化读写锁
INIT_LIST_HEAD(&card->controls); //初始化声卡控制链表
INIT_LIST_HEAD(&card->ctl_files); //初始化声卡控制文件链表
spin_lock_init(&card->files_lock); //初始化自旋锁
INIT_LIST_HEAD(&card->files_list); //初始化声卡文件链表
init_waitqueue_head(&card->shutdown_sleep); //初始化关机队列头
#ifdef CONFIG_PM
mutex_init(&card->power_lock); //初始化电源互斥锁
init_waitqueue_head(&card->power_sleep); //初始化睡眠等待队列头
#endif
err = snd_ctl_create(card); //创建用于控制的声卡设备对象
if (err < 0) {