android系统开发(七)-背光模块

来源:互联网 发布:javascript实战教程 编辑:程序博客网 时间:2024/05/18 00:11

1,总论
背光模块属于HAL层开发,HAL层开发,用一句话来概括就是定义一个hardware.h中定义的名称为宏HAL_MODULE_INFO_SYM的hw_module_t结构体,
然后实现结构体的相关内容

2,驱动方面的准备
简单的嵌入式linux驱动,编写LCD背光驱动,并提供接口给上层修改,我所用的是直接修改接口文件,接口如下:
/sys/class/backlight/pwm-backlight/brightness  这个是亮度调节
/sys/class/backlight/pwm-backlight/max_brightness 这个是最大亮度,按照android系统的要求应该设置成255
控制亮度直接写brightness文件即可
背光驱动主要是通过PWM来完成,这里不详细说明。

3,需要包含的头文件
/hardware/libhardware/include/hardware目录下的hardware.h和lights.h
其中hardware.h中定义了通用硬件模块,lights.h中定义了背光设备相关的内容

4,android已有的硬件模块在/hardware/libhardware/modules目录下,为了区分,我们开发的背光模块放置在如下的目录:
vendor/ardent/merlin/lights目录下,编译成lights.default.so放置到/system/lib/hw目录下,模块命名规则可以
参考上一节的内容。

5,修改vendor/ardent/merlin目录下AndroidBoard.mk文件,添加如下内容:
include $(LOCAL_PATH)/lights/Mdroid.mk

6,lights目录新建Mdroid.mk文件,内容如下:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
LOCAL_SRC_FILES:= lights.c

LOCAL_SHARED_LIBRARIES := /
    libutils /
    libcutils /
    libhardware

LOCAL_PRELINK_MODULE := false

LOCAL_MODULE := lights.default

include $(BUILD_SHARED_LIBRARY)

7,lights目录下新建一个lights.c文件,如下:
const struct hw_module_t HAL_MODULE_INFO_SYM = {
    .tag = HARDWARE_MODULE_TAG,
    .version_major = 1,
    .version_minor = 0,
    .id = LIGHTS_HARDWARE_MODULE_ID,
    .name = "lights module",
    .author = "allen",
    .methods = NULL,
};

8,上面的内容可以直接编译通过,但是因为我将其methods部分指向了空指针,因此没有任何功能,下面来实现此部分
hw_module_t机构体的methods成员是一个指向hw_module_methods_t结构体的一个指针,hw_module_methods_t结构体定义如下:
typedef struct hw_module_methods_t {
    int (*open)(const struct hw_module_t* module, const char* id,struct hw_device_t** device);
} hw_module_methods_t;
据此我们定义一个hw_module_methods_t类型的参数lights_module_methods如下:
struct hw_module_methods_t lights_module_methods = {
    .open = lights_device_open
};
然后将上面的methods由NULL改成lights_module_methods

9,接下来就是定义lights_device_open函数了,此函数的参数和返回值由hw_module_methods_t结构体的open成员决定,此函数定义如下:
static int lights_device_open(const struct hw_module_t *module,const char *id, struct hw_device_t **device)
从lights_device_open函数的参数来看,第一个参数和第二个参数是常量,第三个参数是 一个指向hw_device_t结构体的指针,因此可以断定
实现此函数也就是要完成第三个参数的内容,详细的内容我们可以参考直接调用该函数的内容,在frameworks/base/services/jni目录下的
com_android_server_LightsService.cpp文件中,内容如下:
static light_device_t* get_device(hw_module_t* module, char const* name)
{
    int err;
    hw_device_t* device;
    err = module->methods->open(module, name, &device);
    if (err == 0) {
        return (light_device_t*)device;//device由hw_device_t指针强制转换成light_device_t指针
    } else {
        return NULL;
    }
}

static jint init_native(JNIEnv *env, jobject clazz)
{
    int err;
    hw_module_t* module;
    Devices* devices;
   
    devices = (Devices*)malloc(sizeof(Devices));

    err = hw_get_module(LIGHTS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
    if (err == 0) {
        devices->lights[LIGHT_INDEX_BACKLIGHT]
                = get_device(module, LIGHT_ID_BACKLIGHT);
        devices->lights[LIGHT_INDEX_KEYBOARD]
                = get_device(module, LIGHT_ID_KEYBOARD);
        devices->lights[LIGHT_INDEX_BUTTONS]
                = get_device(module, LIGHT_ID_BUTTONS);
        devices->lights[LIGHT_INDEX_BATTERY]
                = get_device(module, LIGHT_ID_BATTERY);
        devices->lights[LIGHT_INDEX_NOTIFICATIONS]
                = get_device(module, LIGHT_ID_NOTIFICATIONS);
        devices->lights[LIGHT_INDEX_ATTENTION]
                = get_device(module, LIGHT_ID_ATTENTION);
        devices->lights[LIGHT_INDEX_BLUETOOTH]
                = get_device(module, LIGHT_ID_BLUETOOTH);
        devices->lights[LIGHT_INDEX_WIFI]
                = get_device(module, LIGHT_ID_WIFI);
    } else {
        memset(devices, 0, sizeof(Devices));
    }

    return (jint)devices;
}
从上面的内容我们可以看出lights_device_open的第一个参数是JNI层用hw_get_module所获得,第二个参数根据设备的不同有很多种情况
该参数的内容定义在lights.h中,全部情况如下:
#define LIGHT_ID_BACKLIGHT          "backlight"
#define LIGHT_ID_KEYBOARD           "keyboard"
#define LIGHT_ID_BUTTONS            "buttons"
#define LIGHT_ID_BATTERY            "battery"
#define LIGHT_ID_NOTIFICATIONS      "notifications"
#define LIGHT_ID_ATTENTION          "attention"
#define LIGHT_ID_BLUETOOTH          "bluetooth"
#define LIGHT_ID_WIFI               "wifi"
lights调节有背光,键盘,按键,电池,通知,提醒,蓝牙和WIF
第三个参数是一个指向一个hw_device_t的指针,但是com_android_server_LightsService.cpp文件中的背光调节函数定义如下:
static void setLight_native(JNIEnv *env, jobject clazz, int ptr,
        int light, int colorARGB, int flashMode, int onMS, int offMS, int brightnessMode)
{
    Devices* devices = (Devices*)ptr;
    light_state_t state;

    if (light < 0 || light >= LIGHT_COUNT || devices->lights[light] == NULL) {
        return ;
    }

    memset(&state, 0, sizeof(light_state_t));
    state.color = colorARGB;
    state.flashMode = flashMode;
    state.flashOnMS = onMS;
    state.flashOffMS = offMS;
    state.brightnessMode = brightnessMode;

    devices->lights[light]->set_light(devices->lights[light], &state);
}
get_device函数中将hw_device_t指针强制转换成light_device_t指针给调节背光用,而light_device_t定义如下:
struct light_device_t {
    struct hw_device_t common;
    int (*set_light)(struct light_device_t* dev,
            struct light_state_t const* state);
};
因此在实现lights_device_open的第三个参数的时候,我们应该定义一个light_device_t类型结构体,然后
将起common域的指针地址传递过去。这样虽然传递的是一个hw_device_t指针地址,但是JNI层可以将其强制转换
成light_device_t指针地址用,否则devices->lights[light]->set_light就会起不到作用了。实现如下:
static int lights_device_open(const struct hw_module_t *module,const char *id, struct hw_device_t **device)
{
    struct light_device_t *dev = NULL;
    int resvalue = -1;
    dev = calloc(sizeof(struct light_device_t),1);
    dev->common.tag = HARDWARE_DEVICE_TAG;
    dev->common.version = 0;
    dev->common.module = (struct hw_module_t *)module;
    dev->common.close = lights_device_close;
    if(!strcmp(id, LIGHT_ID_BACKLIGHT))
    {
        dev->set_light = lcd_set_light;
        resvalue = 0;
    }
    else
    {
        dev->set_light = other_set_light;
        resvalue = 0;
    }
    *device = &dev->common;
    return resvalue;
}

10,实现lights_device_close,lcd_set_light和other_set_light,这个主要是调用驱动提供的接口直接控制硬件,举例如下:
static int lights_device_close(struct hw_device_t* device)
{
    struct light_device_t *m_device = (struct light_device_t *)device;
    if(m_device)
        free(m_device);
    return 0;
}
static int lcd_set_light(struct light_device_t* dev,struct light_state_t const* state)
{
    int fd = -1;
    int bytes = 0;
    int rlt = -1;
    unsigned char brightness = ((77*((state->color>>16)&0x00ff))
                               + (150*((state->color>>8)&0x00ff))
                               + (29*(state->color&0x00ff))) >> 8;
    fd = open("/sys/class/backlight/pwm-backlight/brightness", O_RDWR);
    if(fd>0)
    {
        char buffer[20];
     memset(buffer, 0, 20);
    bytes = sprintf(buffer, "%d", brightness);
    rlt = write(fd, buffer, bytes);
        if(rlt>0)
        {
           close(fd);
           return 0;
        }
    }
    close(fd);
    return -1;
}

static int other_set_light(struct light_device_t* dev,struct light_state_t const* state)
{
    return 0;
}

11,因为上面调节背光是通过写/sys/class/backlight/pwm-backlight/brightness文件来完成,因此一定要设置该文件的权限,
在init.xxx.rc文件中添加如下的内容:
    # for control LCD backlight
    chown system system /sys/class/backlight/pwm-backlight/brightness
    chmod 0666 /sys/class/backlight/pwm-backlight/brightness

12,修改完成后经验证亮度调节可用,上面的例子只是实现了lights部分功能,如果需要完成所有的功能,请参考hardware.h, lights.h和com_android_server_LightsService.cpp文件中的内容。

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/jiajie961/archive/2010/11/23/6030405.aspx

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 开车撞人骨折了怎么办 开车撞人后住院怎么办 骑车撞到小孩怎么办 开庭不通知家属怎么办 撞人后对方起诉怎么办 驾驶证被别人盗用怎么办 驾照分数扣完了怎么办 驾照分被盗扣怎么办 驾驶证分数不够扣怎么办 驾驶证分数扣完了怎么办 驾驶证分被骗了怎么办 自驾游穷游睡车上洗衣服怎么办 考生密码忘了怎么办 中国公民在菲律宾遇害怎么办 鞋有胶皮味怎么办 pvc下水管渗漏水怎么办 5s主板漏电怎么办 飞机转机延误了怎么办 家里有小丑雕像怎么办 巴黎被抢了怎么办 博彩公司压护照怎么办 跑马拉松手机怎么办 高跟鞋绒面掉皮怎么办 白裤子透短裤怎么办 崖柏珠子脏了怎么办 唱歌总是气息不足怎么办 幻影wifi闪退怎么办 镇魔曲转职后装备怎么办 起诉离婚对方不同意怎么办 后宫无人岛掉血了怎么办 老公不同意离婚该怎么办 爸妈闹离婚我该怎么办 爸妈闹离婚了我怎么办 苹果迅雷链接打不开怎么办 眼睛有灼烧感怎么办 爸妈关系不好怎么办 眼睛下面辣到了怎么办 老公隐瞒妻子欠下巨债怎么办 家庭琐事吵架后怎么办 控制不住想哭怎么办 执行死刑已怀孕怎么办