프로그래밍

KEY(device driver)

Dilrong 2015. 4. 15. 17:03
/* 
 * XHYPER255_TKU3 
 * key.c 
 * 2004-07-01   <newboder@hybus.net> 
 *  
 */ 
#include <linux/module.h> 
#include <linux/sched.h> 
#include <linux/init.h> 
#include <linux/delay.h> 
#include <linux/kernel.h> 
#include <linux/fs.h> 
#include <linux/poll.h> 
#include <linux/types.h> 

#include <asm/uaccess.h> 
#include <asm/irq.h> 
#include <asm/bitops.h> 
#include <asm/hardware.h> 
#include <asm/arch/pxa-regs.h> 
#include <asm/io.h> 
#include <asm/ioctls.h> 

#define KEY_MAJOR           233 
#define KEY_NAME            "key" 
#define SCAN_NUM        4

/* 
    FPGA KEY 

   0x16400000 //FPGA_KEY_OUT#  
   KEYOUT_D[0:3] : X_D[0:3] 

   0x16800000 //FPGA_KEY_IN#  
   KEYIN_D[0:3] : X_D[0:3] 
*/ 
#define FPGA_KEY_OUT            (0x11D00000)
#define FPGA_KEY_IN            (0x11E00000)

// (*((volatile unsigned char *)(mem_base)))  

#define KEYOUT            (*((volatile unsigned char *)(mem_key_out)))     
#define KEYIN           (*((volatile unsigned char *)(mem_key_in)))     

#define dbg(x...)    //    printk(x) 

static void *mem_key_out, *mem_key_in;
static struct timer_list key_timer_str;   // timer 구조체를 정의 // 
static void key_timer_function( unsigned long ptr);
static void init_add_timer(void);
static void remove_timer(void);

static char key_data; 
static int n = 0;

void Print_Key(int out , int in)
{ 
    switch(out) 
    { 
        case 1:                
                if(in == 1)    { dbg("key 4 is pressed\n");    key_data = 4;} 
                   else if(in == 2){ dbg("key 8 is pressed\n");    key_data = 8;} 
                   else if(in == 4){ dbg("key 12 is pressed\n");    key_data = 12;} 
                   else if(in == 8){ dbg("key 16 is pressed\n");    key_data = 16;} 
                break; 
        case 2:                 
                if(in == 1)    { dbg("key 3 is pressed\n");    key_data = 3;} 
                else if(in == 2){ dbg("key 7 is pressed\n");    key_data = 7;} 
                else if(in == 4){ dbg("key 11 is pressed\n");    key_data = 11;} 
                        else if(in == 8){ dbg("key 15 is pressed\n");    key_data = 15;} 
                break; 
        case 3:                  
                if(in == 1)    { dbg("key 2 is pressed\n");    key_data = 2;} 
                else if(in == 2){ dbg("key 6 is pressed\n");    key_data = 6;} 
                else if(in == 4){ dbg("key 10 is pressed\n");    key_data = 10;} 
                else if(in == 8){ dbg("key 14 is pressed\n");    key_data = 14;} 
                break; 
        case 4:                   
                if(in == 1)    { dbg("key 1 is pressed\n");    key_data = 1;} 
                else if(in == 2){ dbg("key 5 is pressed\n");    key_data = 5;} 
                else if(in == 4){ dbg("key 9 is pressed\n");    key_data = 9;} 
                else if(in == 8){ dbg("key 13 is pressed\n");    key_data = 13;} 
                 break;                
    }   
}          

void key_timer_function(unsigned long ptr)
{ 
    int in, out;

    KEYOUT = ((1 << (ptr-1)) & (0x0f)); 
//    KEYOUT = 1; 

    out = ptr; 
    in = KEYIN; 

//    printk("KEYIN = %x\n", in & 0xF); 
    if(in != 0) 
    { 
        Print_Key(out, in);
//        mdelay(200); 
    } 

    init_add_timer(); 
} 

void init_add_timer(void) 
{    
    ++n; 
    if( n > SCAN_NUM) 
        n = 1; 

    init_timer(&key_timer_str); // timer  pointer  
     
    key_timer_str.function =&key_timer_function ; 
    key_timer_str.data = (unsigned long)n; 
    key_timer_str.expires = jiffies + (HZ/100); 

    add_timer(&key_timer_str); 
} 

void remove_timer(void) 
{ 
    del_timer(&key_timer_str); 
}   

int key_open (struct inode *inode, struct file *filp)
{ 
   // MOD_INC_USE_COUNT; 
    return 0;          /* success */
} 

int key_release (struct inode *inode, struct file *filp)
{ 
   // MOD_DEC_USE_COUNT; 
    return 0; 
} 

ssize_t key_read (struct file *filp, char *buf, size_t count, loff_t *f_pos)
{ 
    copy_to_user(buf, &key_data, sizeof(key_data)); 
    key_data = 0; 
    return 0; 
} 

ssize_t key_write (struct file *filp, const char *buf, size_t count, loff_t *f_pos)
{ 
    return 0; 
} 

int key_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{ 
    switch(cmd) 
    { 
        case FIONREAD:   
        { 
            copy_to_user((void *)arg, &key_data, sizeof(key_data)); 
            key_data = 0; 
            break; 
        } 
        default: break; 
    } 
    return 0; 
} 
         
struct file_operations key_fops = { 
    .read    =       key_read, 
    .write    =       key_write, 
    .open    =       key_open, 
    .ioctl    =    key_ioctl, 
    .release    =    key_release, 
}; 

static int key_init(void)
{ 
    int result; 
    unsigned long mem_addr_out, mem_addr_in, mem_len;         

    result = register_chrdev(KEY_MAJOR,  "KEY", &key_fops); 
        if (result < 0) {
            printk(KERN_WARNING " can't get major \n"); 
            return result; 
        } 
     
    mem_addr_out =  FPGA_KEY_OUT; 
    mem_addr_in  =  FPGA_KEY_IN; 
    mem_len    = 0x1000; 
    mem_key_out = ioremap_nocache (mem_addr_out, mem_len); 
    if(!mem_key_out) { 
        printk(" Error mapping key_out memory\n"); 
        return -EBUSY; 
    } 

    mem_key_in = ioremap_nocache (mem_addr_in, mem_len); 
    if(!mem_key_in) { 
        printk(" Error mapping key_in memory\n"); 
        return -EBUSY; 
    } 

    printk("X-Hyper 270TKU %s MAJOR %d\n", KEY_NAME, KEY_MAJOR); 

    init_add_timer(); 
    return 0; 
} 

static void key_exit(void)
{ 
    remove_timer(); 
    unregister_chrdev(KEY_MAJOR, KEY_NAME); 
} 

module_init(key_init); 
module_exit(key_exit); 

/* EOF */ 
반응형