第10章--音频设备驱动程序移植-Linux系统移植(第2版)-教学课件.ppt
《第10章--音频设备驱动程序移植-Linux系统移植(第2版)-教学课件.ppt》由会员分享,可在线阅读,更多相关《第10章--音频设备驱动程序移植-Linux系统移植(第2版)-教学课件.ppt(67页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、第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.1.1 PCM(脉冲编码调制)接口PCM接口针对不同的数字音频子系统,用于数字转换的接口,它是最简单的音频接口,该接口由时钟脉冲(
2、BCLK)、帧同步信号(FS)及接收数据(DR)和发送数据(DX)组成。10.1.2 IIS(Inter-IC Sound)接口IIS接口在20世纪80年代首先被飞利浦用于消费音频,并在一个称为LRCLK(Left/Right CLOCK)的信号机制中经过多路转换,将两路音频信号合成单一的数据队列。当LRCLK信号为高时,左声道数据被传输;LRCLK信号为低时,右声道数据被传输。IIS接口的特点:与PCM相比,IIS接口更适用于立体声系统。对于多通道系统,在同样的BCLK和LRCLK条件下,也可以并行执行几个数据队列。10.1.4 Linux音频设备驱动框架针对音频设备,Linux内核附有两类
3、音频设备驱动框架: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
4、.2.7 播放函数sound_write()10.2.8 控制函数sound_ioctl()10.2.1 OSS驱动架构硬件数字音频接口用来实现录音和播放声音的功能。它的主要参数有:采样频率(电话为8K,DVD为96K)、channel数目(单声道,立体声)、采样分辨率(8-bit,16-bit),对应的设备文件为/dev/dsp。OSS驱动支持的硬件接口有以下几种。mixer(混频器)接口synthesizer(合成器)接口MIDI(Musical Intrument Data Interface)接口10.2.3 OSS初始化函数oss_init()static int _init oss
5、_init(void)int err;int i,j;#ifdef CONFIG_PCIif(dmabug)isa_dma_bridge_buggy=dmabug;#endif/*函数create_special_devices()最终调用函数register_sound_special_dev-ice()注册声音结点,根据第二个参数来指定声音结点的类型。这里指定注册了两个设备sequencer和sequencer2。*/err=create_special_devices();if(err)printk(KERN_ERR sound:driver already loaded/include
6、d in kerneln);return err;/*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+)device_create(sound_class,NULL,MKDEV(SOUND_MAJOR,dev_listi.minor),NULL,%s,dev_listi.name);if(!dev_listi.num)continue;/*如果设备列表的某项数目多
7、于1个则创建剩下的设备,并且注册它们到系统文件中*/for(j=1;j=1024)printk(KERN_ERR Sound warning:Deallocation table was too small.n);return 0;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=4;if(de
8、v=0&dev=num_mixers|mixer_devsdev=NULL)return-ENXIO;if(!try_module_get(mixer_devsdev-owner)return-ENXIO;break;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(
9、printk(sound_read(dev=%d,count=%d)n,dev,count);/*设备接口类型为AUDIO 或者DSP时,调用函数audio_read()读取设备文件数据到buf中*/switch(dev&0 x0f)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
10、=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;10.2.7 播放函数sound_write()static ssize_t sound_write(struct file*file,const char _user*buf,size_t count,loff_t*ppos)i
11、nt dev=iminor(file-f_path.dentry-d_inode);int ret=-EINVAL;/*锁住内核*/lock_kernel();DEB(printk(sound_write(dev=%d,count=%d)n,dev,count);switch(dev&0 x0f)/*设备接口类型为音序器时,调用函数sequencer_ write()将buf中数据写到到设备文件*/case SND_DEV_SEQ:case SND_DEV_SEQ2:ret=sequencer_write(dev,file,buf,count);break;/*设备接口类型为AUDIO 或者D
12、SP时,调用函数audio_write()将buf中数据写到到设备文件*/case SND_DEV_DSP:case SND_DEV_DSP16:case SND_DEV_AUDIO:ret=audio_write(dev,file,buf,count);break;/*设备接口类型为MIDI时,调用函数MIDIbuf_write()将buf中数据写到到设备文件*/case SND_DEV_MIDIN:ret=MIDIbuf_write(dev,file,buf,count);break;unlock_kernel();return ret;10.2.8 控制函数sound_ioctl()/*
13、如果命令的类型为Mixer,调用sound_mixer_ioctl()*/if(_IOC_TYPE(cmd)=M&num_mixers 0&/*Mixer ioctl*/(dev&0 x0f)!=SND_DEV_CTL)dtype=dev&0 x0f;switch(dtype)case SND_DEV_DSP:case SND_DEV_DSP16:case SND_DEV_AUDIO:return sound_mixer_ioctl(audio_devsdev 4-mixer_dev,cmd,p);default:return sound_mixer_ioctl(dev 4,cmd,p);10
14、.2.8 控制函数sound_ioctl()switch(dev&0 x0f)/*设备接口类型为AUDIO 或者DSP时,调用函数sound_mixer_ioctl()*/case SND_DEV_CTL:if(cmd=SOUND_MIXER_GETLEVELS)return get_mixer_levels(p);if(cmd=SOUND_MIXER_SETLEVELS)return set_mixer_levels(p);return sound_mixer_ioctl(dev 4,cmd,p);/*设备接口类型为音序器时,调用函数sequencer_ioctl()*/case SND_D
15、EV_SEQ:case SND_DEV_SEQ2:return sequencer_ioctl(dev,file,cmd,p);/*设备接口类型为AUDIO 或者DSP时,调用函数audio_ioctl()*/case SND_DEV_DSP:case SND_DEV_DSP16:case SND_DEV_AUDIO:return audio_ioctl(dev,file,cmd,p);break;/*设备接口类型为MIDI时,调用函数MIDIbuf_ioctl()*/case SND_DEV_MIDIN:return MIDIbuf_ioctl(dev,file,cmd,p);break;r
16、eturn-EINVAL;10.3 Linux音频设备驱动ALSA驱动框架10.3.1 card和组件10.3.2 PCM设备10.3.3 控制接口10.3.4 AC97 API音频接口10.3.1 card和组件每个声卡必须创建一个card实例,下面通过驱动代码介绍ALSA声卡驱动是如何管理card和组件的。1.创建card函数snd_card_new()2.创建组件函数snd_device_new()3.释放组件函数snd_device_free()4.释放card函数snd_card_free()5.断开所有的ALSA API函数snd_card_disconnect()1.创建card
17、函数snd_card_new()函数snd_card_new()用于创建和初始化snd_card结构体。idx是卡的索引号,xid是标识字符串,module是顶层模块,extra_siz额外分配数据的大小。3.释放组件函数snd_device_free()int snd_device_free(struct snd_card*card,void*device_data)struct snd_device*dev;if(snd_BUG_ON(!card|!device_data)return-ENXIO;/*根据device_data找到要释放的设备*/list_for_each_entry(d
18、ev,&card-devices,list)if(dev-device_data!=device_data)continue;/*该设备从链表中断开*/list_del(&dev-list);/*判断断开是否成功*/if(dev-state=SNDRV_DEV_REGISTERED&dev-ops-dev_disconnect)if(dev-ops-dev_disconnect(dev)snd_printk(KERN_ERR device disconnect failuren);/*判断释放是否成功*/if(dev-ops-dev_free)if(dev-ops-dev_free(dev)s
19、nd_printk(KERN_ERR device free failuren);/*释放设备占用的内存*/kfree(dev);return 0;snd_printd(device free%p(from%pF),not foundn,device_data,_builtin_return_address(0);return-ENXIO;4.释放card函数snd_card_free()int snd_card_free(struct snd_card*card)/*释放操作,并通知连接在card上的所有设备*/int ret=snd_card_disconnect(card);if(ret
20、)return ret;/*所有的设备准备好释放操作*/wait_event(card-shutdown_sleep,card-files=NULL);/*释放card*/snd_card_do_free(card);return 0;5.断开所有的ALSA API函数snd_card_disconnect()int snd_card_disconnect(struct snd_card*card)/*第一阶段:使ALSA API操作失效*/mutex_lock(&snd_card_mutex);snd_cardscard-number=NULL;snd_cards_lock&=(1 numb
21、er);mutex_unlock(&snd_card_mutex);/*第二阶段:用专门的哑操作代替file-f_op*/spin_lock(&card-);mfile=card-files;while(mfile)file=mfile-file;/*its critical part,use endless loop*/*we have no room to fail*/mfile-disconnected_f_op=mfile-file-f_op;spin_lock(&shutdown_lock);list_add(&mfile-shutdown_list,&shutdown_files)
22、;spin_unlock(&shutdown_lock);mfile-file-f_op=&snd_shutdown_f_ops;fops_get(mfile-file-f_op);mfile=mfile-next;spin_unlock(&card-);/*第三阶段:通知所有的连接设备断开信息*/snd_device_disconnect_all(card);snd_info_card_disconnect(card);return 0;1.函数snd_pcm_new()用来创建PCM实例int snd_pcm_new(struct snd_card*card,char*id,int dev
23、ice,int playback_count,int capture_count,struct snd_pcm*rpcm)struct snd_pcm*pcm;int err;static struct snd_device_ops ops=.dev_free=snd_pcm_dev_free,.dev_register=snd_pcm_dev_register,.dev_disconnect=snd_pcm_dev_disconnect,;/*为构造的PCM实例分配空间并进行初始化*/pcm=kzalloc(sizeof(*pcm),GFP_KERNEL);if(pcm=NULL)snd_p
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 10 音频设备 驱动程序 移植 Linux 系统 教学 课件
限制150内