key44driver
时间:2009-08-19 来源:sure_priterand
//==================key44driver.c==============================================
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h> /* printk() */
#include <linux/init.h> /* __init __exit */
#include <linux/types.h> /* size_t */
#include <linux/fs.h> /* file_operation */
#include <linux/errno.h> /* Error number */
#include <linux/delay.h> /* udelay */
#include <asm/uaccess.h> /* copy_to_user, copy_from_user */
#include <asm/hardware.h>
#include <asm/semaphore.h>
#include <linux/timer.h>
#include <linux/spinlock.h>
#include <linux/kfifo.h>
#include <asm/irq.h>
#define DRIVER_NAME "key44Driver"
#ifdef DEBUG
#define PRINTK(fmt, arg...) printk(KERN_NOTICE fmt, ##arg)
#else
#define PRINTK(fmt, arg...)
#endif
struct timer_list myTimer;
static int key44Driver_Major = 0; /* Driver Major Number */
struct semaphore bufflock;
/* Vitual Driver Buffer */
static spinlock_t buffer_lock = SPIN_LOCK_UNLOCKED;
static struct kfifo *buffer;
char key_old[2] = {'0','0'};
#define BUFFER_SIZE 256
/* Driver Operation Functions */
static int key44Driver_open(struct inode *inode, struct file *filp)
{
MOD_INC_USE_COUNT;
PRINTK("key44Driver open called!\n");
enable_irq(IRQ_EINT0);
enable_irq(IRQ_EINT1);
enable_irq(IRQ_EINT2);
enable_irq(IRQ_EINT3);
sema_init(&bufflock, 0);
return 0;
}
static int key44Driver_release(struct inode *inode, struct file *filp)
{
MOD_DEC_USE_COUNT;
disable_irq(IRQ_EINT0);
disable_irq(IRQ_EINT1);
disable_irq(IRQ_EINT2);
disable_irq(IRQ_EINT3);
PRINTK("key44Driver release called!\n");
kfifo_free(buffer);
return 0;
}
static ssize_t key44Driver_read(struct file *filp, char *buf, size_t count,loff_t *f_pos)
{
PRINTK("key44Driver read called!\n");
down_interruptible(&bufflock);
kfifo_get(buffer, buf, 2);
return 2;
}
void timerHandler(unsigned long data)
{
int i;
unsigned int data_buf;
char key[2];
GPFCON = 0X0055;
GPFDAT = 0X0F0;
for(i = 0; i < 1000; i++ );
data_buf = GPFDAT;
data_buf = data_buf & 0x0f0;
switch(data_buf)
{
case 0x0e0:
key[0] = '1';
break;
case 0x0d0:
key[0] = '2';
break;
case 0x0b0:
key[0] = '3';
break;
case 0x070:
key[0] = '4';
break;
default:
key[0] = '0';
break;
}
key[1] = data + '0';
if(((key[0] != key_old[0]) || (key[1] != key_old[1])) && key[0] != '0')
{
kfifo_put(buffer, key, 2);
up(&bufflock);
key_old[0] = key[0];
key_old[1] = key[1];
}
GPFCON = 0X55aa;
GPFDAT = 0X0F;
enable_irq(IRQ_EINT0);
enable_irq(IRQ_EINT1);
enable_irq(IRQ_EINT2);
enable_irq(IRQ_EINT3);
}
void handler(int irq, void *dev_id, struct pt_regs *regs)
{
disable_irq(IRQ_EINT0);
disable_irq(IRQ_EINT1);
disable_irq(IRQ_EINT2);
disable_irq(IRQ_EINT3);
myTimer.expires = jiffies + 3;
myTimer.data = irq;
myTimer.function = timerHandler;
add_timer(&myTimer);
}
/* Driver Operation structure */
static struct file_operations key44Driver_fops = {
owner: THIS_MODULE,
read: key44Driver_read,
open: key44Driver_open,
release: key44Driver_release,
};
/* Module Init & Exit function */
#ifdef CONFIG_DEVFS_FS
devfs_handle_t devfs_key44Driver_dir;
devfs_handle_t devfs_key44Driver_raw;
#endif
static int __init myModule_init(void)
{
/* Module init code */
PRINTK("myModule_init\n");
/* Driver register */
key44Driver_Major = register_chrdev(0, DRIVER_NAME, &key44Driver_fops);
if(key44Driver_Major < 0)
{
PRINTK("register char device fail!\n");
return key44Driver_Major;
}
PRINTK("register key44Driver OK! Major = %d\n", key44Driver_Major);
#ifdef CONFIG_DEVFS_FS
devfs_key44Driver_dir = devfs_mk_dir(NULL, "key44Driver", NULL);
devfs_key44Driver_raw = devfs_register(devfs_key44Driver_dir, "0",DEVFS_FL_DEFAULT, key44Driver_Major, 0, \
S_IFCHR | S_IRUSR | S_IWUSR, &key44Driver_fops, NULL);
PRINTK("add dev file to devfs OK!\n");
#endif
GPFCON = 0X55aa;
GPFUP = 0X00;
GPFDAT = 0X0F;
set_external_irq(IRQ_EINT0, EXT_FALLING_EDGE, 0);
set_external_irq(IRQ_EINT1, EXT_FALLING_EDGE, 0);
set_external_irq(IRQ_EINT2, EXT_FALLING_EDGE, 0);
set_external_irq(IRQ_EINT3, EXT_FALLING_EDGE, 0);
request_irq(IRQ_EINT0, handler, SA_INTERRUPT, "KEY0", NULL);
request_irq(IRQ_EINT1, handler, SA_INTERRUPT, "KEY1", NULL);
request_irq(IRQ_EINT2, handler, SA_INTERRUPT, "KEY2", NULL);
request_irq(IRQ_EINT3, handler, SA_INTERRUPT, "KEY3", NULL);
buffer = kfifo_alloc(BUFFER_SIZE, GFP_KERNEL, &buffer_lock);
init_timer(&myTimer);
return 0;
}
static void __exit myModule_exit(void)
{
/* Module exit code */
PRINTK("myModule_exit\n");
/* Driver unregister */
if(key44Driver_Major > 0)
{
#ifdef CONFIG_DEVFS_FS
devfs_unregister(devfs_key44Driver_raw);
devfs_unregister(devfs_key44Driver_dir);
#endif
unregister_chrdev(key44Driver_Major, DRIVER_NAME);
}
del_timer(&myTimer);
free_irq(IRQ_EINT0, NULL);
free_irq(IRQ_EINT1, NULL);
free_irq(IRQ_EINT2, NULL);
free_irq(IRQ_EINT3, NULL);
return;
}
MODULE_AUTHOR("sure");
MODULE_LICENSE("Dual BSD/GPL");
module_init(myModule_init);
module_exit(myModule_exit);
//===========================Makefile========================================
OUTPUT = key44driver.o
OUTPUT_DIR = output
#s3c2410
KERNEL = /home/sure/kernel_2.4.18
CROSSPREFIX = /usr/local/arm/2.95.3/bin/arm-linux-
#pc 2.4
#KERNEL = /usr/src/linux-2.4
#CROSSPREFIX =
CFLAGS = -Wall -I$(KERNEL)/include -c -DDEBUG
#CFLAGS += -DEXPORT_SYMTAB -DMODVERSIONS -include $(KERNEL)/include/linux/modversions.h
DEST = $(foreach fn, $(OUTPUT), $(OUTPUT_DIR)/$(fn))
all: $(OUTPUT_DIR)/install.sh
$(OUTPUT_DIR)/install.sh: $(OUTPUT_DIR) $(DEST)
@rm $@ -f
@echo -e " $(foreach fn, $(OUTPUT), "insmod $(fn)\\n")" >> $@
@echo "Finished!"
$(OUTPUT_DIR):
@mkdir $@
@chmod 777 -R $@
$(OUTPUT_DIR)/%.o: %.c
@echo -n "Compling $^..."
@$(CROSSPREFIX)gcc $(CFLAGS) $^ -o $@
@echo "OK"
clean:
@find . \( -name '*.[oas]' -o -name install.sh \) -type f -print | xargs rm -f
@echo "Cleaned!"
//==================test.c=============================================
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(void)
{
char buf[2] = "";
int key = 0,i = 0;
if((key = open("/dev/key44Driver/0", O_RDONLY)) <= 0)
{
printf("open error\n");
exit(1);
}
while(read(key, buf, 2) > 0)
{
printf("%d: %s\n\n", i++, buf);
}
}
相关阅读 更多 +
排行榜 更多 +