linux按键驱动视频教程,linux 按键驱动

源代码文件

#include

#include

#include

#include

#include

#include

#if !defined(CONFIG_TANGOX)

#error "Unsupport architecture (TANGOX only)."

#elif defined(CONFIG_TANGO2_SMP863X) && (EM86XX_REVISION < 4)

#error "Unsupport Tango2 (ES4 or above) or Tango3 chip."

#endif

#include

// For poll and select.

#include

#include

#include

#ifdef CONFIG_TANGO2

#include

#elif defined(CONFIG_TANGO3)

#include

#endif

MODULE_DESCRIPTION ( "EM86xx/SMP86xx tamedia front key driver\n" ) ;

MODULE_AUTHOR ( "rui" ) ;

MODULE_LICENSE ( "GPL" ) ;

#define TAKEY_BUF_MAXCOUNT 8

#define KEY_X1 9

#define KEY_X2 10

#define KEY_X3 11

#define KEY_Y1 13

#define KEY_Y2 14

#define KEY_Y3 15

#define KEY_Y4 6

#define TAKEY_DEV_NAME "takey"

static int major = 222 ;

module_param( major, int, 0 ) ;

struct timer_list takey_timer ;

int takey_delay = 50 * HZ / 1000 ;  // 50ms

unsigned char char_buffer[8] = { 0, } ;

unsigned char key_count ;

unsigned char head ;

unsigned char tail ;

struct semaphore sem ;

spinlock_t lock ;

static int takey_open( struct inode *, struct file * ) ;

static int takey_release( struct inode *, struct file * ) ;

static int takey_read( struct file *, char *, size_t, loff_t * ) ;

static int takey_write( struct file *, const char *, size_t, loff_t * ) ;

static unsigned int takey_poll( struct file *, struct poll_table_struct * ) ;

static struct file_operations takey_fops =

{

.owner = THIS_MODULE,

.open = takey_open,

.read = takey_read,

.write = takey_write,

.poll = takey_poll,

.release = takey_release,

};

DECLARE_WAIT_QUEUE_HEAD( takey_wait_queue ) ;

static void initStatus( void )

{

em86xx_gpio_setdirection( KEY_X1, GPIO_OUTPUT ) ;

em86xx_gpio_write( KEY_X1, 1 ) ;

em86xx_gpio_setdirection( KEY_X1, GPIO_INPUT) ;

em86xx_gpio_setdirection( KEY_X2, GPIO_OUTPUT ) ;

em86xx_gpio_write( KEY_X2, 1 ) ;

em86xx_gpio_setdirection( KEY_X2, GPIO_INPUT) ;

em86xx_gpio_setdirection( KEY_X3, GPIO_OUTPUT ) ;

em86xx_gpio_write( KEY_X3, 1 ) ;

em86xx_gpio_setdirection( KEY_X3, GPIO_INPUT) ;

em86xx_gpio_setdirection( KEY_Y1, GPIO_OUTPUT ) ;

em86xx_gpio_write( KEY_Y1, 1 ) ;

em86xx_gpio_setdirection( KEY_Y2, GPIO_OUTPUT ) ;

em86xx_gpio_write( KEY_Y2, 1 ) ;

em86xx_gpio_setdirection( KEY_Y3, GPIO_OUTPUT ) ;

em86xx_gpio_write( KEY_Y3, 1 ) ;

em86xx_uart1_gpio_setdirection( KEY_Y4, GPIO_OUTPUT ) ;

em86xx_uart1_gpio_write( KEY_Y4, 1 ) ;

}

static int setData( const int key, const int data )

{

if ( em86xx_gpio_read( key ) == 0 )

{

while (  em86xx_gpio_read( key ) == 0 ) ;

if ( key_count < TAKEY_BUF_MAXCOUNT)

{

char_buffer[ tail++ ] = data ;

if ( tail >= TAKEY_BUF_MAXCOUNT )

{

tail = 0 ;

}

key_count++ ;

}

wake_up_interruptible( &takey_wait_queue ) ;

mod_timer( &takey_timer,  jiffies + takey_delay ) ;

return 1 ;

}

return 0 ;

}

static void takey_timerhandle( void )

{

spin_lock( lock ) ;

initStatus() ;

// KEY_Y1

em86xx_gpio_write( KEY_Y1, 0 ) ;

if ( setData( KEY_X1, 1 ) == 1 )

{

return ;

}

if ( setData( KEY_X2, 5 ) == 1 )

{

return ;

}

if ( setData( KEY_X3, 9 ) == 1 )

{

return ;

}

// KEY_Y2

em86xx_gpio_write( KEY_Y2, 0 ) ;

if ( setData( KEY_X1, 2 ) == 1 )

{

return ;

}

if ( setData( KEY_X2, 6 ) == 1 )

{

return ;

}

if ( setData( KEY_X3, 10 ) == 1 )

{

return ;

}

// KEY_Y3

em86xx_gpio_write( KEY_Y3, 0 ) ;

if ( setData( KEY_X1, 3 ) == 1 )

{

return ;

}

if ( setData( KEY_X2, 7 ) == 1 )

{

return ;

}

if ( setData( KEY_X3, 11 ) == 1 )

{

return ;

}

// KEY_Y4

em86xx_uart1_gpio_write( KEY_Y4, 0 ) ;

if ( setData( KEY_X1, 4 ) == 1 )

{

return ;

}

if ( setData( KEY_X2, 8 ) == 1 )

{

return ;

}

if ( setData( KEY_X3, 12 ) == 1 )

{

return ;

}

spin_unlock( lock ) ;

mod_timer( &takey_timer,  jiffies + takey_delay ) ;

}

static int takey_open( struct inode *inode_ptr,  struct file *filep )

{

key_count = 0 ;

filep->f_op = &takey_fops ;

return 0;

}

static int takey_release( struct inode *inode_ptr, struct file *filep )

{

return 0;

}

static int takey_read( struct file *filep, char *buffer, size_t count, loff_t * fp )

{

char data[1] = { 0, } ;

down( &sem ) ;

// Do nothing if the buffer is empty.

if ( key_count == 0 )

{

up( &sem ) ;

return 0 ;

}

data[0] = char_buffer[head] ;

if ( copy_to_user( buffer, (char*)data, 1 ) )

{

up( &sem ) ;

return -EFAULT ;

}

head++ ;

if ( head >= TAKEY_BUF_MAXCOUNT )

{

head = 0 ;

}

key_count-- ;

up( &sem ) ;

return 1;

}

static int takey_write( struct file *filep, const char *buffer, size_t size, loff_t * fp )

{

unsigned char nkey ;

down( &sem ) ;

if ( key_count >= TAKEY_BUF_MAXCOUNT )

{

up( &sem ) ;

return 0 ;

}

if ( copy_from_user( &nkey, buffer, 1 ) )

{

up( &sem ) ;

return -EFAULT ;

}

if ( nkey < 1 || nkey > 12 )

{

up( &sem ) ;

return 0;

}

if ( key_count < TAKEY_BUF_MAXCOUNT )

{

char_buffer[tail++] = nkey;

if ( tail >= TAKEY_BUF_MAXCOUNT )

{

tail = 0;

}

key_count++;

wake_up_interruptible( &takey_wait_queue ) ;

}

up( &sem ) ;

return 1;

}

static unsigned int takey_poll( struct file *filep, struct poll_table_struct *ptable )

{

unsigned int mask = 0;

down( &sem ) ;

poll_wait( filep, &takey_wait_queue, ptable ) ;

if ( key_count != 0 )

{

mask |= ( POLLIN | POLLRDNORM ) ;

}

up( &sem ) ;

return mask;

}

static int takey_init( void )

{

int result = 0 ;

spin_lock_init( &lock ) ;

init_MUTEX( &sem ) ;

result = register_chrdev( major, TAKEY_DEV_NAME, &takey_fops ) ;

if ( result < 0 )

{

printk ( "register_chrdev takey failed.\n" ) ;

return result ;

}

init_timer( &takey_timer ) ;

takey_timer.expires = jiffies + takey_delay ;

takey_timer.function = (void *) takey_timerhandle ;

add_timer( &takey_timer ) ;

return 0;

}

static void takey_exit( void )

{

del_timer( &takey_timer ) ;

unregister_chrdev( major, TAKEY_DEV_NAME ) ;

spin_unlock( lock ) ;

}

module_init( takey_init ) ;

module_exit( takey_exit ) ;

makefile

kerdir=/root/8655/smp86xx_kernel_source_R2.6.22-19/linux-2.6.22.19/

obj-m := takey.o

modules:

$(MAKE) -C $(kerdir) M=$(shell pwd) modules

clean:

rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions

测试程序

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

int main( void )

{

int fd ;

struct pollfd Events[1] ;

int ret ;

char buff[2] = { 0, } ;

fd = open( "/dev/takey", O_RDWR | O_NOCTTY ) ;

memset( Events, 0, sizeof( Events ) ) ;

Events[0].fd = fd ;

Events[0].events = POLLIN | POLLERR ;

while ( 1 )

{

ret = poll( (struct pollfd*)&Events, 1, 5000 ) ;

if ( ret < 0 )

{

printf( "poll error .\n" ) ;

return EXIT_FAILURE ;

}

if ( ret == 0 )

{

printf( "5 seconds no data .\n" ) ;

continue ;

}

if ( Events[0].revents & POLLERR )

{

printf( "device error .\n" )  ;

return EXIT_FAILURE ;

}

if ( Events[0].revents & POLLIN )

{

memset( buff, 0, sizeof buff ) ;

read( fd, buff, 1 ) ;

printf( "data : %d\n", buff[0] ) ;

}

}

close( fd ) ;

return EXIT_SUCCESS ;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值