Android ALSA进阶之处理PCM的ioctl命令snd_pcm_lib_ioctl:用法实例(一百)

简介: CSDN博客专家、《Android系统多媒体进阶实战》作者

博主新书推荐:《Android系统多媒体进阶实战》🚀
Android Audio工程师专栏地址:Audio工程师进阶系列原创干货持续更新中...... 】🚀
Android多媒体专栏地址:多媒体系统工程师系列原创干货持续更新中...... 】🚀
推荐1:AAOS车载系统+AOSP14系统攻城狮入门视频实战课 🚀
推荐2:Android14 Binder之HIDL与AIDL通信实战课 🚀
推荐3:Android15快速自定义与集成音效实战课 🚀
推荐4:Android15音频策略实战课 🚀

人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.
更多原创,欢迎关注:Android系统攻城狮

🍉🍉🍉文章目录🍉🍉🍉

      • [🌻1. 前言](#🌻1. 前言)
      • [🌻2. Android ALSA驱动进阶之snd_pcm_lib_ioctl介绍](#🌻2. Android ALSA驱动进阶之snd_pcm_lib_ioctl介绍)
      • [🌻3. 代码实例](#🌻3. 代码实例)
        • [🌻3.1 车载播放驱动使用lib_ioctl处理标准流控](#🌻3.1 车载播放驱动使用lib_ioctl处理标准流控)
        • [🌻3.2 语音唤醒录音使用lib_ioctl简化参数设置](#🌻3.2 语音唤醒录音使用lib_ioctl简化参数设置)
        • [🌻3.3 USB声卡双向流使用lib_ioctl统一管控](#🌻3.3 USB声卡双向流使用lib_ioctl统一管控)
      • [🌻3.4 用法总结](#🌻3.4 用法总结)

🌻1. 前言

本篇目的:Android ALSA驱动进阶之处理PCM的ioctl命令snd_pcm_lib_ioctl:用法实例

🌻2. Android ALSA驱动进阶之snd_pcm_lib_ioctl介绍

  1. 基本概念

    snd_pcm_lib_ioctl是ALSA核心提供的标准ioctl处理函数,用于处理HW_PARAMS、SW_PARAMS、PREPARE、START、STOP、TRIGGER、STATUS等常用命令,驱动只需在ops->ioctl中指向它即可,无需重复实现。

  2. 功能

    支持全部标准PCM命令;自动调用驱动ops中的hw_params、sw_params、trigger等回调;与用户空间ioctl接口完全兼容;可内联调用;返回0或负错误码。

  3. 使用限制

    必须在ops->ioctl中设置;驱动仍需实现hw_params、trigger等回调;不可用于自定义私有命令;不可在中断上下文调用;需要对应ops。

  4. 性能特性

    单次跳转;耗时低于100 ns;无内存分配;支持16路并发;编码体积增加不到16字节。

  5. 使用场景

    车载标准播放控制、语音唤醒录音参数设置、USB声卡双向流控。

🌻3. 代码实例

🌻3.1 车载播放驱动使用lib_ioctl处理标准流控
  1. 应用场景

    车载I2S播放只需实现hw_params与trigger,其余命令由snd_pcm_lib_ioctl代管。

  2. 用法实例

c 复制代码
#include <sound/core.h>
#include <sound/pcm.h>
#include <linux/module.h>

static int car_hw_params(struct snd_pcm_substream *s,
                         struct snd_pcm_hw_params *p)
{
    return snd_pcm_lib_malloc_pages(s, params_buffer_bytes(p));
}

static int car_trigger(struct snd_pcm_substream *s, int cmd)
{
    switch (cmd) {
    case SNDRV_PCM_TRIGGER_START:
        i2s_dma_start();
        break;
    case SNDRV_PCM_TRIGGER_STOP:
        i2s_dma_stop();
        break;
    }
    return 0;
}

static struct snd_pcm_ops car_ops = {
    open      = car_open,
    ioctl     = snd_pcm_lib_ioctl,
    hw_params = car_hw_params,
    trigger   = car_trigger,
    pointer   = car_pointer,
};

static int __init car_ioctl_init(void)
{
    int err;
    struct snd_card *card;
    struct snd_pcm *pcm;
    err = snd_card_new(NULL, -1, "CarCard", THIS_MODULE, 0, &card);
    if (err < 0)
        return err;
    err = snd_pcm_new(card, "CarPlay", 0, 1, 0, &pcm);
    if (err < 0)
        goto fail;
    snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &car_ops);
    strcpy(pcm->name, "Car Ioctl");
    err = snd_card_register(card);
    if (err < 0)
        goto fail;
    return 0;
fail:
    snd_card_free(card);
    return err;
}

static void __exit car_ioctl_exit(void)
{
    struct snd_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简化参数设置
  1. 应用场景

    低功耗语音捕获无需私有命令,所有标准参数设置由lib_ioctl完成。

  2. 用法实例

c 复制代码
#include <sound/core.h>
#include <sound/pcm.h>
#include <linux/module.h>

static int vw_hw_params(struct snd_pcm_substream *s,
                        struct snd_pcm_hw_params *p)
{
    return snd_pcm_lib_malloc_pages(s, params_buffer_bytes(p));
}

static int vw_trigger(struct snd_pcm_substream *s, int cmd)
{
    switch (cmd) {
    case SNDRV_PCM_TRIGGER_START:
        dsp_rec_start();
        break;
    case SNDRV_PCM_TRIGGER_STOP:
        dsp_rec_stop();
        break;
    }
    return 0;
}

static struct snd_pcm_ops vw_ops = {
    open      = vw_open,
    ioctl     = snd_pcm_lib_ioctl,
    hw_params = vw_hw_params,
    trigger   = vw_trigger,
    pointer   = vw_pointer,
};

static int __init vw_ioctl_init(void)
{
    int err;
    struct snd_card *card;
    struct snd_pcm *pcm;
    err = snd_card_new(NULL, -1, "VWCard", THIS_MODULE, 0, &card);
    if (err < 0)
        return err;
    err = snd_pcm_new(card, "VWCap", 0, 0, 1, &pcm);
    if (err < 0)
        goto fail;
    snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &vw_ops);
    strcpy(pcm->name, "VW Ioctl");
    err = snd_card_register(card);
    if (err < 0)
        goto fail;
    return 0;
fail:
    snd_card_free(card);
    return err;
}

static void __exit vw_ioctl_exit(void)
{
    struct snd_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统一管控
  1. 应用场景

    USB音频无需私有扩展,所有参数与流控通过标准ioctl完成。

  2. 用法实例

c 复制代码
#include <sound/core.h>
#include <sound/pcm.h>
#include <linux/module.h>

static int usb_hw_params(struct snd_pcm_substream *s,
                         struct snd_pcm_hw_params *p)
{
    return snd_pcm_lib_malloc_pages(s, params_buffer_bytes(p));
}

static int usb_trigger(struct snd_pcm_substream *s, int cmd)
{
    switch (cmd) {
    case SNDRV_PCM_TRIGGER_START:
        usb_iso_start();
        break;
    case SNDRV_PCM_TRIGGER_STOP:
        usb_iso_stop();
        break;
    }
    return 0;
}

static struct snd_pcm_ops usb_ops = {
    open      = usb_open,
    ioctl     = snd_pcm_lib_ioctl,
    hw_params = usb_hw_params,
    trigger   = usb_trigger,
    pointer   = usb_pointer,
};

static int __init usb_ioctl_init(void)
{
    int err;
    struct snd_card *card;
    struct snd_pcm *pcm;
    err = snd_card_new(NULL, -1, "USBCard", THIS_MODULE, 0, &card);
    if (err < 0)
        return err;
    err = snd_pcm_new(card, "USBDup", 0, 1, 1, &pcm);
    if (err < 0)
        goto fail;
    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)
        goto fail;
    return 0;
fail:
    snd_card_free(card);
    return err;
}

static void __exit usb_ioctl_exit(void)
{
    struct snd_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声卡
相关推荐
Doro再努力6 小时前
【Linux操作系统10】Makefile深度解析:从依赖推导到有效编译
android·linux·运维·服务器·编辑器·vim
Daniel李华7 小时前
echarts使用案例
android·javascript·echarts
做人不要太理性8 小时前
CANN Runtime 运行时组件深度解析:任务调度机制、存储管理策略与维测体系构建逻辑
android·运维·魔珐星云
我命由我123458 小时前
Android 广播 - 静态注册与动态注册对广播接收器实例创建的影响
android·java·开发语言·java-ee·android studio·android-studio·android runtime
朗迹 - 张伟9 小时前
Tauri2 导出 Android 详细教程
android
lpruoyu9 小时前
【Android第一行代码学习笔记】Android架构_四大组件_权限_持久化_通知_异步_服务
android·笔记·学习
独自破碎E10 小时前
【BISHI15】小红的夹吃棋
android·java·开发语言
李堇13 小时前
android滚动列表VerticalRollingTextView
android·java
lxysbly14 小时前
n64模拟器安卓版带金手指2026
android
游戏开发爱好者817 小时前
日常开发与测试的 App 测试方法、查看设备状态、实时日志、应用数据
android·ios·小程序·https·uni-app·iphone·webview