资讯详情

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->wakup = 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");

标签: guh5红外线传感器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台