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;

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

相关内容

热门资讯

李光洁32天走7500公里吃8... 李光洁32天走7500公里吃8城,《拿一座城市下酒》这部纪录片怎么样?我觉得这部纪录片非常好,观看的...
每我世如你果只没界喜就欢的生一... 每我世如你果只没界喜就欢的生一爱有你过在想会。把这22个字组成一句话。我想过,如果在每一生只喜欢你,...
调查校园里的植物和动物说说有哪... 调查校园里的植物和动物说说有哪些动植物?可以分成几类?兰花,梅花可人丌··植物:乔木(杨树、柳树、银...
血脂高的原因? 血脂高的原因?血脂高的原因高血脂的诱因包括原发性和继发性两种:原发性高血脂症的病因:1、遗传因素。2...
为什么孩子总是重复看同一集动画... 为什么孩子总是重复看同一集动画片?是在传递这3个信号 小孩子爱看动画片是非常普遍的,动画片带给他们动...
终极三国里 49集刘备为什么这... 终极三国里 49集刘备为什么这么做?有没有官方回答?下集自己看吧 现在不会有官方回答的哟第一:可能真...
西式糕点制作大全的内容简介 西式糕点制作大全的内容简介《西式糕点制作大全》主要介绍了制作甜点的基本知识,例如各种制作工具,制作点...
逻辑思维又是什么?就是推理吗,... 逻辑思维又是什么?就是推理吗,怎么培养!?逻辑思维是一种严格分析思维。不一定是推理。推理是逻辑思维的...
囊萤夜读有一句俗语就是出自这个... 囊萤夜读有一句俗语就是出自这个故事你知道是什么吗?囊萤映雪 ( náng yíng yìng xuě...
什么是不伦恋情? 什么是不伦恋情?什么是不伦恋情.,?男跟女年龄相差很大?还是?男的比女的小?还是老夫少妻?是近亲谈恋...
有书名带晨星的嘛? 有书名带晨星的嘛?有书名带晨星的嘛?晨星传这本书。漫画书晨星物语
如果有些事情说不出口怎么办? 如果有些事情说不出口怎么办?烦恼皆是因为自己过分的执着 即使你在这样子下去 更不就不会有好的结果 为...
有哪些类似于《非自然死亡》题材... 有哪些类似于《非自然死亡》题材的日剧推荐?非自然死亡的题材电影确实不多,电视剧的话也不好找啊。不喜欢...
素书全集的内容简介 素书全集的内容简介 本书采用了《素书》的权威原著,参照《四库全书》并加上了宋代宰相张商英的注和清代王...
【世纪花园】小区对口的学校有重... 【世纪花园】小区对口的学校有重点小学和初中吗?世纪花园东区里有未来强者幼儿园,小区南边有个华兴小区,...
东南大学现有的专业中有哪些是属... 东南大学现有的专业中有哪些是属于老东南的1928年学校改名为国立中央大学,设理、工、医、农、文、法、...
一个男人一有钱就请朋友吃饭,没... 一个男人一有钱就请朋友吃饭,没钱就又说,买东西还赊账,商店里的老板都找上门来了?像陵念前这种男人的话...
坟上栽什么草好? 坟上栽什么草好?坟地种什么草好耐旱坟上栽野蕨草、扎根不深、浅根植物、可以固土、南方雨水多、不会造成坟...
关于国富潜力基金 关于国富潜力基金我9月24日上午买的国富基金,申购价格是9月24日开盘的价格吗?还是9月28日开盘的...
我是一个高中生。想学武术。在学... 我是一个高中生。想学武术。在学校没什么时间。是练散打还是跆拳道好。我是一个高中生。想学武术。在学校没...