blob: c62182fc8122a323646b3e69880de88e04c6fa1e [file] [log] [blame]
Amit Pundir4c517ea2021-05-23 02:24:19 +05301/*
2 * Copyright (C) 2014, 2017-2018 The Linux Foundation. All rights reserved.
3 * Not a contribution
4 * Copyright (C) 2008 The Android Open Source Project
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
Amit Pundir4c517ea2021-05-23 02:24:19 +053019#include <log/log.h>
20#include <cutils/properties.h>
21
Caleb Connollyb0addf42021-08-13 16:51:20 +010022#include <dirent.h>
23#include <fcntl.h>
Caleb Connollyc306b8a2021-11-15 16:32:22 +000024#include <linux/limits.h>
Amit Pundir4c517ea2021-05-23 02:24:19 +053025#include <stdint.h>
26#include <stdlib.h>
Caleb Connollyb0addf42021-08-13 16:51:20 +010027#include <stdio.h>
Amit Pundir4c517ea2021-05-23 02:24:19 +053028#include <string.h>
29#include <unistd.h>
30#include <errno.h>
31#include <fcntl.h>
32#include <pthread.h>
33
34#include <sys/ioctl.h>
35#include <sys/types.h>
36
37#include <hardware/lights.h>
38
Caleb Connollyc306b8a2021-11-15 16:32:22 +000039#define BACKLIGHT_CLASS "/sys/class/backlight"
40#define BACKLIGHT_CLASS_FSTRING "/sys/class/backlight/%s/brightness"
Amit Pundir4c517ea2021-05-23 02:24:19 +053041
42/**
43 * device methods
44 */
45
Caleb Connollyb0addf42021-08-13 16:51:20 +010046static bool findFirstBacklightDevice(char *filename) {
47 struct dirent *de;
Caleb Connollyc306b8a2021-11-15 16:32:22 +000048 DIR *dir = opendir(BACKLIGHT_CLASS);
Caleb Connollyb0addf42021-08-13 16:51:20 +010049 if (dir == NULL)
50 return NULL;
51 while((de = readdir(dir))) {
52 if(de->d_name[0] == '.' &&
53 (de->d_name[1] == '\0' ||
54 (de->d_name[1] == '.' && de->d_name[2] == '\0')))
55 continue;
56 strcpy(filename, de->d_name);
57 closedir(dir);
58 return true;
59 }
60 closedir(dir);
61 return false;
62}
63
Amit Pundir4c517ea2021-05-23 02:24:19 +053064static int
Caleb Connollyb0addf42021-08-13 16:51:20 +010065write_brightness(int value)
Amit Pundir4c517ea2021-05-23 02:24:19 +053066{
67 int fd;
Caleb Connollyc306b8a2021-11-15 16:32:22 +000068 char brightness_path[PATH_MAX];
69 char filename[NAME_MAX];
Caleb Connollyb0addf42021-08-13 16:51:20 +010070 if (!findFirstBacklightDevice(filename)) {
Caleb Connollyc306b8a2021-11-15 16:32:22 +000071 ALOGE("Couldn't find backlight brightness path");
Caleb Connollyb0addf42021-08-13 16:51:20 +010072 return -EINVAL;
73 }
Amit Pundir4c517ea2021-05-23 02:24:19 +053074
Caleb Connollyc306b8a2021-11-15 16:32:22 +000075 ALOGI("Opening backlight device: %s", filename);
76 snprintf(brightness_path, PATH_MAX, BACKLIGHT_CLASS_FSTRING, filename);
Caleb Connollyb0addf42021-08-13 16:51:20 +010077 fd = open(brightness_path, O_WRONLY);
Amit Pundir4c517ea2021-05-23 02:24:19 +053078 if (fd >= 0) {
79 char buffer[20];
80 ssize_t amt;
81 size_t bytes = snprintf(buffer, sizeof(buffer), "%d\n", value);
82 if(bytes < sizeof(buffer)) {
83 amt = write(fd, buffer, bytes);
84 } else {
85 amt = -1;
86 errno = -EINVAL;
87 }
88 close(fd);
89 return amt == -1 ? -errno : 0;
90 } else {
Caleb Connollyb0addf42021-08-13 16:51:20 +010091 ALOGE("write_brightness failed to open %s, fd = %d, errno = %d\n", brightness_path, fd, errno);
Amit Pundir4c517ea2021-05-23 02:24:19 +053092 return -errno;
93 }
94}
95
96static int
97rgb_to_brightness(struct light_state_t const* state)
98{
99 int color = state->color & 0x00ffffff;
100 return ((77*((color>>16)&0x00ff))
101 + (150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8;
102}
103
104static int
105set_light_backlight(struct light_device_t* dev,
106 struct light_state_t const* state)
107{
108 if(!dev) {
109 return -1;
110 }
111
Caleb Connollyc306b8a2021-11-15 16:32:22 +0000112 int brightness = rgb_to_brightness(state) << 2; // Scale up to 1020
Caleb Connollyb0addf42021-08-13 16:51:20 +0100113 write_brightness(brightness);
Amit Pundir4c517ea2021-05-23 02:24:19 +0530114
115 return 0;
116}
117
118/** Close the lights device */
119static int
120close_lights(struct light_device_t *dev)
121{
122 if (dev) {
123 free(dev);
124 }
125 return 0;
126}
127
Amit Pundir4c517ea2021-05-23 02:24:19 +0530128/**
129 * module methods
130 */
131
132/** Open a new instance of a lights device using name */
133static int open_lights(const struct hw_module_t* module, char const* name,
134 struct hw_device_t** device)
135{
Caleb Connollyb0addf42021-08-13 16:51:20 +0100136 (void)name;
Amit Pundir4c517ea2021-05-23 02:24:19 +0530137
138 struct light_device_t *dev = malloc(sizeof(struct light_device_t));
139
140 if(!dev)
141 return -ENOMEM;
142
143 memset(dev, 0, sizeof(*dev));
144
145 dev->common.tag = HARDWARE_DEVICE_TAG;
146 dev->common.version = LIGHTS_DEVICE_API_VERSION_2_0;
147 dev->common.module = (struct hw_module_t*)module;
148 dev->common.close = (int (*)(struct hw_device_t*))close_lights;
149 dev->set_light = set_light_backlight;
150
151 *device = (struct hw_device_t*)dev;
152 return 0;
153}
154
155static struct hw_module_methods_t lights_module_methods = {
156 .open = open_lights,
157};
158
159/*
160 * The lights Module
161 */
162struct hw_module_t HAL_MODULE_INFO_SYM = {
163 .tag = HARDWARE_MODULE_TAG,
164 .version_major = 1,
165 .version_minor = 0,
166 .id = LIGHTS_HARDWARE_MODULE_ID,
167 .name = "lights Module",
168 .author = "Google, Inc.",
169 .methods = &lights_module_methods,
170};