#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>");
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/
標籤:
Linux Driver
訂閱:
張貼留言 (Atom)
沒有留言:
張貼留言