zoukankan      html  css  js  c++  java
  • Android 从上层到底层-----kernel层

    CPU:RK3288

    系统:Android 5.1

    功能:上层 app 控制 led 亮灭

    开发板:Firefly RK3288

    1、在dts文件中增加 led 设备

    path:kernel/arch/arm/boot/dts/firefly-rk3288.dts

    firefly-led{
        //匹配内容
        compatible = "firefly,led";
        //led引脚及有效电平
        led-work = <&gpio8 GPIO_A2 GPIO_ACTIVE_LOW>;
        status = "okay";
    };

    2、led 驱动

    path:kernel/drivers/firefly/leds.c

    #include <linux/init.h>
    #include <linux/kernel.h>
    #include <linux/uaccess.h>
    #include <linux/proc_fs.h>
    #include <linux/module.h>
    #include <linux/slab.h>
    #include <linux/gpio.h>
    #include <linux/miscdevice.h>
    #include <linux/of_gpio.h>
    #include <linux/of_platform.h>
    #include <linux/platform_device.h>
    #include <linux/of.h>
    #include <linux/of_gpio.h>
    
    #define DEBUG
    
    #ifdef DEBUG
    #define LED_DBG(fmt,arg...)        do{
                                        printk("<LED-DEBUG> [%d]"fmt"
    ", __LINE__, ##arg);
                                    }while(0)
    #else
    #define LED_DBG(fmt,arg...)
    #endif
    
    struct led_data {
        int work_pin;        //led引脚
        int work_status;        //led状态
        int work_enable;    //led使能电平
    };
    
    struct led_data *led_info;
    
    
    static int led_drv_open(struct inode *inode, struct file *filp)
    {
        LED_DBG("--%s()--", __func__);
        return 0;
    }
    
    static int led_drv_release(struct inode *inode, struct file *filp)
    {
        LED_DBG("--%s()--", __func__);
        return 0;
    }
    
    static ssize_t led_drv_read(struct file *filp, char __user *buf, size_t len, loff_t *pos)
    {
        int ret;
        
        LED_DBG("--%s()--", __func__);
        ret = copy_to_user(buf, &(led_info->work_status), len);
        if(ret > 0)
        {
            LED_DBG("copy to user failed.");
            return ret;
        }
        
        return len;
    }
    
    static ssize_t led_drv_write(struct file *filp, const char __user *buf, size_t len, loff_t *pos)
    {
        int on;
        int ret;
        
        LED_DBG("--%s()--", __func__);
        ret = copy_from_user(&on, buf, len);
        if(ret > 0)
        {
            LED_DBG("copy from user failed.");
            return ret;
        }
        
        gpio_direction_output(led_info->work_pin, !on);
        led_info->work_status = on;
        
        return ret;
    }
    
    //上层没添加此函数api
    static long led_drv_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
    {
        LED_DBG("--%s()--", __func__);
        return 0;
    }
    
    struct file_operations led_fops = {
        .owner = THIS_MODULE,
        .open = led_drv_open,
        .release = led_drv_release,
        .write = led_drv_write,
        .read = led_drv_read,
        .unlocked_ioctl = led_drv_ioctl,
    };
    
    //注册为杂项设备
    struct miscdevice led_dev =   
    {  
        .minor  =   MISC_DYNAMIC_MINOR,  
        .fops   =   &led_fops,  
        .name   =   "firefly_leds",  
    };  
    
    static int led_drv_probe(struct platform_device *pdev)
    {
        int ret = -1;
        enum of_gpio_flags work_flags;
        struct device_node *led_node = pdev->dev.of_node;
        
        LED_DBG("--%s()--", __func__);
        
        led_info = kzalloc(sizeof(struct led_data), GFP_KERNEL);
        if(led_info == NULL)
        {
            LED_DBG("Alloc GFP_KERNEL memory failed.");
            return -ENOMEM;
        }
        
        //从dts中获取led的引脚,和有效电平
        led_info->work_pin = of_get_named_gpio_flags(led_node, "led-work", 0, &work_flags);
        if(!gpio_is_valid(led_info->work_pin))
        {
            LED_DBG("Work pin is invaild.");
            ret = -ENODEV;
            goto dev_fail;
        }
        
        led_info->work_enable = (work_flags == OF_GPIO_ACTIVE_LOW) ? 0 : 1;
        
        ret = gpio_request(led_info->work_pin, "work_led");
        if(ret < 0)
        {
            LED_DBG("Work led request failed.");
            goto dev_fail;
        }
        
        gpio_direction_output(led_info->work_pin, !(led_info->work_enable));
        led_info->work_status = 0;
        
        misc_register(&led_dev);
        
        return 0;
        
    request_fail:
        gpio_free(led_info->work_pin);
    dev_fail:
        kfree(led_info);
        
        return ret;
    }
    
    static int led_drv_remove(struct platform_device *pdev)
    {
        misc_deregister(&led_dev);
        LED_DBG("--%s()--", __func__);
        gpio_free(led_info->work_pin);
        kfree(led_info);
    }
    
    int led_drv_suspend(struct device *dev)
    {
        LED_DBG("--%s()--", __func__);
        return 0;
    }
    
    int led_drv_resume(struct device *dev)
    {
        LED_DBG("--%s()--", __func__);
        return 0;
    }
    
    //suspend和resume暂时没调试成功
    const struct dev_pm_ops led_pm_ops = {
        .suspend = led_drv_suspend,
        .resume = led_drv_resume,
    };
    
    static const struct of_device_id of_gpio_leds_match[] = {
        {.compatible = "firefly,led", },
        {},
    };
    
    static struct platform_driver led_drv = {
        .probe = led_drv_probe,
        .remove = led_drv_remove,
        .driver = {
            .name = "leds",
            .owner = THIS_MODULE,
            .pm = &led_pm_ops,
            .of_match_table = of_match_ptr(of_gpio_leds_match),
        },
    };
    
    module_platform_driver(led_drv);
    
    MODULE_LICENSE("GPL");
    MODULE_AUTHOR("AaronLee");

    3、Makefile

    path:kernel/drivers/firefly/Makefile

    obj-$(CONFIG_FIREFLY_RK3288_LEDS)                += leds.o

    4.Kconfig

    path:kernel/drivers/firefly/Kconfig

    menu "Firefly Device Options"
    
    config FIREFLY_RK3288_LEDS
        bool "select firefly rk3288 leds"
        default y
    
    endmenu

    5、defconfig文件中增加led

    path:kernel/arch/arm/configs/firefly-rk3288_defconfig

    CONFIG_FIREFLY_RK3288_LEDS=y

    6、修改led节点的权限

    path:device/rockchip/common/ueventd.rockchip.rc

    /dev/firefly_leds         0666   system        system

    Android 从上层到底层-----hal层

    Android 从上层到底层-----jni层

    Android 从上层到底层-----app层

  • 相关阅读:
    Ubuntu中Nginx的安装与配置
    在Ubuntu中安装Redis
    微博开放平台
    QQ互联 回调地址
    PostgreSQL在Ubuntu上安装指南
    postgresql常用命令
    在Linux下查看环境变量
    vue-04-组件
    vue-03-style与class
    vue-02-安装-指令
  • 原文地址:https://www.cnblogs.com/lialong1st/p/8867754.html
Copyright © 2011-2022 走看看