简介:CSDN博客专家、《Android系统多媒体进阶实战》作者
博主新书推荐:《Android系统多媒体进阶实战》🚀
Android Audio工程师专栏地址:Audio工程师进阶系列【原创干货持续更新中……】🚀
Android多媒体专栏地址:多媒体系统工程师系列【原创干货持续更新中……】🚀
推荐1:AAOS车载系统+AOSP14系统攻城狮入门视频实战课🚀
推荐2:Android14 Binder之HIDL与AIDL通信实战课🚀
推荐3:Android15快速自定义与集成音效实战课🚀
推荐4:Android15音频策略实战课🚀
人生格言:人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.
🍉🍉🍉文章目录🍉🍉🍉
- 🌻1. 前言
- 🌻2. Android ALSA驱动进阶之snd_pcm_lib_ioctl介绍
- 🌻3. 代码实例
- 🌻3.1 车载播放驱动使用lib_ioctl处理标准流控
- 🌻3.2 语音唤醒录音使用lib_ioctl简化参数设置
- 🌻3.3 USB声卡双向流使用lib_ioctl统一管控
- 🌻3.4 用法总结
🌻1. 前言
本篇目的:Android ALSA驱动进阶之处理PCM的ioctl命令snd_pcm_lib_ioctl:用法实例
🌻2. Android ALSA驱动进阶之snd_pcm_lib_ioctl介绍
基本概念
snd_pcm_lib_ioctl是ALSA核心提供的标准ioctl处理函数,用于处理HW_PARAMS、SW_PARAMS、PREPARE、START、STOP、TRIGGER、STATUS等常用命令,驱动只需在ops->ioctl中指向它即可,无需重复实现。功能
支持全部标准PCM命令;自动调用驱动ops中的hw_params、sw_params、trigger等回调;与用户空间ioctl接口完全兼容;可内联调用;返回0或负错误码。使用限制
必须在ops->ioctl中设置;驱动仍需实现hw_params、trigger等回调;不可用于自定义私有命令;不可在中断上下文调用;需要对应ops。性能特性
单次跳转;耗时低于100 ns;无内存分配;支持16路并发;编码体积增加不到16字节。使用场景
车载标准播放控制、语音唤醒录音参数设置、USB声卡双向流控。
🌻3. 代码实例
🌻3.1 车载播放驱动使用lib_ioctl处理标准流控
应用场景
车载I2S播放只需实现hw_params与trigger,其余命令由snd_pcm_lib_ioctl代管。用法实例
#include<sound/core.h>#include<sound/pcm.h>#include<linux/module.h>staticintcar_hw_params(structsnd_pcm_substream*s,structsnd_pcm_hw_params*p){returnsnd_pcm_lib_malloc_pages(s,params_buffer_bytes(p));}staticintcar_trigger(structsnd_pcm_substream*s,intcmd){switch(cmd){caseSNDRV_PCM_TRIGGER_START:i2s_dma_start();break;caseSNDRV_PCM_TRIGGER_STOP:i2s_dma_stop();break;}return0;}staticstructsnd_pcm_opscar_ops={open=car_open,ioctl=snd_pcm_lib_ioctl,hw_params=car_hw_params,trigger=car_trigger,pointer=car_pointer,};staticint__initcar_ioctl_init(void){interr;structsnd_card*card;structsnd_pcm*pcm;err=snd_card_new(NULL,-1,"CarCard",THIS_MODULE,0,&card);if(err<0)returnerr;err=snd_pcm_new(card,"CarPlay",0,1,0,&pcm);if(err<0)gotofail;snd_pcm_set_ops(pcm,SNDRV_PCM_STREAM_PLAYBACK,&car_ops);strcpy(pcm->name,"Car Ioctl");err=snd_card_register(card);if(err<0)gotofail;return0;fail:snd_card_free(card);returnerr;}staticvoid__exitcar_ioctl_exit(void){structsnd_card*card=snd_card_ref(-1);if(card)snd_card_free(card);}module_init(car_ioctl_init);module_exit(car_ioctl_exit);MODULE_LICENSE("GPL");代码功能:ops->ioctl直接指向snd_pcm_lib_ioctl,内核自动处理START、STOP、STATUS等命令,驱动只需关注硬件操作。
🌻3.2 语音唤醒录音使用lib_ioctl简化参数设置
应用场景
低功耗语音捕获无需私有命令,所有标准参数设置由lib_ioctl完成。用法实例
#include<sound/core.h>#include<sound/pcm.h>#include<linux/module.h>staticintvw_hw_params(structsnd_pcm_substream*s,structsnd_pcm_hw_params*p){returnsnd_pcm_lib_malloc_pages(s,params_buffer_bytes(p));}staticintvw_trigger(structsnd_pcm_substream*s,intcmd){switch(cmd){caseSNDRV_PCM_TRIGGER_START:dsp_rec_start();break;caseSNDRV_PCM_TRIGGER_STOP:dsp_rec_stop();break;}return0;}staticstructsnd_pcm_opsvw_ops={open=vw_open,ioctl=snd_pcm_lib_ioctl,hw_params=vw_hw_params,trigger=vw_trigger,pointer=vw_pointer,};staticint__initvw_ioctl_init(void){interr;structsnd_card*card;structsnd_pcm*pcm;err=snd_card_new(NULL,-1,"VWCard",THIS_MODULE,0,&card);if(err<0)returnerr;err=snd_pcm_new(card,"VWCap",0,0,1,&pcm);if(err<0)gotofail;snd_pcm_set_ops(pcm,SNDRV_PCM_STREAM_CAPTURE,&vw_ops);strcpy(pcm->name,"VW Ioctl");err=snd_card_register(card);if(err<0)gotofail;return0;fail:snd_card_free(card);returnerr;}staticvoid__exitvw_ioctl_exit(void){structsnd_card*card=snd_card_ref(-1);if(card)snd_card_free(card);}module_init(vw_ioctl_init);module_exit(vw_ioctl_exit);MODULE_LICENSE("GPL");代码功能:录音流所有标准ioctl由snd_pcm_lib_ioctl代管,驱动聚焦低功耗硬件控制。
🌻3.3 USB声卡双向流使用lib_ioctl统一管控
应用场景
USB音频无需私有扩展,所有参数与流控通过标准ioctl完成。用法实例
#include<sound/core.h>#include<sound/pcm.h>#include<linux/module.h>staticintusb_hw_params(structsnd_pcm_substream*s,structsnd_pcm_hw_params*p){returnsnd_pcm_lib_malloc_pages(s,params_buffer_bytes(p));}staticintusb_trigger(structsnd_pcm_substream*s,intcmd){switch(cmd){caseSNDRV_PCM_TRIGGER_START:usb_iso_start();break;caseSNDRV_PCM_TRIGGER_STOP:usb_iso_stop();break;}return0;}staticstructsnd_pcm_opsusb_ops={open=usb_open,ioctl=snd_pcm_lib_ioctl,hw_params=usb_hw_params,trigger=usb_trigger,pointer=usb_pointer,};staticint__initusb_ioctl_init(void){interr;structsnd_card*card;structsnd_pcm*pcm;err=snd_card_new(NULL,-1,"USBCard",THIS_MODULE,0,&card);if(err<0)returnerr;err=snd_pcm_new(card,"USBDup",0,1,1,&pcm);if(err<0)gotofail;snd_pcm_set_ops(pcm,SNDRV_PCM_STREAM_PLAYBACK,&usb_ops);snd_pcm_set_ops(pcm,SNDRV_PCM_STREAM_CAPTURE,&usb_ops);strcpy(pcm->name,"USB Ioctl");err=snd_card_register(card);if(err<0)gotofail;return0;fail:snd_card_free(card);returnerr;}staticvoid__exitusb_ioctl_exit(void){structsnd_card*card=snd_card_ref(-1);if(card)snd_card_free(card);}module_init(usb_ioctl_init);module_exit(usb_ioctl_exit);MODULE_LICENSE("GPL");代码功能:播放与捕获流均使用snd_pcm_lib_ioctl,USB iso引擎启停由trigger回调控制,其余全部标准命令由核心代管。
🌻3.4 用法总结
| 代码关键字 | 功能描述 | 典型应用 |
|---|---|---|
| snd_pcm_lib_ioctl 播放 | 标准流控 | 车载I2S |
| snd_pcm_lib_ioctl 录音 | 参数设置 | 语音唤醒 |
| snd_pcm_lib_ioctl 双向 | 统一管控 | USB声卡 |