android g-sensor 驱动源码分析

环境: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命令即可读取数据

 

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值