/* debug.c * * utilize debufs * FIXME: R/W from /sys/kernel/debug/hello/magic doesn't work * */ #include #include #include #include #include #include #define BUFF_LEN 256 char kernel_buff[BUFF_LEN] = {'f','o','o','b','a','r','\0'}; /* debugfs_create_file's 4th param * @data: a pointer to something that the caller will want to get to later * on. The inode.i_private pointer will point to this value on * the open() call. */ int fileprv = 1; /* hmm */ /* struct file, an abstract open file, not on disk, which would be a an inode */ static ssize_t hello_hello_debugfs_read(struct file *fp, char __user /* userspace */ *ubuff, size_t c, loff_t *pos) { /** * simple_read_from_buffer - copy data from the buffer to user space * @to: the user space buffer to read to * @count: the maximum number of bytes to read * @ppos: the current position in the buffer * @from: the buffer to read from * @available: the size of the buffer * * The simple_read_from_buffer() function reads up to @count bytes from the * buffer @from at offset @ppos into the user space address starting at @to. * * On success, the number of bytes read is returned and the offset @ppos is * advanced by this number, or negative value is returned on error. **/ return simple_read_from_buffer(ubuff, c, pos, kernel_buff, BUFF_LEN); } static ssize_t hello_debugfs_write(struct file *fp, const char __user *ubuff, size_t c, loff_t *pos) { /** * simple_write_to_buffer - copy data from user space to the buffer * @to: the buffer to write to * @available: the size of the buffer * @ppos: the current position in the buffer * @from: the user space buffer to read from * @count: the maximum number of bytes to read * * The simple_write_to_buffer() function reads up to @count bytes from the user * space address starting at @from into the buffer @to at offset @ppos. * * On success, the number of bytes written is returned and the offset @ppos is * advanced by this number, or negative value is returned on error. **/ if (c > BUFF_LEN) return (-EINVAL); return simple_write_to_buffer(kernel_buff, BUFF_LEN, pos, ubuff, c); #if 0 printk(KERN_INFO "count %lu, offset %u", c, *pos); copy_from_user(kernel_buff + *pos, ubuff, c); return c; #endif } int hello_debugfs_init(struct dentry **dir, struct dentry **file) { /* func ptrs that perform various operations on the device, in this case char device, well not even */ struct file_operations fops = { .read = hello_hello_debugfs_read, .write = hello_debugfs_write }; /* omitted fields are initialized to NULL */ *dir = debugfs_create_dir("hello", NULL); if (!*dir) return (-ENODEV); /* regular file, read by user/group/other, write by user */ *file = debugfs_create_file("magic", S_IFREG | S_IRUGO | S_IWUSR, *dir, &fileprv, &fops); if (!*file) printk(KERN_WARNING "[hello] debugfs: error creating file\n"); return 0; } int hello_debugfs_destroy(struct dentry *dir, struct dentry *file) { if (file) debugfs_remove(file); if (dir) debugfs_remove(dir); return 0; } /* * Function implementing a read on /proc/hellomem, here we print few fields * from internal data structure */ int hello_read_procmem(char *page, char **start, off_t off, int count, int *eof, void *data) { int len = 0; struct hello_dev *dev = (struct hello_dev *) data; if (down_interruptible(&dev->sem)) /* protects page buffer from multiple writes */ return -ERESTARTSYS; len = sprintf(page, "hello module internal buffer is at: %p, with size of: %lu, " "buffer starts with: %c\n", dev->mylist, dev->ll_size, dev->mylist ? dev->mylist->chunk[0] : '0'); up(&dev->sem); *eof = 1; /* signify that we're done with dumping our internal structure */ return len; }