【Linux内核驱动】基于platform总线的miscdevice驱动(LED)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wr132/article/details/78565243

驱动模块编写步骤:

  1. 查找并调用所需的内核函数,同时为所需的结构体命名
  2. 补全所需的结构体,使用vim -t查找结构体声明
  3. 通过结构体声明所在的文件补全头文件
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/miscdevice.h>
#include <linux/gpio.h>     //gpio_request
#include <plat/gpio-cfg.h>  //s3c_gpio_cfgpin
#include <mach/gpio.h>      //GPIO 宏 
#include <linux/fs.h>


#define DRIVER_NAME "led_test"
#define DEVICE_NAME "led_dev"

MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("[email protected]");

//避免出现struct declared inside parameter list
struct platform_deivce;
struct miscdevice;

static int led_plat_probe(struct platform_device *pdev);
static int led_plat_remove(struct platform_deivce *pdev);
struct platform_driver led_pdri = {
    .probe = led_plat_probe,
    .remove = led_plat_remove,
    .driver = {
        .name = DRIVER_NAME,
        .owner = THIS_MODULE,
    }
};


static int led_open(struct inode *inode, struct file *filp);
static int led_release(struct inode *inode, struct file *filp);
static long led_ioctl(struct file *filp, unsigned int cmd, unsigned int arg);
struct file_operations led_fops = {
    .open = led_open,
    .release = led_release,
    .unlocked_ioctl = led_ioctl,
};


struct miscdevice led_mdev = {
    .minor = 10,
    .name = DEVICE_NAME,
    .fops = &led_fops,
};


/*define file operation functions*/

static int led_open(struct inode *inode, struct file *filp)
{
    printk("led open\n");
    return 0;
}

static int led_release(struct inode *inode, struct file *filp)
{
    printk("led release\n");
    return 0;
}

static long led_ioctl(struct file *filp, unsigned int cmd, unsigned int arg)
{
    printk("led ioctl\n");
    switch(cmd) {
        case 0:
            gpio_set_value(EXYNOS4_GPL2(0), 0);
            break;
        case 1:
            gpio_set_value(EXYNOS4_GPL2(0), 1);
            break;
        default:
            printk("wrong cmd\n");
    }
    return 0;
}




/*define platform driver functions*/


static int led_plat_probe(struct platform_device *pdev)
{
    int error;
    printk("led platform driver probe\n");
    error = gpio_request(EXYNOS4_GPL2(0), "led1");
    if(error < 0)
        goto err_gpio_request;
    s3c_gpio_cfgpin(EXYNOS4_GPL2(0), S3C_GPIO_OUTPUT);
    misc_register(&led_mdev);
    return 0;

err_gpio_request:
    printk("fail to request gpio\n");
    return error;
}

static int led_plat_remove(struct platform_deivce *pdev)
{
    printk("led platform driver remove\n");
    misc_deregister(&led_mdev);
    gpio_free(EXYNOS4_GPL2(0));
    return 0;
}




static int led_mod_init(void)
{
    int error;
    printk("led module init\n");
    printk("register led platform driver\n");
    error = platform_driver_register(&led_pdri);
    if(error < 0)
        goto error_register_platform_driver;
    printk("register platform driver success\n");
    return 0;

error_register_platform_driver:
    printk("fail to register platform driver\n");
    return -1;
}

static void led_mod_exit(void)
{
    printk("led module exit\n");
    printk("unregister led platform driver\n");
    platform_driver_unregister(&led_pdri);
}

module_init(led_mod_init);
module_exit(led_mod_exit);

猜你喜欢

转载自blog.csdn.net/wr132/article/details/78565243