高通SDM845平台Sensor学习——2.Hal层

本文详细分析了高通SDM845平台上Sensor Hal层的代码结构和工作原理,重点讲解了sensors文件夹中各sensor类的实现,如accelerometer.cpp,以及framework文件夹的功能。在sensors文件夹中,每个sensor的cpp文件实现了特定的操作,如accelerometer_module_init在加载.so时调用。在framework中,通过sensors_module_t结构与get_sensor_list函数获取sensor列表。文章还介绍了如何启用/禁用Sensor,以及Factory Calibration的过程,包括获取suid、启用sensor和校准操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二:Sensor Hal层代码分析

Hal code放在/vendor/qcom/proprietary/sensors-see/中

图5

sensors-hal文件夹中包含framework和sensors文件夹,为本文重点分析对象。

首先分析sensors文件夹:
根据C++继承的特性,相同的操作各个class共同拥有,不同的操作每个class可以重写,该文件夹内文件为每个sensor不同的地方,porting sensor主要是在这部分做的。sensors文件夹中包含很多sensor cpp文件比如:accelerometer.cpp为accel sensor的hal层code,step_count.cpp为计步器的hal层的code等等,主要是针对不同sensor type的操作。下面以accelerometer.cpp为例:

//accelerometer.cpp
SENSOR_MODULE_INIT(accelerometer_module_init);

//sensor.h
#define SENSOR_MODULE_INIT(module_init_func) \
    static const bool __mod_init = (module_init_func)();

每个cpp都有SENSOR_MODULE_INIT入口,__mod_init具体实现在code没有找到,不过应该类似kernel中module_init,在系统加载.so时调用。故可知,所有特定sensor的cpp在加载.so时会被调SENSOR_MODULE_INIT进行加载。

//accelerometer.cpp
static bool accelerometer_module_init()
{
    /* register supported sensor types with factory */
    sensor_factory::register_sensor(SENSOR_TYPE_ACCELEROMETER,
                                    get_available_accel_calibrated);
    sensor_factory::register_sensor(SENSOR_TYPE_ACCELEROMETER_UNCALIBRATED,
                                    get_available_accel_uncalibrated);
    sensor_factory::request_datatype(SSC_DATATYPE_ACCEL);
    return true;
}

//sensor_factory.h
static void register_sensor(int type, get_available_sensors_func func)
    {
        try {
            callbacks().emplace(type, func);
        } catch (const std::exception& e) {
            sns_loge("failed to register type %d", type);
        }
    }
static std::unordered_map<int, get_available_sensors_func>& callbacks()
    {
        static std::unordered_map<int, get_available_sensors_func> _callbacks;
        return _callbacks;
    }

//sensor_factory.h
static void request_datatype(const char *datatype)
    {
        try {
            datatypes().insert(std::string(datatype));
        } catch (const std::exception& e) {
            sns_loge("failed to insert %s", datatype);
        }
    }

所以在,在.so被调用后,accelerometer_module_init会被执行!通过register_sensor将type和func放入callbacks的unordered_map中。并将datatype插入到datatypes的unordered_set中,以便后面使用。

下面以get_available_accel_calibrated为例继续研究:

//accelerometer.cpp
static vector<unique_ptr<sensor>> get_available_accel_calibrated()
{
    const vector<sensor_uid>& accel_suids =
         sensor_factory::instance().get_suids(SSC_DATATYPE_ACCEL);  //  No.1
    vector<unique_ptr<sensor>> sensors;
    for (const auto& suid : accel_suids) {
        if (!(sensor_factory::instance().get_settings()              // No.2
                                    & DISABLE_WAKEUP_SENSORS_FLAG)) {
            try {
                sensors.push_back(make_unique<accelerometer>(suid, SENSOR_WAKEUP,  //No.3
                                                         SENSOR_CALIBRATED));
            } catch (const exception& e) {
                sns_loge("failed for wakeup, %s", e.what());
            }
        }
        try {
            sensors.push_back(make_unique<accelerometer>(suid, SENSOR_NO_WAKEUP,
                                                     SENSOR_CALIBRATED));
        } catch (const exception& e) {
            sns_loge("failed for nowakeup, %s", e.what());
        }
    }
    return sensors;
}

No.1中:accel_suids可以通过sensor_factory实例中get_suids函数来获取:

const std::vector<sensor_uid>& sensor_factory::get_suids(const std::string& datatype) const
{
    auto it = _suid_map.find(datatype);
    if (it != _suid_map.end()) {
        return it->second;
    } else {
        static vector<sensor_uid> empty;
        return empty;
    }
}

从_suids_map中查找datatype来获取accel的suid。那什么时候将accel的suid插入到_suids_map中内,在framework文件夹中,后续会介绍。

No.2中:通过getsetting来查看是否有DISABLE_WAKEUP_SENSORS_FLAG flag,若有则为no wakeup,若无则为wake up sensor。

No.3中:为调用accelerometer的构造函数。

accelerometer::accelerometer(sensor_uid suid,
                                sensor_wakeup_type wakeup,
                                sensor_cal_type cal_type):
    ssc_sensor(suid, wakeup)              // No.a
{
    if (cal_type == SENSOR_UNCALIBRATED) {                                    // No.b
        set_type(SENSOR_TYPE_ACCELEROMETER_UNCALIBRATED);
        set_string_type(SENSOR_STRING_TYPE_ACCELEROMETER_UNCALIBRATED);
        set_sensor_typename("Accelerometer-Uncalibrated");
    } else {
        set_type(SENSOR_TYPE_ACCELEROMETER);
        set_string_type(SENSOR_STRING_TYPE_ACCELEROMETER);
        set_sensor_typename("Accelerometer");
    }
   ...
    _cal_type = cal_type;
    set_fifo_reserved_count(ACCEL_RESERVED_FIFO_COUNT);
    set_resampling(true);

    /* convert range from Gs to m/s^2 */
    set_max_range(get_sensor_info().maxRange * ONE_G);
    /* convert resolution from mG to m/s^2 */
    set_resolution(get_sensor_info().resolution * ONE_G / 1000.0);

}

No.a中:继承ssc_sensor,ssc_sensor的构造函数中,主要设置一些common的参数。
No.b中:设置accel中不common的参数。比如string_type、sensor_typename、是否使用resampling、最大range、分辨率等等。

Ok,accelerometer.cpp基本介绍完毕。
对了,还有个handle_sns_std_sensor_event函数是干什么的呢?

//accelerometer.cpp
virtual void handle_sns_std_sensor_event(
        const sns_client_event_msg_sns_client_event& pb_event) override;

void accelerometer::handle_sns_std_sensor_event(
    const sns_client_event_msg_sns_client_event& pb_event)
{
    sns_std_sensor_event pb_sensor_event;
    pb_sensor_event.ParseFromString(pb_event.payload());

    sensors_event_t hal_event = create_sensor_hal_event(pb_event.timestamp());

    if (_cal_type == SENSOR_CALIBRATED) {
        hal_event.acceleration.x = pb_sensor_event.data(0);
        hal_event.acceleration.y = pb_sensor_event.data(1);
        hal_event.acceleration.z = pb_sensor_event.data(2);
        hal_event.acceleration.status =
            sensors_hal_sample_status(pb_sensor_event.status());
      ...
    }

    if (_cal_type == SENSOR_UNCALIBRATED) {
        hal_event.uncalibrated_accelerometer.x_uncalib = pb_sensor_event.data(0);
        hal_event.uncalibrated_accel
<think>好的,我现在需要帮助用户查找关于MSM sensor driver command(msm_sensor_driver_cmd)在Android内核中的使用或实现的信息。用户提到参考站内引用中的路径是kernel/msm-4.9/arch/arm64/boot/dts/qcom/<target_name>-camera-sensor-<platform>.dtsi,以及子模块驱动XML文件的位置。首先,我需要回忆Android内核中摄像头传感器驱动的一般结构,特别是与高通MSM平台相关的内容。 MSM传感器驱动通常位于内核的设备树(Device Tree)文件中,这些文件用于描述硬件配置。用户提供的路径中的.dtsi文件是设备树包含文件,可能包含与摄像头传感器相关的配置,比如时钟、GPIO、I2C总线设置等。msm_sensor_driver_cmd可能涉及到传感器初始化的命令序列,这些命令可能通过XML配置文件定义,然后在驱动程序中解析和执行。 接下来,我需要考虑如何找到msm_sensor_driver_cmd的具体实现。通常在Qcom的摄像头驱动中,相关代码可能位于drivers/media/platform/msm/camera_v2/sensor目录下。例如,msm_sensor_driver.c或类似的源文件可能包含驱动命令的处理逻辑。此外,传感器驱动可能会调用I2C或SPI接口的函数来发送配置命令到传感器硬件。 另外,用户提到的子模块驱动XML文件可能是指供应商提供的配置文件,用于描述传感器的寄存器配置、启动序列等。这些XML文件可能在编译时被解析,并生成对应的头文件或C代码,由驱动程序在初始化时加载。 需要注意的是,具体的实现细节可能因内核版本和硬件平台而异。例如,MSM内核版本4.9与更新的版本可能在驱动结构上有所不同。此外,高通的摄像头驱动通常涉及多个,包括用户空间的HAL(硬件抽象)和内核空间的驱动模块,因此可能需要结合用户空间和内核空间的代码来分析。 为了验证这些思路,我需要检查相关内核代码。例如,在msm_sensor_driver.c中查找msm_sensor_driver_cmd相关的函数,或者在设备树文件中查找对应的配置节点。此外,XML配置文件可能定义了命令序列,如初始化命令、电源控制命令等,这些命令会被驱动程序解析并转换为具体的寄存器写入操作。 总结来说,用户需要的信息可能涉及设备树配置、驱动源码中的命令处理逻辑,以及XML配置文件的解析过程。接下来,我需要将这些分析整理成结构化的回答,并提供相关问题供用户进一步探索。</think>关于$msm\_sensor\_driver\_cmd$在Android内核中的实现,主要涉及高通(MSM)摄像头传感器驱动的命令控制机制。根据代码结构分析: 1. **设备树配置** 摄像头传感器的物理接口参数(如I2C地址、时钟频率、GPIO引脚)通常在`.dtsi`文件中定义,例如: ```c // kernel/msm-4.9/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-mtp.dtsi &i2c_freq_1Mhz_cci1 { qcom,hw-thigh = <600>; qcom,hw-tlow = <500>; }; sensor@10 { compatible = "qcom,msm-sensor"; reg = <0x10>; sensor-rotation = <90>; }; ``` 这些配置会被`msm_camera_dt_util.c`解析并生成硬件初始化序列[^1]。 2. **驱动命令实现** 命令处理核心代码位于: ``` drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c ``` 其中关键函数包括: ```c static int32_t msm_sensor_driver_cmd(struct msm_sensor_ctrl_t *s_ctrl, void *arg) { struct msm_camera_cci_client *cci_client = s_ctrl->msm_sensor_cci_client; // 处理I2C/SPI命令传输 rc = s_ctrl->sensor_i2c_client->i2c_func_tbl->i2c_write_table( s_ctrl->sensor_i2c_client, &conf_array); } ``` 该函数通过I2C/SPI总线向传感器发送配置命令表(包含寄存器地址和值)。 3. **XML配置文件** 子模块的XML文件(如`imx350.xml`)定义了传感器的初始化序列: ```xml <sequence> <group> <reg id="0x0100" value="0x00"/> <!-- 软复位 --> <delay_ms value="20"/> <reg id="0x0103" value="0x01"/> <!-- 启动流传输 --> </group> </sequence> ``` 这些XML会在编译时通过`mm-camera`工具链生成C语言头文件,最终被驱动加载。
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值