天天看点

tiny6410_按键驱动程序_轮询

key_drv_poll.c

#include <linux/init.h>			/* For __init/__exit/... */
#include <linux/kernel.h>		/* For printk/panic/... */
#include <linux/module.h>		/* For module specific items */
#include <linux/fs.h>			/* For file operations */
#include <linux/types.h>		/* For standard types (like size_t) */
#include <linux/errno.h>		/* For the -ENODEV/... values */
#include <linux/ioport.h>		/* For io-port access */
#include <linux/uaccess.h>		/* For copy_to_user/put_user/... */
#include <linux/io.h>			/* For inb/outb/.../ioremap/... */
#include <linux/device.h>		/* For class_create */



#define S3C6410_GPNCON_PA 	(0x7F008830)
#define S3C6410_GPNDAT_PA 	(0x7F008834)
#define S3C6410_GPNPUD_PA	(0x7F008838)
#define S3C6410_GPLCON0_PA	(0x7F008810)
#define S3C6410_GPLCON1_PA	(0x7F008814)
#define S3C6410_GPLDAT_PA  	(0x7F008818)
#define S3C6410_GPLPUD_PA  	(0x7F00881C)


static int major = 0;
static struct class* key_drv_poll_class;
static volatile unsigned long* gpncon  = NULL;
static volatile unsigned long* gpndat  = NULL;
static volatile unsigned long* gplcon0 = NULL;
static volatile unsigned long* gplcon1 = NULL;
static volatile unsigned long* gpldat  = NULL;


static int key_drv_poll_open(struct inode *inode, struct file *filp)
{
	/* set key(1~8) gpio pin = input */
	*gpncon &= ~((0x3<<0)|(0x3<<2)|(0x3<<4)|(0x3<<6)|(0x3<<8)|(0x3<<10)); /* set key1~key6 pin = input*/
	*gpncon |=  ((0x0<<0)|(0x0<<2)|(0x0<<4)|(0x0<<6)|(0x0<<8)|(0x0<<10)); /* GPN0~GPN5 */

	*gplcon1 &= ~((0xF<<12)|(0xF<<16)); /* set key7~key8 pin = input*/
	*gplcon1 |=  ((0x0<<12)|(0x0<<16)); /* GPL11~GPL12 */

	return 0;
}

static ssize_t key_drv_poll_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
{
	/* read key gpio pin status */
	unsigned char key_val_arr[8];

	key_val_arr[0] = (*gpndat&(0x1<<0)?1:0);
	key_val_arr[1] = (*gpndat&(0x1<<1)?1:0);
	key_val_arr[2] = (*gpndat&(0x1<<2)?1:0);
	key_val_arr[3] = (*gpndat&(0x1<<3)?1:0);
	key_val_arr[4] = (*gpndat&(0x1<<4)?1:0);
	key_val_arr[5] = (*gpndat&(0x1<<5)?1:0);
	key_val_arr[6] = (*gpldat&(0x1<<11)?1:0);
	key_val_arr[7] = (*gpldat&(0x1<<12)?1:0);

	copy_to_user(buf, key_val_arr, sizeof(key_val_arr));
	
	return sizeof(key_val_arr);
}

static int key_drv_poll_close(struct inode *inode, struct file *file)
{
	return 0;
}

static struct file_operations key_drv_poll = {
	.owner   = THIS_MODULE,
	.open    = key_drv_poll_open,
	.read    = key_drv_poll_read, 
	.release = key_drv_poll_close,
};

static int key_drv_poll_init(void)
{
	major = register_chrdev(0, "key_drv_poll", &key_drv_poll);
	if(major < 0)
	{
		printk(KERN_ALERT "Register key_driver_poll failed!\n");
		return -1;
	}

	printk(KERN_ALERT "Register key_driver_poll succeed!\n");
	
	/* 动态创建设备号,根据创建的设备号创建设备节点(/dev/key_drv_poll) */
	key_drv_poll_class= class_create(THIS_MODULE, "key_drv_poll"); /* sysfs */	
	device_create(key_drv_poll_class, NULL, MKDEV(major, 0), NULL, "key_drv_poll"); /* /dev/key_drv_poll */

	/* map key gpio config_register and data_register virtual address */
	gpncon = ioremap(S3C6410_GPNCON_PA, 4); /* key1~key6 */
	gpndat = ioremap(S3C6410_GPNDAT_PA, 4);

	gplcon0 = ioremap(S3C6410_GPLCON0_PA, 4); /* key7~key8 */
	gplcon1 = ioremap(S3C6410_GPLCON1_PA, 4); /* key7~key8 */
	gpldat  = ioremap(S3C6410_GPLDAT_PA, 4);
	
	return 0;
}

static void key_drv_poll_exit(void)
{
	device_destroy(key_drv_poll_class, MKDEV(major, 0));
	class_destroy(key_drv_poll_class);
	
	unregister_chrdev(major, "key_drv_poll");

	/* unmap key gpio virtual address */
	iounmap(gpncon);
	iounmap(gpndat);
	iounmap(gplcon0);
	iounmap(gplcon1);
	iounmap(gpldat);
	
	printk(KERN_ALERT "Unregister key_driver_poll succeed!\n");
}

module_init(key_drv_poll_init);
module_exit(key_drv_poll_exit);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("key driver use poll");
MODULE_AUTHOR("dl CS0921 WTU");

           

key_app_poll.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


#define DEVICE_NAME "/dev/key_drv_poll"


int main(int argc, char* argv[])
{
	int fd;
	fd = open(DEVICE_NAME, O_RDWR);
	if(fd < 0)
	{
		printf("Open %s failed!\n", DEVICE_NAME);
		exit(-1);
	}

	unsigned char key_val_arr[8];
	
	for( ; ; )
	{
			read(fd, key_val_arr, sizeof(key_val_arr));

			/* 如果有任意一个按键按下,就打印 */
			if(!key_val_arr[0] || !key_val_arr[1]|| !key_val_arr[2] || !key_val_arr[3] || \
				!key_val_arr[4] || !key_val_arr[5]|| !key_val_arr[6] || !key_val_arr[7]  )
			{
				printf("key(1~8) value: %d %d %d %d %d %d %d %d\n", \
					      key_val_arr[0], key_val_arr[1], key_val_arr[2], key_val_arr[3],\
					      key_val_arr[4], key_val_arr[5], key_val_arr[6], key_val_arr[7]);
			}
	}
	
	close(fd);
	
	return 0;
}


           

Makefile

KERNELDIR = /sdb/kernel/linux-2.6.38-tiny6410/linux-2.6.38/
PWD := $(shell pwd)

modules:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

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

.PHONY: modules  clean

obj-m := led_drv.o
           

结果

tiny6410_按键驱动程序_轮询

继续阅读