高通平台虚拟计步器

蚂蚁森林有个行走赚绿色能量的方法,但奈何我的手机不支持运动传感器(https://blog.csdn.net/mike8825/article/details/95898831),Android本身已支持计步传感器,如果写个计步器的驱动,那应该就可以显示步数了。网上搜索发现了一篇文档(lm80-p0436-9_sensors_porting_guide.pdf),感觉这个有希望。

驱动如下

#include 
#include 
#include 
#include 
#define POLL_DEFAULT_INTERVAL_MS 500
static unsigned long step_count;
struct sensors_classdev step_counter_cdev ={.name = "simulated_step_counter",.vendor = "www",.version = 1,.type = SENSOR_TYPE_STEP_COUNTER,.sensors_enable = NULL,.sensors_poll_delay = NULL,
};struct step_counter {atomic_t delay;struct workqueue_struct *data_wq;struct delayed_work dwork;struct sensors_classdev cdev;struct mutex enable_lock;struct mutex step_count_lock;struct input_dev *idev;
};static int step_counter_set_enable(struct sensors_classdev *sensors_cdev,unsigned int enable)
{struct step_counter *virtual_step_counter = container_of(sensors_cdev,struct step_counter, cdev);mutex_lock(&virtual_step_counter->enable_lock);if (enable){queue_delayed_work(virtual_step_counter->data_wq,&virtual_step_counter->dwork,msecs_to_jiffies(atomic_read(&virtual_step_counter->delay)));} else{cancel_delayed_work_sync(&virtual_step_counter->dwork);}mutex_unlock(&virtual_step_counter->enable_lock);return 0;}
static ssize_t step_count_show(struct device *dev,struct device_attribute *attr, char *buf)
{return sprintf(buf, "%lu\n", step_count);
}static ssize_t step_count_store(struct device *dev,struct device_attribute *attr,const char *buf, size_t count)
{unsigned long data;int ret;struct step_counter *virtual_step_counter=dev_get_drvdata(dev);ret = kstrtoul(buf, 10, &data);if (ret)return ret;mutex_lock(&virtual_step_counter->step_count_lock);step_count=data;mutex_unlock(&virtual_step_counter->step_count_lock);return count;
}
static DEVICE_ATTR(step_count, S_IRUSR|S_IRGRP|S_IWUSR,step_count_show,step_count_store);int step_counter_poll_delay(struct sensors_classdev *sensors_cdev,unsigned int delay_msec)
{struct step_counter *virtual_step_counter = container_of(sensors_cdev,struct step_counter, cdev);atomic_set(&virtual_step_counter->delay,delay_msec);return 0;    
}static void step_counter_poll(struct work_struct *work)
{struct step_counter *virtual_step_counter = container_of((struct delayed_work  *)work,struct step_counter, dwork);input_report_abs(virtual_step_counter->idev, ABS_MISC, step_count);mutex_lock(&virtual_step_counter->step_count_lock);step_count=step_count+1;mutex_unlock(&virtual_step_counter->step_count_lock);input_sync(virtual_step_counter->idev);queue_delayed_work(virtual_step_counter->data_wq,&virtual_step_counter->dwork,msecs_to_jiffies(atomic_read(&virtual_step_counter->delay)));
}static struct input_dev *step_counter_init_input(struct device *dev)
{int status;struct input_dev *input = NULL;input = devm_input_allocate_device(dev);if (!input)return NULL;input->name = "step_counter";input_set_capability(input, EV_ABS, ABS_MISC);status = input_register_device(input);if (status) {dev_err(dev,"error registering input device\n");return NULL;}return input;
}static int step_counter_probe(struct platform_device *pdev)
{int ret;struct step_counter *virtual_step_counter;printk("step_counter_probe start\n");virtual_step_counter = devm_kzalloc(&pdev->dev, sizeof(struct step_counter),GFP_KERNEL);if (!virtual_step_counter) {dev_err(&pdev->dev, "memory allocation failed.\n");goto out;}INIT_DELAYED_WORK(&virtual_step_counter->dwork, step_counter_poll);virtual_step_counter->data_wq =create_freezable_workqueue("step_counter_data_work");if (!virtual_step_counter->data_wq) {dev_err(&pdev->dev, "Cannot create workqueue.\n");goto out_create_workqueue;}atomic_set(&virtual_step_counter->delay, POLL_DEFAULT_INTERVAL_MS);virtual_step_counter->idev=step_counter_init_input(&pdev->dev);if(!virtual_step_counter->idev){dev_err(&pdev->dev, "init input device failed\n");ret = -ENODEV;goto out_register_input;}virtual_step_counter->cdev=step_counter_cdev;virtual_step_counter->cdev.sensors_enable=step_counter_set_enable;virtual_step_counter->cdev.sensors_poll_delay=step_counter_poll_delay;ret=sensors_classdev_register(&virtual_step_counter->idev->dev,&virtual_step_counter->cdev);if (ret) {dev_err(&pdev->dev, "sensors class register failed.\n");goto out_register_classdev;}mutex_init(&virtual_step_counter->enable_lock);mutex_init(&virtual_step_counter->step_count_lock);dev_set_drvdata(&pdev->dev, virtual_step_counter);ret = device_create_file(&pdev->dev, &dev_attr_step_count);printk("step_counter_probe ok\n");return 0;out_register_classdev:input_unregister_device(virtual_step_counter->idev);    
out_create_workqueue:
out_register_input:    destroy_workqueue(virtual_step_counter->data_wq);
out:printk("step_counter_probe fail\n");return ret;
}    static int step_counter_remove(struct platform_device *pdev)
{return 0;
}static struct platform_device step_counter_devices =
{.name            = "simulated_step_counter",.id             = 0,
};static struct platform_driver step_counter_driver =
{.probe  = step_counter_probe,.remove = step_counter_remove,.driver = {.name = "simulated_step_counter",.owner = THIS_MODULE,},
};static int sensor_init(void)
{platform_device_register(&step_counter_devices);platform_driver_register(&step_counter_driver);return 0;
}static void __exit sensor_exit(void)
{platform_device_unregister(&step_counter_devices);platform_driver_unregister(&step_counter_driver);
}module_init(sensor_init);
module_exit(sensor_exit);
MODULE_LICENSE("GPL");

                    驱动工作了,并有相关的数据上传了,但上层APP说不支持计步传感器,查找相关
代码在hardware/qcom/sensors/sensors.h加上SENSOR_TYPE_STEP_COUNTER,并将压力传
感器bmp180的相关hal代码进行改造,计步器正常工作了。用其他APP读数,汇报的值跟APP
读到的值一致,但蚂蚁森林上的读数比较久才跟新下,应该跟其内部的实现有关。
 

相关修改如下

 

      见证成果的时候到了。

 


 


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部