ALSA学习(3)——声卡的创建
创始人
2024-05-30 23:42:20
0

文章目录

  • 一、声卡的属性
  • 二、声卡的创建

许久没有更新关于audio的东西了,因为项目原因,接下来又要继续搞audio的东西了,所以继续写一些文章,作为一个温故知新的过程吧。
首先看一下声卡的架构驱动把

一、声卡的属性

开源代码路径

struct snd_card {int number;         /* number of soundcard (index to snd_cards) */char id[16];            /* id string of this card */char driver[16];        /* driver name */char shortname[32];     /* short name of this soundcard */char longname[80];      /* name of this soundcard */char irq_descr[32];     /* Interrupt description */char mixername[80];     /* mixer name */char components[128];       /* card components delimited with space */struct module *module;      /* top-level 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;   /* devices */struct device ctl_dev;      /* control device */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;  /* all controls for this card */struct list_head ctl_files; /* active control files */struct snd_info_entry *proc_root;   /* root for soundcard specific files */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 */struct completion *release_completion;struct device *dev;     /* device assigned to this card */struct device card_dev;     /* cardX object for sysfs */const struct attribute_group *dev_groups[4]; /* assigned sysfs attr */bool registered;        /* card_dev is registered? */int sync_irq;           /* assigned irq, used for PCM sync */wait_queue_head_t remove_sleep;size_t total_pcm_alloc_bytes;   /* total amount of allocated buffers */struct mutex memory_mutex;  /* protection for the above */
#ifdef CONFIG_PMunsigned int power_state;   /* power state */wait_queue_head_t power_sleep;
#endif
#if IS_ENABLED(CONFIG_SND_MIXER_OSS)struct snd_mixer_oss *mixer_oss;int mixer_oss_change_count;
#endifANDROID_KABI_RESERVE(1);ANDROID_KABI_RESERVE(2);
};

这里面每个参数都有对应的说明,比较重要的应该就是两个连表

struct list_head devices;   /* devices */ //记录该声卡下所有逻辑设备的链表 
struct list_head controls;  /* all controls for this card */ //记录该声卡下所有的控制单元的链表
struct list_head ctl_files; /* active control files */ // 用于管理该card下的active的control设备

这些从代码来看就是定义好了的,没有什么问题需要去修改。

二、声卡的创建

以前是通过 snd_card_create 去创建一个声卡,随着kernel的版本迭代,现在已经变为了 snd_card_new,具体是在哪个版本更新的不知道。这个可能需要注意以下。
基本上创建声卡的函数都是在驱动的probe函数里,
不同的平台可能函数也有一些不一样,这个大家得注意。

xxx_probe {error = snd_card_new(dev, index[n], id[n], THIS_MODULE,sizeof(struct snd_es1688), &card);
}
/*
这里面会传递一些参数dev  				总线index          	 	一个整数值,该声卡的编号id                		字符串,声卡的标识符第四个参数    	该参数决定在创建snd_card实例时,需要同时额外分配的私有数据的大小,该数据的指针最终会赋值给snd_card的private_data数据成员card             		返回所创建的snd_card实例的指针
*/

开源代码说明

声卡的专用数据主要用于存放该声卡的一些资源信息,例如中断资源、io资源、dma资源等.可以有两种创建方法:
通过上一步中snd_card_create()中的第四个参数,让snd_card_create自己创建

In general, there are two ways of allocating the chip record.1. Allocating via :c:func:`snd_card_new()`.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~As mentioned above, you can pass the extra-data-length to the 5th
argument of :c:func:`snd_card_new()`, i.e.::err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,sizeof(struct mychip), &card);struct mychip is the type of the chip record.In return, the allocated record can be accessed as::struct mychip *chip = card->private_data;With this method, you don't have to allocate twice. The record is
released together with the card instance.2. Allocating an extra device.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~After allocating a card instance via :c:func:`snd_card_new()`
(with ``0`` on the 4th arg), call :c:func:`kzalloc()`.::struct snd_card *card;struct mychip *chip;err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,0, &card);.....chip = kzalloc(sizeof(*chip), GFP_KERNEL);The chip record should have the field to hold the card pointer at least,::struct mychip {struct snd_card *card;....};Then, set the card pointer in the returned chip instance.::chip->card = card;Next, initialize the fields, and register this chip record as a
low-level device with a specified ``ops``,::static const struct snd_device_ops ops = {.dev_free =        snd_mychip_dev_free,};....snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);:c:func:`snd_mychip_dev_free()` is the device-destructor
function, which will call the real destructor.::static int snd_mychip_dev_free(struct snd_device *device){return snd_mychip_free(device->device_data);}where :c:func:`snd_mychip_free()` is the real destructor.The demerit of this method is the obviously more amount of codes.
The merit is, however, you can trigger the own callback at registering
and disconnecting the card via setting in snd_device_ops.
About the registering and disconnecting the card, see the subsections
below.

英语不好读起来真的吃力阿 。。。

第一种方法相对来说会简单一些,不需要释放两次内存

然后就是设置driver的ID和名字

              strcpy(card->driver, "My Chip");strcpy(card->shortname, "My Own Chip 123");sprintf(card->longname, "%s at 0x%lx irq %i",card->shortname, chip->port, chip->irq);

snd_card的driver字段保存着芯片的ID字符串,user空间的alsa-lib会使用到该字符串,所以必须要保证该ID的唯一性.shortname字段更多地用于打印信息,longname字段则会出现在/proc/asound/cards中.

当一个声卡注册完毕过后,就会去注册这些声卡的功能,包括Mixer和PCM这些,
而这些都是通过各个函数创建的

比如这种:

err = snd_pcm_new(chip->card, "My Chip", 0, 1, 1, &pcm);

在上面那个开源的文章里面,有很多例子,可以仔细去看看。
当所有的东西都农好了过后,最后就把这个声卡注册上去。

             /* (6) */err = snd_card_register(card);if (err < 0)goto error;

当使用完毕过后再释放这个声卡

/* (7) */pci_set_drvdata(pci, card);dev++;return 0;

内核文档真的写的很详细,有时间还是需要自己多去看看。

相关内容

热门资讯

讲题算补课吗 讲题算补课吗不算,讲题并不算补课。讲题只是课后的一个习题讲解,并且这样子最好就是放到一型册个课后服务...
你知道的神话故事有? 你知道的神话故事有?封神之战 逐鹿之战 水神大战火神 精卫填海 夸父逐日 杨戬救母劈桃山 沉香救母劈...
谁有描写声音的 英语单词?我急... 谁有描写声音的 英语单词?我急用!要写出这是什么东西的声音。ring电话声。oh感叹词欧bang 撞...
至尊龙纹为什么从152章就看不... 至尊龙纹为什么从152章就看不了?未克从,黄金赠路岁晏,十载陇西头。
李九重在相声界的地位如何? 李九重在相声界的地位如何?地位是挺高的,而且他也是一位非常优秀的相声演员,出演过很多优秀的作品。李九...
《美好人生》所以歌曲 《美好人生》所以歌曲《美好人生》全部歌曲序号 歌曲名称 歌手 播放 送歌 1 千里之外 周杰伦 ...
3.05 2400AP的兽王L... 3.05 2400AP的兽王LR 24%暴击 120命中.秒伤应该大概多少?我打AG70级的木桩才1...
开塞36首小提琴练习曲1多少级 开塞36首小提琴练习曲1多少级开塞36首练习曲的第一首练习曲,一般收录在小提琴考级的第二级,也有收录...
关于怀孕的。 关于怀孕的。上个月30号来的月经,这个月18号和老公同房了,今天来了月经,是不是就代表不会怀孕了?指...
上夜班很累 上夜班很累以前我也上过夜班,上夜班的人一般都是生物钟与别要刚好完全相反,所以白天的休息时间一定要足,...
九老十三匠是指哪些? 九老十三匠是指哪些?同上 。。木匠、泥水匠、。木匠、泥水匠、石匠、铁匠、船匠、佛匠、雕花匠、搭彩...
有哪些好玩有趣的的休闲益智游戏... 有哪些好玩有趣的的休闲益智游戏?您好,七麦数据为您解答~对抗类的休闲游戏其实也很火,如之前火爆全网的...
找一首老歌 找一首老歌我想找一首歌是一个男的唱的我记得里面有一句歌词是什么难舍难了.........什么岩一首还...
电影《无双》中李问真的是画家吗... 电影《无双》中李问真的是画家吗?电影的结局已经很清楚,李问是画家,歼链秀清终究还是蠢尘无带改禅法忍受...
年轻人一年四季在打工,仍旧穷得... 年轻人一年四季在打工,仍旧穷得叮当响,这是为什么?年轻人一年闹中四季在打工,仍旧穷得叮当响,主要的嫌...
搭帐篷是小猪佩奇搭档吗 搭帐篷是小猪佩奇搭档吗搭帐篷是小猪佩奇搭档。根据查询相关公开信息显示,培衡正《小猪佩奇奇遇记》第57...
垂手可得的幸福可信吗 垂手可得的幸福可信吗恩...最好还是三思而后行啊不要太相信了,不要拿自己的幸福开玩笑,太容易得到的不...
有哪些一流的中文流行歌曲作词人... 有哪些一流的中文流行歌曲作词人?他们各有什么强项?邓丽君,感情很细腻,一般都是做的男女情爱的歌曲,让...
你们炒股的感受经验和心得,分享... 你们炒股的感受经验和心得,分享下抽屉有几抽屉的东西,要不要丢?76还行,一有时间我就追啊32
雾起我在迷雾中爱你,雾散众人皆... 雾起我在迷雾中爱你,雾散众人皆知我爱你下句雾起我在迷雾中爱你,雾散众人皆知我爱你,希望未来的路,有你...