天天看點

基于 Light 介紹安卓 8.0 HAL 變化前言HIDL 簡介相關檔案

文章目錄

  • 前言
  • HIDL 簡介
    • 啟動流程
    • HIDL 使用
    • Jni 流程: HIDL 用戶端使用
    • HIDL 服務端
  • 相關檔案
    • 0.【Java 安卓LED服務類】LightsService.java
    • 1.【JNI 用戶端實作】com_android_server_lights_LightsService.cpp
    • 2.【HIDL 客戶】ILight.與 HIDL 服務庫通信.hal
    • 3.【HIDL 客戶】LightAll.cpp.調用 HIDL 服務庫
    • 4.【HIDL 服務】[email protected].啟動注冊 HIDL 服務庫
    • 4.【HIDL 服務】service.cpp.向上注冊 HIDL 服務庫
    • 5.【HIDL 服務】Light.h
    • 6.【HIDL 服務】Light.cpp.加載調用傳統庫
    • 7.【HAL 實作】lights.c.傳統 HAL 庫
    • 8.【核心實作】leds-qpnp.c

前言

學習筆記,簡單介紹了 light 在 Android 8.0 上的整個調用流程

更新上添加下調用流程線,将各個檔案串起來

HIDL 簡介

一張圖開場

基于 Light 介紹安卓 8.0 HAL 變化前言HIDL 簡介相關檔案
基于 Light 介紹安卓 8.0 HAL 變化前言HIDL 簡介相關檔案
其實主要是就是将以前那種 Java-> Jni -> Hal -> Kernel 的結構變成了
	
	Java -> Jni -> Binder 用戶端 ====== Binder 通信 ======> Binder 服務端 -> Hal -> Kernel 

 	将 framework 與 Hal 之間的互動變成了 CS 結構了。
           

插播下 Java Binder 服務編寫框圖:

基于 Light 介紹安卓 8.0 HAL 變化前言HIDL 簡介相關檔案

C++ Binder 服務編寫框圖:

基于 Light 介紹安卓 8.0 HAL 變化前言HIDL 簡介相關檔案

啟動流程

// SystemServer.java (frameworks\base\services\java\com\android\server)
 import com.android.server.lights.LightsService;
 
 startBootstrapServices()  
    # 此函數可參考 BatteryService 流程分析
    mSystemServiceManager.startService(LightsService.class);
            // SystemServiceManager.java (frameworks\base\services\core\java\com\android\server)
            startService(Class<T> serviceClass)
                # 擷取類名
                final String name = serviceClass.getName();
                # 獲得構造函數: public LightsService(Context context)
                Constructor<T> constructor = serviceClass.getConstructor(Context.class);
                # 調用構造函數,建立類對象
                service = constructor.newInstance(mContext);
                        // LightsService.java (frameworks\base\services\core\java\com\android\server\lights)
                        // 構造函數:
                        LightsService(Context context)
                            super(context);

                            for (int i = 0; i < LightsManager.LIGHT_ID_COUNT; i++) {
                                mLights[i] = new LightImpl(i);
                            }
                
                
                # 添加到 SystemService 連結清單中管理,并啟動服務
                startService(service);
                    mServices.add(service);
                    service.onStart();
                            // LightsService.java (frameworks\base\services\core\java\com\android\server\lights)
                            onStart()
                                // 這是向 systemservice.java 注冊了一些回調,隻讓其調用使用?
                                // Publish the service so it is only accessible to the system process
                                // 讓其隻能在 system 程序中通路?
                                //      ./base/services/core/java/com/android/server/power/PowerManagerService.java:736:            
                                //          mBatteryManagerInternal = getLocalService(BatteryManagerInternal.class);
                                publishLocalService(LightsManager.class, mService);
           

HIDL 使用

// 接口檔案:
//  Z:\work\A306_eng\src\hardware\interfaces\light\2.0\ILight.hal
    package [email protected];

    interface ILight {

        /**
         * Set the provided lights to the provided values.
         *
         * @param type logical light to set
         * @param state describes what the light should look like.
         * @return status result of applying state transformation.
         */
        setLight(Type type, LightState state) generates (Status status);

        /**
         * Discover what indicator lights are available.
         *
         * @return types list of available lights
         */
        getSupportedTypes() generates (vec<Type> types);

    };

// 編譯檔案:
// Z:\work\A306_eng\src\hardware\interfaces\light\2.0\Android.bp
    filegroup {
        name: "[email protected]_hal",
        srcs: [
            "types.hal",
            "ILight.hal",
        ],
    }

    genrule {
        name: "[email protected]_genc++",
        tools: ["hidl-gen"],
        cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport [email protected]",
        srcs: [
            ":[email protected]_hal",
        ],
        out: [
            "android/hardware/light/2.0/types.cpp",
            "android/hardware/light/2.0/LightAll.cpp",
        ],
    }
    
    // 編譯工具: out/host/linux-x86/bin/hidl-gen 
    // 生成檔案:
    //      Z:\work\A306_eng\src\out\soong\.intermediates\hardware\interfaces\light\2.0\[email protected]_genc++\gen\android\hardware\light\2.0\LightAll.cpp
            getService(): 擷取 servicemanager 中的對應 binder 服務 
            BnHwLight::onTransact()# 伺服器端,調用具體子類提供服務操作硬體
                _hidl_mImpl->setLight(type, *state);
                
            BpHwLight::setLight(Type type, const LightState& state): # 用戶端,提供遠端調用服務端接口
                    1. 填充 Parcel 資料
                    2. 調用 remote() 通過 binder 調用到伺服器端執行
                    _hidl_err = remote()->transact(1 /* setLight */, _hidl_data, &_hidl_reply);
           

Jni 流程: HIDL 用戶端使用

// com_android_server_lights_LightsService.cpp (frameworks\base\services\core\jni)
static void setLight_native( JNIEnv* /* env */, jobject /* clazz */, jint light, jint colorARGB, jint flashMode, jint onMS, jint offMS,jint brightnessMode) 
    
    # HAL 服務擷取: HIDL 接口,從 servicemanager 中擷取 Light 服務
    sp<ILight> hal = LightHal::associate();
            // will return the hal if it exists the first time.
            sLight = ILight::getService();
                // Z:\work\A306_eng\src\out\soong\.intermediates\hardware\interfaces\light\2.0\[email protected]_genc++\gen\android\hardware\light\2.0\LightAll.cpp
                ::android::sp<ILight> ILight::getService(const std::string &serviceName, const bool getStub) 
                        const sp<::android::hidl::manager::V1_0::IServiceManager> sm = defaultServiceManager();
                        Return<Transport> transportRet = sm->getTransport(ILight::descriptor, serviceName);
                        
                       
                        if (getStub || vintfPassthru || vintfLegacy) {
                            
                            # 擷取 PassthroughServiceManager 服務 
                            const sp<::android::hidl::manager::V1_0::IServiceManager> pm = getPassthroughServiceManager();
              
                            Return<sp<::android::hidl::base::V1_0::IBase>> ret = pm->get(ILight::descriptor, serviceName);
                                    // ServiceManagement.cpp (system\libhidl\transport)
                                    struct PassthroughServiceManager : IServiceManager {
                                                        Return<sp<IBase>> get(const hidl_string& fqName,
                                                                              const hidl_string& name)
                                    {
                                        # PassthroughServiceManager 的 get(const hidl_string& fqName, const hidl_string& name)
                                        # 函數根據傳入的 fqName=([email protected]::ICameraProvider"),
                                        
                                        # 擷取目前的接口名ICameraProvider,
                                        #   拼接出後面需要載入的函數名:HIDL_FETCH_ICameraProvider 和庫名字:
                                        #           [email protected]
                                        
                                        std::string stdFqName(fqName.c_str());
                                        //fqName looks like [email protected]::IFoo
                                        size_t idx = stdFqName.find("::");

                                        if (idx == std::string::npos ||
                                                idx + strlen("::") + 1 >= stdFqName.size()) {
                                            LOG(ERROR) << "Invalid interface name passthrough lookup: " << fqName;
                                            return nullptr;
                                        }

                                        std::string packageAndVersion = stdFqName.substr(0, idx);
                                        std::string ifaceName = stdFqName.substr(idx + strlen("::"));

                                        const std::string prefix = packageAndVersion + "-impl";
                                        const std::string sym = "HIDL_FETCH_" + ifaceName;
                                        
                                        

                                        # 接着通過 dlopen 載入 /vendor/lib/hw/[email protected];
                                        #   通過 dlsym 載入 HIDL_FETCH_ICameraProvider 函數
                                        # 至此正式進入cameraprovider的implement

                                        
                                        std::vector<std::string> libs = search(path, prefix, ".so");
                                        handle = dlopen(fullPath.c_str(), dlMode);
                                        IBase* (*generator)(const char* name);
                                        *(void **)(&generator) = dlsym(handle, sym.c_str());
                                        IBase *interface = (*generator)(name.c_str());
                                                #################################################################
                                                # 調用 HIDL 服務入口函數
                                                #################################################################
                                                // Z:\work\A306_eng\src\hardware\interfaces\light\2.0\default\Light.cpp
                                                ILight* HIDL_FETCH_ILight(const char* /* name */) {
                                                    std::map<Type, light_device_t*> lights;

                                                    for(auto const &pair : kLogicalLights) {
                                                        Type type = pair.first;
                                                        const char* name = pair.second;

                                                        light_device_t* light = getLightDevice(name);
                                                                    #############################################
                                                                    # 老 HAL 庫加載
                                                                    #############################################
                                                                    light_device_t* getLightDevice(const char* name)
                                                                        int ret = hw_get_module (LIGHTS_HARDWARE_MODULE_ID, &hwModule);
                                                                                    // Lights.c (hardware\qcom\display\liblight)
                                                                                        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 = "Google, Inc.",
                                                                                            .methods = &lights_module_methods,
                                                                                        };

                                                                                        static struct hw_module_methods_t lights_module_methods = {
                                                                                            .open =  open_lights,
                                                                                        };

                                                                        
                                                                        ret = hwModule->methods->open(hwModule, name,reinterpret_cast<hw_device_t**>(&lightDevice));
                                                                                // Light.cpp (vendor\qcom\proprietary\fastmmi\module\light)
                                                                                open_lights(const struct hw_module_t* module, char const* name,struct hw_device_t** device)
                                                                                    set_light = set_light_notifications;
                                                                                            handle_speaker_battery_locked(dev);
                                                                                                set_speaker_light_locked(dev, &g_notification);
                                                                                                    // [email protected] 20180111 begein
                                                                                                    // 閃爍之前清燈狀态
                                                                                                    write_int(RED_LED_FILE, 0);
                                                                                                    write_int(GREEN_LED_FILE, 0);
                                                                                                    write_int(BLUE_LED_FILE, 0);
                                                                                                            # 往 /sys/class/leds/green/brightness 這類的結點寫亮度值
                                                                                                            fd = open(path, O_RDWR);
                                                                                                            int bytes = snprintf(buffer, sizeof(buffer), "%d\n", value);
                                                                                                            ssize_t amt = write(fd, buffer, (size_t)bytes);
                                                                                                            close(fd);
                                                                                                    // [email protected] 20180111 end
                                                                                                
                                                                                                
                                                        if (light != nullptr) {
                                                            lights[type] = light;
                                                        }
                                                    }

                                                    if (lights.size() == 0) {
                                                        // Log information, but still return new Light.
                                                        // Some devices may not have any lights.
                                                        ALOGI("Could not open any lights.");
                                                    }

                                                    return new Light(std::move(lights));
                                                }
                        
                        
    Type type = static_cast<Type>(light);
    // 構造 LightState 狀态類 
    LightState state = constructState( colorARGB, flashMode, onMS, offMS, brightnessMode);
    ALOGD_IF_SLOW(50, "Excessive delay setting light");
    
    # HIDL 接口向 HAL 下發燈狀态給他處理
    Return<Status> ret = hal->setLight(type, state);
    
    # 處理通信傳回值
    processReturn(ret, type, state);
           

HIDL 服務端

// Z:\work\A306_eng\src\hardware\interfaces\light\2.0\default\Android.mk
    include $(CLEAR_VARS)
    LOCAL_MODULE_RELATIVE_PATH := hw
    LOCAL_PROPRIETARY_MODULE := true
    LOCAL_MODULE := [email protected]
    LOCAL_INIT_RC := [email protected]
    LOCAL_SRC_FILES := \
        service.cpp \

    LOCAL_SHARED_LIBRARIES := \
        liblog \
        libcutils \
        libdl \
        libbase \
        libutils \
        libhardware \

    LOCAL_SHARED_LIBRARIES += \
        libhidlbase \
        libhidltransport \
        [email protected] \

    include $(BUILD_EXECUTABLE)

    // 服務啟動:
    // Z:\work\A306_eng\src\hardware\interfaces\light\2.0\default\[email protected]
    service light-hal-2-0 /vendor/bin/hw/[email protected]
        class hal
        user system
        group system    
    
        // Z:\work\A306_eng\src\hardware\interfaces\light\2.0\default\service.cpp
        int main() {
            return defaultPassthroughServiceImplementation<ILight>();
                        /
                        // LegacySupport.h (system\libhidl\transport\include\hidl)
                        defaultPassthroughServiceImplementation(std::string name, size_t maxThreads = 1)
                            configureRpcThreadpool(maxThreads, true);
                                configureBinderRpcThreadpool(maxThreads, callerWillJoin);
                                    ProcessState::self()->setThreadPoolConfiguration(maxThreads, callerWillJoin /*callerJoinsPool*/);
                                
                                
                            status_t result = registerPassthroughServiceImplementation<Interface>(name);                                    
                                                registerPassthroughServiceImplementation( std::string name = "default")
                                                        sp<Interface> service = Interface::getService(name, true /* getStub */);
                                                        status_t status = service->registerAsService(name);
                                                
                            joinRpcThreadpool();
                                joinBinderRpcThreadpool();
                                    IPCThreadState::self()->joinThreadPool();
            
            
        }
           

相關檔案

下面将從上到下介紹:

0.【Java 安卓LED服務類】LightsService.java

public class LightsService extends SystemService {
	
	// 下一級 Jni 接口
	static native void setLight_native(int light, int color, int mode,
        int onMS, int offMS, int brightnessMode);
}
           

1.【JNI 用戶端實作】com_android_server_lights_LightsService.cpp

static const JNINativeMethod method_table[] = {
	    { "setLight_native", "(IIIIII)V", (void*)setLight_native },
	};

	static void setLight_native(
	        JNIEnv* /* env */,
	        jobject /* clazz */,
	        jint light,
	        jint colorARGB,
	        jint flashMode,
	        jint onMS,
	        jint offMS,
	        jint brightnessMode) {
	
	    if (!validate(light, flashMode, brightnessMode)) {
	        return;
	    }
	    sp<ILight> hal = LightHal::associate();
	
	    if (hal == nullptr) {
	        return;
	    }
	
	    Type type = static_cast<Type>(light);
	    LightState state = constructState(
	        colorARGB, flashMode, onMS, offMS, brightnessMode);
	
	    {
	        ALOGD_IF_SLOW(50, "Excessive delay setting light");
			
			// 下一級入口 
	        Return<Status> ret = hal->setLight(type, state);
	        processReturn(ret, type, state);
	    }
	}
           

2.【HIDL 客戶】ILight.與 HIDL 服務庫通信.hal

定義了 HIDL 接口 
	package [email protected];

	interface ILight {
	
	    /**
	     * Set the provided lights to the provided values.
	     *
	     * @param type logical light to set
	     * @param state describes what the light should look like.
	     * @return status result of applying state transformation.
	     */
	    setLight(Type type, LightState state) generates (Status status);
	
	    /**
	     * Discover what indicator lights are available.
	     *
	     * @return types list of available lights
	     */
	    getSupportedTypes() generates (vec<Type> types);
	
	};
           

3.【HIDL 客戶】LightAll.cpp.調用 HIDL 服務庫

::android::status_t BnHwLight::onTransact(
    uint32_t _hidl_code,
    const ::android::hardware::Parcel &_hidl_data,
    ::android::hardware::Parcel *_hidl_reply,
    uint32_t _hidl_flags,
    TransactCallback _hidl_cb)
			// 下一級接口
			Status _hidl_out_status = _hidl_mImpl->setLight(type, *state);
           

4.【HIDL 服務】[email protected].啟動注冊 HIDL 服務庫

service light-hal-2-0 /vendor/bin/hw/android.hardware.ligh[email protected]
	    class hal
	    user system
	    group system
           

4.【HIDL 服務】service.cpp.向上注冊 HIDL 服務庫

int main() {
		    return defaultPassthroughServiceImplementation<ILight>();    
		            /
		            // LegacySupport.h (system\libhidl\transport\include\hidl)
		            defaultPassthroughServiceImplementation(std::string name, size_t maxThreads = 1)
		                configureRpcThreadpool(maxThreads, true);
		                    configureBinderRpcThreadpool(maxThreads, callerWillJoin);
		                        ProcessState::self()->setThreadPoolConfiguration(maxThreads, callerWillJoin /*callerJoinsPool*/);
		                    
		                    
		                status_t result = registerPassthroughServiceImplementation<Interface>(name);                                    
		                                    registerPassthroughServiceImplementation( std::string name = "default")
		                                            sp<Interface> service = Interface::getService(name, true /* getStub */);
		                                            status_t status = service->registerAsService(name);
		                                    
		                joinRpcThreadpool();
		                    joinBinderRpcThreadpool();
		                        IPCThreadState::self()->joinThreadPool();
           

5.【HIDL 服務】Light.h

namespace android {
	namespace hardware {
	namespace light {
	namespace V2_0 {
	namespace implementation {
	
	using ::android::hardware::light::V2_0::ILight;
	using ::android::hardware::light::V2_0::LightState;
	using ::android::hardware::light::V2_0::Status;
	using ::android::hardware::light::V2_0::Type;
	using ::android::hardware::Return;
	using ::android::hardware::Void;
	using ::android::hardware::hidl_vec;
	using ::android::hardware::hidl_string;
	using ::android::sp;
	
	struct Light : public ILight {
	    Light(std::map<Type, light_device_t*> &&lights);
	
	    // Methods from ::android::hardware::light::V2_0::ILight follow.
	    Return<Status> setLight(Type type, const LightState& state)  override;
	    Return<void> getSupportedTypes(getSupportedTypes_cb _hidl_cb)  override;
	
	private:
	    std::map<Type, light_device_t*> mLights;
	};
	
	extern "C" ILight* HIDL_FETCH_ILight(const char* name);
	
	}  // namespace implementation
	}  // namespace V2_0
	}  // namespace light
	}  // namespace hardware
	}  // namespace android
           

6.【HIDL 服務】Light.cpp.加載調用傳統庫

ILight* HIDL_FETCH_ILight(const char* /* name */) {
	   std::map<Type, light_device_t*> lights;
	
	    for(auto const &pair : kLogicalLights) {
	        Type type = pair.first;
	        const char* name = pair.second;
	
			// 加載傳統 HAL 庫 
	        light_device_t* light = getLightDevice(name);
	
	        if (light != nullptr) {
	            lights[type] = light;
	        }
	    }
	
	    if (lights.size() == 0) {
	        // Log information, but still return new Light.
	        // Some devices may not have any lights.
	        ALOGI("Could not open any lights.");
	    }
	
	    return new Light(std::move(lights));
	}


	Light::Light(std::map<Type, light_device_t*> &&lights)
	  : mLights(std::move(lights)) {}
	
	// Methods from ::android::hardware::light::V2_0::ILight follow.
	Return<Status> Light::setLight(Type type, const LightState& state)  {
	    auto it = mLights.find(type);
	
	    if (it == mLights.end()) {
	        return Status::LIGHT_NOT_SUPPORTED;
	    }
	
	    light_device_t* hwLight = it->second;
	
	    light_state_t legacyState {
	        .color = state.color,
	        .flashMode = static_cast<int>(state.flashMode),
	        .flashOnMS = state.flashOnMs,
	        .flashOffMS = state.flashOffMs,
	        .brightnessMode = static_cast<int>(state.brightnessMode),
	    };
	
	    int ret = hwLight->set_light(hwLight, &legacyState);
	
	    switch (ret) {
	        case -ENOSYS:
	            return Status::BRIGHTNESS_NOT_SUPPORTED;
	        case 0:
	            return Status::SUCCESS;
	        default:
	            return Status::UNKNOWN;
	    }
	}	
           

7.【HAL 實作】lights.c.傳統 HAL 庫

/*
	 * The lights Module
	 */
	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 = "Google, Inc.",
	    .methods = &lights_module_methods,
	};

/**
 * module methods
 */

/** Open a new instance of a lights device using name */
static int open_lights(const struct hw_module_t* module, char const* 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)) {
        char property[PROPERTY_VALUE_MAX];
        property_get("persist.extend.brightness", property, "0");

        if(!(strncmp(property, "1", PROPERTY_VALUE_MAX)) ||
           !(strncmp(property, "true", PROPERTY_VALUE_MAX))) {
            property_get("persist.display.max_brightness", property, "255");
            g_brightness_max = atoi(property);
            set_brightness_ext_init();
            set_light = set_light_backlight_ext;
        } else

			// 調用接口 set_light , 上層會調用到這裡來
            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 if (0 == strcmp(LIGHT_ID_BUTTONS, name)) {
        if (!access(BUTTON_FILE, F_OK)) {
          // enable light button when the file is present			  
          set_light = set_light_buttons;
        } else {
          return -EINVAL;
        }
    }
    else if (0 == strcmp(LIGHT_ID_ATTENTION, name))
        set_light = set_light_attention;
    else
        return -EINVAL;

    pthread_once(&g_init, init_globals);

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

    if(!dev)
        return -ENOMEM;

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

    dev->common.tag = HARDWARE_DEVICE_TAG;
    dev->common.version = LIGHTS_DEVICE_API_VERSION_2_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;
}


# 更新燈則通過 sys/class/led/xxx/bright 來操作的
// char const*const RED_LED_FILE    = "/sys/class/leds/red/brightness";
set_speaker_light_locked(struct light_device_t* dev,
    struct light_state_t const* state)
		write_int(RED_LED_FILE, 0);
			int bytes = snprintf(buffer, sizeof(buffer), "%d\n", value);
    		ssize_t amt = write(fd, buffer, (size_t)bytes);
           

8.【核心實作】leds-qpnp.c

【充電 CHG_LED 可用紅燈配置流程】:
	// Msm8937-pmi8940-mtp.dtsi (kernel\msm-3.18\arch\arm64\boot\dts\qcom)
	    &pmi8940_charger {
	        qcom,battery-data = <&mtp_batterydata>;
	        qcom,chg-led-sw-controls;
	        qcom,chg-led-support;
	    };
	
	    解析使用位置:Qpnp-smbcharger.c (kernel\msm-3.18\drivers\power)
	        static int __init smbchg_init(void)
	            // static struct spmi_driver smbchg_driver = {
	            //     .driver		= {
	            //         .name		= "qpnp-smbcharger",
	            //         .owner		= THIS_MODULE,
	            //         .of_match_table	= smbchg_match_table,
	            //         .pm		= &smbchg_pm_ops,
	            //     },
	            //     .probe		= smbchg_probe,
	            //     .remove		= smbchg_remove,
	            //     .shutdown	= smbchg_shutdown,
	            // };
	            return spmi_driver_register(&smbchg_driver);
	
	
	        smbchg_probe(struct spmi_device *spmi)
	            smb_parse_dt(struct smbchg_chip *chip)
	                chip->cfg_chg_led_support =	of_property_read_bool(node, "qcom,chg-led-support");
	                
	            。。。    
	            if (chip->cfg_chg_led_support && chip->schg_version == QPNP_SCHG_LITE)    
	                rc = smbchg_register_chg_led(chip);
	                        chip->led_cdev.name = "red";
	                        chip->led_cdev.brightness_set = smbchg_chg_led_brightness_set;
	                        chip->led_cdev.brightness_get = smbchg_chg_led_brightness_get;
	                        rc = led_classdev_register(chip->dev, &chip->led_cdev);