2024-01-10 00:06:10 +01:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
|
|
|
|
//#define DEBUG 1
|
|
|
|
|
|
|
|
#include <asm/page.h>
|
|
|
|
#include <linux/debugfs.h>
|
|
|
|
#include <linux/jiffies.h>
|
2024-01-11 19:55:48 +01:00
|
|
|
#include <linux/kernel.h>
|
2024-01-10 00:06:10 +01:00
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/rwsem.h>
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
2024-01-11 19:55:48 +01:00
|
|
|
#include <linux/delay.h>
|
2024-01-10 00:06:10 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#define BUFFER_LENGTH 10
|
|
|
|
|
|
|
|
static struct dentry *folder;
|
|
|
|
static struct dentry *id_file;
|
|
|
|
static struct dentry *foo_file;
|
|
|
|
|
|
|
|
static char *id_msg;
|
|
|
|
static char *foo_msg;
|
|
|
|
static struct rw_semaphore foo_sem;
|
|
|
|
|
2024-01-11 19:55:48 +01:00
|
|
|
static ssize_t id_read(struct file *, char __user *buffer, size_t length,
|
|
|
|
loff_t *offset)
|
2024-01-10 00:06:10 +01:00
|
|
|
{
|
2024-01-11 19:55:48 +01:00
|
|
|
int bytes = 0;
|
|
|
|
const char *msg_tmp = id_msg;
|
2024-01-10 00:06:10 +01:00
|
|
|
|
2024-01-11 19:55:48 +01:00
|
|
|
/*
|
|
|
|
* TODO
|
|
|
|
if (!*(msg_tmp + *offset)) {
|
|
|
|
*offset = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
*/
|
2024-01-10 00:06:10 +01:00
|
|
|
|
|
|
|
msg_tmp += *offset;
|
|
|
|
|
|
|
|
while (*msg_tmp && bytes < length) {
|
|
|
|
put_user(*(msg_tmp), (buffer + bytes));
|
|
|
|
bytes++;
|
|
|
|
msg_tmp++;
|
|
|
|
}
|
|
|
|
|
|
|
|
*offset += bytes;
|
|
|
|
return bytes;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t id_write(struct file *, const char __user *buffer,
|
|
|
|
size_t size, loff_t *)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
char *tmp_buffer;
|
|
|
|
|
|
|
|
if (size == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
tmp_buffer = kzalloc(BUFFER_LENGTH, GFP_KERNEL);
|
|
|
|
|
|
|
|
if (copy_from_user(tmp_buffer, buffer, BUFFER_LENGTH)) {
|
|
|
|
kfree(tmp_buffer);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
*(tmp_buffer + BUFFER_LENGTH - 1) = '\0';
|
|
|
|
pr_info("Test %s-\n", tmp_buffer);
|
|
|
|
|
|
|
|
if (!strcmp(tmp_buffer, "congruent"))
|
|
|
|
ret = BUFFER_LENGTH;
|
|
|
|
else
|
|
|
|
ret = -EINVAL;
|
|
|
|
|
|
|
|
kfree(tmp_buffer);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct file_operations id_fops = {
|
|
|
|
.owner = THIS_MODULE,
|
|
|
|
.read = id_read,
|
|
|
|
.write = id_write,
|
|
|
|
};
|
|
|
|
|
2024-01-11 19:55:48 +01:00
|
|
|
static ssize_t foo_read(struct file *, char __user *buffer, size_t count,
|
|
|
|
loff_t *offset)
|
2024-01-10 00:06:10 +01:00
|
|
|
{
|
2024-01-11 19:55:48 +01:00
|
|
|
int bytes = -EINVAL;
|
|
|
|
int tmp_len = strlen(foo_msg);
|
|
|
|
|
|
|
|
if (*offset > tmp_len) {
|
|
|
|
bytes = -EFAULT;
|
|
|
|
} else if (down_read_trylock(&foo_sem)) {
|
|
|
|
char *tmp_str = foo_msg + *offset;
|
|
|
|
|
|
|
|
tmp_len = strlen(tmp_str);
|
|
|
|
bytes = tmp_len > count ? count : tmp_len;
|
|
|
|
|
|
|
|
if (copy_to_user(buffer, tmp_str, bytes))
|
|
|
|
bytes = -EFAULT;
|
|
|
|
else
|
|
|
|
*offset += bytes;
|
2024-01-10 00:06:10 +01:00
|
|
|
#ifdef DEBUG
|
2024-01-11 19:55:48 +01:00
|
|
|
msleep(5000);
|
2024-01-10 00:06:10 +01:00
|
|
|
#endif
|
2024-01-11 19:55:48 +01:00
|
|
|
up_read(&foo_sem);
|
|
|
|
}
|
2024-01-10 00:06:10 +01:00
|
|
|
|
2024-01-11 19:55:48 +01:00
|
|
|
return bytes;
|
2024-01-10 00:06:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t foo_write(struct file *, const char __user *buffer,
|
2024-01-11 19:55:48 +01:00
|
|
|
size_t count, loff_t *offset)
|
2024-01-10 00:06:10 +01:00
|
|
|
{
|
2024-01-11 19:55:48 +01:00
|
|
|
int bytes = -EINVAL;
|
|
|
|
|
|
|
|
if ((*offset + count) > PAGE_SIZE) {
|
|
|
|
bytes = -EFAULT;
|
|
|
|
} else if (down_write_trylock(&foo_sem)) {
|
|
|
|
bytes = count;
|
|
|
|
if (copy_from_user(foo_msg, buffer, bytes))
|
|
|
|
bytes = -EINVAL;
|
2024-01-10 00:06:10 +01:00
|
|
|
#ifdef DEBUG
|
2024-01-11 19:55:48 +01:00
|
|
|
msleep(5000);
|
2024-01-10 00:06:10 +01:00
|
|
|
#endif
|
2024-01-11 19:55:48 +01:00
|
|
|
up_write(&foo_sem);
|
|
|
|
}
|
2024-01-10 00:06:10 +01:00
|
|
|
|
2024-01-11 19:55:48 +01:00
|
|
|
return bytes;
|
2024-01-10 00:06:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static const struct file_operations foo_fops = {
|
|
|
|
.owner = THIS_MODULE,
|
|
|
|
.read = foo_read,
|
|
|
|
.write = foo_write,
|
|
|
|
};
|
|
|
|
|
|
|
|
static int __init my_init(void)
|
|
|
|
{
|
2024-01-11 19:55:48 +01:00
|
|
|
init_rwsem(&foo_sem);
|
|
|
|
id_msg = kmalloc(12, GFP_KERNEL);
|
|
|
|
foo_msg = kmalloc(PAGE_SIZE, GFP_KERNEL);
|
|
|
|
strscpy(id_msg, "pouetpouet\n", 12);
|
2024-01-10 00:06:10 +01:00
|
|
|
pr_info("Coucou le gens !!!!\n");
|
|
|
|
|
2024-01-11 19:55:48 +01:00
|
|
|
folder = debugfs_create_dir("eudyptula", NULL);
|
|
|
|
id_file = debugfs_create_file("id", 0666, folder, NULL, &id_fops);
|
|
|
|
debugfs_create_u64("jiffies", 0444, folder, &jiffies_64);
|
|
|
|
foo_file = debugfs_create_file("foo", 0664, folder, NULL, &foo_fops);
|
|
|
|
|
2024-01-10 00:06:10 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void __exit my_exit(void)
|
|
|
|
{
|
2024-01-11 19:55:48 +01:00
|
|
|
debugfs_remove_recursive(folder);
|
|
|
|
kfree(id_msg);
|
|
|
|
kfree(foo_msg);
|
2024-01-10 00:06:10 +01:00
|
|
|
pr_info("Tschuss !!!\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
module_init(my_init);
|
|
|
|
module_exit(my_exit);
|
|
|
|
|
|
|
|
MODULE_LICENSE("GPL");
|
|
|
|
MODULE_AUTHOR("rick <rick@gnous.eu>");
|
|
|
|
MODULE_DESCRIPTION("Module pour tester le debugfs.");
|