Android开发之应用层到驱动层的接口实现(一)

应用层到驱动层的接口实现(一)

                                                   ----硬件抽象层


   

该系列的文章主要是介绍实现从应用层(app)实现对硬件驱动层的访问,也就是通过读写文件节点的方式,访问Linux内核驱动程序。

在这便文章中介绍的是第一部分:即如何在硬件抽象层中增加硬件模块来和内核驱动程序交互。主要通过android项目翻盖机如果有子屏的话对后屏(sublcd)进行驱动操作(打开关闭)。


一、添加sublcd.h文件

1.1、文件目录:

/hardware/libhardware/include/hardware/

1.2sublcd.h文件内容:

#ifndef ANDROID_SUBLCD_INTERFACE_H
#define ANDROID_SUBLCD_INTERFACE_H
#include <hardware/hardware.h>
__BEGIN_DECLS

/*定义模块 ID*/
#define SUBLCD_HARDWARE_MODULE_ID "sublcd"

/*硬件模块结构体*/
struct sublcd_module_t {
struct hw_module_t common;
};

/*硬件接口结构体*/
struct sublcd_device_t {
struct hw_device_t common;
int fd;
int (*set_val)(struct sublcd_device_t* dev, int val);
int (*get_val)(struct sublcd_device_t* dev, int* val);
};

__END_DECLS

#endif

1.3、代码解释:

 这里的数据结构定义完全按照Android硬件抽象层规范的要求,分别定义模块ID、模块结构体以及硬件接口结构体。在硬件接口结构体中,fd表示设备文件描述符,对应我们将要处理的设备文件节点"/sys/class/ktd20xx/ktd2026/back_light_led"set_valget_val为该HAL对上提供的函数接口。

模块ID的名字是生成的.so文件的前缀名,在framework层就是通过模块IDSUBLCD_HARDWARE_MODULE_ID)去寻找生成的.so文件。所以该ID必须和后面要介绍到的sublcd目录下的Android.mk中定义的LOCAL_MODULE名字(前缀)一致,否则会导致在framework层往下调用HAL层定义的函数接口时失败。


二、添加sublcd文件夹

2.1、文件目录:

/hardware/libhardware/modules/

2.2/sublcd/sublcd.c文件内容:

//相关头文件
#define LOG_TAG "SubLcdStub"

#include <hardware/hardware.h>
#include <hardware/sublcd.h>
#include <fcntl.h>
#include <errno.h>
#include <cutils/log.h>
#include <cutils/atomic.h>

//相关数据结构与宏的定义及函数声明
#define DEVICE_NAME "/sys/class/ktd20xx/ktd2026/back_light_led"
#define MODULE_NAME "Sublcd"
#define MODULE_AUTHOR "xiangang.zhu@tcl.com"

static int light_sublcd();
static int died_sublcd();

/*Open and close sublcd device*/
static int sublcd_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device);
static int sublcd_device_close(struct hw_device_t* device);

/*Point to Interface*/
static int sublcd_set_val(struct sublcd_device_t* dev, int val);
static int sublcd_get_val(struct sublcd_device_t* dev, int* val);

/*Table of Module*/
static struct hw_module_methods_t sublcd_module_methods = {
open: sublcd_device_open
};

struct sublcd_module_t HAL_MODULE_INFO_SYM = {
common: {
tag: HARDWARE_MODULE_TAG,
version_major: 1,
version_minor: 0,
id: SUBLCD_HARDWARE_MODULE_ID,
name: MODULE_NAME,
author: MODULE_AUTHOR,
methods: &sublcd_module_methods,
}
};

//打开和关闭文件节点方法定义(包括相关数据结构初始化)
static int sublcd_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device) 
{
	ALOGI("SublcdStub: Sublcd_device_open");
	struct sublcd_device_t* dev;
	dev = (struct sublcd_device_t*)malloc(sizeof(struct sublcd_device_t));
		if(!dev) {
			ALOGI("SublcdStub: failed to alloc space");
			return -EFAULT;
			}
	memset(dev, 0, sizeof(struct sublcd_device_t));
	dev->common.tag = HARDWARE_DEVICE_TAG;
	dev->common.version = 0;
	dev->common.module = (hw_module_t*)module;
	dev->common.close = sublcd_device_close;
	dev->set_val = sublcd_set_val;
	dev->get_val = sublcd_get_val;
		if((dev->fd = open(DEVICE_NAME, O_RDWR)) == -1) {
			ALOGI("SublcdStub: failed to open /dev/graphics/fb2 -- %s.", strerror(errno));
			free(dev);
			return -EFAULT;
			}
	*device = &(dev->common);
	ALOGI("SublcdStub: open /dev/graphics/fb2 successfully.");

	return 0;
	}
static int sublcd_device_close(struct hw_device_t* device)
{
	ALOGI("SublcdStub: sublcd_device_close");
	struct sublcd_device_t* sublcd_device = (struct sublcd_device_t*)device;
	
		if(sublcd_device) {
			close(sublcd_device->fd);
			free(sublcd_device);
		}

	return 0;
}

//往上(HAL)接口函数和文件系统节点操作函数具体定义
static int sublcd_set_val(struct sublcd_device_t* dev, int val) {
	int iflight,ifsublcdTest;	
	if(iflight = light_sublcd() == -1){
		ALOGI("SublcdStub: iflight == -1");
		return -EFAULT;
	}
	return 0;
}
static int sublcd_get_val(struct sublcd_device_t* dev, int* val) {
	int ifdied_sublcd,ifsublcdTest_exit;
	if(ifdied_sublcd = died_sublcd() == -1){
		ALOGI("SublcdStub: iflight == -1");
		return -EFAULT;
	}
	return 0;
}
static int light_sublcd(){	
	char *aa = "200";
	int back_fd = -1;
    back_fd = open(DEVICE_NAME, O_RDWR);
    if (back_fd < 0) {
		ALOGI("SublcdStub: light_sublcd failed");
		return -EFAULT;
    }
    write(back_fd, aa, 3);    
    if(back_fd){
    	close(back_fd);
    }
    return 0;
}
static int died_sublcd(){	
	char *aa = "0";
	int back_fd = -1;
    back_fd = open(DEVICE_NAME, O_RDWR);
    if (back_fd < 0) {
		ALOGI("SublcdStub: died_sublcd failed");
		return -EFAULT;
    }
    write(back_fd, aa, 1);    
    if(back_fd){
    	close(back_fd);
    }
    return 0;
}

以上便是sublcd.c的全部内容,主要是定义相关方法接口供framework层调用驱动,并实现对内核驱动程序的访问。

需要注意的是:

  1. open函数直接打开的是文件系统节点,当打开失败的时候返回的值<0,可以此判断open函数是否成功。open函数的第二个参数是文件系统节点的打开方式权限定义,其中:O_RDONLY(只读)、O_WRONLY(只写)、O_RDWR(可读可写)……

  2. write函数是对文件系统节点写入需要写入的值,需要注意的是第一个参数是open函数的返回,第二个参数是需要写入的值,是字符串类型,最后一个参数是该段字符串的长度。Write函数的返回值是该函数的最后一个参数。

2.3/sublcd/Android.mk文件内容:

#android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
LOCAL_SHARED_LIBRARIES := liblog
LOCAL_SRC_FILES := sublcd.c
LOCAL_MODULE := sublcd.default
include $(BUILD_SHARED_LIBRARY)

需要注意的是LOCAL_MODULE:= sublcd.defaultsublcd便是上面所提到的模块ID,需要对应。


三、修改Android.mk文件

3.1、文件目录

/hardware/libhardware/modules/Android.mk

3.2、修改内容:

hardware_modules := ……sublcd ……

说明:在hardware_modules下添加对新增文件sublcd的编译。


至此便实现了硬件抽象层的方法接口,到hardware/libhardware/modules/sublcd下执行mm编译会在out/target/product/projectName/system/lib/hw生成sublcd.default.so。可使用adbpush直接导入到手机的/system/lib/hw/下,或者执行makesnod重新打包system.img,导入手机。


附:  

问题:HelloStub: failed to open /dev/hello -- Permission denied.

 解决:解决办法是类似于Linuxudev规则,打开Android源代码工程目录下,进入到system/core/rootdir目录,里面有一个名为ueventd.rc文件,往里面添加一行:

      /dev/hello0666 root root


以上是在驱动层的接口实现,在上层(应用层)怎么去调用这边封装好的接口呢?请参加下篇Bolg介绍:

· 应用层到驱动层的接口实现(二) ---- 应用框架层&&app应用层


  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Android底层接口驱动开发技术是指在Android操作系统中,为了使用硬件设备而开发接口驱动程序。 在Android系统中,底层接口用于实现与硬件设备之间的通信和交互。底层接口包括HAL(Hardware Abstraction Layer,硬件抽象层)和JNI(Java Native Interface,Java本地接口)。HAL负责抽象化硬件设备的功能,并提供统一的接口供上层框架和应用程序调用。JNI则提供了一种机制,使得Java代码可以与底层C/C++代码进行交互。 而驱动开发技术是指开发与特定硬件设备相关的驱动程序。驱动程序是一个软件模块,它负责处理硬件设备的通信和控制,使得操作系统和上层应用程序能够与硬件设备进行交互。在Android系统中,驱动程序通常以模块的形式存在,被加载到内核中。驱动程序需要与硬件设备之间进行交互,通过底层接口提供的函数和接口来完成数据的传输和控制。 在Android底层接口驱动开发的过程中,需要对硬件设备的功能和特性进行了解和研究,并根据设备的规格和文档进行开发和调试。开发者需要熟悉底层接口驱动程序的编程技术,掌握C/C++语言以及底层接口的使用方法。同时还需要了解Android系统的架构和内核机制,以便于将驱动程序正确地集成到系统中。 总之,Android底层接口驱动开发技术是开发与硬件设备相关的接口驱动程序的技术,它们是实现Android系统与硬件设备之间通信和交互的重要组成部分,需要开发者具备深入的硬件和系统知识,以及相关的编程技术。 ### 回答2: Android底层接口驱动开发技术是指在Android系统中通过编写底层接口驱动程序,与硬件进行交互的一种开发技术。 首先,Android底层接口是指在Android系统中与硬件进行交互的接口Android系统提供了一套接口,用于与底层硬件设备进行通信,如传感器、摄像头、WiFi、蓝牙等。开发者可以通过使用这些接口实现与硬件的交互功能。 其次,Android驱动开发技术是指在Android系统中编写驱动程序,使得Android系统能够正确地识别并使用硬件设备。Android系统支持多种硬件设备,如显示器、触摸屏、键盘等,每种设备都需要相应的驱动程序才能正常工作。开发者可以使用C/C++等编程语言编写驱动程序,然后将其编译为可执行文件,将其加载到Android系统中,使系统能够正确地识别和使用硬件设备。 在Android底层接口驱动开发技术中,开发者需要了解Linux内核和Android系统的架构,并熟悉C/C++编程语言。通过理解Android系统的硬件抽象层(HAL)和设备树(Device Tree)机制,开发者可以编写底层接口驱动程序,实现与硬件的交互。 总而言之,Android底层接口驱动开发技术是一项与硬件设备进行交互的开发技术。通过编写底层接口驱动程序,开发者可以实现Android系统与硬件设备的正常通信和使用。这对于Android系统的定制化开发和移植到特定硬件平台上非常重要。 ### 回答3: Android的底层接口驱动开发技术是指在Android操作系统中,开发人员可以使用底层接口驱动程序编写代码,以实现底层硬件的访问与控制。 首先,Android底层接口是指Android操作系统提供的一系列接口开发人员可以通过这些接口与底层硬件进行交互。例如,开发人员可以使用底层接口来控制手机的摄像头、传感器、蓝牙模块等硬件设备,并获取相应的数据。 其次,驱动开发技术是指开发人员可以编写底层驱动程序,将硬件设备与Android操作系统连接起来。通过编写驱动程序,Android系统可以识别并正确操作各种硬件设备。驱动程序的开发需要对硬件设备的底层工作原理有一定了解,并使用相应的编程技术来实现与硬件设备的通信。 在Android底层接口驱动开发技术中,需要掌握Linux内核的相关知识,因为Android操作系统基于Linux内核开发。了解Linux内核可以帮助开发人员理解Android底层接口实现方式和驱动程序的运行机制。 另外,掌握C/C++等底层编程语言也是必要的,因为底层接口驱动程序通常使用这些语言进行编写。熟练掌握编程语言可以更好地实现对底层硬件的控制和访问。 总之,Android底层接口驱动开发技术对于开发人员来说是一项重要的技能。掌握这些技术可以使开发人员更好地理解和利用Android操作系统的底层功能,从而实现更加高效和优质的应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值