copy_to_user linux驱动程序不发送数据

时间:2016-01-24 13:00:17

标签: linux-device-driver mmap

我尝试将数据从用户空间发送到驱动程序,然后从驱动程序发送到用户空间。我使用copy_from_user和copy_to_user。 我可以将数据从用户发送到驱动程序,但是当我尝试使用copy_to_user时,我遇到了问题 - 数据没有发送。我使用printk来查找错误,在my_read中,message_buf具有正确的值,但不是。

我使用mmap,也许这里有错误?

司机:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
#include <linux/sem.h>
#include <linux/slab.h>
#include <linux/semaphore.h>
#include <linux/ipc.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/scatterlist.h>
#include <linux/mm.h>
#include "query_ioctl.h"

#define FIRST_MINOR 0
#define MINOR_CNT 1
#define BUFSIZE 30

#define PCI_VENDOR_ID_WZAB 0xabba
#define PCI_DEVICE_ID_WZAB_WZADC1 0x0133

static dev_t dev;
static struct cdev c_dev;
static struct class *cl;
//static char buf[] = " ";

int buffsize = 0;

char *message_buf;
char *write_buf;



struct semaphore sem;


static const struct vm_operations_struct mod_mem_ops = { 

};

static int my_open(struct inode *i, struct file *f) {
    message_buf = kmalloc(BUFSIZE, GFP_KERNEL);
    if(down_interruptible(&sem))
    {
        printk("KERN_ALERT device is already held ..cant be opened\n");

        return -1;
    }
    else
    {
        printk("KERN_ALERT device opened\n");
        return 0;
    }
}


static int my_mmap(struct file *filp, struct vm_area_struct *vma) {

    size_t size = vma->vm_end - vma->vm_start;
    vma->vm_ops = &mod_mem_ops;
    vma->vm_pgoff = virt_to_phys(message_buf)>>PAGE_SHIFT;

    if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, size, vma->vm_page_prot)){
    return -EAGAIN;
    }
return 0;
}



static ssize_t my_read(struct file *f, char *buf, size_t len, loff_t *f_pos){
    int retval;
    ssize_t bytes;
    if(buffsize < len)
    bytes = buffsize;
    else
    bytes = len;

    retval = copy_to_user(buf, message_buf, sizeof(message_buf));
    printk("read %d bytes as : %s \n", retval, buf);
    printk(KERN_INFO "message read: %s \n", message_buf);
    printk(KERN_INFO "buf : %s \n", buf);
    if (retval){
    printk(KERN_INFO "copy_to_user fail");
    return -EFAULT;
        }
    else
    {
    printk(KERN_INFO "copy_to_user successed\n");
    buffsize -= bytes;
    return bytes;
    }
}

static ssize_t my_write(struct file *f, char *buf, size_t len, loff_t *f_pos){
    int retval; 
    memset(message_buf, 0, BUFSIZE);

    if (len >BUFSIZE)
    len = BUFSIZE;

    retval = copy_from_user(message_buf, buf, len);
    printk("write %d bytes as : %s \n", retval, message_buf);
    printk("buf write : %s \n", buf);
    buffsize = len;
    return len;

}


static ssize_t my_ioctl(struct file *f, unsigned int cmd, unsigned long arg)

{
size_t len;
    switch (cmd) {
        case GET_VARIABLES:
        /*//funkcja kodująca - arg buf
        encode(buf);
        strcpy(d.bufor_enc, buf);
        //printk("temp2 : %s zmienna ", d.bufor_enc);
            if (copy_to_user((data *) arg, &d, sizeof(data))) 
                {
                    return -EACCES;
                }
    */
        len = strlen(message_buf);
        my_read(f, (char*)arg, len, 0);
            break;
        case SET_VARIABLES:
        len = strlen((char *)arg);
    my_write(f, (char*)arg, len, 0);

           /* if (copy_from_user(&d, (data *) arg, sizeof(data)))
                {
                    return -EACCES;
                }
            strcpy(buf, d.bufor_mess);
    */
            break;
        default:
            return -EINVAL;
    }

    return 0;
}


static int my_close(struct inode *i, struct file *f) {
    up(&sem);
    return 0;
}


static struct file_operations fops =
        {
                .owner = THIS_MODULE,
                .open = my_open,
                .release = my_close,
                .unlocked_ioctl = my_ioctl,
        .mmap = my_mmap

        };

static int __init ioctl_init(void) {

    int ret;
    struct device *dev_ret;
    sema_init(&sem,1);


    if ((ret = alloc_chrdev_region(&dev, FIRST_MINOR, MINOR_CNT, "query_ioctl")) < 0) {
        return ret;
    }

    cdev_init(&c_dev, &fops);

    if ((ret = cdev_add(&c_dev, dev, MINOR_CNT)) < 0) {
        return ret;
    }

    if (IS_ERR(cl = class_create(THIS_MODULE, "char"))) {
        cdev_del(&c_dev);
        unregister_chrdev_region(dev, MINOR_CNT);
        return PTR_ERR(cl);
    }
    if (IS_ERR(dev_ret = device_create(cl, NULL, dev, NULL, "query"))) {
        class_destroy(cl);
        cdev_del(&c_dev);
        unregister_chrdev_region(dev, MINOR_CNT);
        return PTR_ERR(dev_ret);
    }

    return 0;
}

static void __exit ioctl_exit(void) {
    device_destroy(cl, dev);
    class_destroy(cl);
    cdev_del(&c_dev);
    unregister_chrdev_region(dev, MINOR_CNT);
}

module_init(ioctl_init);
module_exit(ioctl_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Anna Czabatorowicz");
MODULE_DESCRIPTION("Encoder Driver");

APP:

#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>

#include "query_ioctl.h"

char number_sem = 0;

int choose_option();

void get_vars(int fd)
{
    data d;

    if (ioctl(fd, GET_VARIABLES, &d) == -1)
    {
        perror("get data not access");
    }
    else
    {
        printf("Character sequence to encoder : %s\n", d.var);
    }
}
void clr_vars(int fd)
{
    if (ioctl(fd, CLR_VARIABLES) == -1)
    {
        perror("character sequence clr");
    }
}
void set_vars(int fd)
{
    char v[30];
    data d;

    printf("Enter character sequence - max 30 char: ");
    scanf("%s", v);
    getchar();
    strcpy(d.var, v);
    if (ioctl(fd, SET_VARIABLES, &d) == -1)
    {
        perror("character sequence not set");
    }
}

int main(int argc, char *argv[]){
    char *file_name = "/dev/query";
    int fd;
    //int option;

    fd = open(file_name, O_RDWR);
    if (fd == -1)
    {
        perror("query_apps not open");
        return 2;
    }
    //option = choose_option();
    /**
    switch (option)
    {
        case 1:
            get_vars(fd);
            break;
        case 2:
            clr_vars(fd);
            break;
        case 3:
            set_vars(fd);
            break;
        default:
            break;
    }
    **/

    number_sem = fork();

    set_vars(fd);
    get_vars(fd);
    clr_vars(fd);
    close(fd);
    return 0;
}

头文件:

 #ifndef QUERY_IOCTL_H
#define QUERY_IOCTL_H
#include <linux/ioctl.h>



#define GET_VARIABLES _IOR('d', 1, data *)
#define CLR_VARIABLES _IO('d', 2)
#define SET_VARIABLES _IOW('d', 3, data *)

#endif

0 个答案:

没有答案