2016-03-30 75 views
0
#include <linux/init.h>   
#include <linux/module.h>   
#include <linux/device.h>   
#include <linux/kernel.h>   
#include <linux/fs.h>    
#include <asm/uaccess.h>   
#include <linux/interrupt.h> 
#include <asm/io.h> 

#define DEVICE_NAME "kbdozgur" 
#define CLASS_NAME "kbdozgur" 
MODULE_AUTHOR("Mehmet Ozgur Bayhan"); 
MODULE_LICENSE("GPL"); 
MODULE_DESCRIPTION("Interrupt buffering skeleton"); 
MODULE_VERSION("0.2"); 

#define BUFFER_SIZE 20 
static unsigned char bfr[BUFFER_SIZE]; 
static int bufferCounter = 0; 

static int majorNumber; 
static char message[BUFFER_SIZE] = { 0 }; 
static short size_of_message; 
static int numberOpens = 0; 
static struct class* kbdozgurcharClass = NULL; 
static struct device* kbdozgurcharDevice = NULL; 


static int dev_release(struct inode *, struct file *); 
static ssize_t dev_read(struct file *, char *, size_t, loff_t *); 
static ssize_t dev_write(struct file *, const char *, size_t, loff_t *); 

static struct file_operations fops = { .open = dev_open, .read = dev_read, .write = dev_write, .release = dev_release, }; 

irq_handler_t irq_handler(int irq, void *dev_id, struct pt_regs *regs) { 
    static unsigned char scancode; 
    //Read keyboard status 
    scancode = inb(0x60); 

    if (scancode == 0x01) { 
     printk(KERN_INFO "MOB: Inputs are > %s\n", bfr); 
     bufferCounter = 0; 
     memset(&bfr[0], 0, sizeof(bfr)); 
    } 
    else if (scancode == 0x1E) { 
     bfr[bufferCounter] = 'a'; 
     bufferCounter++; 
    } 
    else if (scancode == 0x1F) { 
     bfr[bufferCounter] = 's'; 
     bufferCounter++; 
    } 
    else if (scancode == 0x20) { 
     bfr[bufferCounter] = 'd'; 
     bufferCounter++; 
    } 
    else if (scancode == 0x21) { 
     bfr[bufferCounter] = 'f'; 
     bufferCounter++; 
    } 
    else if (scancode == 0x22) { 
     bfr[bufferCounter] = 'g'; 
     bufferCounter++; 
    } 
    else if (scancode == 0x23) { 
     bfr[bufferCounter] = 'h'; 
     bufferCounter++; 
    } 
    else if (scancode == 0x24) { 
     bfr[bufferCounter] = 'j'; 
     bufferCounter++; 
    } 
    if (bufferCounter >= BUFFER_SIZE) { 
     bufferCounter = 0; 
     memset(&bfr[0], 0, sizeof(bfr)); 
    } 

    return (irq_handler_t) IRQ_HANDLED; 
} 

static int init_mod(void) { 
    int result; 

    /* 
    ***************************** 
    * Create Character device 
    ***************************** 
    */ 

    // Try to dynamically allocate a major number for the device 
    majorNumber = register_chrdev(0, DEVICE_NAME, &fops); 
    if (majorNumber < 0) { 
     printk(KERN_ALERT "MOB: kbdozgurcharClass failed to register a major number\n"); 
     return majorNumber; 
    } 
    printk(KERN_INFO "MOB: registered correctly with major number %d\n", majorNumber); 
    // Register the device class 
    kbdozgurcharClass = class_create(THIS_MODULE, CLASS_NAME); 
    if (IS_ERR(kbdozgurcharClass)) { // Check for error and clean up if there is 
     unregister_chrdev(majorNumber, DEVICE_NAME); 
     printk(KERN_ALERT "MOB: Failed to register device class\n"); 
     return PTR_ERR(kbdozgurcharClass); // Correct way to return an error on a pointer 
    } 
    printk(KERN_INFO "MOB: device class registered correctly\n"); 

    // Register the device driver 
    kbdozgurcharDevice = device_create(kbdozgurcharClass, NULL, MKDEV(majorNumber, 0), NULL, DEVICE_NAME); 
    if (IS_ERR(kbdozgurcharDevice)) { // Clean up if there is an error 
     class_destroy(kbdozgurcharClass); // Repeated code but the alternative is goto statements 
     unregister_chrdev(majorNumber, DEVICE_NAME); 
     printk(KERN_ALERT "MOB: Failed to create the device\n"); 
     return PTR_ERR(kbdozgurcharDevice); 
    } 
    printk(KERN_INFO "MOB: device class created correctly\n"); // Made it! device was initialized 
    /* 
    ***************************** 
    * Bind interrupt 
    ***************************** 
    */ 

    result = request_irq(1, (irq_handler_t) irq_handler, IRQF_SHARED, "kbdozgur", (void *) (irq_handler)); 
    if (result) printk(KERN_INFO "MOB: can't get shared interrupt for keyboard\n"); 

    printk(KERN_INFO "MOB: kbdozgur loaded.\n"); 
    return result; 

} 

static void exit_mod(void) { 
    /* 
    * **************************** 
    * Destroy Character Device 
    * **************************** 
    */ 
    device_unregister(kbdozgurcharDevice); 
    device_destroy(kbdozgurcharClass, MKDEV(majorNumber, 0)); // remove the device 
    class_unregister(kbdozgurcharClass); // unregister the device class 
    class_destroy(kbdozgurcharClass); // remove the device class 
    unregister_chrdev(majorNumber, DEVICE_NAME); // unregister the major number 
    printk(KERN_INFO "MOB: Goodbye from the LKM!\n"); 

    /* 
    * **************************** 
    * Free IRQ bind 
    * **************************** 
    */ 
    free_irq(1, (void *) (irq_handler)); 
    printk(KERN_INFO "MOB: kbdozgur unloaded.\n"); 
} 

static int dev_open(struct inode *inodep, struct file *filep) { 
    numberOpens++; 
    printk(KERN_INFO "MOB: Device has been opened %d time(s)\n", numberOpens); 
    return 0; 
} 


static ssize_t dev_read(struct file *filep, char *buffer, size_t len, loff_t *offset) { 
    int error_count = 0; 
    // copy_to_user has the format (* to, *from, size) and returns 0 on success 
// error_count = copy_to_user(buffer, message, size_of_message); 
    error_count = copy_to_user(buffer, "test", 4); 

    if (error_count == 0) { // if true then have success 
//  printk(KERN_INFO "MOB: Sent %d characters to the user >> %s\n", size_of_message, message); 
     printk(KERN_INFO "MOB: Sent %d characters to the user >> %s\n", 4, "test"); 
     return (size_of_message = 0); // clear the position to the start and return 0 
    } 
    else { 
     printk(KERN_INFO "MOB: Failed to send %d characters to the user\n", error_count); 
     return -EFAULT; // Failed -- return a bad address message (i.e. -14) 
    } 
} 


static ssize_t dev_write(struct file *filep, const char *buffer, size_t len, loff_t *offset) { 
    sprintf(message, "%s(%d letters)", buffer, len); // appending received string with its length 
    size_of_message = strlen(message); // store the length of the stored message 
    printk(KERN_INFO "MOB: Received %d characters from the user\n", len); 
    return len; 
} 

static int dev_release(struct inode *inodep, struct file *filep) { 
    printk(KERN_INFO "MOB: Device successfully closed\n"); 
    return 0; 
} 
module_init(init_mod); 
module_exit(exit_mod); 

Ara belleğe alma ve kullanıcı alanlarına hizmet vermek için bir iskelet sürücüsü oluşturmaya çalışıyorum. Karakterim cihaz kullanıcı uzaya boş bir dize döndürür AncakLinux kernel karakter aygıt sürücüsü, kullanıcı arabirimine boş dize döndürüyor

. Ben kabuğunda kedi ve açık ve python okumak çalıştı. Her ikisi de boş dizgeyi döndürür. Bu arada, normalde ve beklediğim gibi kullanıcı uzayından karakter dizisi alır.

İlgili bölüm >>

static ssize_t dev_read(struct file *filep, char *buffer, size_t len, loff_t *offset) { 
    int error_count = 0; 
    // copy_to_user has the format (* to, *from, size) and returns 0 on success 
    // error_count = copy_to_user(buffer, message, size_of_message); 
    error_count = copy_to_user(buffer, "test", 4); 

    if (error_count == 0) { // if true then have success 
//  printk(KERN_INFO "MOB: Sent %d characters to the user >> %s\n", size_of_message, message); 
     printk(KERN_INFO "MOB: Sent %d characters to the user >> %s\n", 4, "test"); 
     return (size_of_message = 0); // clear the position to the start and return 0 
    } 
    else { 
     printk(KERN_INFO "MOB: Failed to send %d characters to the user\n", error_count); 
     return -EFAULT; // Failed -- return a bad address message (i.e. -14) 
    } 
} 

İlk denedim:

error_count = copy_to_user(buffer, message, size_of_message); 

Sonra ben kontrol için çalıştı:

error_count = copy_to_user(buffer, "test", 4); 

Aynı hikaye. Her ikisi de boş dizgeyi döndürür. Hata yok. Dmesg ile ilgili hiçbir şey yok.

Ben kök kullanıcı olarak benim denemeler yapmak ve dosya izinleri olduğunu vardır:

crw------- 1 root root 250, 0 Mar 30 14:43 /dev/kbdozgur

Yani ben yanlış nerede yaptı?

+0

yapmalıyım 0.

size_message = 0

dönüş vardır? –

+1

Kullanıcı tamponuna 'len' bayt daha fazla kopyası asla. –

+0

Evet ben şimdi anladım :) teşekkür ederim. – obayhan

cevap

2

read okunan bayt sayısını dönmelidir. Sizin durumunuzda, size `dev_read` dan 0 döndürür Neden Aşağıdaki

size_t size_requested; 
... 
if (len >= size_of_message) { 
    size_requested = size_of_message; 
} else { 
    size_requested = len; 
} 
if (copy_to_user (buf, message, size_requested)) { 
    retval = -EFAULT; 
    return retval 
} 
return size_requested; 
+0

Şimdi – obayhan

+0

çözümünüz için teşekkür ederiz çalışıyorum. Çalışıyor ama şimdi "sprintf (message,"% s (% d letters) ", buffer, len) ile farklı bir problemim var; bölüm :) – obayhan

+0

snprintf'i deneyin (message, sizeof (message), "% * s (% d letters)", len, buffer, len); '. –