Linux红外遥控驱动HS0038
测试平台imx6q linux5.4.215
华为电信高清IPTV遥控器
使用其它遥控器可以更改key_table和user_id
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/sched.h>
#include <linux/pm.h>
#include <linux/slab.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/gpio_keys.h>
#include <linux/workqueue.h>
#include <linux/gpio.h>
#include <asm/io.h>
#include <linux/jiffies.h>
#include <asm/irq.h>#define DEVICE_DEBUG
//undefine DEVICE_DEBUGstruct key_table_t{unsigned char key_val;unsigned char key_code;unsigned char key_name[20];
};struct key_table_t key_table[]={{0xF2, KEY_POWER, "POWER" }, //1{0xDC, KEY_SLEEP, "SLEEP" },{0xF3, KEY_LEFTMETA, "TV+" },{0xF4, KEY_RIGHTMETA, "TV-" },{0xF1, KEY_MEDIA, "TV/IPTV" },{0x98, KEY_SOUND, "VOL CANCEL" }, //6{0x9C, KEY_MUTE, "MUTE" },{0x8D, KEY_SETUP, "SETUP" },{0xD6, KEY_ROTATE_DISPLAY, "ROTATE_DISPLAY"},{0x91, KEY_CHAT, "LOOK BACK" },{0xCD, KEY_LINEFEED, "LIVE" }, //11{0x83, KEY_PLAYCD, "Request Play" },{0xC3, KEY_HELP, "INFO/HELP" },{0x88, KEY_HOME, "DESKTOP" },{0x82, KEY_MENU, "MENU" },{0xCA, KEY_UP, "UP" }, //16 {0xD2, KEY_DOWN, "DOWN" },{0x99, KEY_LEFT, "LEFT" },{0xC1, KEY_RIGHT, "RIGHT" },{0xCE, KEY_ENTER, "ENTER" },{0x80, KEY_VOLUMEUP, "VOLUME+" }, //21{0x81, KEY_VOLUMEDOWN, "VOLUME-" },{0xDD, KEY_PAGEUP, "PAGE UP" },{0x8C, KEY_PAGEDOWN, "PAGE DOWN" },{0x85, KEY_LEFTSHIFT, "CHANEL+" },{0x86, KEY_RIGHTSHIFT, "CHANEL-" }, //26{0x92, KEY_1, "Num:1" },{0x93, KEY_2, "Num:2" },{0xCC, KEY_3, "Num:3" },{0x8E, KEY_4, "Num:4" },{0x8F, KEY_5, "Num:5" }, //31{0xC8, KEY_6, "Num:6" },{0x8A, KEY_7, "Num:7" },{0x8B, KEY_8, "Num:8" },{0xC4, KEY_9, "Num:9" },{0x87, KEY_0, "Num:0" }, //36{0xDA, KEY_SEARCH, "*" },{0xD0, KEY_INSERT, "#" },{0x95, KEY_PLAYPAUSE, "PLAY/PAUSE" },{0xC5, KEY_BACK, "BACK" },
};
#define KEY_NUM sizeof(key_table)/sizeof(key_table[0])struct ir_key_info_t{unsigned char user_id;unsigned int key_num;struct key_table_t *key_data;
};static struct ir_key_info_t ir_remote_keycode ={.user_id = 0xB2,.key_num = KEY_NUM,.key_data = key_table,
};struct remote_ctrl{struct input_dev *input;struct gpio_keys_button *button;unsigned int keycode[KEY_NUM];spinlock_t lock;struct work_struct work;
};
// IR timing
/* │ │ │ │ │ │* │ 9ms │ 4.5ms │ │560us│ 1690us │ │ 560us│ 560us│* │<-----1350us---->│ │<-------2250us------->│ │<--1120us--->│*¯¯¯│_________│¯¯¯¯¯¯¯│_..._│_____│¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯│_..._│______│¯¯¯¯¯¯│__...* │-----------------│-----│----------------------│ │-------------│----* │---IR start up---│ │ Logic:1 │ │ Logic:0 │*/static int __inline ir_bus_startup_timing(int pin){int i;i = 0;while(1){if( 0 == ( (gpio_get_value(pin)) & 1 ) ){udelay(900);if( i>9 )return -1;i++;} //wait bus release;elsebreak;}i = 0;while(1){//0 1 2 3 4if( 1 == ( (gpio_get_value(pin)) & 1 ) ){udelay(900);if(i>4) //5*900us + (program run time) > 4.5msreturn -1; //ir repect statusi++;}elsebreak; //ir nomoal status}return 0;
}static u32 __inline__ ir_bus_read_byte(struct remote_ctrl *hs0038)
{int j;//struct gpio_keys_button *button = hs0038->button;int ir_pin = hs0038->button->gpio;u32 tmp=0;for(j=1;j<=8;j++){ //每个字节8个bit的判断while( ((gpio_get_value(ir_pin)) & 1 ) ==0 ); //等待上升沿udelay(900);if(((gpio_get_value(ir_pin)) & 1) ==1 ){udelay(900);tmp=tmp|0x80;if(j<8) tmp=tmp>>1;}elseif(j<8)tmp=tmp>>1;//如果是"0",则向右移一位,自动补"0"}return tmp;
}
static unsigned int get_key_table_id(unsigned int kv)
{int id;for(id=0; id<KEY_NUM; id++){if(kv == key_table[id].key_val){if(KEY_NUM >= id)return id;}}return 0xFFFF;
}static int hs0038_read_data(struct remote_ctrl *hs0038)
{//struct gpio_keys_button *button;int ir_pin;u8 user_id,n_user_id = 0;u8 k_val,nk_val = 0;int id=0;ir_pin = hs0038->button->gpio;gpio_direction_input(ir_pin);if( 0 != ir_bus_startup_timing(ir_pin)){printk("unknow ir startup timing.\n");return -1;}user_id = ir_bus_read_byte(hs0038); //user id low byten_user_id= (ir_bus_read_byte(hs0038)); //user id high bytek_val = ir_bus_read_byte(hs0038); //user id low bytenk_val = (ir_bus_read_byte(hs0038)); //user id high byteif( k_val&nk_val || user_id&n_user_id){//dev_info(hs0038->input->dev, "ir dat check sum error.\n");printk("data error or repect operater.\n");}else{
#ifdef DEVICE_DEBUGprintk("hs0038 read-> [user id]:0x%2X, [~user id]:0x%2X, [kv]:0x%2X, [~kv]0x%2X.\n",user_id, n_user_id,k_val, nk_val);
#endif}id = get_key_table_id(k_val);switch (user_id){case 0xB2:input_report_key(hs0038->input,key_table[id].key_code, 1); //report pressinput_report_key(hs0038->input,key_table[id].key_code, 0); //report releaseinput_sync(hs0038->input);
#ifdef DEVICE_DEBUGprintk("val=0x%2X, code=0x%2X, remote name:%s.\n",key_table[id].key_val,key_table[id].key_code,key_table[id].key_name);
#endifbreak;default ://dev_info(hs0038->input->dev, "Unkonw ir remote button.\n");return -1;break;}return 0;
}void hs0038_do_work(struct work_struct *wk)
{
#if 0struct remote_ctrl *hs0038;hs0038 = container_of(wk, struct remote_ctrl, work);hs0038->button->irq = gpio_to_irq(hs0038->button->gpio);printk("do work\n");//hs0038_read(hs0038);irq_set_irq_type(hs0038->button->irq, IRQF_TRIGGER_FALLING);enable_irq(hs0038->button->irq);
#endifstruct remote_ctrl *hs0038;//struct gpio_keys_button *button; //int irq;hs0038 = container_of(wk, struct remote_ctrl, work);//button = hs0038->button; //irq = gpio_to_irq(button->gpio);hs0038_read_data(hs0038);//irq_set_irq_type(irq, IRQF_TRIGGER_FALLING);enable_irq(hs0038->button->irq);}static irqreturn_t hs0038_irq_handler(int irq, void *dev_id)
{struct remote_ctrl *hs0038 = dev_id;disable_irq_nosync(irq);schedule_work(&hs0038->work); //irq request function schedule, as follow INIT_WORKreturn IRQ_HANDLED;
}static int hs0038_gpio_init(struct platform_device *pdev)
{struct remote_ctrl *hs0038;struct gpio_keys_button *button;const char *desc; //description infoint ret;hs0038 = platform_get_drvdata(pdev);button = hs0038->button;desc = button->desc ? button->desc : "HS0038 IR Remote"; //if unset decription inforet = gpio_request_one(button->gpio, GPIOF_IN, desc);if (ret < 0) {dev_err(&pdev->dev, "Failed to request GPIO %d, error %d\n",button->gpio, ret);return ret;}ret = gpio_to_irq( button->gpio ); //gpio pin config as irq inputif (ret < 0){dev_err(&pdev->dev, "Unable to get irq id for GPIO %d,error %d\n",button->gpio, ret);goto fail;}else{hs0038->button->irq = ret;dev_info(&pdev->dev, "irq:%d.\n", hs0038->button->irq);}ret = request_irq( hs0038->button->irq, //irq idhs0038_irq_handler, //irq handler functionIRQF_TRIGGER_FALLING, //irq modehs0038->input->name, //device namehs0038 ); //dev id/priv dataif (ret){dev_err(&pdev->dev, "Unable to claim irq %d; error %d\n", hs0038->button->irq, ret);goto fail;}ret = gpio_direction_input(button->gpio);if (ret < 0){dev_err(&pdev->dev, "Failed to configure direction for GPIO %d , error %d\n",button->gpio, ret);goto fail;}return 0;fail:gpio_free(button->gpio);return ret;
}
#define IMX_GPIO_NR(bank, nr) (((bank) - 1) * 32 + (nr))
static int hs0038_probe(struct platform_device *pdev)
{int ret=0, i=0;struct device *dev = &pdev->dev;struct remote_ctrl *hs0038=NULL;dev_info(dev, "Remote cotrol probe.\n");hs0038 = kzalloc(sizeof(struct remote_ctrl),GFP_KERNEL);hs0038 ->button = kzalloc(sizeof(struct gpio_keys_button),GFP_KERNEL);platform_set_drvdata(pdev, hs0038);hs0038->input = input_allocate_device();if (!hs0038->input || !hs0038){dev_err(dev, "Failed to allocate state\n");ret= -ENOMEM;goto err_free_mem;}hs0038->input->name = "HS0038 IR Remote control";hs0038->input->phys = "hs0038/input1";hs0038->input->id.bustype = BUS_HOST;hs0038->input->id.vendor = 0xabce;hs0038->input->id.product = 0xecba;hs0038->input->id.version = 0x0100;hs0038->input->evbit[0] = BIT(EV_KEY);hs0038->input->keycode = hs0038->keycode;hs0038->input->keycodesize = sizeof(unsigned int);hs0038->input->keycodemax = KEY_NUM;set_bit(EV_KEY, hs0038->input->evbit);for (i = 0; i < KEY_NUM; i++){hs0038->keycode[i]= ir_remote_keycode.key_data[i].key_code;set_bit(hs0038->keycode[i], hs0038->input->keybit);}INIT_WORK(&hs0038->work, hs0038_do_work); //dcspin_lock_init(&hs0038->lock);hs0038->button->gpio = IMX_GPIO_NR(1, 6);hs0038->button->desc = "HS0038 IR Remote";ret=hs0038_gpio_init(pdev);if(ret)goto err_gpio_free;ret = input_register_device(hs0038->input);if (ret < 0){dev_err(dev,"probe input device register failed.\n");goto err_input_free;}return 0;err_input_free:input_free_device(hs0038->input);err_gpio_free:gpio_free(hs0038->button->gpio);err_free_mem:kfree(hs0038->input);kfree(hs0038->button);kfree(hs0038);return ret;
}
static int hs0038_remove(struct platform_device *pdev)
{struct device *dev = &pdev->dev;struct remote_ctrl *hs0038;hs0038 = platform_get_drvdata(pdev);dev_info(dev, "Remote cotrol remove.\n");input_unregister_device(hs0038->input);//input_free_device(hs0038->input);free_irq(hs0038->button->irq, hs0038);gpio_free(hs0038->button->gpio);kfree(hs0038->input);kfree(hs0038->button);kfree(hs0038);return 0;
}static const struct of_device_id hs0038_of_match[] = {{ .compatible = "hs0038", },{ },
};static struct platform_driver hs0038_driver = {.probe = hs0038_probe,.remove = hs0038_remove,.driver = {.name = "IR Remote",.owner = THIS_MODULE,.of_match_table = of_match_ptr(hs0038_of_match),},
};
static int __init hs0038_init(void)
{return platform_driver_register(&hs0038_driver);
}static void __exit hs0038_exit(void)
{platform_driver_unregister(&hs0038_driver);
}module_init(hs0038_init);
module_exit(hs0038_exit);MODULE_AUTHOR("YuanBin");
MODULE_DESCRIPTION("GPIO IR Remote Driver");
MODULE_LICENSE("GPL");
Linux红外遥控驱动HS0038相关推荐
- 移动咪咕盒子红外遥控驱动
最近入手了一块显示屏,又惊喜的发现移动咪咕盒子一直落灰,(反正盒子没破解也不能看电视),那给我的讯为4412开发板刷个安卓系统,写个红外遥控驱动烧进去,这样就能用咪咕盒子的遥控器看电视了.说干就干,开 ...
- android红外遥控驱动
在 Linux 内核中,IR 驱动仅支持 NEC 编码格式. 设备树文件 pwm0: pwm@ff680000 {compatible = "rockchip,rk-pwm";re ...
- 嵌入式Linux红外遥控,树莓派红外遥控 (lirc、gpio-ir)—— 一篇就够了!
超简单!树莓派红外遥控配置 前言 第一步:驱动配置(/boot/config.txt) 第二步:安装lirc,并配置 第三步:测试 第四步:按键配置(/etc/lirc/lircd.conf) 第五步 ...
- 嵌入式Linux红外遥控,一个简单的IAL分析(红外遥控)(转)
简单的IAL分析 一.程序说明 1.下面程序是基于一个红外的设备文件,从该设备中能接收到红外遥控的硬件编码. 2.两个文件需要覆盖掉libmingiui*/src/ial/中的两个文件编译时加上 -- ...
- linux红外遥控进程,46.Linux-分析rc红外遥控平台驱动框架,修改内核的NEC解码函数BUG(1)...
内核版本 : Linux 3.10.14 rc红外接收类型: GPIO 类型的NEC红外编码 本章内容 1)rc体系结构分析 2) 分析红外platform_driver平台驱动框 ...
- linux 怎么往内核加驱动,向Linux内核添加驱动
Linux内核中提供了很多设备的驱动代码,但每个项目中总会需要添加我们自己的驱动,比如我们需要添加红外遥控驱动.我们可以先独立去编写和调试这个驱动,等成熟后应该放到内核目录树中,使用make modu ...
- linux树莓派网易云音乐,基于树莓派的红外遥控版网易云音乐播放器
基于树莓派的红外遥控版网易云音乐播放器.下面是遥控键盘示意图: CH- CH CH+ << >> || - + EQ 0 100+ 200+ 1 2 3 4 5 6 7 8 9 ...
- 搭建红外遥控arm-hadoop集群过程
很多人玩开发板用树莓派,树莓派的确很好,但是对于hadoop来说,内存有点小,只有512MB.所以我找了一圈,最后用的是国内一个开源硬件团队的产品叫CubieTruck.内存有2G,板载存储有8G,千 ...
- 遥控窗帘c语言程序,使用AT89C2051的红外遥控窗帘
本文介绍一款使用微电脑管理的.红外遥控器控制的多功能窗帘控制器.该窗帘控制器采用89C2051单片机的最小系统设计,控制一个220V的可逆.变速电动机控制窗帘的拉开和关闭.窗帘控制器可以使用红外遥控器 ...
最新文章
- centos ezhttp mysql_CentOS安装mysq
- AlphaCode惊世登场!编程版“阿法狗”悄悄参赛,击败一半程序员
- Nginx配置与使用
- MySQL AS:设置别名
- LVS NAT/DR
- 前端学习(2761):uni-app样式的学习
- rman 备份后恢复整个数据库文件的操作
- java获取当前时间星期几_java怎么获取当前日期是星期几
- linux网络命令详解
- Python字符串index()方法应用案例一则
- #动态规划 LeetCode 120 三角形最小路径和
- 从架构设计到系统实施-基于.NET 3.0的全新企业应用之基于WCF的系统服务
- matlab自动交易系统 浏览
- 修改tomcat版本号解决eclipse中tomcat版本不对应
- html文件转为其他格式文件格式,HTML文件转Word文件格式
- 工程制图与计算机绘图试卷A,工程制图与计算机绘图第4章
- C语言-打印菱形三角形等图形
- Python基础知识-pycharm版 第3节
- python 桑基图_3行代码基于python的matplotlib绘制桑基图
- Linux的时间和时区设置