Android 에서 HAL 은 어떻게 상부 에 인터페이스 정 리 를 제공 합 니까?

참고 문헌:
http://blog.csdn.net/luoshengyang/article/details/6573809
http://blog.csdn.net/hongtao_liu/article/details/6060734
본 고 를 읽 을 때 먼저 상기 두 편의 글 을 조회 하 는 것 을 권장 합 니 다. 본 고 는 상기 두 편의 글 이 HAL 에서 상부 인터페이스 화제 에 대한 정리 입 니 다.
1. HAL 이 뭐야?
HAL 의 전 칭 은 Hardware Abstraction Layer, 즉 하드웨어 추상 층 입 니 다. 그 구 조 는 다음 과 같 습 니 다.
안 드 로 이 드 의 HAL 은 일부 하드웨어 공급 업 체 의 지적 재산권 을 보호 하기 위해 제 기 된 것 으로, Liux 의 GPL 속박 을 피하 기 위해 제 기 된 것 이다.아 이 디 어 는 하드웨어 를 제어 하 는 동작 을 모두 Android HAL 에 넣 었 고 Liux driver 는 간단 한 데이터 상호작용 만 완 성 했 을 뿐 하드웨어 레지스터 공간 을 user space 에 직접 투사 했다.한편, Android 는 Aparch 를 기반 으로 하 는 license 이기 때문에 하드웨어 업 체 는 바 이 너 리 코드 만 제공 할 수 있 기 때문에 Android 는 오픈 플랫폼 일 뿐 오픈 소스 플랫폼 이 아니다.안 드 로 이 드 가 GPL 을 따 르 지 않 기 때문에 Greg Kroah - Hartman 은 2.6.33 커 널 에서 Andorid 드라이브 를 Liux 에서 삭제 한 것 일 수도 있 습 니 다.GPL 과 하드웨어 업 체 는 아직 봉합 할 수 없 는 균열 이 있다.안 드 로 이 드 가 이 문 제 를 잘 처리 하 는 것 도 쉽 지 않다.
요약 하면 Android HAL 이 존재 하 는 이 유 는 다음 과 같 습 니 다.
1. 모든 하드웨어 장치 에 표준 Liux kernel 인터페이스 가 있 는 것 은 아 닙 니 다.
2. KERNEL DRIVER 는 GPL 의 저작권 과 관련된다.일부 설비 제조 사 들 은 하드웨어 구동 을 공개 하 는 이유 가 없어 서 HAL 방식 으로 GPL 을 돌 았 다.
3. 일부 하드웨어 에 대해 Android 는 특별한 수요 가 있 습 니 다.
2 인터페이스 와 관련 된 몇 개의 구조 체
먼저 HAL 의 상부 인터페이스 와 관련 된 세 개의 구조 체 를 살 펴 보 자.
struct hw_module_t;       //    
struct hw_module_methods_t;      //    
struct hw_device_t;              //    
이 몇 가지 데이터 구 조 는 안 드 로 이 드 작업 디 렉 터 리 / hardware / libhardware / include / hardware / hardware. h 파일 에서 정 의 됩 니 다.
해명
일반적으로 HAL 관련 코드 를 쓸 때 이 hardware. h 헤더 파일 을 포함해 야 하기 때문에 이 헤더 파일 의 내용 을 먼저 알 아 볼 필요 가 있 습 니 다.
/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ANDROID_INCLUDE_HARDWARE_HARDWARE_H
#define ANDROID_INCLUDE_HARDWARE_HARDWARE_H

#include 
#include 

#include 
#include 

__BEGIN_DECLS

/*
 * Value for the hw_module_t.tag field
 */

#define MAKE_TAG_CONSTANT(A,B,C,D) (((A) << 24) | ((B) << 16) | ((C) << 8) | (D))

#define HARDWARE_MODULE_TAG MAKE_TAG_CONSTANT('H', 'W', 'M', 'T')
#define HARDWARE_DEVICE_TAG MAKE_TAG_CONSTANT('H', 'W', 'D', 'T')

struct hw_module_t;
struct hw_module_methods_t;
struct hw_device_t;

/**
 * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM
 * and the fields of this data structure must begin with hw_module_t
 * followed by module specific information.
 */
//                HAL_MODULE_INFO_SYM       ,             hw_module_t
typedef struct hw_module_t {
    /** tag must be initialized to HARDWARE_MODULE_TAG */
    uint32_t tag;

    /** major version number for the module */
    uint16_t version_major;

    /** minor version number of the module */
    uint16_t version_minor;

    /** Identifier of module */
    const char *id;

    /** Name of this module */
    const char *name;

    /** Author/owner/implementor of the module */
    const char *author;

    /** Modules methods */
    //      ,  hw_module_methods_t*
    struct hw_module_methods_t* methods;

    /** module's dso */
    void* dso;

    /** padding to 128 bytes, reserved for future use */
    uint32_t reserved[32-7];

} hw_module_t;

typedef struct hw_module_methods_t {                 //           ,        open  
    /** Open a specific device */
    int (*open)(const struct hw_module_t* module, const char* id, //    open               struct hw_device_t**
            struct hw_device_t** device);
} hw_module_methods_t;

/**
 * Every device data structure must begin with hw_device_t
 * followed by module specific public methods and attributes.
 */
//                    hw_device_t  ,             
typedef struct hw_device_t {
    /** tag must be initialized to HARDWARE_DEVICE_TAG */
    uint32_t tag;

    /** version number for hw_device_t */
    uint32_t version;

    /** reference to the module this device belongs to */
    struct hw_module_t* module;

    /** padding reserved for future use */
    uint32_t reserved[12];

    /** Close this device */
    int (*close)(struct hw_device_t* device);

} hw_device_t;

/**
 * Name of the hal_module_info
 */
#define HAL_MODULE_INFO_SYM         HMI

/**
 * Name of the hal_module_info as a string
 */
#define HAL_MODULE_INFO_SYM_AS_STR  "HMI"

/**
 * Get the module info associated with a module by id.
 *
 * @return: 0 == success, <0 == error and *module == NULL
 */
int hw_get_module(const char *id, const struct hw_module_t **module);

/**
 * Get the module info associated with a module instance by class 'class_id'
 * and instance 'inst'.
 *
 * Some modules types necessitate multiple instances. For example audio supports
 * multiple concurrent interfaces and thus 'audio' is the module class
 * and 'primary' or 'a2dp' are module interfaces. This implies that the files
 * providing these modules would be named audio.primary..so and
 * audio.a2dp..so
 *
 * @return: 0 == success, <0 == error and *module == NULL
 */
int hw_get_module_by_class(const char *class_id, const char *inst,
                           const struct hw_module_t **module);

__END_DECLS

#endif  /* ANDROID_INCLUDE_HARDWARE_HARDWARE_H */

이상 의 내용 을 통 해 알 수 있 습 니 다 (typedef struct hw module t, typedef struct hw device t). 사용자 정의 장치 가 구동 하 는 HAL 층 을 쓰 려 면 먼저 두 개의 데이터 구 조 를 사용자 정의 해 야 합 니 다.
우리 가 할 장치 이름 이 XXX 라 고 가정 하면:
헤더 파일 에서 정의: XXX. h
/*    ID*/
#define XXX_HARDWARE_MODULE_ID "XXX"

/*       */
// hardware.h  hw_module_t     ,xxx_module_t         hw_module_t  ,             ,        ,
//             
struct xxx_module_t {
	struct hw_module_t common;
};

/*       */
// hardware.h  hw_device_t   ,     xxx_device_t         hw_device_t  ,             . 
struct xxx_device_t {
	struct hw_device_t common;
        //     HAL             
       int fd;
	int (*set_val)(struct xxx_device_t* dev, int val);
	int (*get_val)(struct xxx_device_t* dev, int* val);
};
주의: xxxdevice_t 의 구조 정의, 이것 이 야 말로 HAL 이 상부 에 인터페이스 함 수 를 제공 하 는 데이터 구조 이 고 그 구성원 은 우리 가 관심 을 가 지 려 는 인터페이스 함수 입 니 다.
다음은 파일 XXX. c 파일 에서 xxx 를 정의 합 니 다.module_t 의 변수:
/*      */
struct xxx_module_t HAL_MODULE_INFO_SYM = {    //      HAL_MODULE_INFO_SYM,       ,   Android HAL          ,
                                               // hardware.h  hw_module_t       .
       common: {
		tag: HARDWARE_MODULE_TAG,
		version_major: 1,
		version_minor: 0,
		id: XXX_HARDWARE_MODULE_ID,    //       
		name: MODULE_NAME,
		author: MODULE_AUTHOR,
		methods: &xxx_module_methods,  //      ,     
	}
};

위 에 HAL 이 있 음 을 알 아 챘 어 요.MODULE_INFO_SYM 변수의 멤버 common 에는 함수 목록 xxx 가 포함 되 어 있 습 니 다.module_methods, 이 구성원 함수 목록 은 로 컬 에서 사용자 정의 합 니 다.그러면 이 멤버 함수 열 은 HAL 이 상부 에 함 수 를 제공 하 는 곳 이 아 닐 까요?실망 입 니 다. 여기 가 아 닙 니 다. 앞에서 말씀 드 렸 듯 이 xxx 입 니 다.device_t 에서 정의 하 는 이 xxxmodule_methods 는 실제 적 으로 하나의 open 함수 만 제공 하 는 것 은 하나의 모듈 초기 화 함수 만 제공 하 는 것 과 같 습 니 다. 그 정 의 는 다음 과 같 습 니 다.
/*     */
static struct hw_module_methods_t xxx_module_methods = {
	open: xxx_device_open
};
위의 함수 목록 에 xxx 만 표시 되 어 있 음 을 알 수 있 습 니 다.device_open 함수, 이 함수 도 현지에서 이 루어 져 야 하 는 함수 입 니 다.앞에서 말 했 듯 이 이 함 수 는 모듈 초기 화 함수 에 불과 합 니 다.
그러면 HAL 은 도대체 xxx 를device_t 에서 정 의 된 인 터 페 이 스 는 위로 제 공 됩 니까?
위 에 있 는 이 함수 목록 중 유일한 xxx 를 보 세 요.device_open 의 정의:
static int xxx_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device) {
	struct xxx_device_t* dev;
	dev = (struct hello_device_t*)malloc(sizeof(struct xxx_device_t));//      
	
	if(!dev) {
		LOGE("Hello Stub: failed to alloc space");
		return -EFAULT;
	}

	memset(dev, 0, sizeof(struct xxx_device_t));
        // dev->common     ,
       dev->common.tag = HARDWARE_DEVICE_TAG;
	dev->common.version = 0;
	dev->common.module = (hw_module_t*)module;
	dev->common.close = xxx_device_close;
        // dev      
       dev->set_val = xxx_set_val;
	dev->get_val = xxx_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;
	}
        
        //  &(dev->common),      dev,  &(dev->common)!(common         close   ?)
	*device = &(dev->common);
	LOGI("Hello Stub: open /dev/hello successfully.");

	return 0;
}
경험 을 통 해 알 수 있 듯 이 보통 모듈 초기 화 를 할 때 모듈 의 인터페이스 함수 도 '등록' 합 니 다. 위 에 모듈 초기 화 함수 가 있 으 면 인 터 페 이 스 는 어디 에 등록 합 니까?그래서 우 리 는 * device = & (dev - > common) 를 찾 았 습 니 다.이 줄 코드, 그런데 문 제 는 이렇게 되면 호출 자 에 게 되 돌아 가 는 것 이 & (dev - > common) 가 아 닙 니까?이 dev - > common 은 하나의 모듈 만 포함 하고 인 터 페 이 스 를 닫 습 니 다!도대체 어떻게 된 거 야?왜 dev 로 바로 돌아 가지 않 습 니까? dev 에서 모든 HAL 상부 인 터 페 이 스 를 제공 하지 않 습 니까?
상술 한 문제 에 대답 하기 전에 이 xxx 를 먼저 봅 시다.device_open 함수 원형 입 니까? 아니면 hardware. h 헤더 파일 에서 다음 몇 줄 의 코드 를 찾 습 니까?
typedef struct hw_module_methods_t {
    /** Open a specific device */
    int (*open)(const struct hw_module_t* module, const char* id,
            struct hw_device_t** device);

} hw_module_methods_t;
이것 은 방법 목록 의 정의 입 니 다. 방법 목록 에 있 고 하나의 open 방법 만 요구 합 니 다. 즉, 모듈 초기 화 방법 에 해당 합 니 다. 또한 이 방법의 세 번 째 매개 변 수 는 유형 이 struct hw 임 을 명확 하 게 밝 혔 습 니 다.device_t * *, 사용자 정의 xxx 가 아 닙 니 다.device_t. 이것 은 open 함수 실현 에서 왜 dev 가 아 닌 & (dev - > common) 를 출력 하 는 지 를 번역 한 것 입 니 다. 원래 되 돌아 오 는 유형 은 hardware. h 중의 open 함수 원형 에서 hw 만 되 돌아 갈 수 있다 고 명확 하 게 밝 혔 습 니 다.device_t 타 입.
그런데 dev - > common 은 close 인터페이스 만 포함 되 지 않 습 니까?HAL 의 상층 부 로 서 HAL 이 제공 하 는 모든 인 터 페 이 스 를 어떻게 '볼 수 있 습 니까?'
다음은 HAL 상층 부 로 서 HAL 에서 돌아 온 dev - > common 을 어떻게 사용 하 는 지 살 펴 보 자.
참고: Ubuntu 에서 Android 하드웨어 추상 층 (HAL) 모듈 에 JNI 방법 을 작성 하여 자바 액세스 하드웨어 서비스 인 터 페 이 스 를 제공 합 니 다. 이 글 에서 몇 줄 의 코드 를 볼 수 있 습 니 다.
/*                        */  
static inline int hello_device_open(const hw_module_t* module, struct hello_device_t** device) {  
     return module->methods->open(module, HELLO_HARDWARE_MODULE_ID, (struct hw_device_t**)device);  
}  
이 를 통 해 알 수 있 듯 이 되 돌아 오 는 & (dev - > common) 는 결국 struce hello 에 게 돌아 갑 니 다.device_t * * 유형의 출력 변수 device, 다시 말 하면 유형 은 hwdevice_t 의 dev - > common 은 함수 open 을 초기 화하 고 돌아 오 면 강제로 xxx 로 전 환 됩 니 다.device_t. 사용 하 러 왔 습 니 다. 드디어 알 게 되 었 습 니 다. 그 렇 군요!또한, hardware. h 에서 xxxdevice_t 형식 에 대한 설명 이 있 습 니 다.
첫 번 째 멤버 의 유형 은 hw 여야 합 니 다.device_t, 원래 HAL 상층 부 에서 사용 할 때의 강제 전환 을 위 한 목적 이 었 습 니 다. 만약 xxxdevice_t 의 첫 번 째 멤버 유형 은 hw 가 아 닙 니 다.device_t. 그러면 HAL 상층 부 사용 중 강제 전환 은 의미 가 없습니다. 이 럴 때 HAL 이 제공 하 는 인 터 페 이 스 를 정말 볼 수 없습니다.
이 밖 에 hardware. h 헤더 파일 에 xxx 정 의 를 명 확 히 요구 합 니 다.module_t 타 입 시 첫 번 째 멤버 변수 타 입 은 hw 이 어야 함 을 명 확 히 요구 합 니 다.module_t. 이것 도 첫 번 째 구성원 변 수 를 쉽게 찾 고 로 컬 정의 방법 목록 을 찾 아 open 함 수 를 호출 하여 모듈 초기 화 를 하기 위해 서 입 니 다.
다시 말하자면 HAL 은 structxxx 를 통 해device_t. 이 구조 체 는 상부 에 인 터 페 이 스 를 제공 합 니 다.
즉, 인 터 페 이 스 는 structxxx 에 포함 된다.device_t. 이 구조 체 내.
구체 적 인 집행 은 struct xxx 를 통 해module_t HAL_MODULE_INFO_SYM 이라는 구조 체 변수의 함수 목록 구성원 의 open 함수 가 상부 로 되 돌아 갑 니 다.

좋은 웹페이지 즐겨찾기