如何在Android自定义内核模块中模拟SD卡物理插入检测
实现SD卡模拟物理插入的内核模块方案
核心思路
直接重启MMC主机控制器属于高危操作,极易触发系统panic,正确的做法是复用内核MMC子系统的原生检测流程,模拟卡插入的状态变化与触发逻辑,完全贴合物理插入的处理路径。
具体实现步骤
1. 定位目标MMC主机
先获取对应SD卡槽的struct mmc_host实例,可通过设备树节点名、总线ID匹配:
struct mmc_host *mmc = mmc_get_host_by_name("mmc0"); // 替换为你的控制器名称 if (!mmc) { pr_err("Failed to locate target MMC host\n"); return -ENODEV; }
2. 模拟卡插入状态并触发检测
内核通过mmc_detect_change函数处理卡状态变更,直接调用该函数即可模拟物理插入:
// 持有MMC主机锁,避免并发操作 mutex_lock(&mmc->lock); // 标记卡已插入 mmc->card_present = 1; // 强制触发检测流程 mmc_detect_change(mmc, 1); mutex_unlock(&mmc->lock);
3. 补全卡初始化流程(可选)
如果需要完整模拟物理插入后的识别流程,可手动触发MMC卡识别命令:
struct mmc_command cmd = {0}; cmd.opcode = MMC_ALL_SEND_CID; cmd.flags = MMC_RSP_R1 | MMC_CMD_BCR; mutex_lock(&mmc->lock); int ret = mmc_wait_for_cmd(mmc, &cmd, MMC_CMD_RETRIES); mutex_unlock(&mmc->lock); if (ret == 0) { pr_info("SD card simulated insertion completed\n"); }
4. 避免系统重启的关键注意事项
- 绝对禁止直接操作MMC控制器的硬件寄存器执行重启,这会导致总线状态混乱触发panic
- 所有操作必须基于内核MMC子系统提供的上层API,不要直接触碰底层硬件
- 确保模块加载时机晚于MMC控制器初始化,可通过依赖
mmc_core模块或延迟初始化实现 - 操作MMC主机时必须持有
mmc->lock,避免并发冲突
完整示例模块代码
#include <linux/module.h> #include <linux/mmc/core.h> #include <linux/mmc/host.h> #include <linux/mutex.h> static struct mmc_host *target_mmc; static int __init sd_insert_sim_init(void) { target_mmc = mmc_get_host_by_name("mmc0"); if (!target_mmc) { pr_err("MMC host not found\n"); return -ENODEV; } mutex_lock(&target_mmc->lock); target_mmc->card_present = 1; mmc_detect_change(target_mmc, 1); mutex_unlock(&target_mmc->lock); pr_info("SD card insertion simulated successfully\n"); return 0; } static void __exit sd_insert_sim_exit(void) { if (target_mmc) { mutex_lock(&target_mmc->lock); target_mmc->card_present = 0; mmc_detect_change(target_mmc, 1); mutex_unlock(&target_mmc->lock); mmc_put_host(target_mmc); } } module_init(sd_insert_sim_init); module_exit(sd_insert_sim_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Simulate SD card insertion for fixed slot devices");
编译与加载说明
- 将代码保存为
sd_sim.c,编写Makefile:
obj-m += sd_sim.o KDIR := /path/to/your/android/kernel/source PWD := $(shell pwd) default: $(MAKE) -C $(KDIR) M=$(PWD) modules
- 编译生成
.ko文件后,使用insmod sd_sim.ko加载模块模拟卡插入;rmmod sd_sim模拟卡拔出。
内容的提问来源于stack exchange,提问作者Beqa Gozalishvili
相关产品推荐
相关产品推荐

