简介:usim_drv.h是联发科(MTK)平台实现双卡双待功能的核心驱动头文件,专注SIM卡控制模块的接口规范。文件内含函数声明、结构体定义、宏常量及关键枚举类型,覆盖双卡识别、卡槽切换、状态同步、插拔检测、PIN码验证、EF文件读写等标准USIM操作所需API。不包含具体实现逻辑,仅面向上层通信协议栈或RIL层调用,需配合对应版本的vendor HAL和modem固件协同工作。支持主流MTK芯片平台,如MT6735、MT6755、MT6765等,适用于Android终端开发中多SIM卡场景下的底层协议交互与硬件抽象层对接。开发者可通过该头文件完成AT指令封装、USIM协议适配、卡状态机管理等关键任务,是构建稳定双卡功能的基础接口层资源。
1. 这不是普通头文件,而是MTK双卡功能的“交通指挥图”
如果你正在做基于联发科平台的Android终端开发,尤其是涉及双卡双待(DSDS)功能的定制ROM、运营商定制固件、或者eSIM+物理卡混合方案,那么你迟早会和usim_drv.h打上照面——它不像stdio.h那样被开发者天天念叨,但一旦你发现RIL层卡在“SIM状态未就绪”、插拔事件不触发、或者双卡切换后第二卡始终显示“无服务”,十有八九,问题就卡在这份看似安静的头文件里。它不是实现逻辑,却决定了所有USIM操作能不能“说对语言”;它不跑在CPU上,却定义了HAL层与Modem之间那条最窄也最关键的指令通道。我做过6款MTK平台定制机的通信模块重构,从MT6735到MT6765,每次调试双卡状态机,第一件事就是打开usim_drv.h,对照着看函数签名有没有被误删、枚举值是否被错位覆盖、结构体padding有没有因编译器差异导致内存偏移错乱。它本质上是一份硬件抽象契约:上层协议栈(比如RIL daemon)承诺按这个接口发请求,底层vendor HAL承诺按这个格式回响应,中间Modem固件则负责把AT指令翻译成射频动作。漏掉一个宏定义,可能让PIN2验证永远返回USIM_ERR_INVALID_PARAM;改错一个枚举值顺序,可能导致卡槽切换时主副卡身份颠倒。这份头文件之所以“必备”,正因为它处在整个双卡控制链路的绝对零点——没有它,上层代码连调用入口都找不到;有了它,但没吃透它的设计逻辑,照样会在实机测试中栽跟头。它面向的是熟悉AT指令集、了解GSM/UMTS/LTE USIM协议栈、能看懂HAL层IPC机制的开发者,而不是刚学完JNI调用的新手。但好消息是:它不复杂,它只是严谨。只要你愿意花两小时逐行读完结构体字段含义、对照3GPP TS 27.007规范理解每个函数背后的协议动作,你就能把它从“黑盒接口”变成“可控开关”。接下来,我会带你一层层剥开它的设计肌理,告诉你哪些字段动不得、哪些宏必须同步更新、哪些函数调用背后藏着硬件级时序陷阱。
2. 接口设计逻辑:为什么是这套结构,而不是别的?
2.1 整体架构定位:HAL层之上的“协议翻译器”
usim_drv.h在MTK Android架构中的位置非常明确:它位于RIL层(libril.so)与vendor HAL(libmtk-ril.so或类似命名)之间,属于HAL Interface Definition的一部分。注意,它不是Linux内核驱动头文件(比如sim_card.h),也不直接操作GPIO或UART寄存器;它更像一份“外交照会”——RIL作为上层政府机构,需要向HAL这个地方执行部门下达指令(比如“请查询卡槽2的IMSI”),而usim_drv.h就是双方约定好的公文格式模板。这种设计源于MTK的模块化分层思想:
- Kernel Space:只负责最基础的卡检测(如SIM detect pin电平变化)、电源控制(VCC供电开关);
- HAL Layer:封装Modem AT命令交互、状态缓存、错误重试逻辑;
- RIL Layer:对接Android Telephony Framework,将Java层请求(如getIccId())转换为HAL可识别的C结构体;
- usim_drv.h:就是RIL→HAL这条通路上的“标准信封”,规定了信封上写什么(字段名)、怎么写(数据类型)、哪些字段必填(__attribute__((packed))约束)。
这种分离带来三个关键优势:一是RIL可跨平台复用(高通/展锐项目只需替换HAL实现);二是HAL可独立升级(Modem固件更新时,只要保持usim_drv.h接口不变,上层无需修改);三是调试边界清晰(当IMSI读取失败,先查RIL是否填对了usim_read_imsi_req_t结构体,再查HAL是否正确解析并下发AT+CIMI)。我曾遇到一个案例:某MT6755项目在升级Modem固件后,第二卡IMSI始终为空。排查发现新固件要求AT+CIMI指令必须带卡槽参数(AT+CIMI=2),但旧版usim_drv.h中usim_read_imsi_req_t结构体缺少slot_id字段,RIL传参时默认填0,HAL只能发AT+CIMI,结果Modem返回空响应。解决方案不是改HAL,而是同步更新usim_drv.h,增加slot_id字段,并确保RIL层调用时显式赋值——这正是该头文件存在的核心价值:它是变更的锚点,而非障碍。
2.2 函数声明设计哲学:状态驱动 vs 命令驱动
翻开源码,你会发现所有函数声明都遵循usim_xxx_xxx()前缀,且几乎全是异步回调模式,例如:
typedef void (*usim_read_imsi_cb_t)(const usim_read_imsi_rsp_t *rsp, void *user_data);
int usim_read_imsi(int slot_id, usim_read_imsi_cb_t cb, void *user_data);
这里藏着MTK双卡设计的关键逻辑:USIM操作必须与Modem状态机解耦。为什么不用同步阻塞调用?因为一次EF文件读取可能耗时数百毫秒(尤其在信号弱时Modem需重试AT指令),若RIL线程在此阻塞,会导致整个Telephony服务卡死,Android ANR(Application Not Responding)必然触发。异步设计强制RIL层使用callback,在收到响应后再更新Framework状态,符合Android Binder IPC的非阻塞原则。更深层的原因是双卡资源竞争:当卡槽1正在执行PIN验证时,卡槽2发起IMSI读取请求,HAL必须能排队、优先级调度、避免AT指令冲突。usim_drv.h通过slot_id参数明确区分操作目标,再配合内部状态机(如USIM_STATE_READY/USIM_STATE_PIN_REQUIRED)决定是否允许并发。我实测过,在MT6765平台上,若强行在callback里嵌套调用另一个usim函数(如usim_verify_pin()后立刻usim_read_iccid()),会导致HAL内部锁死,必须重启rild进程。正确做法是:在第一个callback返回成功后,再通过handler post延迟调用下一个——这恰恰印证了头文件设计的意图:它不提供便利性API,只提供安全边界。
2.3 结构体与枚举:为何要“过度定义”?
usim_drv.h中大量使用enum和struct,且常伴随冗余字段。以卡状态枚举为例:
typedef enum {
USIM_STATE_UNKNOWN = 0,
USIM_STATE_ABSENT,
USIM_STATE_PRESENT,
USIM_STATE_READY,
USIM_STATE_PIN_REQUIRED,
USIM_STATE_PUK_REQUIRED,
USIM_STATE_NETWORK_LOCKED,
USIM_STATE_RUIM_READY, // 注意:RUIM是CDMA遗留,MT6735后已弃用
USIM_STATE_MAX
} usim_state_t;
表面看USIM_STATE_RUIM_READY多余,但MTK为兼容老版本Modem固件(尤其面向北美市场的CDMA机型),保留该枚举值并设为无效状态。若开发者在switch-case中漏掉default分支,新固件返回未知状态时程序可能崩溃。这就是“过度定义”的防御性设计。再看核心结构体usim_read_iccid_rsp_t:
typedef struct {
int result; // 0=success, <0=error code
char iccid[21]; // ICCID固定20字符+1'\0'
int slot_id; // 响应对应的卡槽ID
uint8_t reserved[3]; // 强制4字节对齐,防止ARM/AArch64结构体偏移差异
} __attribute__((packed)) usim_read_iccid_rsp_t;
reserved[3]看似浪费空间,实则是为跨架构编译埋的伏笔。ARMv7与ARMv8对char[21]的内存对齐策略不同,若无reserved字段,slot_id可能在v7上偏移21字节,在v8上偏移24字节,导致HAL解析出错。MTK工程师在注释里写:“Avoid ABI breakage across toolchains”——这才是工业级头文件的严谨。我曾因忽略这点,在MT6755(ARMv8)上调试时发现ICCID总多出3个乱码字符,最后追查到是RIL层结构体定义少了reserved,与HAL的packed结构体不匹配。所以,当你看到usim_drv.h里那些“看不懂”的预留字段、冗余枚举,别急着删,它们大概率是某个深夜调试崩溃后留下的血泪注释。
3. 核心接口详解:从函数到实战场景
3.1 卡槽管理:usim_get_slot_count()与usim_set_active_slot()
双卡功能的基础是明确“谁在说话”。usim_get_slot_count()看似简单,仅返回整数:
int usim_get_slot_count(void);
但它背后关联着硬件DTS(Device Tree Source)配置。MTK平台通过/proc/device-tree/soc/simctl@...节点定义物理卡槽数量,usim_get_slot_count()实际读取该节点并缓存。关键陷阱在于:它返回的是硬件支持槽数,而非当前启用槽数。例如MT6765硬件支持双卡,但若用户在Settings里关闭了第二卡,则usim_get_slot_count()仍返回2,但后续操作需检查usim_get_slot_status()确认槽位是否激活。我见过太多开发者直接用for (i=0; i<usim_get_slot_count(); i++)循环读取所有卡信息,结果在单卡模式下对已禁用槽位调用usim_read_imsi(),HAL返回USIM_ERR_SLOT_DISABLED却未处理,导致UI显示“第二卡无服务”而非“已关闭”。
真正控制权在usim_set_active_slot():
typedef struct {
int slot_id; // 目标卡槽ID(0或1)
int active; // 1=激活,0=去激活
} usim_set_active_slot_req_t;
int usim_set_active_slot(const usim_set_active_slot_req_t *req,
usim_set_active_slot_cb_t cb, void *user_data);
这个函数不等于“切换主卡”,而是通知Modem:“从此刻起,所有无显式slot_id的AT指令(如AT+CPIN)默认作用于该槽位”。实测发现,MTK Modem固件对此有严格时序要求:必须在usim_set_active_slot()回调成功后,再发起usim_verify_pin(),否则PIN验证会失败。原因在于Modem内部状态机需时间同步——就像飞机切换跑道前,塔台必须确认导航系统已校准。我在MT6735项目中曾因在callback外立即调用PIN验证,导致连续10次失败,日志显示AT+CPIN?返回+CPIN: SIM PIN而非+CPIN: READY。解决方案是:在usim_set_active_slot_cb里启动一个delay handler(50ms),再执行PIN操作。这并非bug,而是usim_drv.h隐含的设计契约:状态变更与指令下发必须分两步,且有最小间隔。
3.2 状态同步:usim_register_status_callback()的生存周期管理
双卡体验的核心痛点是状态滞后——插卡后UI仍显示“无SIM”,拔卡后信号格还在跳动。根源在于状态通知机制。usim_drv.h提供注册回调:
typedef void (*usim_status_cb_t)(int slot_id, usim_state_t state, void *user_data);
int usim_register_status_callback(usim_status_cb_t cb, void *user_data);
但文档从不提一个致命细节:该回调由HAL线程池触发,而非RIL主线程。这意味着,若你在callback里直接调用Android Framework API(如TelephonyManager.setSimState()),会因线程不匹配导致Binder异常。正确姿势是:
// RIL层注册时传入Handler
static Handler sMainHandler;
usim_register_status_callback([](int slot, usim_state_t state, void*) {
Message msg = sMainHandler.obtainMessage();
msg.arg1 = slot;
msg.arg2 = state;
sMainHandler.sendMessage(msg); // 切换到主线程处理
}, nullptr);
更隐蔽的坑是内存泄漏。usim_register_status_callback()注册后,HAL会持续持有callback指针。若RIL进程重启(如adb shell killall rild),旧callback未注销,HAL仍尝试调用已释放内存,引发SIGSEGV。MTK官方解决方案是在rild退出前调用usim_unregister_status_callback(),但很多第三方ROM忘记实现。我的经验是:在rild的main()函数末尾添加atexit()钩子,确保进程退出时清理。另外,usim_state_t中的USIM_STATE_PRESENT不等于“可用”,它仅代表物理卡存在,还需等待USIM_STATE_READY才可读取IMSI——这点常被UI逻辑忽略,导致“卡已插入”提示过早出现。
3.3 EF文件读写:usim_read_ef()与usim_write_ef()的协议陷阱
USIM卡的EF(Elementary File)操作是双卡调试的深水区。usim_drv.h定义:
typedef struct {
int slot_id;
uint16_t file_id; // 如0x6F07=IMSI, 0x6F02=ICCID
uint8_t *data; // 输出缓冲区
int data_len; // 缓冲区长度
int offset; // 读取起始偏移
int length; // 读取长度
} usim_read_ef_req_t;
int usim_read_ef(const usim_read_ef_req_t *req, usim_read_ef_cb_t cb, void *user_data);
表面看是标准文件IO,实则暗藏3GPP协议约束。以读取IMSI(EF 0x6F07)为例:
- 长度陷阱:IMSI最大20字符,但EF文件实际存储为BCD编码(每字节存2位数字),故data_len必须≥10(字节),而非20(字符)。若传入data_len=20,HAL可能截断或填充垃圾数据。
- 偏移陷阱:某些老旧USIM卡(尤其2G卡)的IMSI EF开头有2字节TLV头,offset需设为2才能读到真实IMSI。MTK Modem固件通常自动处理,但若遇到非标卡,需手动调整offset。
- 权限陷阱:读取EF 0x6F3A(ADN电话簿)需先通过usim_verify_pin()认证,否则返回USIM_ERR_ACCESS_DENIED。但usim_read_ef()不检查PIN状态,它只管发AT指令——AT+CRSM指令会失败,HAL再转为对应错误码。
我处理过一个运营商定制需求:需读取EF 0x6F39(扩展ADN)中的邮箱字段。调试发现,MT6755 Modem固件对length参数敏感,若length超过EF实际长度(如设为100但卡只存50字节),AT+CRSM返回+CRSM: 144,0(Command not supported),而非预期的+CRSM: 142,0(Memory failure)。最终解决方案是:先调用usim_get_ef_info()(该函数在头文件中未定义,需从vendor HAL源码反推)获取EF大小,再动态设置length。这说明usim_drv.h虽是接口规范,但实际开发必须结合Modem固件手册交叉验证参数边界——头文件只保证“能调”,不保证“一定对”。
4. 实操避坑指南:从编译到真机调试的全流程陷阱
4.1 编译期陷阱:头文件包含路径与宏定义污染
usim_drv.h本身不依赖其他头文件,但实际编译时极易因包含顺序出错。典型错误:
// 错误示范:在usim_drv.h之前包含android/log.h
#include <android/log.h>
#include "usim_drv.h" // 编译失败!log.h定义了LOG_TAG,与usim_drv.h中同名宏冲突
MTK头文件习惯用LOG_TAG作为调试标签,若外部头文件已定义,会导致重定义错误。解决方案是严格遵循包含顺序:
// 正确顺序
#include "usim_drv.h" // 第一顺位
#include <android/log.h>
#include <utils/Log.h>
更隐蔽的是宏定义污染。usim_drv.h中大量使用#ifdef MTK_MULTI_SIM等条件编译宏,这些宏由BoardConfig.mk中的BOARD_HAVE_MTK_MULTI_SIM := true控制。若在Android.mk中遗漏该定义,usim_drv.h会跳过双卡相关结构体,编译通过但运行时报undefined reference to usim_set_active_slot。我的检查清单:
1. 确认BoardConfig.mk包含BOARD_HAVE_MTK_MULTI_SIM := true;
2. 在Android.mk中添加LOCAL_CFLAGS += -DMTK_MULTI_SIM(双重保险);
3. 使用grep -r "MTK_MULTI_SIM" vendor/mediatek/proprietary/验证vendor HAL源码是否启用对应分支。
4.2 链接期陷阱:符号未定义与版本错配
即使编译通过,链接时常见undefined reference to usim_xxx。根本原因不是头文件缺失,而是vendor HAL库未正确链接。MTK平台HAL库路径为vendor/mediatek/proprietary/hardware/ril/libmtkril.so,但不同芯片平台库名不同:
- MT6735:libmtkril.so
- MT6755:libmtkril_mt6755.so
- MT6765:libmtkril_mt6765.so
若在Android.mk中硬编码LOCAL_SHARED_LIBRARIES := libmtkril,在MT6765上会链接失败。正确做法是:
# 根据TARGET_BOARD_PLATFORM动态选择
ifeq ($(TARGET_BOARD_PLATFORM), mt6765)
LOCAL_SHARED_LIBRARIES += libmtkril_mt6765
else ifeq ($(TARGET_BOARD_PLATFORM), mt6755)
LOCAL_SHARED_LIBRARIES += libmtkril_mt6755
endif
更致命的是版本错配。某次升级MT6765 Modem固件后,usim_drv.h新增了usim_get_imsi_on_slot()函数,但vendor HAL库仍是旧版,链接时无报错(因函数声明存在),运行时却crash。原因是新函数在HAL中未实现,调用时跳转到非法地址。解决方案:在usim_drv.h顶部添加版本宏:
#define USIM_DRV_VERSION_MAJOR 2
#define USIM_DRV_VERSION_MINOR 1
// 构建时检查
#if USIM_DRV_VERSION_MAJOR != 2 || USIM_DRV_VERSION_MINOR != 1
#error "Vendor HAL version mismatch! Update libmtkril.so"
#endif
并在HAL源码中定义相同宏,编译时强制校验。
4.3 运行时陷阱:真机调试的黄金三招
招式一:AT指令日志抓取(绕过HAL直击Modem)
当usim_read_imsi()返回失败,别急着查RIL代码。先确认Modem是否收到指令:
adb shell
su
echo "AT+CIMI" > /dev/stty_vt0 # MT6735/MT6755路径
# 或
echo "AT+CIMI" > /dev/ttyHS0 # MT6765路径
cat /dev/stty_vt0 # 查看响应
若返回+CIMI: 460011234567890,说明Modem正常,问题在HAL或RIL;若超时无响应,则是硬件或Modem固件问题。注意:此操作需root权限,且不同平台设备节点名不同,需查/proc/tty/drivers确认。
招式二:HAL层状态dump
MTK提供调试接口:
adb shell "echo 'usim dump' > /sys/class/mtk-stp-wmt/wmtWifiDrv"
# 或
adb shell "cat /proc/mtk_ril/usim_state"
输出类似:
Slot0: STATE_READY, IMSI=460011234567890
Slot1: STATE_PRESENT, IMSI=
若Slot1显示STATE_PRESENT但IMSI为空,说明卡存在但未完成初始化,需检查usim_init()是否被调用。
招式三:RIL层callstack分析
当callback不触发,用adb shell kill -3 $(pidof rild)生成trace,搜索usim_关键字:
"ril-daemon" prio=5 tid=12 Runnable
| group="main" sCount=0 dsCount=0 obj=0x12c0a8a0 self=0xb400007f8a8c0000
| sysTid=12345 nice=0 cgrp=default sched=0/0 handle=0xb400007f8a8c1000
| state=R schedstat=( 123456789 987654321 123 ) utm=12 stm=3 core=2 HZ=100
| stack=0x7f8a8b0000-0x7f8a8b2000 stackSize=1037KB
| held mutexes= "mutator lock"(shared held)
at com.android.internal.telephony.RIL$UsimHandler.handleMessage(RIL.java:1234)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:242)
若trace中无usim_调用栈,说明RIL层根本没发起请求,问题在Framework层;若有但卡在native_usim_read_imsi,则聚焦HAL实现。
5. 常见问题速查表与独家调试技巧
| 问题现象 | 可能原因 | 快速验证方法 | 解决方案 |
|---|---|---|---|
usim_read_imsi()始终返回USIM_ERR_TIMEOUT | Modem AT通道阻塞 | adb shell "echo 'AT' > /dev/stty_vt0 && cat /dev/stty_vt0"看是否返回OK | 重启Modem进程:adb shell "setprop ctl.stop ril-daemon && setprop ctl.start ril-daemon" |
| 双卡切换后第二卡信号格消失 | usim_set_active_slot()未生效 | adb shell "cat /proc/mtk_ril/usim_state"检查active slot字段 | 确保callback成功后延迟50ms再发起AT指令,避免Modem状态机未同步 |
插卡事件不触发usim_status_cb | HAL未注册中断监听 | adb shell "cat /sys/class/mtk-sim/sim1/state"(路径依平台而异) | 检查kernel dts中sim_detect_gpio配置是否正确,GPIO电平是否与硬件匹配 |
usim_verify_pin()返回USIM_ERR_INVALID_PIN但PIN正确 | PIN缓存未清除 | 拔卡后重新插卡,观察是否仍失败 | 在verify前调用usim_reset_pin_cache()(若HAL支持)或重启rild |
| 读取EF文件返回乱码 | data_len设置过大导致缓冲区溢出 | 检查usim_read_ef_req_t.data_len是否≥EF实际长度(BCD编码) | 计算公式:data_len = ceil(EF_max_length_in_chars / 2),如IMSI 20字符→data_len ≥ 10 |
独家技巧一:构建“头文件健康度”检查脚本
每次更新usim_drv.h,运行以下Python脚本自动校验:
import re
# 检查所有函数声明是否含slot_id参数(双卡必需)
with open('usim_drv.h') as f:
content = f.read()
funcs = re.findall(r'int\s+usim_\w+\([^)]*\)', content)
for func in funcs:
if 'slot_id' not in func and not ('get_slot_count' in func or 'register' in func):
print(f"WARNING: {func} missing slot_id parameter!")
# 检查结构体是否全为packed
packed_structs = re.findall(r'typedef\s+struct\s*{[^}]*}\s*__attribute__\(\(packed\)\)\s*(\w+);', content)
print(f"Packed structs: {packed_structs}")
独家技巧二:模拟HAL层单元测试
用Fake HAL验证RIL调用逻辑(无需真机):
// fake_usim_hal.c
static usim_read_imsi_cb_t g_imsi_cb;
int usim_read_imsi(int slot_id, usim_read_imsi_cb_t cb, void *user_data) {
g_imsi_cb = cb;
// 模拟Modem响应
usim_read_imsi_rsp_t rsp = {.result=0, .slot_id=slot_id};
strcpy(rsp.imsi, "460011234567890");
cb(&rsp, user_data); // 立即触发callback
return 0;
}
// 在RIL测试中链接此fake库,可100%覆盖callback路径
独家技巧三:状态机可视化调试
在usim_status_cb中添加日志:
__android_log_print(ANDROID_LOG_INFO, "USIM",
"Slot%d state change: %d -> %d", slot_id, old_state, new_state);
然后用adb logcat -s USIM:I | grep "state change"实时观察状态流转,绘制状态图(如ABSENT→PRESENT→PIN_REQUIRED→READY),比读代码快10倍。
6. 扩展思考:当usim_drv.h遇上eSIM与5G SA
随着eSIM普及和5G SA独立组网落地,usim_drv.h的设计正面临新挑战。传统双卡基于物理卡槽(Slot 0/1),而eSIM需支持Profile下载、启用、删除,这超出了现有接口范围。MTK已在MT6768+平台引入usim_esim_*系列函数,但它们未纳入公开usim_drv.h,而是放在vendor/mediatek/proprietary/hardware/ril/include/usim_esim.h中。这意味着:双卡开发者必须同时维护两套头文件——usim_drv.h处理物理卡,usim_esim.h处理eSIM Profile。更复杂的是5G SA场景:USIM需支持5GSN(5G Subscription Permanent Identifier),其长度达32字符(vs IMSI的20字符),现有usim_read_imsi_rsp_t.iccid[21]缓冲区必然溢出。我的建议是:在自定义结构体中预留扩展字段,如:
typedef struct {
int result;
char imsi[33]; // 5G SA兼容
char iccid[21];
int slot_id;
uint8_t reserved[4]; // 为未来字段留白
} __attribute__((packed)) usim_read_imsi_rsp_ext_t;
并用宏控制:
#ifdef MTK_5G_SA_SUPPORT
#define USIM_IMSI_MAX_LEN 32
#else
#define USIM_IMSI_MAX_LEN 20
#endif
这延续了usim_drv.h的原始哲学:接口稳定,实现演进。头文件不是终点,而是你与MTK硬件对话的起点——它给你画好跑道,但飞多高、飞多远,取决于你如何读懂每一行注释里的潜台词。
简介:usim_drv.h是联发科(MTK)平台实现双卡双待功能的核心驱动头文件,专注SIM卡控制模块的接口规范。文件内含函数声明、结构体定义、宏常量及关键枚举类型,覆盖双卡识别、卡槽切换、状态同步、插拔检测、PIN码验证、EF文件读写等标准USIM操作所需API。不包含具体实现逻辑,仅面向上层通信协议栈或RIL层调用,需配合对应版本的vendor HAL和modem固件协同工作。支持主流MTK芯片平台,如MT6735、MT6755、MT6765等,适用于Android终端开发中多SIM卡场景下的底层协议交互与硬件抽象层对接。开发者可通过该头文件完成AT指令封装、USIM协议适配、卡状态机管理等关键任务,是构建稳定双卡功能的基础接口层资源。


被折叠的 条评论
为什么被折叠?



