您的位置:首页 > 运维架构 > Linux

输入服务子系统实例分析(韦东山的视频总结及针对linux-2.6.30.4)

2013-05-26 15:19 423 查看
根据韦东山视频讲解,和自己理解总结的:

1.分配一个input_dev结构体,

2.设置input_dev。

3.注册input_dev结构体。

4.硬件相关的操作。

/*参考/keyboard/corgikbd.c*/

static int __init corgikbd_init(void)

{


return platform_driver_register(&corgikbd_driver);

}



static struct platform_driver corgikbd_driver = {

.probe = corgikbd_probe,

.remove = __devexit_p(corgikbd_remove),

.suspend = corgikbd_suspend,

.resume = corgikbd_resume,

.driver = {

.name = "corgi-keyboard",

.owner = THIS_MODULE,

},

};



static int __devinit corgikbd_probe(struct platform_device *pdev)

{

struct corgikbd *corgikbd;

struct input_dev *input_dev;

int i, err = -ENOMEM;



corgikbd = kzalloc(sizeof(struct corgikbd), GFP_KERNEL);

/*1.分配一个input_dev结构*/

input_dev = input_allocate_device();

if (!corgikbd || !input_dev)

goto fail;

platform_set_drvdata(pdev, corgikbd); corgikbd->input = input_dev;

spin_lock_init(&corgikbd->lock);

/* Init Keyboard rescan timer */

init_timer(&corgikbd->timer);

corgikbd->timer.function = corgikbd_timer_callback;

corgikbd->timer.data = (unsigned long) corgikbd;

/* Init Hinge Timer */

init_timer(&corgikbd->htimer);

corgikbd->htimer.function = corgikbd_hinge_timer;

corgikbd->htimer.data = (unsigned long) corgikbd;

corgikbd->suspend_jiffies=jiffies; (corgikbd->keycode, corgikbd_keycode, sizeof(corgikbd->keycode));



input_dev->name = "Corgi Keyboard";

input_dev->phys = "corgikbd/input0";

input_dev->id.bustype = BUS_HOST;

input_dev->id.vendor = 0x0001;

input_dev->id.product = 0x0001;

input_dev->id.version = 0x0100;

input_dev->dev.parent = &pdev->dev;

/*2.设置input_dev*/


/*2.1设置能产生哪些事件 Event types

*EV_KEY 定义为#define EV_KEY 0x01

*能产生按键类事件

*EV_REP 重复,当按下,不松时能产生多个值

*/

input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) |

BIT_MASK(EV_PWR) | BIT_MASK(EV_SW);

input_dev->keycode = corgikbd->keycode;

input_dev->keycodesize = sizeof(unsigned char);

input_dev->keycodemax = ARRAY_SIZE(corgikbd_keycode);

/*2.2设置能产生这类事件的哪些事件*/

for (i = 0; i < ARRAY_SIZE(corgikbd_keycode); i++)

set_bit(corgikbd->keycode[i], input_dev->keybit);

clear_bit(0, input_dev->keybit);

set_bit(SW_LID, input_dev->swbit);

set_bit(SW_TABLET_MODE, input_dev->swbit);

set_bit(SW_HEADPHONE_INSERT, input_dev->swbit);

/*3.注册 input_dev */

err = input_register_device(corgikbd->input);

if (err)

goto fail;

mod_timer(&corgikbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));

/*4.硬件相关的操作*/

/* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */

for (i = 0; i < CORGI_KEY_SENSE_NUM; i++) {

pxa_gpio_mode(CORGI_GPIO_KEY_SENSE(i) | GPIO_IN);


/*注册中断*/

if (request_irq(CORGI_IRQ_GPIO_KEY_SENSE(i),corgikbd_interrupt,

IRQF_DISABLED | IRQF_TRIGGER_RISING,"corgikbd",corgikbd))

printk(KERN_WARNING "corgikbd:Can't get IRQ:%d!\n",i);

}

/* Set Strobe lines as outputs - set high */

for (i = 0; i < CORGI_KEY_STROBE_NUM; i++)

pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i)|GPIO_OUT|GPIO_DFLT_HIGH);

/* Setup the headphone jack as an input */

pxa_gpio_mode(CORGI_GPIO_AK_INT | GPIO_IN);

return 0;fail: input_free_device(input_dev);

kfree(corgikbd);

return err;

}



下面我们自己下符合输入子服务系统的程序

/*引脚描述结构体*/

struct pin_dec{

int irq;

char *name;

unsigned int pin;

unsigned int key_val;

};


/*定义的按键的四个引脚描述结构体数组*/

struct pin_dec pins_desc[4] = {

{IRQ_EINT1,"s1",S3C2410_GPF1, KEY_L},

{IRQ_EINT4,"s2",S3C2410_GPF4, KEY_S},

{IRQ_EINT2,"s3",S3C2410_GPF2, KEY_ENTER},

{IRQ_EINT0,"s4",S3C2410_GPF0, KEY_LEFTSHIFT},

};



/*定义一个定时器*/

static struct timer_list buttons_timer;



/*入口函数*/

static int buttons_init(void)

{

int i;

/*1.分配一个input_dev结构体*/

buttons_dev = input_allocate_device();

/*2.设置*/

/*2.1能产生的哪类事件*/

buttons_dev->evbit = BIT_MASK(EV_KEY)|BIT_MASK(EV_REP);

/*2.2能产生这类操作里的哪些事件*/

__set_bit(KEY_L,buttons_dev->keybit);

__set_bit(KEY_S,buttons_dev->keybit);

__set_bit(KEY_ENTER,buttons_dev->keybit);

__set_bit(KEY_LEFTSHIFT,buttons_dev->keybit);

/*3.注册*/

input_register_device(buttons_dev);

/*4.硬件相关的操作*/

init_timer(&buttons_timer); /*初始化定时器*/


[b]/*指定定时器中断的处理函数*/

buttons_timer.function = buttons_timer_function; [/b]

[b]/*增加一个定时器*/

add_timer(&buttons_timer);

for(i=0;i<4;i++){[/b]

/*注册中断*/

request_irq(pins_desc[i].irq,buttons_irq,
IRQ_TYPE_EDGE_BOTH,pins_desc[i].name,

&pins_desc[i]);

}

return 0;

}



static irqreturn_t buttons_irq(int irq, void *dev_id){

/*10ms后启动定时器,消抖*/

irq_pd = (struct pin_dec*)dev_id;


/*修改定时器*/

mod_timer(&buttons_timer,jiffies+HZ/100);

return IRQ_RETVAL(IRQ_HANDLED);

}



/*定时器的处理函数*/

static void buttons_timer_function(unsigned long data)

{

struct pin_dec*pindesc = irq_pd;

unsigned int pinval;

pinval = s3c2410_gpio_getpin(pindesc->pin);

if(pinval){


/*上报事件*/

/*也可以用input_report_key([b]buttons_dev,pindesc->key_val,0)*/[/b]

[b]/*松开时*/[/b]

input_event(buttons_dev,EV_KEY,pindesc->key_val,0);

input_sync(buttons_dev);

}

else

{


[b]/*按下时*/[/b]

[b]/*也可以用input_report_key(buttons_dev,pindesc->key_val,1)*/

input_event(buttons_dev,EV_KEY,pindesc->key_val,1);

input_sync(buttons_dev);

}

}

[/b]

/*出口函数*/

static void buttons_exit(void)

{

int i;

for(i=0;i<4;i++){


/*释放中断*/

free_irq(pins_desc[i].irq,&pins_desc[i]);

}


/*吊销定时器*/

del_timer(&buttons_timer);


/*注销注册的buttons_dev*/

input_unregister_device(buttons_dev);


/*释放掉buttons_dev占用的内存*/

input_free_device(buttons_dev);

}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐