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

    本文转载自:https://blog.csdn.net/qq_33443989/article/details/77074411

    1>. 编写灯光系统的HAL层 之 HAL_light.c
    1<. 现在的关于灯光系统的JNI访问框架


    2<. 涉及的文件

    Java android_system_code/frameworks/base/services/core/java/com/android/server/lights/LightsService.java

    JNI: android_system_code/frameworks/base/services/core/jni/com_android_server_lights_LightsService.cpp

    Hal: lights.c

    默认配色: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
    1
    2
    3
    4
    5
    6
    7
    8
    9
    3<.怎么写代码

    1<. 实现一个名为HMI的hw_module_t结构体
    2<. 实现一个open函数,他会根据name返回一个light_device_t结构体
    3<. 实现多个light_device_t结构体,每个对应一个DEVICE
        light_device_t结构体里的第一项是hw_module_t结构体,紧接着一个set_light的函数
    1
    2
    3
    4
    2>. 开始狗血的写代码 : 参考索尼的lights.c
    1<. 关键的结构体解释

    设置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的背光亮度模式
        };
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    2<. 修改函数

    set_light_backlight() : 用于控制背光的函数
        char const*const LCD_BACKLIGHT_FILE     = "/dev/backlight-1wire";
        值得一提的是 Tiny4412开发板液晶显示屏采用的是 1线协议 进行处理显示屏数据的
        同时它的驱动程序里指明最大亮度设置为127 {
            if (v > 127) {    //摘抄自Linux3.0.86 tiny4412_1wire_host.c 有厂家提供
                v = 127;
            }
        }

    set_light_battery()   :用于处理电量显示的函数
    set_light_notifications() : 用于处理有通知的函数
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    3<. 上传 && 编译
    1<. 上传
    hardware/libhardware/modules/lights/lights.c
    hardware/libhardware/modules/lights/Android.mk

        Android.mk内容:
            LOCAL_PATH := $(call my-dir)

            include $(CLEAR_VARS)

            LOCAL_MODULE := lights.tiny4412
            LOCAL_MODULE_RELATIVE_PATH := hw
            LOCAL_C_INCLUDEs := hardware/libhardware
            LOCAL_SRC_FILES := lights.c
            LOCAL_SHARED_LIBRARIES := liblog
            LOCAL_MODULE_TAGS := eng

            include $(BUILD_SHARED_LIBRARY)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    2<. 修改文件:去掉默认的灯光系统文件
    vim vendor/friendly-arm/tiny4412/device-tiny4412.mk

    : # $(VENDOR_PATH)/proprietary/lights.tiny4412.so:system/lib/hw/lights.tiny4412.so
    1
    3<. 编译
    . setenv
    lunch
    mmm hardware/libhardware/modules/lights [-B]:强制编译
    make snod
    ./gen-img.sh

    4<. 调试
    logcat lights:V *:S

    [发现问题]:
        1<. 打印级别低:
          [解决方法]:#define LOG_NDEBUG 0

        2<. 权限不够:write_string failed to open /sys/class/leds/led1/trigger
          [解决方法]:将linux->led-class.c
              修改:led_class_attrs[]数组:
               __ATTR(brightness, 0666, led_brightness_show, led_brightness_store),
               __ATTR(trigger, 0666, led_trigger_show, led_trigger_store),

        [善后工作]将修改过的文件重新上传
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    示例代码:
    1<. 原厂 lights.c

    /*
     * Copyright (C) 2008 The Android Open Source Project
     * Copyright (C) 2011 Diogo Ferreira <defer@cyanogenmod.com>
     * Copyright (C) 2012 The CyanogenMod Project <http://www.cyanogenmod.org>
     *
     * 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.
     */

    #define LOG_TAG "lights.sony"

    #include <cutils/log.h>
    #include <stdint.h>
    #include <string.h>
    #include <unistd.h>
    #include <errno.h>
    #include <fcntl.h>
    #include <pthread.h>
    #include <math.h>

    #include <sys/ioctl.h>
    #include <sys/types.h>

    #include <hardware/lights.h>
    #include "sony_lights.h"

    /* Synchronization primities */
    static pthread_once_t g_init = PTHREAD_ONCE_INIT;
    static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER;

    /* Mini-led state machine */
    static struct light_state_t g_notification;
    static struct light_state_t g_battery;

    /* The leds we have */
    enum {
        LED_RED,
        LED_GREEN,
        LED_BLUE,
        LED_BLANK
    };

    const int LCD_BRIGHTNESS_MIN = 10;

    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) {
                ALOGE("write_int failed to open %s ", path);
                already_warned = 1;
            }
            return -errno;
        }

        char buffer[20];
        int bytes = snprintf(buffer, sizeof(buffer), "%d ", 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) {
                ALOGE("write_string failed to open %s ", path);
                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;
    }

    /* Color tools */
    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))) >> 8;
    }

    static int brightness_apply_gamma (int brightness) {
        double floatbrt = (double) brightness;
        floatbrt /= 255.0;
        ALOGV("%s: brightness = %d, floatbrt = %f", __func__, brightness, floatbrt);
        floatbrt = pow(floatbrt,2.2);
        ALOGV("%s: gamma corrected floatbrt = %f", __func__, floatbrt);
        floatbrt *= 255.0;
        brightness = (int) floatbrt;
        if (brightness < LCD_BRIGHTNESS_MIN)
            brightness = LCD_BRIGHTNESS_MIN;
        ALOGV("%s: gamma corrected brightness = %d", __func__, brightness);
        return brightness;
    }

    /* The actual lights controlling section */
    static int set_light_backlight (struct light_device_t *dev, struct light_state_t const *state) {
        int err = 0;
        int brightness = rgb_to_brightness(state);

        if (brightness > 0) {
            brightness = brightness_apply_gamma(brightness);
            brightness = 4095 * brightness / 255;
        }
        if (brightness < 188)
            brightness = 188;

        ALOGV("%s brightness=%d", __func__, brightness);
        pthread_mutex_lock(&g_lock);
        err |= write_int (LCD_BACKLIGHT_FILE, brightness);
        err |= write_int (LCD_BACKLIGHT2_FILE, brightness);

        pthread_mutex_unlock(&g_lock);

        return err;
    }

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

    static void set_shared_light_locked (struct light_device_t *dev, struct light_state_t *state) {
        int r, g, b, i;
        int delayOn, delayOff;
        char *pattern=NULL;
        char dOn[8],dOff[8];

        r = (state->color >> 16) & 0xFF;
        g = (state->color >> 8) & 0xFF;
        b = (state->color) & 0xFF;

        delayOn = state->flashOnMS;
        delayOff = state->flashOffMS;

        if (state->flashOnMS == 1)
            state->flashMode = LIGHT_FLASH_NONE;
        else {
            //PATTERN=DelayOn,DelayOff,FadeIn,FadeOut
            sprintf (dOn,"%d",delayOn);
            sprintf (dOff,"%d",delayOff);
            asprintf (&pattern,"%s,%s,100,100",dOn,dOff);
            ALOGV("pattern=%s",pattern);
        }

        switch (state->flashMode) {
        case LIGHT_FLASH_TIMED:
        case LIGHT_FLASH_HARDWARE:
            for (i = 0; i < sizeof(LED_FILE_PATTERN)/sizeof(LED_FILE_PATTERN[0]); i++) {
            write_string (LED_FILE_PATTERN[i], pattern);
            }
            break;

        case LIGHT_FLASH_NONE:
            for (i = 0; i < sizeof(LED_FILE_PATTERN)/sizeof(LED_FILE_PATTERN[0]); i++) {
                write_string (LED_FILE_PATTERN[i], PATTERNOFF);
            }
            break;
        }

        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 const* 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 const* state) {
        pthread_mutex_lock (&g_lock);
        g_notification = *state;
        handle_shared_battery_locked(dev);
        pthread_mutex_unlock (&g_lock);
        return 0;
    }

    /* Initializations */
    void init_globals () {
        pthread_mutex_init (&g_lock, NULL);
    }

    /* Glueing boilerplate */
    static int close_lights (struct light_device_t *dev) {
        if (dev)
            free(dev);

        return 0;
    }

    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))
            set_light = set_light_backlight;
        else if (0 == strcmp(LIGHT_ID_BUTTONS, name))
            set_light = set_light_buttons;
        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));
        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;
    }

    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       = "Sony lights module",
        .author     = "Diogo Ferreira <defer@cyanogenmod.com>, Andreas Makris <Andreas.Makris@gmail.com>",
        .methods    = &lights_module_methods,
    };
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    2<. 修改后 lights.c

    /*
     * Copyright (C) 2008 The Android Open Source Project
     * Copyright (C) 2011 Diogo Ferreira <defer@cyanogenmod.com>
     * Copyright (C) 2012 Andreas Makris <andreas.makris@gmail.com>
     * Copyright (C) 2012 The CyanogenMod Project <http://www.cyanogenmod.com>
     *
     * 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.
     */

    #define LOG_NDEBUG 0
    #define LOG_TAG "lights"
    #include <cutils/log.h>
    #include <stdint.h>
    #include <string.h>
    #include <unistd.h>
    #include <errno.h>
    #include <fcntl.h>
    #include <pthread.h>
    #include <sys/ioctl.h>
    #include <sys/types.h>
    #include <hardware/lights.h>

    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";

    /* Synchronization primities */
    static pthread_once_t g_init = PTHREAD_ONCE_INIT;
    static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER;
    /* Mini-led state machine */
    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) {
                ALOGE("write_int failed to open %s ", path);
                already_warned = 1;
            }
            return -errno;
        }
        char buffer[20];
        int bytes = snprintf(buffer, sizeof(buffer), "%d ", 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) {
                ALOGE("write_string failed to open %s ", path);
                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;
    }

    /* Color tools */
    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))) >> 8;
    }

    /* The actual lights controlling section */
    static int set_light_backlight (struct light_device_t *dev, struct light_state_t const *state) {
        int brightness = rgb_to_brightness(state);
        ALOGV("%s brightness=%d color=0x%08x", __func__,brightness,state->color);
        pthread_mutex_lock(&g_lock);

        /* brightness 0-255 */
        /* LCD_BACKLIGHT_FILE能接收是0-127 */

        write_int (LCD_BACKLIGHT_FILE, 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, "timer");
            write_string (GREEN_LED_FILE_TRIGGER, "timer");
            write_string (BLUE_LED_FILE_TRIGGER, "timer");
            write_int (RED_LED_FILE_DELAYON, delayOn);
            write_int (GREEN_LED_FILE_DELAYON, delayOn);
            write_int (BLUE_LED_FILE_DELAYON, delayOn);
            write_int (RED_LED_FILE_DELAYOFF, delayOff);
            write_int (GREEN_LED_FILE_DELAYOFF, delayOff);
            write_int (BLUE_LED_FILE_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 const* state) {

        ALOGV("%s flashMode=%d onMS = %d offMS = %d color=0x%08x", __func__,state->flashMode,state->flashOnMS,state->flashOffMS,state->color);

        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 const* state) {
        ALOGV("%s flashMode=%d onMS = %d offMS = %d color=0x%08x", __func__,state->flashMode,state->flashOnMS,state->flashOffMS,state->color);
        pthread_mutex_lock (&g_lock);
        g_notification = *state;
        handle_shared_battery_locked(dev);
        pthread_mutex_unlock (&g_lock);
        return 0;
    }
    /* Initializations */
    void init_globals () {
        pthread_mutex_init (&g_lock, NULL);
    }

    /* Glueing boilerplate */
    static int close_lights (struct light_device_t *dev) {
        if (dev)
            free(dev);
        return 0;
    }

    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)) {
            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));
        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;
    }

    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 = "Sony lights module",
        .author = "Diogo Ferreira <defer@cyanogenmod.com>, Andreas Makris <Andreas.Makris@gmail.com>",
        .methods = &lights_module_methods,
    };

  • 相关阅读:
    深度学习练习(三)
    深度学习核心技术笔记(一)
    tensorflow的函数
    举例
    Tensorflow 笔记
    tensorflow框架
    基于python的感知机
    深度学习练习(一)
    深度学习练习(二)
    [javascript 实践篇]——那些你不知道的“奇淫巧技”
  • 原文地址:https://www.cnblogs.com/zzb-Dream-90Time/p/10185041.html
Copyright © 2011-2022 走看看