From b8e5f60912c77d52214c21e67fa91ec5f522c54c Mon Sep 17 00:00:00 2001
From: guowenxue <guowenxue@gmail.com>
Date: Mon, 23 Dec 2024 16:33:12 +0800
Subject: [PATCH] Update x86 example driver

---
 bsp/drivers/x86/driver/chrdev3.c |  150 +++++++++++++++++---------------------------------
 1 files changed, 51 insertions(+), 99 deletions(-)

diff --git a/bsp/drivers/x86_64/ldd3_ioctl.c b/bsp/drivers/x86/driver/chrdev3.c
similarity index 62%
copy from bsp/drivers/x86_64/ldd3_ioctl.c
copy to bsp/drivers/x86/driver/chrdev3.c
index 295808d..1b4777b 100644
--- a/bsp/drivers/x86_64/ldd3_ioctl.c
+++ b/bsp/drivers/x86/driver/chrdev3.c
@@ -1,50 +1,31 @@
+/*
+ * Copyright (C) 2024 LingYun IoT System Studio
+ * Author: Guo Wenxue <guowenxue@gmail.com>
+ *
+ * A character skeleton driver example in linux kernel.
+ */
 
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>   /* printk() */
-#include <linux/slab.h>     /* kmalloc() */
 #include <linux/fs.h>       /* everything... */
 #include <linux/errno.h>    /* error codes */
 #include <linux/types.h>    /* size_t */
 #include <linux/cdev.h>     /* cdev */
-#include <linux/fcntl.h>    /* O_ACCMODE */
-#include <linux/uaccess.h>  /* copy_*_user */
+#include <linux/slab.h>     /* kmalloc() */
 #include <linux/version.h>  /* kernel version code */
+#include <linux/uaccess.h>  /* copy_from/to_user() */
 #include <linux/moduleparam.h>
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0)
-#define access_ok_wrapper(type,arg,cmd) access_ok(type, arg, cmd)
-#else
-#define access_ok_wrapper(type,arg,cmd) access_ok(arg, cmd)
-#endif
-
-/* ioctl definitions, use 'z' as magic number */
-#define CHRDEV_IOC_MAGIC  'z'
-#define CHRDEV_IOCRESET    _IO(CHRDEV_IOC_MAGIC, 0)
-#define CHRDEV_IOCSET      _IOW(CHRDEV_IOC_MAGIC, 1, int)
-#define CHRDEV_IOCGET      _IOR(CHRDEV_IOC_MAGIC, 2, int)
-#define CHRDEV_IOC_MAXNR   3
 
 /* device name and major number */
 #define DEV_NAME         "chrdev"
-#define DEV_SIZE         1024
-#define CONFIG_AUTODEV   1 /* Auto create device node in driver or not */
-
-//#define DEV_MAJOR  79
-#ifndef DEV_MAJOR
-#define DEV_MAJOR  0
-#endif
-
-int dev_major = DEV_MAJOR;
+int dev_major = 0;
 module_param(dev_major, int, S_IRUGO);
 
+#define BUF_SIZE         1024
 typedef struct chrdev_s
 {
     struct cdev    cdev;
-#ifdef CONFIG_AUTODEV
-    struct class  *class;
-    struct device *device;
-#endif
     char          *data;   /* data buffer */
     uint32_t       size;   /* data buffer size */
     uint32_t       bytes;  /* data bytes in the buffer */
@@ -109,19 +90,29 @@
     return rv;
 }
 
-/* The ioctl() implementation */
-long chrdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0)
+#define access_ok_wrapper(type,arg,cmd) access_ok(type, arg, cmd)
+#else
+#define access_ok_wrapper(type,arg,cmd) access_ok(arg, cmd)
+#endif
+
+/* ioctl definitions, use 'c' as magic number */
+#define CHR_MAGIC           'c'
+#define CHR_MAXNR           2
+#define CMD_READ            _IOR(CHR_MAGIC, 0, int)
+#define CMD_WRITE           _IOW(CHR_MAGIC, 1, int)
+
+static long chrdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-    struct chrdev_s *dev = file->private_data;
-    int rv, data;
-    size_t  bytes = sizeof(data);
+    static int value = 0xdeadbeef;
+    int rv = 0;
 
     /*
      * extract the type and number bitfields, and don't decode
      * wrong cmds: return ENOTTY (inappropriate ioctl) before access_ok()
      */
-    if (_IOC_TYPE(cmd) != CHRDEV_IOC_MAGIC) return -ENOTTY;
-    if (_IOC_NR(cmd) > CHRDEV_IOC_MAXNR) return -ENOTTY;
+    if (_IOC_TYPE(cmd) != CHR_MAGIC) return -ENOTTY;
+    if (_IOC_NR(cmd) > CHR_MAXNR) return -ENOTTY;
 
     /*
      * the direction is a bitmask, and VERIFY_WRITE catches R/W transfers.
@@ -132,32 +123,26 @@
         rv = !access_ok_wrapper(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));
     else if (_IOC_DIR(cmd) & _IOC_WRITE)
         rv =  !access_ok_wrapper(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));
-    if (rv) return -EFAULT;
 
-    switch(cmd) {
-        case CHRDEV_IOCRESET:
-            dev->bytes = 0;
-            memset(dev->data, 0, dev->size);
-            rv = 0;
+    if (rv)
+        return -EFAULT;
+
+    switch (cmd) {
+        case CMD_READ:
+            if (copy_to_user((int __user *)arg, &value, sizeof(value)))
+                return -EFAULT;
             break;
 
-        /* Last 4 bytes in the buffer used to save ioctl() data*/
-        case CHRDEV_IOCSET:
-            rv = __get_user(data, (int __user *)arg);
-            if( !rv )
-                 memcpy(&dev->data[dev->size-bytes], &data, bytes);
-            break;
-
-        case CHRDEV_IOCGET:
-            memcpy(&data, &dev->data[dev->size-bytes], bytes);
-            rv = __put_user(data, (int __user *)arg);
+        case CMD_WRITE:
+            if (copy_from_user(&value, (int __user *)arg, sizeof(value)))
+                return -EFAULT;
             break;
 
         default:
-            return -ENOTTY;
+            return -EINVAL;
     }
 
-    return rv;
+    return 0;
 }
 
 static int chrdev_open (struct inode *inode, struct file *file)
@@ -179,12 +164,12 @@
 }
 
 static struct file_operations chrdev_fops = {
-    .owner   = THIS_MODULE,
-    .open    = chrdev_open,          /* open()  implementation */
-    .read    = chrdev_read,          /* read()  implementation */
-    .write   = chrdev_write,         /* write() implementation */
-    .release = chrdev_close,         /* close() implementation */
-    .unlocked_ioctl = chrdev_ioctl,  /* ioctl() implementation */
+    .owner          = THIS_MODULE,
+    .open           = chrdev_open,  /* open()  implementation */
+    .read           = chrdev_read,  /* read()  implementation */
+    .write          = chrdev_write, /* write() implementation */
+    .unlocked_ioctl = chrdev_ioctl, /* ioctl() implementation */
+    .release        = chrdev_close, /* close() implementation */
 };
 
 static int __init chrdev_init(void)
@@ -193,17 +178,17 @@
     int        rv;
 
     /* malloc and initial device read/write buffer */
-    dev.data = kmalloc(DEV_SIZE, GFP_KERNEL);
+    dev.data = kmalloc(BUF_SIZE, GFP_KERNEL);
     if( !dev.data )
     {
         printk(KERN_ERR " %s driver kmalloc() failed\n", DEV_NAME);
         return -ENOMEM;
     }
-    dev.size = DEV_SIZE;
+    dev.size = BUF_SIZE;
     dev.bytes = 0;
     memset(dev.data, 0, dev.size);
 
-    /* dynamic alloc device node major number if not set */
+    /* allocate device number */
     if(0 != dev_major)
     {
         devno = MKDEV(dev_major, 0);
@@ -221,9 +206,11 @@
         return -ENODEV;
     }
 
-    /* setup and register cdev into kernel */
+    /* initialize cdev and setup fops */
     cdev_init(&dev.cdev, &chrdev_fops);
     dev.cdev.owner = THIS_MODULE;
+
+    /* register cdev to linux kernel */
     rv = cdev_add(&dev.cdev, devno, 1);
     if( rv )
     {
@@ -232,41 +219,11 @@
         goto failed1;
     }
 
-#ifdef CONFIG_AUTODEV
-    /* create device node in user space */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 5, 0)
-    dev.class = class_create(DEV_NAME);
-#else
-    dev.class = class_create(THIS_MODULE, DEV_NAME);
-#endif
-    if (IS_ERR(dev.class)) {
-        rv = PTR_ERR(dev.class);
-        goto failed2;
-    }
-
-    dev.device = device_create(dev.class, NULL, MKDEV(dev_major, 0), NULL, DEV_NAME);
-    if( !dev.device )
-    {
-        rv = -ENODEV;
-        printk(KERN_ERR "%s driver create device failed\n", DEV_NAME);
-        goto failed3;
-    }
-#endif
-
     printk(KERN_INFO "%s driver on major[%d] installed.\n", DEV_NAME, dev_major);
     return 0;
 
-#ifdef CONFIG_AUTODEV
-failed3:
-    class_destroy(dev.class);
-
-failed2:
-    cdev_del(&dev.cdev);
-#endif
-
 failed1:
     unregister_chrdev_region(devno, 1);
-    kfree(dev.data);
 
     printk(KERN_ERR "%s driver installed failed.\n", DEV_NAME);
     return rv;
@@ -274,11 +231,6 @@
 
 static void __exit chrdev_exit(void)
 {
-#ifdef CONFIG_AUTODEV
-    device_del(dev.device);
-    class_destroy(dev.class);
-#endif
-
     cdev_del(&dev.cdev);
     unregister_chrdev_region(MKDEV(dev_major,0), 1);
 

--
Gitblit v1.9.1