一管脚注册
耳机插入的管脚gpio注册放在了sys_config.fex文件里面了。
Linein_gpio1 = port:PG09<0>~~~
二 驱动代码文件
/*
* Copyright (c) 2015, lvan xiong
* All rights reserved.
*
* 文件名称: zhc_key.c
* 摘 要: 按键检测驱动
*
* 当前版本: 1.0
* 作 者: ~~~~
* 完成日期:
*
* 取代版本:
* 原作者 :
* 完成日期:
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/input.h>
#ifdef CONFIG_HAS_EARLYSUSPEND
#include <linux/pm.h>
#include <linux/earlysuspend.h>
#endif
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/keyboard.h>
#include <linux/ioport.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/timer.h>
#include <linux/clk.h>
#include <mach/sys_config.h>
#include <linux/gpio.h>
#include <mach/irqs.h>
//#include <mach/system.h>
#include <mach/hardware.h>
#include <mach/gpio.h>
//#include <mach/clock.h>
#include <linux/regulator/consumer.h>
#include <linux/platform_device.h>
//#include "sun8i-keyboard.h"
//#include <linux/power/scenelock.h>
//#define __ISDEBUG__
#ifdef __ISDEBUG__
#define dprintk(format,...) printk(" --> Fun: %s, Line: %05d "format" <--\n", __func__, __LINE__,##__VA_ARGS__)
#else
#define dprintk(format,...)
#endif
u32 linein1 = 0;
u32 linein2 = 0;
static char* machine;
script_item_u item_val;
script_item_value_type_e item_type;
//u32 g_PowerDetectIO2 = 0; // 船型开关检测IO
//u32 TouchKeyIO2 = 0; // 功放电源控制电路
//u32 TouchKeyIO3 = 0; // 小负载控制电路
int gpio1,gpio2;
//static int virq;
//u32 g_IRQPowerDetectHandle = 0; // 中断句柄
//struct work_struct g_stIRQPowerDetect; // 中断下半部
struct delayed_work g_DelayTask;
//static struct input_dev *g_PowerDec_input_dev; // 键值上报
//struct device g_dev;
//struct device *dev = &pdev->dev;
#ifdef CONFIG_HAS_EARLYSUSPEND
struct sunxi_g_power_data {
struct early_suspend early_suspend;
};
/*
#else
#ifdef CONFIG_PM
static struct dev_pm_domain keyboard_pm_domain;
#endif
*/
#endif
#ifdef CONFIG_HAS_EARLYSUSPEND
static struct sunxi_g_power_data *g_power_data;
#endif
///////////////////////////////////////////////////////////////////////////
int GetLineInDetectStatus(void)
{
gpio1 = __gpio_get_value(linein1);
item_type = script_get_item("product", "machine", &item_val);
if(SCIRPT_ITEM_VALUE_TYPE_STR != item_type) {;
printk("%s: product machine script_get_item err.\n", __func__);
} else {
machine = item_val.str;
// printk("MYDEBUG --->> linein_detect.c line = %d machine = %s\n",__LINE__, machine);
if (!strncmp(machine, "dolphin-h3-zhc-a803-gb", strlen(machine))) {
gpio2 = __gpio_get_value(linein2);
// printk("MYDEBUG --->> linein gpio detect gpio1 = %d, gpio2 = %d", gpio1, gpio2);
if((gpio1 == 0) && (gpio2 == 0))
{
return 2;
}
if((gpio1 == 1) && (gpio2 == 1))
return 1;
if(((gpio1 == 1) && (gpio2 == 0)) || ((gpio1 == 0) && (gpio2 == 1)))
return 0;
}
}
return gpio1;
}
#if 1
static void linein_decetect(struct work_struct *work)
{
// dprintk();
int ret;
ret = GetLineInDetectStatus();
// printk("MYDEBUG --->>GetLineInDetectStatus = %d\n", ret);
schedule_delayed_work(&g_DelayTask, 50);
}
#endif
#if 0
u32 sunxi_gpio_irq_test_handler(void * para)
{
u32 upio_index = *(u32 *)para;
printk("MYDEBUG ---> %s :upio_index 0x%08x\n", __func__, upio_index);
}
static int LineInDetect_Probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
int virq;
int ret;
/* map the virq of gpio */
virq = gpio_to_irq(GPIOG(9));
if (IS_ERR_VALUE(virq)) {
pr_warn("map gpio [%d] to virq failed, errno = %d\n",
GPIOL(0), virq);
return -EINVAL;
}
pr_debug("gpio [%d] map to virq [%d] ok\n", GPIOL(0), virq);
/* request virq, set virq type to high level trigger */
ret = devm_request_irq(dev, virq, sunxi_gpio_irq_test_handler,
IRQF_TRIGGER_HIGH, "PL0_EINT", NULL);
if (IS_ERR_VALUE(ret)) {
pr_warn("request virq %d failed, errno = %d\n", virq, ret);
return -EINVAL;
}
return 0;
}
#endif
static struct platform_device LineInDetect_device = {
.name = "LineInDetect",//"PowerControl",
};
static struct platform_driver LineInDetect_driver = {
.driver = {
.name = "LineInDetect",//"PowerControl",
.owner = THIS_MODULE,
},
// .shutdown = PowerControl_shutdown,
// .probe = LineInDetect_Probe,
};
static int Init(void) //重要的函数来了
{
#if 1
int ret = 0;
static script_item_u val;
static script_item_value_type_e type;
dprintk();
type = script_get_item("linein_detect", "linein_user" , &val); //“linein_detect”,“linein_user”在sys_config.fex里面预先定义的元素
if (SCIRPT_ITEM_VALUE_TYPE_INT != type) { //判断获取的元素是否正确
printk("[linein_detect] linein_user type err\n");
goto err;
}
if( 0 == val.val){
printk("[linein_detect] linein_user type == 0\n");
goto err;
}
type = script_get_item("linein_detect", "linein_gpio1", &val);
if (SCIRPT_ITEM_VALUE_TYPE_PIO != type) {
printk("[linein_detect] script_get_item linein_gpio1 err\n");
goto err;
}
//以上几个if均为判断元素对应属性,错误代码返回err:-EFAULT,反之则goto err1:gpio_free(~~); 将这个gpio口释放掉
linein1 = val.gpio.gpio;
ret = gpio_request(linein1, "linein1"); //返回0 表示成功申请到gpio
if (ret != 0)
{
printk("[linein_detect] gpio_request linein1 failed\n");
goto err1; //释放gpio
}
ret = gpio_direction_input(linein1); //以上各种判断OK之后将此gpio设置为输入模式
if (ret != 0) //再次判断设置是否成功(0---成功,否则设置失败)
{
printk("[linein_detect]Set linein1 by input failed\n");
}
item_type = script_get_item("product", "machine", &item_val);
if(SCIRPT_ITEM_VALUE_TYPE_STR != item_type) {;
printk("%s: product machine script_get_item err.\n", __func__);
} else {
machine = item_val.str;
printk("MYDEBUG --->> linein_detect.c line = %d machine = %s\n",__LINE__, machine);
if (!strncmp(machine, "dolphin-h3-zhc-a803-gb", strlen(machine))) {
type = script_get_item("linein_detect", "linein_gpio2", &val);
if (SCIRPT_ITEM_VALUE_TYPE_PIO != type) {
printk("[linein_detect] script_get_item linein_gpio2 err\n");
goto err;
}
linein2 = val.gpio.gpio;
ret = gpio_request(linein2, "linein2");
if (ret != 0)
{
printk("[linein_detect] gpio_request linein2 failed\n");
goto err1;
}
ret = gpio_direction_input(linein2);
if (ret != 0)
{
printk("[linein_detect]Set linein2 by input failed\n");
}
}
}
INIT_DELAYED_WORK(&g_DelayTask, linein_decetect);
__cancel_delayed_work(&g_DelayTask);
schedule_delayed_work(&g_DelayTask, 2000);
#endif
ret = platform_device_register(&LineInDetect_device);
if (ret == 0) {
ret = platform_driver_register(&LineInDetect_driver);
}
// PowerOnProcess();
return 0;
//err3:
// gpio_free(TouchKeyIO3);
//err2:
// gpio_free(TouchKeyIO2);
err1:
gpio_free(linein1);
err:
return -EFAULT;
}
static void Exit(void)
{
platform_driver_unregister(&LineInDetect_driver);
platform_device_unregister(&LineInDetect_device);
}
static ssize_t LineInDetect_store(struct class *class, struct class_attribute *attr, const char *buf, size_t count)
{
dprintk();
return count;
}
static ssize_t LineInDetect_show(struct class *class, struct class_attribute *attr, char *buf)
{
// dprintk();
return sprintf(buf, "%d", GetLineInDetectStatus());
}
//注册文件节点
// __ATTR(cmd, 0777, PowerControl_show, PowerControl_store),
static struct class_attribute LineInDetect_class_attrs[] = {
__ATTR(cmd, 0777, LineInDetect_show, LineInDetect_store),
__ATTR_NULL
};
//文件节点的路径名字:KeyDetect, 文件节点的属性:KeyDetect_class_attrs //PowerControl_class
static struct class LineInDetect_class = {
.name = "LineInDetect",
.class_attrs = LineInDetect_class_attrs,
.class_attrs = LineInDetect_class_attrs,
};
#if 1
#ifdef CONFIG_HAS_EARLYSUSPEND
struct early_suspend linein_detect_early_suspend;
// 休眠
static void linein_detect_pm_early_suspend(struct early_suspend *handler)
//static void sunxi_keyboard_early_suspend(struct early_suspend *h)
{
printk("MYDEBUG ----->> LineIn_Detect_suspend++++++++++++++\n");
// PowerOffProcess();
}
// 唤醒
static void linein_detect_pm_resume(struct early_suspend *handler)
//static void sunxi_keyboard_late_resume(struct early_suspend *h)
{
printk("MYDEBUG ----->> LineIn_Detect_pm_resume++++++++++++++\n");
// PowerOnProcess();
// if(Exp_GetPowerDetectStatus())
// SendPowerOffKey();
}
/*
#else
#ifdef CONFIG_PM
static int sunxi_keyboard_suspend(struct device *dev)
{
printk("MYDBUG --->> line = %d, fun = %s \n", __LINE__, __func__);
return 0;
}
static int sunxi_keyboard_resume(struct device *dev)
{
printk("MYDBUG --->> line = %d, fun = %s \n", __LINE__, __func__);
return 0;
}
#endif
*/
#endif /* CONFIG_HAS_EARLYSUSPEND */
#endif
//调用初始化函数的地方(请看返回的函数)
static int __init LineInDetect_init(void)
{
dprintk();
class_register(&LineInDetect_class); //PowerControl_class
#if 0
/*
g_PowerCtrl_early_suspend.suspend = PowerCtrl_pm_early_suspend;
g_PowerCtrl_early_suspend.resume = PowerCtrl_pm_resume;
g_PowerCtrl_early_suspend.level = 3;
register_early_suspend(&g_PowerCtrl_early_suspend); // <--- 向电源管理系统注册
*/
printk("MYDBUG zhc_power_ctr--->> ==register_early_suspend init=\n");
g_PowerCtrl_data = kzalloc(sizeof(*g_PowerCtrl_data), GFP_KERNEL);
if (g_PowerCtrl_data == NULL) {
printk("MYDBUG zhc_power_ctr--->> g_PowerCtrl_data == err \n");
}
g_PowerCtrl_data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 3;
g_PowerCtrl_data->early_suspend.suspend = PowerCtrl_pm_early_suspend;
g_PowerCtrl_data->early_suspend.resume = PowerCtrl_pm_resume;
g_PowerCtrl_data(&g_PowerCtrl_data->early_suspend);
#endif
/*
#ifdef CONFIG_HAS_EARLYSUSPEND
#else
#ifdef CONFIG_PM
keyboard_pm_domain.ops.suspend = sunxi_keyboard_suspend;
keyboard_pm_domain.ops.resume = sunxi_keyboard_resume;
g_PowerDec_input_dev->dev.pm_domain = &keyboard_pm_domain;
#endif
#endif
*/
#ifdef CONFIG_HAS_EARLYSUSPEND
linein_detect_early_suspend.suspend = linein_detect_pm_early_suspend;
linein_detect_early_suspend.resume = linein_detect_pm_resume;
linein_detect_early_suspend.level = 0;
register_early_suspend(&linein_detect_early_suspend);
#endif
return Init();
// return 0;
}
static void __exit LineInDetect_exit(void)
{
//#ifdef CONFIG_HAS_EARLYSUSPEND
unregister_early_suspend(&linein_detect_early_suspend);
//#endif
dprintk();
Exit();
class_unregister(&LineInDetect_class);
}
late_initcall(LineInDetect_init); //PowerControl_init
module_exit(LineInDetect_exit);//PowerControl_exit
MODULE_LICENSE("GPL");