Lab environment:1) ubuntu9.10 OS
2) arm-Linux-GCC 4.3.2 Cross Compiler
3) diligent development board of S3C2440 (Linux kernel 2.6.29)
Implemented functions:The keyboard driver reports the key event to the upper-layer application through the input subsystem, and the application prints the corresponding key event
For more information about the input subsystem, see the blog 《Input subsystem for Linux device models"
Http://blogold.chinaunix.net/u1/51562/showart_1090628.html
Not much nonsense, with the source code included:
1) source code of the S3C2440 keyboard driver, refer to the implementation of the touch screen driver s3c2410_ts.c in 2.6.29 Kernel
/* <Br/> * copyright (c) 2011 Shen Yunlong <br/> * syl272365943@126.com <br/> * this program is free software; you can redistribute it and/or modify it <br/> * under the terms of the GNU General Public License version 2 as published by <br/> * the Free Software Foundation. <br/> */<br/> # include <Linux/kernel. h> <br/> # include <Linux/module. h> <br/> # include <Linux/input. h> <br/> # include <Lin UX/errno. h> <br/> # include <Linux/IRQ. h> <br/> # include <ASM/Io. h> <br/> # include <Mach/regs-gpio.h> <br/> # include <Mach/irqs. h> <br/> # include <Linux/interrupt. h> <br/> # include <Linux/irqreturn. h> <br/> # include <Mach/regs-irq.h> <br/> # include <Linux/bitops. h> <br/> module_license ("GPL"); <br/> module_author ("syl_usst"); <br/> static struct input_dev * dev; <br/> static char * s3c2440_keyboard_name = "initi24 40_keyboard_syl "; <br/>/** <br/> * Set gpf0, gpf1, gpf2, gpf3 ports used as Eint [0], Eint [1], eint [2], Eint [3] <br/> * Set gpg0, gpg1 used as Eint [8], eint [9] <br/> */<br/> static inline void s3c2440_keyboard_connect (void) <br/>{< br/> s3c2410_gpio_cfgpin (s3c2410_gpf0, s3c2410_gpf0_eint0 ); <br/> s3c2410_gpio_cfgpin (s3c2410_gpf1, s3c2410_gpf1_eint1); <br/> s3c2410_gpio_cfgpin (s3c2410_gpf2, s3c2410_gpf2_eint2); <Br/> s3c2410_gpio_cfgpin (s3c2410_gpf3, expires); <br/> s3c2410_gpio_cfgpin (s3c2410_gpg0, expires); <br/> s3c2410_gpio_cfgpin (s3c2410_gpg1, expires ); <br/>}< br/>/** <br/> * interrupt handlers of Eint [0] ~ Eint [3] & Eint [8] & Eint [9] <br/> * Note: Once the ISR has reported a key with a specified value, <br/> * then the next time it (the key with the same value) will be 'filtered '. <br/> * it means that the program in user-space can not get the input_event from the kernel. <br/> */<br/> static irqreturn_t keyboard_sw1_action (int irq, void * dev_id) <br/>{< br/> // printk (kern_info "SW1 is pressed! /N "); <br/> unsigned int updown = ioread32 (s3c2410_gpfdat) & 0x1; <br/> If (updown) <br/>/* The Key btn_0 is raised */<br/> input_report_key (Dev, btn_0, 0 ); <br/> else <br/>/* The Key btn_0 is pressed */<br/> input_report_key (Dev, btn_0, 1); <br/> input_sync (Dev ); </P> <p> return irq_handled; <br/>}< br/> static irqreturn_t keyboard_sw2_action (int irq, void * dev_id) <br/> {<br/> // printk (kern_info "sw2 is pre Ssed! /N "); <br/> unsigned int updown = ioread32 (s3c2410_gpfdat) & (0x1 <1); <br/> If (updown) <br/> input_report_key (Dev, btn_1, 0); <br/> else <br/> input_report_key (Dev, btn_1, 1); <br/> input_sync (Dev ); <br/> return irq_handled; <br/>}< br/> static irqreturn_t keyboard_up_action (int irq, void * dev_id) <br/> {<br/> // printk (kern_info "Up is pressed! /N "); <br/> unsigned int updown = ioread32 (s3c2410_gpfdat) & (0x1 <2); <br/> If (updown) <br/> input_report_key (Dev, btn_2, 0); <br/> else <br/> input_report_key (Dev, btn_2, 1); <br/> input_sync (Dev ); <br/> return irq_handled; <br/>}< br/> static irqreturn_t keyboard_down_action (int irq, void * dev_id) <br/>{< br/> // printk (kern_info "down is pressed! /N "); <br/> unsigned int updown = ioread32 (s3c2410_gpfdat) & (0x1 <3); </P> <p> If (updown) <br/> input_report_key (Dev, btn_3, 0); <br/> else <br/> input_report_key (Dev, btn_3, 1); <br/> input_sync (Dev ); <br/> return irq_handled; <br/>}< br/> static irqreturn_t keyboard_left_action (int irq, void * dev_id) <br/>{< br/> // printk (kern_info "Left is pressed! /N "); <br/> unsigned int updown = ioread32 (s3c2410_gpgdat) & 0x1; <br/> If (updown) <br/> input_report_key (Dev, btn_4, 0); <br/> else <br/> input_report_key (Dev, btn_4, 1); <br/> input_sync (Dev); <br/> return irq_handled; <br/>}< br/> static irqreturn_t keyboard_right_action (int irq, void * dev_id) <br/>{< br/> // printk (kern_info "right is pressed! /N "); <br/> unsigned int updown = ioread32 (s3c2410_gpgdat) & (0x1 <1); <br/> If (updown) <br/> input_report_key (Dev, btn_5, 0); <br/> else <br/> input_report_key (Dev, btn_5, 1); <br/> input_sync (Dev ); <br/> return irq_handled; <br/>}< br/>/** <br/> * S3C2440 my_keyboard module initialization <br/> */<br/> static int _ init s3c2440_keyboard_init (void) <br/> {<br/> printk ("S3C2440 my_keyboard module start/N "); <Br/> struct input_dev * input_dev; <br/>/* configure S3C2440 gpios */<br/> s3c2440_keyboard_connect (); <br/> printk ("gpio has configured/N"); <br/>/* Set eint0 ~ Eint3 and eint8, eint9 rising edge triggered */<br/> set_irq_type (temperature, temperature); <br/> set_irq_type (irq_eint1, temperature); <br/> set_irq_type, temperature, struct); <br/> set_irq_type (irq_eint3, struct); <br/> set_irq_type (irq_eint8, struct); <br/> set_irq_type (irq_eint9, struct ); <br/> input_dev = input_allocate_device (); <br/> If (! Input_dev) <br/>{< br/> printk (kern_err "unable to allocate the input device !! /N "); <br/> return-enomem; <br/>}< br/> Dev = input_dev; <br/> Dev-> evbit [0] = bit (ev_syn) | bit (ev_key ); <br/>/* do not forget to set keybit [] of BTN_0--BTN_5 */<br/> Dev-> keybit [bit_word (btn_0)] = bit_mask (btn_0) | bit_mask (btn_1) | bit_mask (btn_2) | bit_mask (btn_3) | bit_mask (btn_4) | bit_mask (btn_5); <br/> Dev-> name = maid; <br/> // Dev-> ID. bustype <br/> // Dev-> ID. vendor <br/> // Dev-> I D. product <br/> // Dev-> ID. version <br/> printk ("input device has allocated/N "); <br/>/* register an interrupt handler to irq_eint0 */<br/> If (request_irq (irq_eint0, keyboard_sw1_action, expires, "s3c2440_keyboard_action", Dev )) <br/>{< br/> printk (kern_err "my_keyboard.c: cocould not allocate keyboard irq_eint0! /N "); <br/> return-EIO; <br/>}< br/> If (request_irq (irq_eint1, keyboard_sw2_action, ir1_sample_random," s3c2440_keyboard_action ", Dev )) <br/>{< br/> printk (kern_err "my_keyboard.c: cocould not allocate keyboard irq_eint1! /N "); <br/> return-EIO; <br/>}< br/> If (request_irq (irq_eint2, keyboard_up_action, ir1__sample_random," s3c2440_keyboard_action ", Dev )) <br/>{< br/> printk (kern_err "my_keyboard.c: cocould not allocate keyboard irq_eint2! /N "); <br/> return-EIO; <br/>}< br/> If (request_irq (irq_eint3, keyboard_down_action, ir1__sample_random," s3c2440_keyboard_action ", Dev )) <br/>{< br/> printk (kern_err "my_keyboard.c: cocould not allocate keyboard irq_eint3! /N "); <br/> return-EIO; <br/>}< br/> If (request_irq (irq_eint8, keyboard_left_action, irqf_sample_random," s3c2440_keyboard_action ", Dev )) <br/>{< br/> printk (kern_err "my_keyboard.c: cocould not allocate keyboard irq_eint8! /N "); <br/> return-EIO; <br/>}< br/> If (request_irq (irq_eint9, keyboard_right_action, irqf_sample_random," s3c2440_keyboard_action ", Dev )) <br/>{< br/> printk (kern_err "my_keyboard.c: cocould not allocate keyboard irq_eint9! /N "); <br/> return-EIO; <br/>}< br/> printk (kern_info" % s successfully loaded/N ", s3c2440_keyboard_name ); <br/> input_register_device (Dev); <br/> return 0; <br/>}< br/>/** <br/> * S3C2440 my_keyboard module exit function <br/> */<br/> static void _ exit s3c2440_keyboard_exit (void) <br/>{< br/> disable_irq (irq_eint0); <br/> disable_irq (irq_eint1); <br/> disable_irq (irq_eint2 ); <br/> disable_irq (irq_eint3); <br/> disable_irq (irq_eint8); <br/> disable_irq (irq_eint9); <br/> free_irq (Dev ); <br/> free_irq (irq_eint1, Dev); <br/> free_irq (irq_eint2, Dev); <br/> free_irq (irq_eint3, Dev ); <br/> free_irq (irq_eint8, Dev); <br/> free_irq (irq_eint9, Dev); <br/> input_unregister_device (Dev ); <br/>}< br/> module_init (s3c2440_keyboard_init); <br/> module_exit (s3c2440_keyboard_exit); <br/>
2) A simple upper-layer application reads the device files corresponding to the keyboard to print the keyboard events reported by the input subsystem.
/* <Br/> * copyright (c) 2011 Shen Yunlong <br/> * syl272365943@126.com <br/> * this program is free software; you can redistribute it and/or modify it <br/> * under the terms of the GNU General Public License version 2 as published by <br/> * the Free Software Foundation. <br/> */<br/> # include <stdio. h> <br/> # include <unistd. h> <br/> # include <fcntl. h> <br/> # include <sys/types. h> <br/> # include <sys/STAT. h> <br/> # include <sys/select. h> <br/> # include <sys/time. h> <br/> # include <Linux/input. h> <br/> # define my_debug 0 <br/> int main () <br/> {<br/> char * Dev = "/dev/event1 "; <br/> struct input_event ievent; <br/> int retval; <br/> unsigned short type; <br/> unsigned short code; <br/> int value; <br/> int FD = open (Dev, o_rdwr | o_nonblock); <br/> If (FD <0) {<br/> printf ("Open File % s failed/N", Dev); <br/> return-1; <br/>}< br/> while (1) <br/>{< br/> retval = read (FD, & ievent, sizeof (struct input_event )); <br/> If (retval> 0) <br/>{< br/> type = ievent. type; <br/> code = ievent. code; <br/> value = ievent. value; </P> <p> # If my_debug <br/> printf ("% d/N", type, code, value ); <br/> # endif </P> <p> If (type = ev_key) <br/> {<br/> switch (CODE) <br/>{< br/> case btn_0: If (value = 1) printf ("SW1 is pressed/N"); break; <br/> case btn_1: if (value = 1) printf ("sw2 is pressed/N"); break; <br/> case btn_2: If (value = 1) printf ("Up is pressed/N"); break; <br/> case btn_3: If (value = 1) printf ("down is pressed/N"); break; <br/> case btn_4: If (value = 1) printf ("Left is pressed/N"); break; <br/> case btn_5: if (value = 1) printf ("right is pressed/N"); break; <br/>}< br/> close (FD); <br/> return 0; <br/>}
The above code is successfully tested on the Development Board of qinyan 2440!
This is my first Linux device driver. I'm so excited that I am sure there will be deficiencies or even errors in the above content. I hope you will not be able to give me any questions about the children's shoes you are interested in.