zoukankan      html  css  js  c++  java
  • 8.3 Android灯光系统_编写HAL_lights.c

      

    注意在led-classes.c中定义的led_class_attrs[]所建立的文件的属性应该改为0666,否则应用程序无权操作它

     同时ledtrig-time.c里面对应新建的那几个delay_on/delay_off也要改为0666,这样才能写它

    Java: frameworks/base/services/core/java/com/android/server/lights/LightsService.java
    JNI: frameworks/base/services/core/jni/com_android_server_lights_LightsService.cpp
    Hal: lights.c  //参考google上搜索到的lights.c,我们的开发上只有HAL的so库,在vendor/friendly-arm/tiny4412/proprietary/lights_tiny4412.so

    默认配色:frameworks/base/core/res/res/values/config.xml
    电池灯:frameworks/base/services/core/java/com/android/server/BatteryService.java
    通知灯:frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java

    怎么写LIGHTS HAL
    a. 实现一个名为HMI的hw_module_t结构体
    b. 实现一个open函数, 它会根据name返回一个light_device_t结构体
    c. 实现多个light_device_t结构体,每一个对应一个DEVICE
     light_device_t结构体里第1个成员是hw_device_t结构体, 紧接着一个set_light函数



    设置LED状态:
    struct light_state_t {
    /**
    * The color of the LED in ARGB.
    *
    * Do your best here.
    * - If your light can only do red or green, if they ask for blue,
    * you should do green.
    * - If you can only do a brightness ramp, then use this formula:
    * unsigned char brightness = ((77*((color>>16)&0x00ff))
    * + (150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8;
    * - If you can only do on or off, 0 is off, anything else is on.
    *
    * The high byte should be ignored. Callers will set it to 0xff (which
    * would correspond to 255 alpha).
    */
    unsigned int color; // 把灯设为什么颜色, 或 把LCD的亮度设为什么

    /**
    * See the LIGHT_FLASH_* constants
    */
    int flashMode; // 是否闪烁, LIGHT_FLASH_NONE表示不闪
    int flashOnMS; // 亮的时间
    int flashOffMS;// 灭的时间

    /**
    * Policy used by the framework to manage the light's brightness.
    * Currently the values are BRIGHTNESS_MODE_USER and BRIGHTNESS_MODE_SENSOR.
    */
    int brightnessMode; // 表示LCD的背光亮度模式
    };

    lights.c文件

    注意在led-classes.c中定义的led_class_attrs[]所建立的文件的属性应该改为0666,否则应用程序无权操作它

    #define LOG_TAG “lights”

    #define LOG_NDEBUG 0  //加上这句就可以用ALOGV来打印了,否则打印信息被忽略

    #include <hardware/led_hal.h>

    #include <hardware/hardware.h>

    ......还有很多头文件.........

    //HAL里面操作led等就是往这些文件里面写值来完成的

    char const*const RED_LED_FILE                                = "sys/class/leds/led1/brightness";

    char const*const GREEN_LED_FILE          = "sys/class/leds/led2/brightness";

    char const*const BLUE_LED_FILE        = "sys/class/leds/led3/brightness";

    char const*const RED_LED_FILE_TRIGGER    =  "sys/class/leds/led1/trigger";

    char const*const GREEN_LED_FILE_TRIGGER  =  "sys/class/leds/led2/trigger";

    char const*const BLUE_LED_FILE_TRIGGER    =  "sys/class/leds/led3/trigger";

    char const*const RED_LED_FILE_DELAYON    =  "sys/class/leds/led1/delay_on";

    char const*const GREEN_LED_FILE_DELAYON    =  "sys/class/leds/led2/delay_on";

    char const*const BLUE_LED_FILE_DELAYON    =  "sys/class/leds/led3/delay_on";

    char const*const RED_LED_FILE_DELAYOFF    =  "sys/class/leds/led1/delay_off";

    char const*const GREEN_LED_FILE_DELAYOFF    =  "sys/class/leds/led2/delay_off";

    char const*const BLUE_LED_FILE_DELAYOFF    =  "sys/class/leds/led3/delay_off";

    char const*const LCD_BACKLIGHT_FILE = "/dev/backlight-1wire";//反汇编厂家提供的HAL层SO,lights_tiny4412.so,可以看到对背光灯的操作是该文件,在内核中搜索“backlight-1wire”,发现其是对应drivers/input/touchscreen/tiny4412_1wire_host.c中注册的设备,其是一个miscdevice,提供了file_operation结构体

    static pthread_one_t g_init = PTHREAD_ONCE_INIT;

    static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER;

    //通知灯和电池灯公用一个硬件

    static struct light_state_t g_notification;

    static struct light_state_t g_battery;

    static int write_int(const char *path,int value){

      int fd;

      static int already_warned = 0;

      fd = open(path,O_RDWR);

      if(fd<0)

      {

        if(already_warned == 0)

        {

          already_warned = 1;

        }

        return -errno;

      }

      char buffer[20];

      int bytes = snprintf(buffer,sizeof(buffer),"%s ",value);

      int written = write(fd,buffer,bytes);

      close(fd);

      return written == -1?-errno:0;

    }

    static int write_string(const char *path,const char *value){

      int fd;

      static int already_warned = 0;

      fd = open(path,O_RDWR);

      if(fd<0)

      {

        if(already_warned == 0)

        {

          already_warned = 1;

        }

        return -errno;

      }

      char buffer[20];

      int bytes = snprintf(buffer,sizeof(buffer),"%s ",value);

      int written = write(fd,buffer,bytes);

      close(fd);

      return written == -1?-errno:0;

    }

    static int is_lit(struct light_state_t const * state){

      return state->color & 0x00ffffff;

    }

    static int rgb_to_brightness(struct light_state_t const * state){

      int color = state->color & 0x00ffffff;

      return ((77*((color>>16)&0x00ff))+(150*((color>>8)&0x00ff))+(29*(color&0x00ff)))>>

    }

    static int set_light_backlight(struct light_device_t *dev,,struct light_state_t *state){

      int brightness = rgb_to_brightness(state);

      pthread_mutex_lock(&g_lock);

      //brightness在这里的范围是0-255,但是设备文件能接受的是0-127

      write_int(LCD_BACKLIGHT_FILR,brightness/2);

      pthread_mutex_unlock(&g_lock);

      return 0;

    }

    static void set_shared_light_locked(struct light_device_t *dev,struct light_state_t *state){

      int r,g,b;

      int delayOn,delayOff;

      r = (state->color>>16)&0xff;

      g = (state->color>>8)&0xff;

      b = (state->color)&0xff;

      delayOn = state->flashOnMS;

      delayOff = state->flashOffMS;

      if(state->flashMode != LIGHT_FLASH_NONE){

        write_string(RED_LED_FILE_TRIGGER,"trigger");

        write_string(GREEN_LED_FILE_TRIGGER,"trigger");

        write_string(BLUE_LED_FILE_TRIGGER,"trigger");

        write_int(RED_LED_FILR_DELAYON,delayOn);

        write_int(GREEN_LED_FILR_DELAYON,delayOn);

        write_int(BLUE_LED_FILR_DELAYON,delayOn);

        write_int(RED_LED_FILR_DELAYOFF,delayOff);

        write_int(GREEN_LED_FILR_DELAYOFF,delayOff);

        write_int(BLUE_LED_FILR_DELAYOFF,delayOff);

      }else{

        write_string(RED_LED_FILE_TRIGGER,"none");

        write_string(GREEN_LED_FILE_TRIGGER,"none");

        write_string(BLUE_LED_FILE_TRIGGER,"none");

        

      }

      write_int(RED_LED_FILE,r);

      write_int(GREEN_LED_FILE,g);

      write_int(BLUE_LED_FILE,b)

    }

    static void handle_shared_battery_locked(struct light_device_t *dev){

      if(is_lit(&g_notification)){//优先设置通知灯

        set_shared_light_locked(dev,&g_notification);

      }else{

        set_shared_light_locked(dev,&g_battery);

      }

    }

    static int set_light_battery((struct light_device_t *dev,struct light_state_t *state){

      pthread_mutex_lock(&g_lock);

      g_battery = *state;

      handle_shared_battery_locked(dev);

      pthread_mutex_unlock(&g_lock);

      return 0;

    }

    static int set_light_notifications((struct light_device_t *dev,struct light_state_t *state){

      pthread_mutex_lock(&g_lock);

      g_notification = *state;

      handle_shared_battery_locked(dev);

      pthread_mutex_unlock(&g_lock);

      return 0;

    }

     void init_globals(){

      pthread_mutex_init(&g_lock,NULL);

    }

    static int close_lights(struct light_device_t* dev){

    }

    static int open_lights(const struct hw_module_t *module,const char *name,struct hw_device_t **device)

    {

      int (*set_light)(struct light_device_t* dev,struct light_state_t const *state);

      if(0 == strcmp(LIGHT_ID_BACKLIGHT,name))

        set_light = set_light_backlight;

      }else if(0 == strcmp(LIGHT_ID_BATTERY,name))

        set_light = set_light_battery;

      }else if(0 == strcmp(LIGHT_ID_NOTIFICATIONS,name))

        set_light = set_light_notifications;

      }else{

        return -EINVAL;

      }

      pthread_once(&g_init,init_globals);

      struct light_device_t *dev = malloc(sizeof(struct light_device_t),GPKERNEL);

      memset(dev,0,sizeof(*dev));

      dev->common.tag = HARDWARE_DEVICE_TAG;

      dev->common.version = 0;

      dev->common.module = (struct hw_module_t *)module;

      dev->common.close = (int (*)(struct hw_device_t *))close_lights;

      dev->set_light = set_light;

      *device = (struct hw_device_t*)dev;

      return 0;

      *device = &led_dev //led_dev 的第一个成员就是hw_device_t ,他们地址一样

    }

    static struct hw_module_methods_t lights_module_methods {

      .open = open_lights,

    };

    struct hw_module_t HAL_MODULE_INFO_SYM = {

      .tag = HARDWARE_MODULE_TAG,

      .version_major = 1,

      .version_minor = 0,

      .id = LIGHTS_HARDWARE_MODULE_ID,

      .name ="Snoy_lights_module",

      .methods = lights_module_methods ;

    }

    在lights.c下添加Android.mk

    Android.mk内容如下:

    LOCAL_PATH := $(call my-dir)

    include $(CLEAR_VARS)

    LOCAL_MODULE := lights.tiny4412;

    LOCAL_MODULE_RELATIVE_PATH :=hw  //指定了so存在的目录在/system/lib/hw下

    LOCAL_C_INCLUDES := hardware/libhardware  //头文件

    LOCAL__SRC_FILES := lights.c  //源文件

    LOCAL_SHARED_LIBRARIES := liblog

    LOCAL_MODULE_TAGS := eng

    include $(BUILD_SHARED_LIBRARY)

    上传HAL:lights.c

     hardware/libhardware/modules/lights/lights.c

     hardware/libhardware/modules/lights/Android.mk

     修改:

    vi vendor friendly-arm/tiny4412/device-tiny4412.mk

    注释掉device-tiny4412.mk里面的(应该是去掉厂家提供的HAL)

    ifeq ($(BOARD_USES_PWMLIGHTS),false)

    #PRODUCT_COPY_FILES +=

    #      $(VENDOR_PATH)/proprietary/lights.tiny4412.so:system/lib/hw/lights.tiny4412.so

    endif

    编译:

    .setenv//先设置环境变量

    lunch//执行后选择23 full_tiny4412_eng  这里的eng对应的Android.mk里面设置的eng

    mmm hardware/libhardware/modules/lights -B  //强制编译C库

    make snod

    ./gen-img.sh

    对比下厂家提供HAL和我们自己生成的HAL,会发现不一样,同时该命令也能确保我们提供的lights.c已经编进system.img

    diff vendor/friendly-arm/tiny4412/proprietary/lights.tiny4412.so  out/target/product/tiny4412/system/lib/hw/lights.tiny4412.so

    更新system.img 和上一节中得到的zImage

  • 相关阅读:
    vue-cli脚手架工具构建&初始化vue项目
    2020/05/17 Github加速-DNS配置
    同时将本地git仓库提交到gitee和github
    git远程仓库在本地看不到&push 到远程仓库失败的解决方案
    stylus的使用-变量和函数
    webpack使用4-HRM热替换&SourceMap&解析es语法
    webpack使用3-plugin插件的使用
    webpack使用2-常用的几个loader的使用
    webpack基本使用
    spring框架里面的注入?
  • 原文地址:https://www.cnblogs.com/liusiluandzhangkun/p/9130005.html
Copyright © 2011-2022 走看看