2019年12月16日 星期一

create a folder in /sys with kobject and read/write files in user space from kernel space

Create a file of sn and foo in /sys/abcd/efg/ijk/
#include <linux/kobject.h>
#include <linux/string.h>
#include <linux/sysfs.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/module.h>

#define BUF_LEN 16*2
#define PATH "/home/quiet/abcd/abc.txt"

static int foo;
struct kobject *sn_kobj;
struct kobj_attribute *sn_attr;
static char sn[BUF_LEN]= {0};

static int read_file (void)
{
    int ret=0, i=0;
    loff_t pos;
    char buff[BUF_LEN]= {0};
    unsigned char empty[16];
    struct file *fp;

    fp = filp_open(PATH, O_RDONLY | O_CREAT, 0444);
    if (IS_ERR(fp))
    {
        printk(KERN_ERR "Cannot open the file-1 %ld\n, Nice", PTR_ERR(fp));
        return -ENOENT;
    }

    pos = fp->f_pos;
    ret=kernel_read(fp, buff, BUF_LEN,  &pos); //work on kernel 4.1.5
    //ret=kernel_read(fp, pos, buff, BUF_LEN); //work on kernel 4.9
    if(ret == BUF_LEN)
    {
        buff[BUF_LEN-1]='\0';
    }
    else if (ret < 0)
    {
        printk(KERN_ERR "reading data has issue");
        return -EINVAL;
    }
    else
    {
        buff[strlen(buff)]='\0';
    }
    memcpy(sn, buff, strlen(buff));
    filp_close(fp, NULL);

    return 0;
}

static int write_file (void)
{
    int ret=0;
    loff_t pos;
    char buff[BUF_LEN]= {0};
    struct file *fp;
    struct AES_ctx ctx;

    fp = filp_open(PATH, O_WRONLY | O_TRUNC, 0644);
    if (IS_ERR(fp))
    {
        printk(KERN_ERR "Cannot open the file-3 %ld\n", PTR_ERR(fp));
        return -ENOENT;
    }

    pos = fp->f_pos;
    memcpy(buff, sn, strlen(sn));
    if (kernel_write(fp, buff, strlen(buff), &pos)) //work on kernel 4.1.5
    //if (kernel_write(fp, buff, strlen(buff), pos)) //wrok on kernel 4.9
    {
        //nothing to do
        ret=0;
    }
    else
    {
        printk(KERN_ERR "writing data has issue");
        ret = -EINVAL;
    }
    filp_close(fp, NULL);
    return ret;
}

static ssize_t foo_show(struct kobject *kobj, struct kobj_attribute *attr,
                        char *buf)
{
    printk(KERN_WARNING "Nice, foo_show-1");
    return sprintf(buf, "%d\n", foo);
}

static ssize_t foo_store(struct kobject *kobj, struct kobj_attribute *attr,
                         const char *buf, size_t count)
{
    int ret=0;
    struct kernfs_node *dir_knode, *file_knode;

    dir_knode = sn_kobj->sd;
    file_knode = sysfs_get_dirent(dir_knode, sn_attr->attr.name);
    if (strcmp("12345678", buf) == 0)
    {
        file_knode->mode = (file_knode->mode & S_IFMT) | 0666;
    }
    else
    {
        ret = kstrtoint(buf, BUF_LEN, &foo);
        if (ret < 0)
            return -EINVAL;
        file_knode->mode = (file_knode->mode & S_IFMT) | 0444;
    }
    return count;
}

static struct kobj_attribute foo_attribute =
//__ATTR(foo1, 0664, foo_show, foo_store);
    __ATTR(foo, S_IRUGO|S_IWUSR, foo_show, foo_store);




static ssize_t sn_show(struct kobject *kobj, struct kobj_attribute *attr,
                       char *buf)
{
    sn_kobj=kobj;
    sn_attr=attr;
    return sprintf(buf, "%s\n", sn);
}

static ssize_t sn_store(struct kobject *kobj, struct kobj_attribute *attr,
                        const char *buf, size_t count)
{
    struct kernfs_node *dir_knode, *file_knode;

    dir_knode = kobj->sd;
    file_knode = sysfs_get_dirent(dir_knode, attr->attr.name);
    if (strcmp("87654321", buf) == 0)
    {
        file_knode->mode = (file_knode->mode & S_IFMT) | 0666;
    }
    else
    {
        memcpy(sn, buf, BUF_LEN);
        file_knode->mode = (file_knode->mode & S_IFMT) | 0444;
    }
    return count;
}

static struct kobj_attribute sn_attribute =
//__ATTR(sn, 0444, sn_show, sn_store);
    __ATTR(sn, S_IRUGO, sn_show, sn_store);

static struct attribute *attrs[] =
{
    &sn_attribute.attr,
    &foo_attribute.attr,
    NULL, /* need to NULL terminate the list of attributes */
};

static struct attribute_group attr_group =
{
    .attrs = attrs,
};

static struct kobject *init_kobj_abcd;
static struct kobject *init_kobj_efg;
static struct kobject *init_kobj_hij;

static int __init module_newera_init(void)
{
    int retval=0;

    printk(KERN_WARNING "module_ttt_init");

    retval=read_file();
    if (retval < 0)
        goto err;

    init_kobj_abcd = kobject_create_and_add("abcd", NULL);
    if (!init_kobj_abcd)
        return -ENOMEM;

    init_kobj_efg = kobject_create_and_add("efg", init_kobj_monitor);
    if (!init_kobj_efg)
        return -ENOMEM;

    init_kobj_hij = kobject_create_and_add("hij", init_kobj_usbport);
    if (!init_kobj_hij)
        return -ENOMEM;

    /* Create the files associated with this kobject */
    retval = sysfs_create_group(init_kobj_hij, &attr_group);
    if (retval)
    {
        kobject_put(init_kobj_hij);
        kobject_put(init_kobj_efg);
        kobject_put(init_kobj_abcd);
    }

err:
    printk(KERN_WARNING "init retval=%d", retval);
    return retval;
}

static void __exit module_newera_exit(void)
{
    printk(KERN_WARNING "module_ttt_exit");
    write_file();
    kobject_put(init_kobj_hij);
    kobject_put(init_kobj_efg);
    kobject_put(init_kobj_abcd);
}

module_init(module_newera_init);
module_exit(module_newera_exit);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Quiet<blue_quiet@gmail.com>");

沒有留言:

張貼留言