第10章 音频设备驱动程序移植 Linux系统移植(第2版) 教学课件

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

10.2.1 OSS驱动架构硬件
数字音频接口用来实现录音和播放声音的功 能。它的主要参数有:采样频率(电话为8K, DVD为96K)、channel数目(单声道,立体 声)、采样分辨率(8-bit,16-bit),对应的 设备文件为/dev/dsp。OSS驱动支持的硬件接 口有以下几种。
✓ mixer(混频器)接口 ✓ synthesizer(合成器)接口 ✓ MIDI(Musical Intrument Data Interface)接
10.1.1 PCM(脉冲编码调制)接 口
PCM接口针对不同的数字音频子系统, 用于数字转换的接口,它是最简单的音频 接口,该接口由时钟脉冲(BCLK)、帧 同步信号(FS)及接收数据(DR)和发 送数据(DX)组成。
10.1.4 Linux音频设备驱动框架
针对音频设备,Linux内核附有两类音频设备驱 动框架:OSS(Open Sound System)和ALSA (Advanced Linux Sound Architecture)。在内核 配置时,选择Device Drivers |Sound card support 命令进入Sound card support配置窗口。
10.2 Linux音频设备驱动—— OSS驱动框架
10.2.1 OSS驱动架构硬件 10.2.2 OSS驱动架构代码 10.2.3 OSS初始化函数oss_init() 10.2.4 OSS释放函数oss_cleanup() 10.2.5 打开设备文件函数sound_open() 10.2.6 录音函数sound_read() 10.2.7 播放函数sound_write() 10.2.8 控制函数sound_ioctl()
10.2.3 OSS初始化函数oss_init()
static int __init oss_init(void)
{
int
err;
int i, j;
#ifdef CONFIG_PCI if(dmabug) isa_dma_bridge_buggy = dmabug; #endif /*函数criecaet(e)_注sp册ec声ial音_d结ev点ice,s(根)最据终第调二用个函参数数re来gis指te定r_s声ou音nd结_s点pe的cia类l_型de。v- 这里指定注册了两个设备
device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].min-or));
if (!dev_list[i].num)
continue;
for (j = 1; j < *dev_list[i].num; j++) device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10))); }
第10章 音频设备驱动程序移植
10.1 音频设备接口 10.2 Linux音频设备驱动——OSS驱动框
架 10.3 Linux音频设备驱动——ALSA驱动
框架 10.4 音频设备应用程序编写 10.5 音频设备驱动移植 10.6 音频播放程序madplay的移植
10.1 音频设备接口
10.1.1 PCM(脉冲编码调制)接口 10.1.2 IIS(Inter-IC Sound)接口 10.1.3 AC97(Audio Codec 1997)接口 10.1.4 Linux音频设备驱动框架
}
10.2.5 打开设备文件函数
sound_open()
static int sound_open(struct inode *inode, struct file *file) { int dev = iminor(inode); int retval;
DEB(printk("sound_open(dev=%d)\n", dev)); if ((dev >= SND_NDEVS) || (dev < 0)) { printk(KERN_ERR "Invalid minor device %d\n", dev); return -ENXIO; } switch (dev & 0x0f) { /*音频设备接口为控制设备即混频器*/ case SND_DEV_CTL: dev >>= 4; if (dev >= 0 && dev < MAX_MIXER_DEV && mixer_devs[dev] == NULL) { request_module("mixer%d", dev); } if (dev && (dev >= num_mixers || mixer_devs[dev] == NULL)) return -ENXIO;
if (!try_module_get(mixer_devs[dev]->owner)) return -ENXIO; break;
10.2.5 打开设备文件函数
sound_open()
/*打开的设备接口为音序器*/ case SND_DEV_SEQ: case SND_DEV_SEQ2: if ((retval = sequencer_open(dev, file)) < 0) return retval; break; /*打开的设备为MIDI*/ case SND_DEV_MIDIN: if ((retval = MIDIbuf_open(dev, file)) < 0) return retval; break; /*打开的设备接口为AUDIO 或者DSP*/ case SND_DEV_DSP: case SND_DEV_DSP16: case SND_DEV_AUDIO: if ((retval = audio_open(dev, file)) < 0) return retval; break; default: printk(KERN_ERR "Invalid minor device %d\n", dev); return -ENXIO; } return 0; }
}
/*Protecting the innocent*/ sound_dmap_flag = (dmabuf > 0 ? 1 : 0); /*创建设备列表中的设备,并且注册它到系统文件中。*/
10.2.3 OSS初始化函数oss_init()
for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
/了*在设初备始se化qu函en数ceor和ss_seinqiut(e)n中ce调r2用,函在数注c销re函ate_special_数de中vi对ces应()注,销在这函两数个cr设eat备e_的sp驱eci动al_程de序vi。ce*s/ ()中分别注册 unregister_sound_special(1);
printk(KERN_ERR "Sound: Hmm, DMA%d was left allocated - fixed\n",
i);
百度文库
sound_free_dma(i);
} /*释放静态分配的内存资源*/ for (i = 0; i < sound_nblocks; i++)
vfree(sound_mem_blocks[i]);
unregister_sound_special(8);
/*停止定时器*/ sound_stop_timer();
/*音序器卸载,释放资源*/ sequencer_unload(); /*释放DMA资源*/ for (i = 0; i < MAX_DMA_CHANNELS; i++)
if (dma_alloc_map[i] != DMA_MAP_UNAVAIL) {
10.2.6 录音函数sound_read()
static ssize_t sound_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { int dev = iminor(file->f_path.dentry->d_inode); int ret = -EINVAL; /*锁住内核*/ lock_kernel(); DEB(printk("sound_read(dev=%d, count=%d)\n", dev, count)); /*设备接口类型为AUDIO 或者DSP时,调用函数audio_read ()读取设备文件数据到buf中*/ switch (dev & 0x0f) { case SND_DEV_DSP: case SND_DEV_DSP16: case SND_DEV_AUDIO: ret = audio_read(dev, file, buf, count); break; /*设备接口类型为音序器时,调用函数sequencer_read ()读取设备文件数据到buf中*/ case SND_DEV_SEQ: case SND_DEV_SEQ2: ret = sequencer_read(dev, file, buf, count); break; /*设备接口类型为MIDI时,调用函数MIDIbuf_read ()读取设备文件数据到buf*/ case SND_DEV_MIDIN: ret = MIDIbuf_read(dev, file, buf, count); } /*完成读取后解锁内核*/ unlock_kernel(); return ret; }
sequencer和sequencer2。*/ err = create_special_devices(); if (err) { printk(KERN_ERR "sound: driver already loaded/included in kernel
\n"); return err;

10.2.2 OSS驱动架构代码
当vwsnd驱动模块被加载时函数init_vwsnd()被调用, 音频驱动被初始化,驱动初始化过程会查找硬件配置 和匹配相应的驱动程序。函数init_vwsnd()的主要内容 如下:
static int __init init_vwsnd(void) { //驱动的探针函数 if (!probe_vwsnd(&the_hw_config)) return -ENODEV; //驱动附着函数 err = attach_vwsnd(&the_hw_config); }
device_create(sound_class, NULL,
MKDEV(SOUND_MAJOR, dev_list[i].minor), NULL,
"%s", dev_list[i].name);
if (!dev_list[i].num)
continue; /*如果设备列表的某项数目多于1个则创建剩下的设备,并且注册它们到系统文件中*/ for (j = 1; j < *dev_list[i].num; j++) device_create(sound_class, NULL,
return 0; }
10.2.4 OSS释放函数oss_cleanup()
static void __exit oss_cleanup(void)
{
int i, j; /*删除函数device_create()创建的设备。*/ for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
MKDEV(SOUND_MAJOR,
dev_list[i].minor + (j*0x10)),
NULL, "%s%d", dev_list[i].name, j);
}
if (sound_nblocks >= 1024)
printk(KERN_ERR "Sound warning: Deallocation table was too small. \n");
相关文档
最新文档