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"\n", __LINE__, ##arg);\
}while()
#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 ;
} static int led_drv_release(struct inode *inode, struct file *filp)
{
LED_DBG("--%s()--", __func__);
return ;
} 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 > )
{
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 > )
{
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 ;
} 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 = -;
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", , &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) ? : ; ret = gpio_request(led_info->work_pin, "work_led");
if(ret < )
{
LED_DBG("Work led request failed.");
goto dev_fail;
} gpio_direction_output(led_info->work_pin, !(led_info->work_enable));
led_info->work_status = ; misc_register(&led_dev); return ; 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 ;
} int led_drv_resume(struct device *dev)
{
LED_DBG("--%s()--", __func__);
return ;
} //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 system system
Android 从上层到底层-----hal层
Android 从上层到底层-----jni层
Android 从上层到底层-----app层
Android 从上层到底层-----kernel层的更多相关文章
- Android 从上层到底层-----app层
CPU:RK3288 系统:Android 5.1 功能:上层 app 控制 led 亮灭 开发板:Firefly RK3288 MainActivity.java package com.aaron ...
- Android 从上层到底层-----jni层
CPU:RK3288 系统:Android 5.1 功能:上层 app 控制 led 亮灭 开发板:Firefly RK3288 led_jni.h path:hardware/rockchip/fi ...
- Android 从上层到底层-----hal层
CPU:RK3288 系统:Android 5.1 功能:上层 app 控制 led 亮灭 开发板:Firefly RK3288 led_hal.c path:hardware/rockchip/fi ...
- Linux、Android系统调用从上层到底层的调用路径浅析
参考: https://blog.csdn.net/liuhangtiant/article/details/85149369 http://blog.sina.com.cn/s/blog_79433 ...
- Android HAL层与Linux Kernel层驱动开发简介
近日稍微对Android中的驱动开发做了一些简要的了解. HAL:Hardware Abstract Layer 硬件抽象层,由于Linux Kernel需要遵循GPL开源协议,硬件厂商为了保护自己硬 ...
- Linux/Android——input系统之 kernel层 与 frameworks层交互 (五)【转】
本文转载自:http://blog.csdn.net/jscese/article/details/42291149 之前的四篇博文记录的都是linux中的input体系相关的东西,最底层以我调试的u ...
- Android Camera 通过V4L2与kernel driver的完整交互过程
http://blog.chinaunix.net/uid-26215986-id-3552456.html 原文地址:Android Camera 通过V4L2与kernel driver的完整交互 ...
- Android源码剖析之Framework层升级版(窗口、系统启动)
本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处! 看本篇文章之前,建议先查看: Android源码剖析之Framework层基础版 前面讲了frame ...
- 创建Android守护进程(底层服务)【转】
本文转载自:https://blog.csdn.net/myfriend0/article/details/80016739 创建Android守护进程(底层服务) 前言 Android底层服务,即运 ...
随机推荐
- cocos对象池的使用
enemy.js cc.Class({ extends: cc.Component, properties: { enemySpeed: 0, //设置加速度 }, //初始化当前节点的y坐标 ini ...
- HDU 4681 STRING dp+暴力。
题意:不说了很好懂. 这题这么水= =...当时竟然没有勇气暴力搜一下.昨天(好吧前天.)比赛的时候胃疼,看到这题想了一个办法就是对每一个出现最短的C串前后连接然后对这个串求最长公共子序列.其实优化一 ...
- 初次使用Bootstrap
一.概述也好,过程也好,反正就是这样 知道这个还是从群里听到的,一个人的视野是有限,必须借助他人来扩展.好奇使我去搜索了解了一下.原来是一个网页前端框架,可以适合不同大小屏幕,自动适应正常显示.这就是 ...
- 通过ping 主机名,或者主机名对应的IP地址
通过ping 主机名,或者主机名对应的IP地址: 如下图: 懵了吧? 但是你用 ping 主机名 -4
- C++面向对象高级编程(二)基础篇
技术在于交流.沟通,转载请注明出处并保持作品的完整性. 概要 知识点1.重载成员函数 知识点2 . return by value, return by reference 知识点3 重载非成员函数 ...
- MoreEffectiveC++Item35 条款26: 限制某个class所能产生的对象个数
一 允许零个或一个对象 我们知道每当即将产生一个对象,我们有一个constructor被调用,那么我们现在想组织某个对象的产生,最简单的方法就是将其构造函数声明成private(这样做同事防止了这个类 ...
- 解析xml节点属性及子节点内容
xml样例 <microNearlyThreeYearsOverdueInfo subReportType="13204" subReportTypeCost="9 ...
- C++ writestring 为什么不能写进中文 CStdioFile向无法向文本中写入中文【二】
本地化设置需要具备三个条件:a. 语言代码 (Language Code)b. 国家代码 (Country Code) c. 编码(Encoding)本地名字可以用下面这些部分来构造:语言代码_国家代 ...
- Ubuntu在图形界面和命令行界面都循环登录解决办法
在做机器ip变化自动发送邮件的时候,在/etc/profile.d/目录下添加了一个脚本,重启的时候就循环登录了,无论是在图形界面还是命令行界面. 解决方法:利用系统U盘进入系统进行修改,具体如下: ...
- Android中的“再按一次返回键退出程序”实现 (转) 按返回键退出程序时进行提醒
原文地址: https://blog.csdn.net/xichenguan/article/details/47030303 最近在研究 Android 编程方面的东西, 有了以下发现, 该 ...