1 /*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "led_lut_calibrator.h"
18
19 #include <android-base/logging.h>
20 #include <android-base/properties.h>
21 #include <fcntl.h>
22
23 #include <iostream>
24 #include <sstream>
25
26 using ::android::base::GetProperty;
27
28 const char D_kCalibrationPath[] = "/mnt/vendor/persist/led/led_calibration_LUT.txt";
29 const char G_WHT_kCalibrationPath[] = "/vendor/etc/led_golden_calibration_LUT_white_CG.txt";
30 const char G_BLK_kCalibrationPath[] = "/vendor/etc/led_golden_calibration_LUT_black_CG.txt";
31
LedLutCalibrator(PanelCalibrationStatus status)32 LedLutCalibrator::LedLutCalibrator(PanelCalibrationStatus status) {
33 cal_status_ = status;
34 if (!ReadCalibrationTable()) {
35 LOG(ERROR) << "Failed to read calibration table";
36 cal_table_.clear();
37 }
38 }
39
GetByColorIntensity(const std::string & color,int intensity) const40 int LedLutCalibrator::GetByColorIntensity(const std::string &color, int intensity) const {
41 std::string key = MakeLutKey(color, intensity);
42 const auto cal_data = cal_table_.find(key);
43
44 if (cal_data == cal_table_.end()) {
45 LOG(ERROR) << "Failed to get calibration data";
46 return -1;
47 }
48
49 return cal_data->second;
50 }
51
ReadCalibrationTable()52 bool LedLutCalibrator::ReadCalibrationTable() {
53 int fd;
54 int bytes;
55 bool ret = true;
56 const char *k_path = D_kCalibrationPath;
57 std::vector<uint8_t> buffer;
58 buffer.resize(512);
59
60 fd = open(D_kCalibrationPath, O_RDONLY);
61 // If default calibration not found or display changed, deploy golen calibration.
62 if (fd < 0 || cal_status_ == PanelCalibrationStatus::GOLDEN) {
63 // Using golden white calibration as default
64 // even though bezel prooerty not found.
65 k_path = G_WHT_kCalibrationPath;
66 std::string cdt_hwid = GetProperty("ro.boot.cdt_hwid", "");
67 std::string hex_variant_str = cdt_hwid.substr(16, 2);
68 int bezel_color;
69 sscanf(hex_variant_str.c_str(), "%x", &bezel_color);
70 // 0: white, 2: black
71 if (bezel_color == 2)
72 k_path = G_BLK_kCalibrationPath;
73 }
74
75 fd = open(k_path, O_RDONLY);
76 if (fd < 0) {
77 LOG(ERROR) << "Failed to open " << k_path;
78 ret = false;
79 goto ReadCalibrationTable_err;
80 }
81
82 bytes = read(fd, buffer.data(), buffer.size());
83 if (bytes == -1) {
84 LOG(ERROR) << "Failed to read " << k_path;
85 ret = false;
86 goto ReadCalibrationTable_err;
87 }
88
89 if (!ParseBlock(&buffer)) {
90 LOG(ERROR) << "Failed to parse calibration table ";
91 ret = false;
92 goto ReadCalibrationTable_err;
93 }
94
95 ReadCalibrationTable_err:
96 if (fd != -1)
97 close(fd);
98
99 return ret;
100 }
101
ParseBlock(const std::vector<uint8_t> * table)102 bool LedLutCalibrator::ParseBlock(const std::vector<uint8_t> *table) {
103 std::string str(table->begin(), table->end());
104 auto result = std::vector<std::string>{};
105 auto ss = std::stringstream{str};
106
107 for (std::string line; std::getline(ss, line, '\n');) {
108 size_t start;
109 size_t end = 0;
110 std::vector<std::string> colon_separated;
111 while ((start = line.find_first_not_of(':', end)) != std::string::npos) {
112 end = line.find(':', start);
113 if (end == std::string::npos) {
114 end = line.size();
115 }
116 colon_separated.push_back(line.substr(start, end - start));
117 }
118 if (colon_separated.size() != 3) {
119 continue;
120 }
121 std::string color_name = colon_separated[0];
122 uint16_t intensity = atoi(colon_separated[1].c_str());
123 uint16_t pwm = atoi(colon_separated[2].c_str());
124 std::cout << color_name << intensity << pwm << std::endl;
125 std::string key = MakeLutKey(color_name, intensity);
126 cal_table_[key] = pwm;
127 }
128
129 return true;
130 }
131
MakeLutKey(const std::string & color,int intensity) const132 std::string LedLutCalibrator::MakeLutKey(const std::string &color, int intensity) const {
133 std::string intensity_str = std::to_string(intensity);
134 std::string terms{color};
135
136 terms.append(intensity_str);
137
138 return terms;
139 }
140