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;

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

相关内容

热门资讯

嵩山少林寺对联 嵩山少林寺对联九州名山数嵩岳四海古刹推少林
哪里可以看关于不知火舞的动漫 哪里可以看关于不知火舞的动漫专门描写不知火舞的我还没有听说,不过部分的话,你去看拳皇把。专门描写KI...
出租车为什么叫TAXI或的士? 出租车为什么叫TAXI或的士?出租车的英文是TAXI。 “的士”应该是广东香港一带的说法,用广东话说...
江雪这首诗的作者是? 江雪这首诗的作者是?《江雪》这首诗的作者是柳宗元《江雪》作者:柳宗元 (唐)千山鸟飞绝,万径人踪灭。...
王昌龄《出塞》里的度阴山 究竟... 王昌龄《出塞》里的度阴山 究竟是哪个度字 是渡还是度度,在文中是翻过昆仑山的意思是“度”字,是“过,...
求推荐几本类似于惊世亡妃,夜行... 求推荐几本类似于惊世亡妃,夜行歌,女子无殇的小说,就是情节跌宕起伏,男主深爱女主,好结局的古代言情求...
找一部小说,都市类型,女主高冷... 找一部小说,都市类型,女主高冷总裁,叫慕什么!男主和女主是没有公开结婚,男主在女主公司做的小保安,是...
往生问题? 往生问题?临终的人才回答得到你。但参与多次助念活动中,那些往生者临终前回光返照,都说已经见到阿弥陀佛...
怎样追求自己喜欢的女孩子 怎样追求自己喜欢的女孩子她是隔壁班的女孩子,非常可爱。我该怎么追她呢?我是学生。送花..然后悄悄表白...
你是不是饿的荒啊,十娘我给你做... 你是不是饿的荒啊,十娘我给你做面汤是什么歌 《杜十娘下面汤》曲调是江苏扬州民歌《杨柳青》杜十娘~...