Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/i2c.h>
- #include <linux/kernel.h>
- #include <linux/fs.h>
- #include <linux/proc_fs.h>
- #include <linux/slab.h>
- #include <linux/uaccess.h>
- #include <linux/cdev.h>
- #include <linux/ctype.h>
- static int buff_size = 1000;
- module_param(buff_size, int, 0);
- static char *buff;
- static dev_t dev_hello;
- static int hello_count = 1;
- static struct cdev cdev_hello;
- #define HELLO_IOCTL_LOWERCASE_ALL 1
- #define HELLO_IOCTL_FIRST_LOWER_REST_UPPER 3
- static ssize_t hello_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
- {
- int remaining_size, transfer_size;
- remaining_size = buff_size - (int)(*ppos);
- if (remaining_size == 0) { /* All read, returning 0 (End Of File) */
- return 0;
- }
- transfer_size = min(remaining_size, (int)count);
- if (copy_to_user(buf, buff + *ppos, transfer_size)) {
- return -EFAULT;
- } else {
- *ppos += transfer_size;
- return transfer_size;
- }
- }
- static ssize_t hello_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
- {
- int remaining_bytes = buff_size - (*ppos);
- if (count > remaining_bytes) {
- return -EIO; // Can't write beyond the end of the device
- }
- if (copy_from_user(buff + *ppos, buf, count)) {
- return -EFAULT;
- } else {
- *ppos += count;
- return count;
- }
- }
- static long hello_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
- {
- size_t i;
- switch (cmd) {
- case HELLO_IOCTL_LOWERCASE_ALL:
- for (i = 0; i < buff_size && buff[i] != '\0'; i++) {
- buff[i] = tolower(buff[i]);
- }
- pr_info("Buffer converted to lowercase.\n");
- break;
- case HELLO_IOCTL_FIRST_LOWER_REST_UPPER:
- if (buff_size > 0 && buff[0] != '\0') {
- buff[0] = tolower(buff[0]);
- }
- for (i = 1; i < buff_size && buff[i] != '\0'; i++) {
- buff[i] = toupper(buff[i]);
- }
- pr_info("First character lowercase, rest uppercase.\n");
- break;
- default:
- return -EINVAL; // Invalid command
- }
- return 0;
- }
- static struct file_operations fops_hello = {
- .owner = THIS_MODULE,
- .read = hello_read,
- .write = hello_write,
- .unlocked_ioctl = hello_ioctl,
- };
- static int __init hello_init(void)
- {
- int err;
- pr_info("Hello world!\n");
- buff = kmalloc(buff_size, GFP_KERNEL);
- if (buff == NULL) {
- pr_err("Error allocating buffer\n");
- return -ENOMEM;
- }
- memset(buff, 0x00, buff_size);
- err = alloc_chrdev_region(&dev_hello, 0, hello_count, "hello");
- if (err) {
- pr_err("Error allocating chardev region\n");
- kfree(buff);
- return err;
- }
- cdev_init(&cdev_hello, &fops_hello);
- err = cdev_add(&cdev_hello, dev_hello, hello_count);
- if (err) {
- pr_err("Error adding device\n");
- unregister_chrdev_region(dev_hello, hello_count);
- kfree(buff);
- return err;
- }
- pr_info("Major number: %d\n", MAJOR(dev_hello));
- return 0;
- }
- static void __exit hello_exit(void)
- {
- pr_info("Goodbye!\n");
- cdev_del(&cdev_hello);
- unregister_chrdev_region(dev_hello, hello_count);
- kfree(buff);
- }
- module_init(hello_init);
- module_exit(hello_exit);
- MODULE_LICENSE("GPL");
- MODULE_DESCRIPTION("Greeting module with ioctl support");
- MODULE_AUTHOR("William Shakespeare");
- //////////////
- User-space program
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <sys/ioctl.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <string.h>
- #define HELLO_IOCTL_LOWERCASE_ALL 1
- #define HELLO_IOCTL_FIRST_LOWER_REST_UPPER 3
- void bb_show_usage(void) {
- fprintf(stderr, "Usage: ioctl <device_file> <command_number>\n");
- fprintf(stderr, "Command numbers:\n");
- fprintf(stderr, " 1 - Convert buffer to lowercase\n");
- fprintf(stderr, " 3 - Convert first character lowercase, rest uppercase\n");
- exit(1);
- }
- int open_or_warn(const char *filename, int flags) {
- int fd = open(filename, flags);
- if (fd < 0) {
- fprintf(stderr, "Error opening file %s: %s\n", filename, strerror(errno));
- }
- return fd;
- }
- int ioctl_main(int argc, char **argv) {
- int file;
- int cmd;
- if (argc != 3) {
- bb_show_usage();
- return -1;
- }
- sscanf(argv[2], "%i", &cmd);
- file = open_or_warn(argv[1], O_RDWR);
- if (file < 0) {
- return -1;
- }
- if (ioctl(file, cmd)) {
- fprintf(stderr, "Error sending ioctl command %d to %s\n", cmd, argv[1]);
- close(file);
- return -1;
- }
- close(file);
- return 0;
- }
- int main(int argc, char **argv) {
- return ioctl_main(argc, argv);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement