MTK Android P Sensor架构(二)

不过不同的芯片平台,kernel层中的sensor框架是不同的,这里针对的是mt8167s平台。不过这里提醒一下,MTK平台应该从kernel 3.x版本后就不支持温湿度传感器的框架了,不过幸好他们还保留了框架的雏形在,我们需要自行解决一下编译问题。

正文

我们先看一下代码的具体目录:

cpp 复制代码
drivers/misc/mediatek/sensors-1.0$ ls
accelerometer/    alsps/      dummy.c     humidity/       magnetometer/  sensorHub/        accelgyro/
barometer/        geofence/   hwmon/      Makefile        situation/     activity_sensor/  
biometric/        gyroscope/  Kconfig     sensorfusion/   step_counter

目录结构很清晰,不同的sensor都有单独的目录,这篇文章我们还是以湿度传感器为例,所以这里单独研究一下humidity。还是先看一下代码目录结构:

cpp 复制代码
drivers/misc/mediatek/sensors-1.0/humidity$ ls
aht10/  hmdyhub/  humidity.c  humidity_factory.c  inc/  Kconfig  Makefile

humidity.c文件为不同型号的湿度传感器驱动提供一些公共的接口,也可以说是MTK为我们抽象一个有关humidity sensor的基本架构。在移植一个新型号的sensor时,只要将其通过公共接口注册进系统就可以了。

1、初始化

cpp 复制代码
static struct hmdy_init_info aht10_init_info = {
  .name = "aht10",
  .init = aht10_local_init,
  .uninit = aht10_local_uninit,
 
};
 
static int __init aht10_init(void)
{
 hmdy_driver_add(&aht10_init_info);
 AHT_FUN();   
 return 0;
}

在aht10驱动初始化的时候,通过hmdy_driver_add接口把我们的aht10驱动注册进系统

cpp 复制代码
int hmdy_driver_add(struct hmdy_init_info *obj)
{
 int err = 0;
 int i = 0;
 
 HMDY_FUN();
 if (!obj) {
  HMDY_PR_ERR("HMDY driver add fail, hmdy_init_info is NULL\n");
  return -1;
 }
 
 for (i = 0; i < MAX_CHOOSE_HMDY_NUM; i++) {
  if (i == 0) {
   HMDY_LOG("register humidity driver for the first time\n");
   if (platform_driver_register(&humidity_driver))
    HMDY_PR_ERR("failed to register gensor driver already exist\n");
  }
 
  if (humidity_init_list[i] == NULL) {
   obj->platform_diver_addr = &humidity_driver;
   humidity_init_list[i] = obj;
   break;
  }
 }
 if (i >= MAX_CHOOSE_HMDY_NUM) {
  HMDY_PR_ERR("HMDY driver add err\n");
  err = -1;
 }
 
 return err;
 
}

其实就是将我们自定义的struct hmdy_init_info aht10_init_info结构体保存到全局变量数组humidity_init_list中。然后在humidity驱动起来的时候,会通过hmdy_real_driver_init()接口调用已经注册的sensor的init函数:

cpp 复制代码
static int hmdy_real_driver_init(void)
{
 int i = 0;
 int err = 0;
 
 for (i = 0; i < MAX_CHOOSE_HMDY_NUM; i++) {
  if (humidity_init_list[i] != 0) {
   err = humidity_init_list[i]->init();
   if (err == 0) {
    break;
   }
  }
 }
 
 if (i == MAX_CHOOSE_HMDY_NUM) {
  err = -1;
 }
 return err;
 
}

这里的init()函数对应到我们sensor的aht10_local_init函数:

cpp 复制代码
static int aht10_local_init(void)
{
    if (i2c_add_driver(&aht10_i2c_driver)) {
  return -1;
 }
 if (-1 == aht10_init_flag) {
  return -1;
 }
 return 0;
}

到这里就是我们熟悉的I2C设备注册函数了i2c_add_driver()。假设我们的sensor设备也正常加入到系统,调用我们自定义的probe函数,这里面就需要我们进行三步重要的操作:

(1)设置设备资源 sensor框架为我们提供了接口get_hmdy_dts_func()去解析我们的设备资源,包含I2C的地址,是否支持设置采样率等等。

(2)struct hmdy_control_path 我们要设置自己的struct hmdy_control_path结构体初始值:

cpp 复制代码
struct hmdy_control_path hmdy_control_path = {0};
 
hmdy_control_path.is_use_common_factory = false;
hmdy_control_path.open_report_data = aht10_open_report_data; /* 作用未知,一般直接返回就好 */
hmdy_control_path.enable_nodata = aht10_enable_nodata; /* 上层在打开sensor设备的时候,会调用到这个函数 */
hmdy_control_path.set_delay = aht10_set_delay; /* 字面上是用来设置延时,不过如果不需要可以直接返回 */
hmdy_control_path.is_report_input_direct = false; 
hmdy_control_path.is_support_batch = dev_data->hw->is_batch_supported_hmdy; /* 是否支持设置采样率 */
 
ret = hmdy_register_control_path(&hmdy_control_path); /* 将前面设置好的struct hmdy_control_path结构体通过公共接口注册进系统 */
if (ret) {
 AHT_INFO("register hmdy control path err\n");
 goto exit_delete_attr;
}

(3)struct hmdy_data_path

cpp 复制代码
struct hmdy_data_path hmdy_data_path = {0};
hmdy_data_path.get_data = aht10_get_humidity_data;
hmdy_data_path.vender_div = 10;
ret = hmdy_register_data_path(&hmdy_data_path);
if (ret) {
 AHT_INFO("hmdy_register_data_path failed, ret = %d\n", ret);
 goto exit_delete_attr;
}

这个结构体才是重头戏,其中get_data接口就是用来获取sensor想要上报的数据:

cpp 复制代码
int (*get_data)(int *value, int *status);

其中,value就是上报的数据值,同时通过status上报sensor的状态。另外,上报的数据有时候需要调整一个百分比,那么就会用到vender_div值了,在调试过程中自行调整即可。设置完毕就可以通过接口hmdy_register_data_path()将我们自定义的结构体注册进系统了。

结语

kernel层框架的要点大概就这么多,不同的sensor,基本的驱动流程都类似,读完我这系列文章后应该就能一通百通了。

相关推荐
Estar.Lee10 分钟前
时间操作[计算时间差]免费API接口教程
android·网络·后端·网络协议·tcp/ip
找藉口是失败者的习惯1 小时前
从传统到未来:Android XML布局 与 Jetpack Compose的全面对比
android·xml
Jinkey2 小时前
FlutterBasic - GetBuilder、Obx、GetX<Controller>、GetxController 有啥区别
android·flutter·ios
大白要努力!4 小时前
Android opencv使用Core.hconcat 进行图像拼接
android·opencv
天空中的野鸟5 小时前
Android音频采集
android·音视频
小白也想学C6 小时前
Android 功耗分析(底层篇)
android·功耗
曙曙学编程6 小时前
初级数据结构——树
android·java·数据结构
闲暇部落8 小时前
‌Kotlin中的?.和!!主要区别
android·开发语言·kotlin
诸神黄昏EX10 小时前
Android 分区相关介绍
android
大白要努力!11 小时前
android 使用SQLiteOpenHelper 如何优化数据库的性能
android·数据库·oracle