Android驱动-霍尔摁键hall_sensor的实现

第一步移植.c文件

将修改好的hall_sensor.c文件放到input路径下

drivers/input/hall_sensor.c

第二步Kconfig配置

路径在 drivers/input/Kconfig

在这里插入图片描述

第三步Makefile配置

路径在:drivers/input/Makefile
在这里插入图片描述

第四步deconfig配置

路径arch/arm/configs/msm8937go_defconfig

在这里插入图片描述

第五步设备树配置

路径在arch/arm64/boot/dts/qcom/qm215-qrd.dtsi

在这里插入图片描述

第六步(如果上图注释中pinctrl需要配置则需要配置)

在这里插入图片描述

第七步 检查是否生效

adb shell 进入后 getevent 事件可以查看是否有设备生效

在这里插入图片描述

第八步 新增加hall_sensor.kl文件

新增方法,跳转到查看matrix_keypad.kl的增加

第九步 功能测试

翻盖看是否亮灭(注意是否有磁性)
还可以看cat proc/interrupts 中断是否有产生

hall_sensor.c代码
 /*
 *
 * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */
 
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/input.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/pm.h>
#include <linux/module.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
 
#define	LID_DEV_NAME	"hall_sensor"
#define HALL_INPUT	"/dev/input/hall_dev"
 
struct hall_data {
	int gpio;	/* device use gpio number */
	int irq;	/* device request irq number */
	int active_low;	/* gpio active high or low for valid value */
	bool wakeup;	/* device can wakeup system or not */
	struct input_dev *hall_dev;
    struct device *dev;
};
 
static irqreturn_t hall_interrupt_handler(int irq, void *dev)
{
	int value;
	struct hall_data *data = dev;
 
	value = (gpio_get_value_cansleep(data->gpio) ? 1 : 0) ^
		data->active_low;
	if (value) {
		//input_report_key(data->hall_dev, KEY_SLEEP, 1);
		//input_sync(data->hall_dev);
		//input_report_key(data->hall_dev, KEY_SLEEP, 0);
		//input_sync(data->hall_dev);
		input_report_key(data->hall_dev, FLIP, 0);
	        input_sync(data->hall_dev);
		dev_info(&data->hall_dev->dev, "near\n");
	} else {
		
		//input_report_key(data->hall_dev, KEY_WAKEUP, 1);
		//input_sync(data->hall_dev);
		//input_report_key(data->hall_dev, KEY_WAKEUP, 0);
		//input_sync(data->hall_dev);
		input_report_key(data->hall_dev, FLIP, 1);
	        input_sync(data->hall_dev);
		dev_info(&data->hall_dev->dev, "far\n");
	}
	//input_report_key(data->hall_dev, KEY_FLIP, 1);
   	//input_sync(data->hall_dev);
    	//input_report_key(data->hall_dev, KEY_FLIP, 0);
	input_sync(data->hall_dev);
 
	return IRQ_HANDLED;
}
 
static int hall_input_init(struct platform_device *pdev,
		struct hall_data *data)
{
	int err = -1;
 
	data->hall_dev = devm_input_allocate_device(&pdev->dev);
	if (!data->hall_dev) {
		dev_err(&data->hall_dev->dev,
				"input device allocation failed\n");
		return -EINVAL;
	}
	data->hall_dev->name = LID_DEV_NAME;
	data->hall_dev->phys = HALL_INPUT;
	set_bit(EV_KEY, data->hall_dev->evbit);
	//set_bit(KEY_WAKEUP, data->hall_dev->keybit);
	//set_bit(KEY_SLEEP, data->hall_dev->keybit);
        set_bit(FLIP,data->hall_dev->keybit);
	err = input_register_device(data->hall_dev);
	if (err < 0) {
		dev_err(&data->hall_dev->dev,
				"unable to register input device %s\n",
				LID_DEV_NAME);
		return err;
	}
 
	return 0;
}
 
#ifdef CONFIG_OF
static int hall_parse_dt(struct device *dev, struct hall_data *data)
{
	unsigned int tmp;

	struct device_node *np = dev->of_node;
 
	data->gpio = of_get_named_gpio_flags(dev->of_node,
			"linux,gpio-int", 0, &tmp);
	if (!gpio_is_valid(data->gpio)) {
		dev_err(dev, "hall gpio is not valid\n");
		return -EINVAL;
	}
	data->active_low = tmp & OF_GPIO_ACTIVE_LOW ? 0 : 1;
 
	data->wakeup = of_property_read_bool(np, "linux,wakeup");
 
	return 0;
}
#else
static int hall_parse_dt(struct device *dev, struct hall_data *data)
{
	return -EINVAL;
}
#endif

// Begin: add by hyangde for hall status show on 220516 
static ssize_t hall_status_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct hall_data *pdata = dev_get_drvdata(dev);
	int value;

	value = (gpio_get_value_cansleep(pdata->gpio) ? 1 : 0) ^ pdata->active_low;

	return snprintf(buf, PAGE_SIZE, "%d\n", value);
}

static DEVICE_ATTR(hall_status, 0664, hall_status_show, NULL);

static struct attribute *hall_attrs[] = {
	&dev_attr_hall_status.attr,
	NULL,
};

static struct attribute_group hall_attr_group = {
	.attrs = hall_attrs,
};
// End: add by hyangde for hall status show on 220516 

static int hall_driver_probe(struct platform_device *dev)
{
	struct hall_data *data;
	int err = 0;
	int irq_flags;
 	printk("guh hall probe start");
	dev_info(&dev->dev, "hall_driver probe\n");
	data = devm_kzalloc(&dev->dev, sizeof(struct hall_data), GFP_KERNEL);
	if (data == NULL) {
		err = -ENOMEM;
		dev_err(&dev->dev,
				"failed to allocate memory %d\n", err);
		goto exit;
	}

	data->dev = &dev->dev;
	dev_set_drvdata(&dev->dev, data);
	if (dev->dev.of_node) {
		err = hall_parse_dt(&dev->dev, data);
		if (err < 0) {
			dev_err(&dev->dev, "Failed to parse device tree\n");
			goto exit;
		}
	} else if (dev->dev.platform_data != NULL) {
		memcpy(data, dev->dev.platform_data, sizeof(*data));
	} else {
		dev_err(&dev->dev, "No valid platform data.\n");
		err = -ENODEV;
		goto exit;
	}
 
	err = hall_input_init(dev, data);
	if (err < 0) {
		dev_err(&dev->dev, "input init failed\n");
		goto exit;
	}
 
	if (!gpio_is_valid(data->gpio)) {
		dev_err(&dev->dev, "gpio is not valid\n");
		err = -EINVAL;
		goto free_gpio;
	}
 
	irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
		| IRQF_ONESHOT;
	err = gpio_request_one(data->gpio, GPIOF_DIR_IN, "hall_sensor_irq");
	if (err) {
		dev_err(&dev->dev, "unable to request gpio %d\n", data->gpio);
		goto exit;
	}
 
	data->irq = gpio_to_irq(data->gpio);
	err = devm_request_threaded_irq(&dev->dev, data->irq, NULL,
			hall_interrupt_handler,
			irq_flags, "hall_sensor", data);
	if (err < 0) {
		dev_err(&dev->dev, "request irq failed : %d\n", data->irq);
		goto free_irq;
	}

	err = sysfs_create_group(&data->dev->kobj, &hall_attr_group);
	if (err) {
		printk(KERN_ERR "%s sysfs_create_group fail\n", __func__);
		return err;
	}

	device_init_wakeup(&dev->dev, data->wakeup);
	enable_irq_wake(data->irq);
 	printk("guh hall probe end");
	return 0;
 
free_irq:
	disable_irq_wake(data->irq);
	device_init_wakeup(&dev->dev, 0);
free_gpio:
	gpio_free(data->gpio);
exit:
	return err;
}
 
static int hall_driver_remove(struct platform_device *dev)
{
	struct hall_data *data = dev_get_drvdata(&dev->dev);
 
	disable_irq_wake(data->irq);
	device_init_wakeup(&dev->dev, 0);
	if (data->gpio)
		gpio_free(data->gpio);
 
	return 0;
}
 
static struct platform_device_id hall_id[] = {
	{LID_DEV_NAME, 0 },
	{ },
};
 
 
#ifdef CONFIG_OF
static struct of_device_id hall_match_table[] = {
	{.compatible = "hall-switch", },
	{ },
};
#endif
 
static struct platform_driver hall_driver = {
	.driver = {
		.name = LID_DEV_NAME,
		.owner = THIS_MODULE,
		.of_match_table = of_match_ptr(hall_match_table),
	},
	.probe = hall_driver_probe,
	.remove = hall_driver_remove,
	.id_table = hall_id,
};
 
static int __init hall_init(void)
{
	return platform_driver_register(&hall_driver);
}
 
static void __exit hall_exit(void)
{
	platform_driver_unregister(&hall_driver);
}
 
module_init(hall_init);
module_exit(hall_exit);
MODULE_DESCRIPTION("Hall sensor driver");
MODULE_LICENSE("GPL v2");
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值