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 함수 가 상부 로 되 돌아 갑 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.