zoukankan      html  css  js  c++  java
  • uio设备:发送中断&共享内存

    1,内核代码

    #include <linux/init.h>  
    #include <linux/version.h>  
    #include <linux/module.h>  
    #include <linux/sched.h>  
    #include <linux/uaccess.h>  
    #include <linux/proc_fs.h>  
    #include <linux/fs.h>  
    #include <linux/seq_file.h>   
    #include <linux/platform_device.h>
    #include <linux/uio_driver.h>
    #include <asm/io.h>
    #include <linux/slab.h> /* kmalloc, kfree */
    #include <linux/irq.h> /* IRQ_TYPE_EDGE_BOTH */
    #include <asm/uaccess.h>  
     
    #define STRING_LEN 256  
     
    char global_buffer[STRING_LEN] = {0};
    
    #if 1
    
    static irqreturn_t my_interrupt(int irq, void *dev_id)
    {
        struct uio_info *info = (struct uio_info *)dev_id;
        unsigned long *ret_val_add = (unsigned long *)(info->mem[0].addr);
        *ret_val_add = 222;
        printk("my_interrupt: %d 
    " ,(int)(*ret_val_add));
    
        return IRQ_RETVAL(IRQ_HANDLED);
    }
    
    struct uio_info kpart_info = {  
        .name = "kpart",
        .version = "0.1",
        .irq = 10, //unused
        .handler = my_interrupt, //unused
        .irq_flags = IRQ_TYPE_EDGE_RISING, //unused
    };
    
    static int drv_kpart_probe(struct device *dev);
    static int drv_kpart_remove(struct device *dev);
    
    static struct device_driver uio_dummy_driver = {  
        .name = "kpart",
        .bus = &platform_bus_type,
        .probe = drv_kpart_probe,
        .remove = drv_kpart_remove,
    };
    
    #ifdef HW_ENABLE
    struct button_irq_desc {
        int irq;
        int num;
        char *name;    
    };
     
    static struct button_irq_desc button_irqs [] = {
        {8 , 1, "KEY0"},
        {11, 2, "KEY1"},
        {13, 3, "KEY2"},
        {14, 4, "KEY3"},
        {15, 5, "KEY4"},
    };
    
    static irqreturn_t buttons_interrupt(int irq, void *dev_id)
    {
        struct button_irq_desc *button_irqs = (struct button_irq_desc *)dev_id;
    
        unsigned long *ret_val_add = (unsigned long *)(kpart_info.mem[1].addr);
        *ret_val_add = button_irqs->num;
    
        printk("%s is being pressed ..... 
    ", button_irqs->name);
    
        uio_event_notify(&kpart_info);
    
        return IRQ_RETVAL(IRQ_HANDLED);
    }
    #endif    
    
    static int drv_kpart_probe(struct device *dev)
    {  
        unsigned long *ret_val_addr;
    
        kpart_info.mem[0].addr = (unsigned long)kmalloc(1024, GFP_KERNEL);
        if(kpart_info.mem[0].addr == 0)
            return -ENOMEM;
        kpart_info.mem[0].memtype = UIO_MEM_LOGICAL;
        kpart_info.mem[0].size = 1024;
    
        ret_val_addr = (unsigned long *)(kpart_info.mem[0].addr);
        *ret_val_addr = 222;
    
        if(uio_register_device(dev, &kpart_info)){
            kfree((void *)kpart_info.mem[0].addr);
            return -ENODEV;
        }
    
    #ifdef HW_ENABLE
        int i = 0 ,err = 0;
        for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) {
            err = request_irq(button_irqs[i].irq, buttons_interrupt, IRQ_TYPE_EDGE_RISING, 
                              button_irqs[i].name, (void *)&button_irqs[i]);
            if (err)
                break;
        }
    #endif    
    
        return 0;
    }  
    
    static int drv_kpart_remove(struct device *dev)
    {
        kfree((void *)kpart_info.mem[0].addr);
        uio_unregister_device(&kpart_info);
        return 0;
    }
    
    #endif
    
    #if 1
    
    static int user_cmd_proc(char *user_cmd)
    {
        if(strncmp(user_cmd, "sendsig", 7) == 0) {
            unsigned long *ret_val_add = (unsigned long *)(kpart_info.mem[0].addr);
            *ret_val_add = 333;
            uio_event_notify(&kpart_info);
        }
        
        return 0;
    }
    
    static int my_proc_show(struct seq_file *seq, void *v)
    {
        seq_printf(seq, "current kernel time is %ld
    ", jiffies);  
        seq_printf(seq, "last cmd: %s", global_buffer);
    
        return 0;        
    }
    
    static int my_proc_open(struct inode *inode, struct file *file)
    {
        return single_open(file, my_proc_show, inode->i_private);
    } 
    
    static ssize_t my_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *pos)
    {
        if (count > 0) {
            printk("my_proc_write called
    ");
            copy_from_user(global_buffer, buffer, count);  
            user_cmd_proc(global_buffer);
        }
    
        return count;
    } 
    
    struct file_operations proc_fops =
    {
        .open  = my_proc_open,
        .read  = seq_read,
        .write  = my_proc_write,
        .llseek  = seq_lseek,
        .release = single_release,
    };
    
    static struct proc_dir_entry *proc_dir = NULL;
    static struct proc_dir_entry *proc_file = NULL; 
    static struct platform_device * uio_dummy_device;
    
    static int __init proc_test_init(void) 
    {  
        proc_dir = proc_mkdir("my_proc", NULL);
        if (!proc_dir) {
             printk(KERN_DEBUG"proc_mkdir failed");
             return 0;
        }
        
        proc_file = proc_create("buffer", 0666, proc_dir, &proc_fops);
        if (!proc_file) {
             printk(KERN_DEBUG"proc_create failed");
             return 0;
        }
    
        uio_dummy_device = platform_device_register_simple("kpart", -1, NULL, 0);
        driver_register(&uio_dummy_driver);   
        
        return 0;  
    }  
     
    static void __exit proc_test_exit(void) 
    {  
        remove_proc_entry("buffer", proc_dir);  
        remove_proc_entry("my_proc", NULL);  
    
        platform_device_unregister(uio_dummy_device);
        driver_unregister(&uio_dummy_driver);    
    }  
    #endif
     
    module_init(proc_test_init);  
    module_exit(proc_test_exit);
    MODULE_AUTHOR("derek.yi");  
    MODULE_LICENSE("GPL");  

    2,用户代码

    #include <stdio.h>  
    #include <fcntl.h>  
    #include <stdlib.h>  
    #include <string.h>  
    #include <sys/types.h>  
    #include <sys/stat.h>
    #include <unistd.h>
    #include <sys/ioctl.h>
    #include <fcntl.h>
    #include <errno.h>
    #include <signal.h>
    #include <sys/syscall.h>
    #include <sys/mman.h>  
    
    #define UIO_DEV     "/dev/uio0" ///sys/class/uio/uio0/name: kpart
    
    #define UIO_ADDR0     "/sys/class/uio/uio0/maps/map0/addr"
    #define UIO_SIZE0     "/sys/class/uio/uio0/maps/map0/size"
    #define UIO_ADDR1     "/sys/class/uio/uio0/maps/map1/addr"
    #define UIO_SIZE1    "/sys/class/uio/uio0/maps/map1/size"
    
    static char uio_addr_buf[16], uio_size_buf[16];
    
    int main()
    {
        int uio_fd, addr_fd, size_fd;
        int uio_size;
        void *uio_addr, *access_address;
        fd_set rd_fds, tmp_fds;
        int c, ret;
    
        uio_fd = open(UIO_DEV, O_RDWR);
        addr_fd = open(UIO_ADDR0, O_RDONLY);
        size_fd = open(UIO_SIZE0, O_RDONLY);
    
        if(addr_fd < 0 || size_fd < 0 || uio_fd < 0 ) {
            fprintf(stderr, "mmap: %s
    ", strerror(errno));
            exit(-1);
        }
    
    #if 0
        read(addr_fd, uio_addr_buf, sizeof(uio_addr_buf));
        read(size_fd, uio_size_buf, sizeof(uio_size_buf));
        uio_addr = (void*)strtoul(uio_addr_buf, NULL, 0);
        uio_size = (int)strtol(uio_size_buf, NULL, 0);
    #endif
    
        access_address = mmap(NULL, 1024, PROT_READ | PROT_WRITE, MAP_SHARED, uio_fd, 0);
        if (access_address == (void*) -1 ) {
            fprintf(stderr, "mmap: %s
    ", strerror(errno));
            exit(-1);
        }
    
        while (1) {
            FD_ZERO(&rd_fds);
            FD_SET(uio_fd, &rd_fds);
            tmp_fds = rd_fds;
    
            ret = select(uio_fd+1, &tmp_fds, NULL, NULL, NULL);
            if (ret > 0) {
                if (FD_ISSET(uio_fd, &tmp_fds)) {
                    read(uio_fd, &c, sizeof(int));
                    printf("current event count %d, data %d
    ", c, *(int *)access_address);
                }
            }
        }
    
        close(uio_fd);
    
        return 0;
    }

    3,测试脚本

    sudo modprobe uio
    sudo insmod myuio.ko
    
    echo "sendsig" > /proc/my_proc/buffer
    cat /proc/my_proc/buffer
    
    derek@ubox:~/share/ldd5$ gcc app.c 
    derek@ubox:~/share/ldd5$ sudo ./a.out 
    current event count 10, data 333
    current event count 11, data 333
    current event count 12, data 333
  • 相关阅读:
    MySQL的事务用法:
    MySQL基本命令(增删改查,check约束)总结:
    (转)nodejs npm国内镜像
    NodeJS学习笔记(三)
    NodeJS学习笔记(二).js
    minimist的用法
    npm link没有效果的问题
    DOM Based XSS介绍
    NodeJS学习笔记(一)
    用Ruby写自动生成Sql语句脚本遇到的问题
  • 原文地址:https://www.cnblogs.com/soul-stone/p/6718688.html
Copyright © 2011-2022 走看看