MTK Android G-Sensor auto detect源码分析

环境:MTK Android4.4  硬件:MT8127 MMA8653 日期:2015年6月19日

在MTK的Gsensor构架中有一个auto detect的功能,只要作用是可以添加多个GSensor驱动,然后会自动找到与硬件匹配的Gsensor驱动,这个功能是用hwmsen驱动模块来完成的。 先来看看驱动里是如何使用auto detect的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
static struct sensor_init_info mma8653q_init_info = {
        .name =  “mma8653q”,
        .init = mma8653q_local_init,
        .uninit = mma8653q_remove,
};

//在模块初始化的时候把mma8653q_init_info加入到hwmsen中
static  int __init mma8653q_init( void) {
//…
    hwmsen_gsensor_add( & mma8653q_init_info);
//…
}

static  int mma8653q_i2c_probe(struct i2c_client * client,  const struct i2c_device_id * id) {
    struct i2c_client * new_client;
    struct mma8653q_i2c_data * obj;
    struct hwmsen_object sobj;
int err =  0;
int retry =  0;
    GSE_FUN();
//获得8653的基本数据,I2C总线,hwmsen_convert(Gsensor数据轴和方向的定义)等
    obj->hw = mma8653q_get_cust_acc_hw();
//获取hwmsen_convert map
    hwmsen_get_convert(obj->hw->direction, & obj->cvt);
    atomic_set( & obj->trace,  0);
    atomic_set( & obj->suspend,  0);
#ifdef CONFIG_MMA8653Q_LOWPASS
if(obj->hw->firlen > C_MAX_FIR_LENGTH) {
        atomic_set( & obj->firlen, C_MAX_FIR_LENGTH);
    }  else {
        atomic_set( & obj->firlen, obj->hw->firlen);
    }
if(atomic_read( & obj->firlen) >  0) {
        atomic_set( & obj->fir_en,  1);
    }
#endif

    sobj.self = obj;                        
    sobj.polling =  1;                        //数据传输方式
    sobj.sensor_operate = mma8653q_operate;   //mma8653的接口函数
    hwmsen_attach(ID_ACCELEROMETER, & sobj);     //把sobj加入到队列中,如果相应ID队伍里不为空,则无法加入
        
#ifdef USE_EARLY_SUSPEND
    obj->early_drv.level    = EARLY_SUSPEND_LEVEL_STOP_DRAWING –  2,
                   obj->early_drv.suspend  = mma8653q_early_suspend,
                                  obj->early_drv.resume   = mma8653q_late_resume,
                                                 register_early_suspend( & obj->early_drv);
#endif
//=0时,加入成功,hwmsen不会再搜索并加入其他的gsensor驱动
    mma8653q_init_flag =  0;
}

首先是整个hwmsen驱动的hwmsen_driver和hwmsen_device的匹配

1
2
3
4
5
6
7
8
9
10
11
static  struct platform_driver hwmsen_driver = {
    .probe      = hwmsen_probe,
    .remove     = hwmsen_remove,
    .suspend    = hwmsen_suspend,
    .resume     = hwmsen_resume,
    .driver     =   {
        .name = HWM_SENSOR_DEV_NAME,
//      .owner = THIS_MODULE,
    }
};

hwmsen_probe

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
static  int hwmsen_probe( struct platform_device *pdev) {
//清空所有的列表,数据区等
    init_static_data();

//设置总的hwmdev_object,主要是初始化队列,时间中断
     //这个时间中断是用来轮询sensor数据时频率,这里为5hz即200ms
    hwm_obj = hwmsen_alloc_object();

//初始化化Input子系统    
    hwm_obj->idev = input_allocate_device();    
    set_bit(EV_REL, hwm_obj->idev->evbit);
    set_bit(EV_SYN, hwm_obj->idev->evbit);
    input_set_capability(hwm_obj->idev, EV_REL, EVENT_TYPE_SENSOR);    
    hwm_obj->idev->name = HWM_INPUTDEV_NAME;

    input_register_device(hwm_obj->idev);
    input_set_drvdata(hwm_obj->idev, hwm_obj);

//注册一个misc驱动,主要是提供对sensor操作的接口
    hwm_obj->mdev.minor = MISC_DYNAMIC_MINOR;
    hwm_obj->mdev.name  = HWM_SENSOR_DEV_NAME;
    hwm_obj->mdev.fops  = &hwmsen_fops;
    misc_register(&hwm_obj->mdev);    
    dev_set_drvdata(hwm_obj->mdev.this_device, hwm_obj);

//创建属性文件
    hwmsen_create_attr(hwm_obj->mdev.this_device) !=  0);

// add for fix resume bug
    atomic_set(&(hwm_obj->early_suspend),  0);
    hwm_obj->early_drv.level    = EARLY_SUSPEND_LEVEL_STOP_DRAWING –  1,
    hwm_obj->early_drv.suspend  = hwmsen_early_suspend,
    hwm_obj->early_drv.resume   = hwmsen_late_resume,
    register_early_suspend(&hwm_obj->early_drv);

    wake_lock_init(&(hwm_obj->read_data_wake_lock), WAKE_LOCK_SUSPEND,  “read_data_wake_lock”);
// add for fix resume bug end
     return  0;
}

接下来按照上面的使用流程来分析hwmsen hwmsen_gsensor_add, 就是把sensor_init_info结构体加入到list中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
static struct platform_driver gsensor_driver = {
    .probe      = gsensor_probe,
    .remove     = hwmsen_gsensor_remove,
    .driver     =    {
        .name  =  “gsensor”,
//      .owner = THIS_MODULE,
    }
};

int hwmsen_gsensor_add(struct sensor_init_info * obj) {
for(i =  0; i < MAX_CHOOSE_G_NUM; i++ ) {
if(NULL == gsensor_init_list[i]) {
            gsensor_init_list[i] = kzalloc(sizeof(struct sensor_init_info), GFP_KERNEL);
if(NULL == gsensor_init_list[i]) {
                HWM_ERR( “kzalloc error”);
return – 1;
            }
//初始化obj的gsensor_driver。
            obj->platform_diver_addr = & gsensor_driver;
//把obj添加到队列中
            gsensor_init_list[i] = obj;
break;
        }
    }
return err;
}



gsensor_driver如果与gsensor_device匹配上了之后就会调用gsensor_probe

1
2
3
4
5
6
7
8
9
10
11
12
13
14
static  int gsensor_probe( struct platform_device *pdev) {
for(i =  0; i < MAX_CHOOSE_G_NUM; i++) {
if( 0 != gsensor_init_list[i]) {
//调用sensor_init_info的init函数,即hwmsen_msensor_add添加进来的结构体
            err = gsensor_init_list[i]->init();
if( 0 == err) {
                strcpy(gsensor_name, gsensor_init_list[i]->name);
                HWM_LOG( ” gsensor %s probe ok\n”, gsensor_name);
break;
            }
        }
    }
return  0;
}

gsensor_probe会调用驱动的init函数,这里是mma8653q_local_init

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
static  int mma8653q_local_init( void) {
struct acc_hw *hw = mma8653q_get_cust_acc_hw();

//上电,并增加i2c驱动
    MMA8653Q_power(hw,  1);
    i2c_add_driver(&mma8653q_i2c_driver);

//这里很奇怪,i2c_add_driver完之后如果找到了相应的i2c设备,
     //则会等执行完相应的i2c_probe,再执行到这里。
     //i2c_probe会填充mma8653q_init_flag    
     if(- 1 == mma8653q_init_flag) {
return – 1;
    }
return  0;
}

后面的就会在mma8653q_i2c_probe中执行,其主要是执行struct hwmsen_object sobj;并加入到hwmsen的sensor队列中。 hwmsen_get_convert:决定gsensor数据的格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
struct hwmsen_convert map[] = {
    { {  1, – 1, – 1}, { 012} },
    { { – 111}, { 102} },
    { { – 1, – 11}, { 012} },
    { {  1, – 11}, { 102} },

    { { – 11, – 1}, { 012} },
    { {  1, – 1, – 1}, { 102} },
    { {  1, – 1, – 1}, { 102} },
    { { – 1, – 1, – 1}, { 102} },

};
/*—————————————————————————-*/
//通过direction在上面的map里找出gsensor数据的模式。
//每组的前3个为数据是否要倒转。
//每组的后面3个为x,y,z轴的摆放位置
int hwmsen_get_convert( int direction,  struct hwmsen_convert *cvt) {
if (!cvt)
return -EINVAL;
else  if (direction >=  sizeof(map) /  sizeof(map[ 0]))
return -EINVAL;
    * cvt = map[direction];
return  0;
}

hwmsen_attach:把sensor加入到总的sensor队列里,这个队列里可以有光感,陀螺仪等…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
struct dev_context {
int     polling_running;
struct mutex lock;
struct hwmsen_context* cxt[MAX_ANDROID_SENSOR_NUM+ 1];
};

int hwmsen_attach( int sensor,  struct hwmsen_object *obj) {
struct dev_context *mcxt = &dev_cxt;

//确保每个sensor只有一个实例
     if(mcxt->cxt[sensor] !=  NULL) {
        err = -EEXIST;
goto err_exit;
    }  else {
//所有的Sensor列表,根据ID去放入相应的位置
        mcxt->cxt[sensor] = kzalloc( sizeof( struct hwmsen_context), GFP_KERNEL);
if(mcxt->cxt[sensor] ==  NULL) {
            err = -EPERM;
goto err_exit;
        }
        atomic_set(&mcxt->cxt[sensor]->enable,  0);
        memcpy(&mcxt->cxt[sensor]->obj, obj,  sizeof(*obj));
// add for android2.3 set  sensors default polling delay time is 200ms
        atomic_set(&mcxt->cxt[sensor]->delay,  200);
    }
}

到这里hwmsens的初始化就完成了

接下来就先open hwmsen驱动,然后就把工作都交给了hwmsen的unlocked_ioctl,即hwmsen_unlocked_ioctl函数 里面的操作函数主要是调用hwmsen_attach函数传入的hwmsen_object里面的sensor_operate,即为mma8653q_operate

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int mma8653q_operate( void *self, uint32_t command,  void *buff_in,  int size_in,
void *buff_out,  int size_out,  int *actualout) {
switch (command) {
case SENSOR_DELAY:
//…
             break;
case SENSOR_ENABLE:
//…
             break;
case SENSOR_GET_DATA:
//…
             break;
default:
//…
             break;
    }
return err;
}

hwmsen_unlocked_ioctl首先是HWM_IO_ENABLE_SENSOR命令,调用的是hwmsen_enable();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
static  int hwmsen_enable( struct hwmdev_object *obj,  int sensor,  int enable) {
    mutex_lock(&obj->dc->lock);
    cxt = obj->dc->cxt[sensor];
if(enable ==  1) {
        enable_again =  true;
        obj->active_data_sensor |= sensor_type;
if((obj->active_sensor & sensor_type) ==  0) {    // no no-data active nodata模式
             if (cxt->obj.sensor_operate(cxt->obj.self, SENSOR_ENABLE, &enable,  sizeof( int),  NULL0NULL) !=  0)
//…
                atomic_set(&cxt->enable,  1);
        }
//polling模式
         // Need to complete the interrupt sensor work
         if(( 0 == obj->dc->polling_running) && (obj->active_data_sensor !=  0)) {
            obj->dc->polling_running =  1;
//使能定时器
            mod_timer(&obj->timer, jiffies + atomic_read(&obj->delay) / ( 1000 / HZ));
        }
    }  else {
//…
    }
}

数据的读取: 在sensro初始化的时候,初始化了一个工作队列和一个定时器:

1
2
3
4
5
6
sensor_workqueue = create_singlethread_workqueue( “sensor_polling”);
INIT_WORK(&obj->report, hwmsen_work_func);
init_timer(&obj->timer);
obj->timer.expires  = jiffies + atomic_read(&obj->delay) / ( 1000 / HZ);
obj->timer.function = hwmsen_poll;
obj->timer.data     = ( unsigned  long)obj;

每次对sensor enable后就会使能这个定时器,会执行hwmsen_poll,这个函数会唤醒工作队列。工作队列会执行hwmsen_work_func函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
static  void hwmsen_work_func( struct work_struct *work) {
//遍历所有的sensor
     for(idx =  0; idx < MAX_ANDROID_SENSOR_NUM; idx++) {
        cxt = obj->dc->cxt[idx];

//我们是polling模式
         // Interrupt sensor
         if(cxt->obj.polling ==  0) {
//…
        }

//如果sensor指定了delay时间
         //added to surpport set delay to specified sensor
         if(cxt->delayCount >  0) {
            cxt->delayCount–;
if( 0 == cxt->delayCount) {
                cxt->delayCount = cxt->delayCountSet;
            }  else {
continue;
            }
        }

//从sensor里获取数据
        err = cxt->obj.sensor_operate(cxt->obj.self, SENSOR_GET_DATA,  NULL0,
                                      &sensor_data,  sizeof(hwm_sensor_data), &out_size);
if(err) {
            HWM_ERR( “get data from sensor (%d) fails!!\n”, idx);
continue;
        }  else {
//LIGHT Sensor…
             if((idx == ID_LIGHT) || (idx == ID_PRESSURE)
                    || (idx == ID_PROXIMITY) || (idx == ID_TEMPRERATURE)) {
// data changed, update the data            
                }
            }  else {
// data changed, update the data
                     //填充数据
                    obj_data.sensors_data[idx].values[ 0] = sensor_data.values[ 0];
                    obj_data.sensors_data[idx].values[ 1] = sensor_data.values[ 1];
                    obj_data.sensors_data[idx].values[ 2] = sensor_data.values[ 2];
                    obj_data.sensors_data[idx].value_divide = sensor_data.value_divide;
                    obj_data.sensors_data[idx].status = sensor_data.status;
                    obj_data.sensors_data[idx].time = nt;
                    event_type |= ( 1 << idx);
            }
        }
    }
//
     //mutex_unlock(&obj_data.lock);
     if(enable_again ==  true) {
        event_type = obj->active_data_sensor;
        enable_again =  false;
//filter -1 value
         for(idx =  0; idx <= MAX_ANDROID_SENSOR_NUM; idx++) {
if(ID_ACCELEROMETER == idx || ID_MAGNETIC == idx || ID_ORIENTATION == idx
                    || ID_GYROSCOPE == idx || ID_TEMPRERATURE == idx
                    || ID_LINEAR_ACCELERATION == idx || ID_ROTATION_VECTOR == idx
                    || ID_GRAVITY == idx) {
if(SENSOR_INVALID_VALUE == obj_data.sensors_data[idx].values[ 0] ||
                        SENSOR_INVALID_VALUE == obj_data.sensors_data[idx].values[ 1] ||
                        SENSOR_INVALID_VALUE == obj_data.sensors_data[idx].values[ 2]) {
                    event_type &= ~( 1 << idx);
//HWM_LOG(“idx=%d,obj->active_sensor after clear: %d\n”,idx);
                }
            }
if(ID_PROXIMITY == idx || ID_LIGHT == idx || ID_PRESSURE == idx) {
if(SENSOR_INVALID_VALUE == obj_data.sensors_data[idx].values[ 0]) {
                    event_type &= ~( 1 << idx);
                }
            }
        }
    }

if((event_type & ( 1 << ID_PROXIMITY)) && SENSOR_INVALID_VALUE == obj_data.sensors_data[ID_PROXIMITY].values[ 0]) {
        event_type &= ~( 1 << ID_PROXIMITY);
//HWM_LOG(“remove ps event!!!!!!!!!!!\n”);
    }
if(event_type !=  0) {
//上报sensro类型
        input_report_rel(obj->idev, EVENT_TYPE_SENSOR, event_type);
        input_sync(obj->idev); //modified
    }  else {
    }
if(obj->dc->polling_running ==  1) {
        mod_timer(&obj->timer, jiffies + atomic_read(&obj->delay) / ( 1000 / HZ));
    }
}

然后会调用
hwmsen_unlocked_ioctl的HWM_IO_GET_SENSORS_DATA命令即可读取数据

    原文作者:Android源码分析
    原文地址: https://blog.csdn.net/shell812/article/details/49764235
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞