Ubuntu 에 서 는 Android 에 하드웨어 추상 층(HAL)모듈 을 추가 하여 Linux 커 널 드라이버 에 접근 합 니 다.

Ubuntu Android 하드웨어 추상 층 간단하게 소개(HAL)글 에서 우 리 는 안 드 로 이 드 시스템 에서 하드웨어 를 위해 드라이버 를 만 드 는 방법 을 간략하게 소개 했다.쉽게 말 하면 하드웨어 드라이버 는 한편 으로 는 Linux 커 널 에 분포 되 고 다른 한편 으로 는 사용자 공간의 하드웨어 추상 층 에 분포 된다.이 어Ubuntu Android 시스템 에서 Linux 커 널 드라이버 구현 방법 작성글 에서 리 눅 스 커 널 에서 드라이버 를 만 드 는 방법 을 예 로 들 었 다.이 글 에서 우 리 는 안 드 로 이 드 시스템 하드웨어 드라이버 의 다른 측면 에서 어떻게 하드웨어 추상 층 에서 하드웨어 모듈 을 추가 하여 커 널 드라이버 와 상호작용 을 하 는 지 계속 소개 할 것 이다.이 글 에서 우 리 는 안 드 로 이 드 시스템 에서 장치 파일 을 만 들 때 리 눅 스 와 유사 한 udev 규칙 으로 장치 파일 모드 를 수정 하 는 방법 도 배 울 것 이다.
      1.Ubuntu Android 시스템 에서 Linux 커 널 드라이버 구현 자 를 작성 합 니 다.법 1 문 을 참조 하여 예제 커 널 구동 서 를 준비 합 니 다.이 커 널 드라이버 를 완성 하면 안 드 로 이 드 시스템 에서 세 개의 파일 을 얻 을 수 있 습 니 다.각각/dev/hello,/sys/class/hello/hello/val 과/proc/hello 입 니 다.본 논문 에서 우 리 는 장치 파일/dev/hello 를 통 해 하드웨어 추상 층 모듈 과 Linux 커 널 드라이버 모듈 을 연결 할 것 이다.
      2.hardware/libhardware/include/hardware 디 렉 터 리 에 들 어가 서 hello.h 파일 을 새로 만 듭 니 다.
      USER-NAME@MACHINE-NAME:~/Android$ cd hardware/libhardware/include/hardware
      USER-NAME@MACHINE-NAME:~/Android/hardware/libhardware/include/hardware$ vi hello.h
      hello.h 파일 의 내용 은 다음 과 같 습 니 다.

#ifndef ANDROID_HELLO_INTERFACE_H
#define ANDROID_HELLO_INTERFACE_H
#include <hardware/hardware.h>

__BEGIN_DECLS

/*    ID*/
#define HELLO_HARDWARE_MODULE_ID "hello"

/*       */
struct hello_module_t {
	struct hw_module_t common;
};

/*       */
struct hello_device_t {
	struct hw_device_t common;
	int fd;
	int (*set_val)(struct hello_device_t* dev, int val);
	int (*get_val)(struct hello_device_t* dev, int* val);
};

__END_DECLS

#endif
 여 기 는 Android 하드웨어 추상 층 규범 의 요구 에 따라 모듈 ID,모듈 구조 체 와 하드웨어 인터페이스 구조 체 를 각각 정의 합 니 다.하드웨어 인터페이스 구조 체 에서 fd 는 장치 파일 설명 자 를 표시 하고 우리 가 처리 할 장치 파일'/dev/hello',setval 과 getval 은 이 HAL 쌍 에 제공 하 는 함수 인터페이스 입 니 다.
      3.hardware/libhardware/modules 디 렉 터 리 에 들 어가 hello 디 렉 터 리 를 새로 만 들 고 hello.c 파일 을 추가 합 니 다.hello.c 의 내용 이 비교적 많 습 니 다.단계별 로 보 겠 습 니 다.
      우선 관련 헤더 파일 을 포함 하고 관련 구 조 를 정의 합 니 다.

#define LOG_TAG "HelloStub"

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

#define DEVICE_NAME "/dev/hello"
#define MODULE_NAME "Hello"
#define MODULE_AUTHOR "[email protected]"

/*         */
static int hello_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device);
static int hello_device_close(struct hw_device_t* device);

/*      */
static int hello_set_val(struct hello_device_t* dev, int val);
static int hello_get_val(struct hello_device_t* dev, int* val);

/*     */
static struct hw_module_methods_t hello_module_methods = {
	open: hello_device_open
};

/*      */
struct hello_module_t HAL_MODULE_INFO_SYM = {
	common: {
		tag: HARDWARE_MODULE_TAG,
		version_major: 1,
		version_minor: 0,
		id: HELLO_HARDWARE_MODULE_ID,
		name: MODULE_NAME,
		author: MODULE_AUTHOR,
		methods: &hello_module_methods,
	}
};
  여기 서 인 스 턴 스 변수 이름 은 HAL 이 어야 합 니 다.MODULE_INFO_SYM,tag 도 HARDWAREMODULE_TAG,이것 은 Android 하드웨어 추상 층 규범 에 규정된 것 입 니 다.
      정의 hellodevice_open 함수:

static int hello_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device) {
	struct hello_device_t* dev;dev = (struct hello_device_t*)malloc(sizeof(struct hello_device_t));
	
	if(!dev) {
		LOGE("Hello Stub: failed to alloc space");
		return -EFAULT;
	}

	memset(dev, 0, sizeof(struct hello_device_t));
	dev->common.tag = HARDWARE_DEVICE_TAG;
	dev->common.version = 0;
	dev->common.module = (hw_module_t*)module;
	dev->common.close = hello_device_close;
	dev->set_val = hello_set_val;dev->get_val = hello_get_val;

	if((dev->fd = open(DEVICE_NAME, O_RDWR)) == -1) {
		LOGE("Hello Stub: failed to open /dev/hello -- %s.", strerror(errno));free(dev);
		return -EFAULT;
	}

	*device = &(dev->common);
	LOGI("Hello Stub: open /dev/hello successfully.");

	return 0;
 DEVICE_NAME 는'/dev/hello'로 정의 한다.장치 파일 은 커 널 구동 에서 device 를 통과 하기 때 문 입 니 다.create 가 만 든,devicecreate 가 만 든 장치 파일 은 기본적으로 루트 사용자 만 읽 고 쓸 수 있 으 며 hellodevice_open 은 보통 상부 APP 에서 호출 되 는데 이런 APP 는 루트 권한 이 없 기 때문에 장치 파일 을 여 는 데 실 패 했 습 니 다.
      Hello Stub: failed to open /dev/hello -- Permission denied.   
       해결 방법 은 Linux 와 유사 한 udev 규칙 입 니 다.Android 소스 코드 프로젝트 디 렉 터 리 를 열 고 system/core/rootdir 디 렉 터 리 에 들 어 갑 니 다.그 안에 ueventd.rc 파일 이 있 습 니 다.그 안에 한 줄 을 추가 합 니 다.  
           /dev/hello 0666 root root    
         정의 hellodevice_close、hello_set_val 과 helloget_val 이 세 가지 함수:

static int hello_device_close(struct hw_device_t* device) {
	struct hello_device_t* hello_device = (struct hello_device_t*)device;

	if(hello_device) {
		close(hello_device->fd);
		free(hello_device);
	}
	
	return 0;
}

static int hello_set_val(struct hello_device_t* dev, int val) {
	LOGI("Hello Stub: set value %d to device.", val);

	write(dev->fd, &val, sizeof(val));

	return 0;
}

static int hello_get_val(struct hello_device_t* dev, int* val) {
	if(!val) {
		LOGE("Hello Stub: error val pointer");
		return -EFAULT;
	}

	read(dev->fd, val, sizeof(*val));

	LOGI("Hello Stub: get value %d from device", *val);

	return 0;
}
  4.hello 디 렉 터 리 에 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 := hello.c
      LOCAL_MODULE := hello.default
      include $(BUILD_SHARED_LIBRARY)
 주의:LOCALMODULE 의 정의 규칙,hello 뒤에 default 가 있 습 니 다.hello.default 는 우리 의 모듈 이 항상 하 드 이미지 추상 층 에 불 러 올 수 있 도록 보장 합 니 다.
       5.컴 파일:
      USER-NAME@MACHINE-NAME:~/Android$ mmm hardware/libhardware/modules/hello 
      컴 파일 에 성공 하면 out/target/produt/generic/system/lib/hw 디 렉 터 리 에서 hello.default.so 파일 을 볼 수 있 습 니 다.
      6.안 드 로 이 드 시스템 미 러 system.img 재 포장:
      USER-NAME@MACHINE-NAME:~/Android$ make snod
      다시 포장 하면 system.img 은 우리 가 정의 하 는 하드웨어 추상 층 모듈 hello.default 을 포함 합 니 다.
      비록 우 리 는 안 드 로 이 드 시스템 에서 우리 자신의 하드웨어 에 하드웨어 추상 층 모듈 을 추 가 했 지만,현재 자바 응용 프로그램 은 우리 의 하드웨어 에 접근 할 수 없다.JNI 방법 과 Android 의 Application Frameworks 층 에 API 인 터 페 이 스 를 추가 해 야 상위 애플 리 케 이 션 이 하드웨어 에 접근 할 수 있 습 니 다.다음 글 에서 우 리 는 이 시스템 과정 을 완성 하여 자바 응용 프로그램 에서 우리 가 맞 춤 형 하드웨어 를 방문 할 수 있 도록 할 것 이다.
이상 은 안 드 로 이 드 하드웨어 추상 층(HAL)모듈 이 리 눅 스 커 널 드라이버 에 접근 한 자 료 를 정리 한 것 이 며,추 후 계속 보완 해 안 드 로 이 드 소스 를 배 우 는 친구 들 에 게 도움 이 되 기 를 바 랍 니 다.

좋은 웹페이지 즐겨찾기