基于linux switch模块的HDMI检测状态驱动
2014-07-27 03:34
387 查看
/* * drivers\staging\android\switch\switch_hdmiset.c * * Copyright (C) 2008 Google, Inc. * Author: Johnny <liujun@eken.com> * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and * may be copied, distributed, and modified under those terms. * * 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/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/workqueue.h> #include <linux/gpio.h> #include "switch.h" #undef SWITCH_DBG #if (1) #define SWITCH_DBG(format,args...) printk("[SWITCH] "format,##args) #else #define SWITCH_DBG(...) #endif static unsigned int hdmi_status; static struct gpio_switch_data { struct switch_dev sdev; unsigned pio_hdle; int state; unsigned long delay_time; struct delayed_work hdmi_work; struct workqueue_struct *mywork_queue; unsigned char switch_flag; }; static void hdmi_work_func(struct delayed_work *hdmi_work) { int state = -1; SWITCH_DBG("enter:%s,line:%d\n", __func__, __LINE__); struct gpio_switch_data *switch_data = container_of(hdmi_work, struct gpio_switch_data, hdmi_work); //state = gpio_get_value(switch_data->pio_hdle);//获取GPIO输入状态值 hdmi_status = gpio_get_value(switch_data->pio_hdle);//获取GPIO输入状态值 //hdmi_status = 1; //switch_set_state(&switch_data->sdev, state); queue_delayed_work(switch_data->mywork_queue, &switch_data->hdmi_work, switch_data->delay_time); } static ssize_t switch_gpio_print_state(struct switch_dev *sdev, char *buf) { SWITCH_DBG("enter:%s,line:%d\n", __func__, __LINE__); //struct gpio_switch_data *switch_data = // container_of(sdev, struct gpio_switch_data, sdev); return sprintf(buf, "%d\n", hdmi_status); } static int gpio_switch_probe(struct platform_device *pdev) { struct gpio_switch_platform_data *pdata = pdev->dev.platform_data; struct gpio_switch_data *switch_data; int ret = 0; SWITCH_DBG("enter:%s,line:%d\n", __func__, __LINE__); if (!pdata) return -EBUSY; switch_data = kzalloc(sizeof(struct gpio_switch_data), GFP_KERNEL); if (!switch_data) return -ENOMEM; switch_data->delay_time = 100; switch_data->sdev.name = pdata->name; switch_data->pio_hdle = pdata->gpio; switch_data->state = 0; switch_data->switch_flag = 0; switch_data->sdev.print_state = switch_gpio_print_state; #if 1 switch_data->pio_hdle = GPIOB(6); if(0 != gpio_request(switch_data->pio_hdle, NULL)) { pr_err("ERROR: HDMI request gpio is failed\n"); //goto err_request_gpio; } ret = gpio_direction_input(switch_data->pio_hdle); //if (ret < 0) //goto err_set_gpio_input; #endif ret = switch_dev_register(&switch_data->sdev); if (ret < 0) goto err_switch_dev_register; INIT_DELAYED_WORK(&switch_data->hdmi_work, hdmi_work_func);//初始化工作队列 switch_data->mywork_queue = create_singlethread_workqueue("hdmi_gpio");//创建线程mywork_queue queue_delayed_work(switch_data->mywork_queue,&switch_data->hdmi_work,switch_data->delay_time); return 0; //err_set_gpio_input: // gpio_free(switch_data->pio_hdle); //err_request_gpio: // switch_dev_unregister(&switch_data->sdev); err_switch_dev_register: kfree(switch_data); return ret; } static int switch_resume(struct platform_device *pdev) { struct gpio_switch_data *switch_data; //switch_data = (struct gpio_switch_data *)platform_get_drvdata(pdev); //if (switch_data != NULL) { // queue_delayed_work(switch_data->mywork_queue,&switch_data->hdmi_work,switch_data->delay_time); //} } static int switch_suspend(struct platform_device *pdev,pm_message_t state) { struct gpio_switch_data *switch_data = platform_get_drvdata(pdev); //cancel_delayed_work_sync(&switch_data->hdmi_work); //flush_workqueue(switch_data->mywork_queue); return 0; } static int __devexit gpio_switch_remove(struct platform_device *pdev) { struct gpio_switch_data *switch_data = platform_get_drvdata(pdev); //销毁工作队列 cancel_delayed_work_sync(&switch_data->hdmi_work); destroy_workqueue(switch_data->mywork_queue); gpio_free(switch_data->pio_hdle); switch_dev_unregister(&switch_data->sdev); kfree(switch_data); return 0; } static struct platform_driver gpio_switch_driver = { .probe = gpio_switch_probe, .remove = __exit_p(gpio_switch_remove), .driver = { .name = "switch-hdmi", .owner = THIS_MODULE, }, .suspend = switch_suspend, .resume = switch_resume, }; static struct gpio_switch_platform_data hdmiset_switch_data = { .name = "hdmi", }; static struct platform_device gpio_switch_device = { .name = "switch-hdmi", .dev = { .platform_data = &hdmiset_switch_data, } }; static int __init gpio_switch_init(void) { int ret = 0; ret = platform_device_register(&gpio_switch_device); if (ret == 0) { ret = platform_driver_register(&gpio_switch_driver); } return ret; } static void __exit gpio_switch_exit(void) { platform_driver_unregister(&gpio_switch_driver); platform_device_unregister(&gpio_switch_device); } module_init(gpio_switch_init); module_exit(gpio_switch_exit); MODULE_AUTHOR("liujun-style@foxmail.com>"); MODULE_DESCRIPTION("Switch driver"); MODULE_LICENSE("GPL");
相关文章推荐
- Android使用switch模块进行GPIO口检测(一)-->LINUX驱动部分
- Android drivers/switch驱动详解(用于通过GPIO状态检测耳机、HDMI等的插拔状态)
- Linux驱动编程 step-by-step (六) 用户地址检测 简单模块调试 以及一些杂项
- 基于linux2.6.30.4内核的DM9000网卡驱动编译成模块成功ping通
- 基于状态驱动的AOP技术在模块解耦中的应用
- 基于linux2.6.30.4内核的DM9000网卡驱动编译成模块成功ping通
- Linux驱动编程 step-by-step (六) 用户地址检测 简单模块调试 以及一些杂项
- 【转载】从 2.4 到 2.6:Linux 内核可装载模块机制的改变对设备驱动的影响
- 从 2.4 到 2.6:Linux 内核可装载模块机制的改变对设备驱动的影响
- 基于S3C2410平台的Linux 2.6.14内核+平台驱动的移植指南(最终版)
- 基于linux2.6.16的nand驱动开发(三)
- 基于S3C2410平台移植Linux 2.6.14内核&驱动指南
- SWFObject: 基于Javascript的Flash媒体版本检测与嵌入模块
- 基于linux2.6.16的nand驱动开发(一)
- 基于嵌入式linux的usb摄像头的驱动及采集程序的实现
- 基于S3C2410平台的LCD for Linux 2.6 驱动移植
- 从 2.4 到 2.6:Linux 内核可装载模块机制的改变对设备驱动的影响
- 《嵌入式设计及Linux驱动开发指南——基于ARM9处理器》读书笔记
- SWFObject: 基于Javascript的Flash媒体版本检测与嵌入模块
- SWFObject: 基于Javascript的Flash媒体版本检测与嵌入模块