Linux输入子系统(6):设备驱动层之LED驱动

input输入子系统不仅能够处理输入事件,也可以处理输出事件,处理输入事件最终会导致input_handler的event函数被调用,处理输出事件最终会导致input_dev的event的函数被调用。下面以通过输入子系统来控制led为例来说明。
注:内核:kernel-2.6.30.4 编译器:arm-linux-gcc 4.3.3 目标板:TQ2440
一、设备驱动层程序
#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/sysctl.h>
#include <linux/input.h>
#include <linux/gpio_keys.h>
#include <mach/regs-gpio.h>
#include <asm/gpio.h>
#include <linux/kernel.h>
#include <asm/uaccess.h>
#include <mach/hardware.h>
#include <linux/cdev.h>

static struct input_dev *input_led_dev;//输入设备
//这是重点,应用程序发过来的event事件最后会由该函数来进行处理
int input_led_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
  printk("tq2440 input_led_event!\n");
  if(type != EV_LED)
      return -1;
  //根据发过来的code和value值设置led的点灭
  switch(code)
  {
   case LED_NUML              :{s3c2410_gpio_setpin(S3C2410_GPB5,value?0:1); break;}
   case LED_CAPSL:{s3c2410_gpio_setpin(S3C2410_GPB6,value?0:1); break;}
   case LED_SCROLLL:{s3c2410_gpio_setpin(S3C2410_GPB7,value?0:1); break;}
   case LED_COMPOSE:{s3c2410_gpio_setpin(S3C2410_GPB8,value?0:1); break;} 
  }
}

static int input_led_init(void)
{
//1. 分配一个input_dev结构体 
input_led_dev = input_allocate_device();;
//2. 设置 
// 2.1 能产生哪类事件 
set_bit(EV_LED, input_led_dev->evbit);
//2.2 能产生这类操作里的哪些事件
set_bit(LED_NUML, input_led_dev->ledbit);
set_bit(LED_CAPSL, input_led_dev->ledbit);
set_bit(LED_SCROLLL, input_led_dev->ledbit);
set_bit(LED_COMPOSE, input_led_dev->ledbit);
//3. 注册 
input_led_dev->event=input_led_event;//指定input_dev的event项
input_register_device(input_led_dev);
printk("input_led_initsucceed!\n");
return 0;
}

static void input_led_exit(void)
{
input_unregister_device(input_led_dev);
input_free_device(input_led_dev);
printk("input_led_exit succeed!\n");
}

module_init(input_led_init);
module_exit(input_led_exit);
MODULE_LICENSE("GPL");
二、测试程序
#include<sys/types.h>
#include<unistd.h>
#include<fcntl.h>
#include<linux/rtc.h>
#include<linux/ioctl.h>
#include<stdio.h>
#include<stdlib.h>
#include<linux/input.h>
#include<signal.h>

int main(int argc,char *argv[])
{
 int fd = -1;
 if ((fd = open("/dev/event1", O_RDWR)) < 0)  //打开的event设备,根据实际情况调整
 {
  printf("evdev open error!\n");
  return -1;
 }
 if(argc!=3)
 {
  printf("the right Usage:input_led_test <num> <1:0>\n");
  return -1 ;
 }
 struct input_event event[4];
 event[0].type=EV_LED;
 event[0].code=LED_NUML;
 
 event[1].type=EV_LED;
 event[1].code=LED_CAPSL;
 
 event[2].type=EV_LED;
 event[2].code=LED_SCROLLL;
 
 event[3].type=EV_LED;
 event[3].code=LED_COMPOSE;

 switch(*(argv[1]+0)-'0') //根据程序输入的数据,给设备驱动层发event
 {
   case 1: 
   {
    event[0].value=*(argv[2]+0)-'0';
    write(fd,&event[0],sizeof(struct input_event));
    break;
   }
   case 2: 
   {
    event[1].value=*(argv[2]+0)-'0';
    write(fd,&event[1],sizeof(struct input_event));
    break;
   }
   case 3: 
   {
    event[2].value=*(argv[2]+0)-'0';
    write(fd,&event[2],sizeof(struct input_event));
    break;
   }
   case 4: 
   {
    event[3].value=*(argv[2]+0)-'0';
    write(fd,&event[3],sizeof(struct input_event));
    break;
   }
 }
 close(fd);
 return 0;
}
在开发板测试
#insmod input_led.ko
#./input_led_test   1 1(打开第一个led灯)
#./input_led_test   1 0(关闭第一个led灯)
#./input_led_test   2 1(打开第二个led灯)
#./input_led_test   2 0(关闭第二个led灯)
程序源代码连接:
http://pan.baidu.com/share/link?shareid=395783&uk=101680913

你可能感兴趣的:(input,led)