1 /*
2 * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include "hdf_bl.h"
10 #include <securec.h>
11 #include "hdf_base.h"
12 #include "hdf_disp.h"
13 #include "hdf_log.h"
14 #include "osal.h"
15
16 #define OFFSET_TWO_BYTE 16
17 #define MAX_BL_NAME_LEN 32
18 #define MAX_BL_DEV 32
19 #define NAME_BUFFER_LEN 1220 // 32 * 38
20 #define MAX_DEST_STRING_LEN 38 // MAX_BL_NAME_LEN(32) + 6
21
22 enum BrightnessType {
23 MIN_BRIGHTNESS,
24 CURRENT_BRIGHTNESS,
25 DEFAULT_BRIGHTNESS,
26 MAX_BRIGHTNESS,
27 };
28
29 typedef int32_t (*BlCmdHandle)(struct HdfDeviceObject *device,
30 struct HdfSBuf *reqData, struct HdfSBuf *rspData);
31
32 struct BacklightDev {
33 char name[MAX_BL_NAME_LEN];
34 struct BacklightProperties props;
35 struct BacklightOps *ops;
36 struct OsalMutex mutex;
37 bool isRegister;
38 void *priv;
39 };
40
41 struct BlDevManager {
42 struct BacklightDev *blDev[MAX_BL_DEV];
43 int32_t devNum;
44 };
45
46 static struct BlDevManager g_blDevManager;
47
GetBlDevManager(void)48 static struct BlDevManager *GetBlDevManager(void)
49 {
50 return &g_blDevManager;
51 }
52
BlDevInstance(const char * devName,struct BacklightProperties * props,struct BacklightOps * ops)53 static struct BacklightDev *BlDevInstance(const char *devName,
54 struct BacklightProperties *props, struct BacklightOps *ops)
55 {
56 int32_t ret;
57 struct BacklightDev *blDev = NULL;
58
59 blDev = (struct BacklightDev *)OsalMemCalloc(sizeof(struct BacklightDev));
60 if (blDev == NULL) {
61 HDF_LOGE("%s blDev malloc fail", __func__);
62 return NULL;
63 }
64 blDev->ops = ops;
65 ret = memcpy_s(blDev->name, MAX_BL_NAME_LEN - 1, devName, strlen(devName) + 1);
66 if (ret != 0) {
67 HDF_LOGE("%s blDev->name %s", __func__, blDev->name);
68 goto FAIL;
69 }
70 ret = memcpy_s(&blDev->props, sizeof(struct BacklightProperties),
71 props, sizeof(struct BacklightProperties));
72 if (ret != 0) {
73 HDF_LOGE("%s props memcpy fail", __func__);
74 goto FAIL;
75 }
76 return blDev;
77 FAIL:
78 OsalMemFree(blDev);
79 return NULL;
80 }
81
RegisterBlDev(const char * name,struct BacklightProperties * props,struct BacklightOps * ops,void * priv)82 struct BacklightDev *RegisterBlDev(const char *name, struct BacklightProperties *props,
83 struct BacklightOps *ops, void *priv)
84 {
85 int32_t devNum;
86 struct BacklightDev *blDev = NULL;
87 struct BlDevManager *blDevManager = NULL;
88
89 if ((name == NULL) || (ops == NULL) || (props == NULL)) {
90 HDF_LOGE("%s: name , ops or props is null", __func__);
91 return NULL;
92 }
93 blDevManager = GetBlDevManager();
94 devNum = blDevManager->devNum;
95 if (devNum >= MAX_BL_DEV) {
96 HDF_LOGE("%s: number of backlight device registrations exceeded", __func__);
97 return NULL;
98 }
99 for (int32_t i = 0; i < devNum; i++) {
100 if (strcmp(name, blDevManager->blDev[i]->name) == 0) {
101 HDF_LOGE("%s: backlight name should be unique", __func__);
102 return NULL;
103 }
104 }
105 blDev = BlDevInstance(name, props, ops);
106 if (blDev == NULL) {
107 HDF_LOGE("%s: BlDevInstance fail", __func__);
108 return NULL;
109 }
110 blDev->priv = priv;
111 blDevManager->blDev[devNum] = blDev;
112 blDevManager->devNum++;
113 OsalMutexInit(&blDev->mutex);
114 HDF_LOGE("%s: success", __func__);
115 return blDev;
116 }
117
ToBlDevPriv(struct BacklightDev * blDev)118 void *ToBlDevPriv(struct BacklightDev *blDev)
119 {
120 if (blDev == NULL) {
121 HDF_LOGE("%s blDev is null", __func__);
122 return NULL;
123 }
124 return blDev->priv;
125 }
126
GetBacklightDev(const char * name)127 struct BacklightDev *GetBacklightDev(const char *name)
128 {
129 struct BlDevManager *blDevManager = NULL;
130
131 if (name == NULL) {
132 HDF_LOGE("%s name is null", __func__);
133 return NULL;
134 }
135 blDevManager = GetBlDevManager();
136 for (int32_t i = 0; i < blDevManager->devNum; i++) {
137 if (strcmp(name, blDevManager->blDev[i]->name) == 0) {
138 return blDevManager->blDev[i];
139 }
140 }
141 return NULL;
142 }
143
UpdateBacklightState(struct BacklightDev * blDev,enum FbPowerStatus status)144 int32_t UpdateBacklightState(struct BacklightDev *blDev, enum FbPowerStatus status)
145 {
146 if (blDev == NULL) {
147 HDF_LOGE("%s blDev is null", __func__);
148 return HDF_FAILURE;
149 }
150 if ((status < FB_POWER_ON) || (status > FB_POWER_OFF)) {
151 HDF_LOGE("%s the status is illegal", __func__);
152 return HDF_FAILURE;
153 }
154 OsalMutexLock(&blDev->mutex);
155 blDev->props.fbStatus = status;
156 OsalMutexUnlock(&blDev->mutex);
157 return HDF_SUCCESS;
158 }
159
UpdateBrightness(struct BacklightDev * blDev,uint32_t brightness)160 int32_t UpdateBrightness(struct BacklightDev *blDev, uint32_t brightness)
161 {
162 int32_t ret = HDF_FAILURE;
163
164 if (blDev == NULL) {
165 HDF_LOGE("%s blDev is null", __func__);
166 return HDF_FAILURE;
167 }
168 if (brightness > blDev->props.maxBrightness) {
169 brightness = blDev->props.maxBrightness;
170 }
171 if (brightness < blDev->props.minBrightness) {
172 brightness = blDev->props.minBrightness;
173 }
174 OsalMutexLock(&blDev->mutex);
175 if (brightness == blDev->props.brightness) {
176 HDF_LOGI("%s brightness does not change", __func__);
177 OsalMutexUnlock(&blDev->mutex);
178 return HDF_SUCCESS;
179 }
180 if ((blDev->props.fbStatus == FB_POWER_STANDBY) ||
181 (blDev->props.fbStatus == FB_POWER_SUSPEND) ||
182 (blDev->props.fbStatus == FB_POWER_OFF)) {
183 brightness = 0;
184 }
185 if (blDev->ops != NULL && blDev->ops->updateBrightness != NULL) {
186 ret = blDev->ops->updateBrightness(blDev, brightness);
187 if (ret == HDF_SUCCESS) {
188 blDev->props.brightness = brightness;
189 } else {
190 HDF_LOGE("%s: fail", __func__);
191 }
192 }
193 OsalMutexUnlock(&blDev->mutex);
194 return ret;
195 }
196
GetBlDevBrightness(struct BacklightDev * blDev,enum BrightnessType type)197 static int32_t GetBlDevBrightness(struct BacklightDev *blDev, enum BrightnessType type)
198 {
199 uint32_t brightness;
200
201 OsalMutexLock(&blDev->mutex);
202 switch (type) {
203 case MIN_BRIGHTNESS:
204 brightness = blDev->props.minBrightness;
205 break;
206 case CURRENT_BRIGHTNESS:
207 if ((blDev->props.fbStatus == FB_POWER_STANDBY) ||
208 (blDev->props.fbStatus == FB_POWER_SUSPEND) ||
209 (blDev->props.fbStatus == FB_POWER_OFF)) {
210 blDev->props.brightness = 0;
211 }
212 if ((blDev->ops != NULL) && (blDev->ops->getBrightness != NULL)) {
213 brightness = blDev->ops->getBrightness(blDev);
214 } else {
215 brightness = blDev->props.brightness;
216 }
217 break;
218 case DEFAULT_BRIGHTNESS:
219 brightness = blDev->props.defBrightness;
220 break;
221 case MAX_BRIGHTNESS:
222 brightness = blDev->props.maxBrightness;
223 break;
224 }
225 OsalMutexUnlock(&blDev->mutex);
226 return brightness;
227 }
228
GetMinBrightness(struct BacklightDev * blDev,uint32_t * brightness)229 int32_t GetMinBrightness(struct BacklightDev *blDev, uint32_t *brightness)
230 {
231 if (blDev == NULL || brightness == NULL) {
232 HDF_LOGE("%s: blDev or brightness is null", __func__);
233 return HDF_FAILURE;
234 }
235 *brightness = GetBlDevBrightness(blDev, MIN_BRIGHTNESS);
236 return HDF_SUCCESS;
237 }
238
GetCurrBrightness(struct BacklightDev * blDev,uint32_t * brightness)239 int32_t GetCurrBrightness(struct BacklightDev *blDev, uint32_t *brightness)
240 {
241 if (blDev == NULL || brightness == NULL) {
242 HDF_LOGE("%s: blDev or brightness is null", __func__);
243 return HDF_FAILURE;
244 }
245 *brightness = GetBlDevBrightness(blDev, CURRENT_BRIGHTNESS);
246 return HDF_SUCCESS;
247 }
248
GetDefBrightness(struct BacklightDev * blDev,uint32_t * brightness)249 int32_t GetDefBrightness(struct BacklightDev *blDev, uint32_t *brightness)
250 {
251 if (blDev == NULL || brightness == NULL) {
252 HDF_LOGE("%s: blDev or brightness is null", __func__);
253 return HDF_FAILURE;
254 }
255 *brightness = GetBlDevBrightness(blDev, DEFAULT_BRIGHTNESS);
256 return HDF_SUCCESS;
257 }
258
GetMaxBrightness(struct BacklightDev * blDev,uint32_t * brightness)259 int32_t GetMaxBrightness(struct BacklightDev *blDev, uint32_t *brightness)
260 {
261 if (blDev == NULL || brightness == NULL) {
262 HDF_LOGE("%s: blDev or brightness is null", __func__);
263 return HDF_FAILURE;
264 }
265 *brightness = GetBlDevBrightness(blDev, MAX_BRIGHTNESS);
266 return HDF_SUCCESS;
267 }
268
HdfGetBrightness(enum BrightnessType type,struct HdfSBuf * reqData,struct HdfSBuf * rspData)269 static int32_t HdfGetBrightness(enum BrightnessType type,
270 struct HdfSBuf *reqData, struct HdfSBuf *rspData)
271 {
272 uint32_t devId;
273 int32_t brightness;
274 struct BlDevManager *blDevManager = NULL;
275 struct BacklightDev *blDev = NULL;
276
277 if (reqData == NULL) {
278 return HDF_ERR_INVALID_PARAM;
279 }
280 if (!HdfSbufReadUint32(reqData, &devId)) {
281 HDF_LOGE("%s: HdfSbufReadBuffer failed", __func__);
282 return HDF_FAILURE;
283 }
284 blDevManager = GetBlDevManager();
285 if (devId >= (uint32_t)blDevManager->devNum) {
286 HDF_LOGE("%s: devId is illegal", __func__);
287 return HDF_FAILURE;
288 }
289 blDev = blDevManager->blDev[devId];
290 brightness = GetBlDevBrightness(blDev, type);
291 if (!HdfSbufWriteUint32(rspData, brightness)) {
292 HDF_LOGE("%s: HdfSbufWriteUint32 failed", __func__);
293 return HDF_FAILURE;
294 }
295 return HDF_SUCCESS;
296 }
297
HdfGetMinBrightness(struct HdfDeviceObject * device,struct HdfSBuf * reqData,struct HdfSBuf * rspData)298 static int32_t HdfGetMinBrightness(struct HdfDeviceObject *device,
299 struct HdfSBuf *reqData, struct HdfSBuf *rspData)
300 {
301 (void)device;
302 return HdfGetBrightness(MIN_BRIGHTNESS, reqData, rspData);
303 }
304
HdfGetCurrBrightness(struct HdfDeviceObject * device,struct HdfSBuf * reqData,struct HdfSBuf * rspData)305 static int32_t HdfGetCurrBrightness(struct HdfDeviceObject *device,
306 struct HdfSBuf *reqData, struct HdfSBuf *rspData)
307 {
308 (void)device;
309 return HdfGetBrightness(CURRENT_BRIGHTNESS, reqData, rspData);
310 }
311
HdfGetDefBrightness(struct HdfDeviceObject * device,struct HdfSBuf * reqData,struct HdfSBuf * rspData)312 static int32_t HdfGetDefBrightness(struct HdfDeviceObject *device,
313 struct HdfSBuf *reqData, struct HdfSBuf *rspData)
314 {
315 (void)device;
316 return HdfGetBrightness(DEFAULT_BRIGHTNESS, reqData, rspData);
317 }
318
HdfGetMaxBrightness(struct HdfDeviceObject * device,struct HdfSBuf * reqData,struct HdfSBuf * rspData)319 static int32_t HdfGetMaxBrightness(struct HdfDeviceObject *device,
320 struct HdfSBuf *reqData, struct HdfSBuf *rspData)
321 {
322 (void)device;
323 return HdfGetBrightness(MAX_BRIGHTNESS, reqData, rspData);
324 }
325
HdfSetBrightness(struct HdfDeviceObject * device,struct HdfSBuf * reqData,struct HdfSBuf * rspData)326 static int32_t HdfSetBrightness(struct HdfDeviceObject *device,
327 struct HdfSBuf *reqData, struct HdfSBuf *rspData)
328 {
329 struct BlDevManager *blDevManager = NULL;
330 struct BacklightDev *blDev = NULL;
331
332 (void)device;
333 (void)rspData;
334 if (reqData == NULL) {
335 return HDF_ERR_INVALID_PARAM;
336 }
337 uint32_t para = 0;
338 if (!HdfSbufReadUint32(reqData, ¶)) {
339 HDF_LOGE("%s: HdfSbufReadBuffer failed", __func__);
340 return HDF_FAILURE;
341 }
342 uint32_t devId = (para >> OFFSET_TWO_BYTE) & 0xffff;
343 uint32_t level = para & 0xffff;
344 blDevManager = GetBlDevManager();
345 if (devId >= blDevManager->devNum) {
346 HDF_LOGE("%s: devId is illegal", __func__);
347 return HDF_FAILURE;
348 }
349 blDev = blDevManager->blDev[devId];
350 return UpdateBrightness(blDev, level);
351 }
352
HdfGetBlDevList(struct HdfDeviceObject * device,struct HdfSBuf * reqData,struct HdfSBuf * rspData)353 static int32_t HdfGetBlDevList(struct HdfDeviceObject *device,
354 struct HdfSBuf *reqData, struct HdfSBuf *rspData)
355 {
356 (void)device;
357 (void)reqData;
358 int32_t ret;
359 char *devName = NULL;
360 char *tmp = NULL;
361 char buffer[NAME_BUFFER_LEN] = {0};
362 struct BlDevManager *blDevManager = NULL;
363
364 blDevManager = GetBlDevManager();
365 tmp = buffer;
366 for (int32_t i = 0; i < blDevManager->devNum; i++) {
367 devName = blDevManager->blDev[i]->name;
368 if ((tmp + MAX_DEST_STRING_LEN) > &buffer[NAME_BUFFER_LEN]) {
369 HDF_LOGE("%s: Memory out of bounds", __func__);
370 break;
371 }
372 // strlen("%d : \n") = 6
373 ret = snprintf_s(tmp, MAX_DEST_STRING_LEN, strlen(devName) + 6, "%d : %s\n", i, devName);
374 if (ret < 0) {
375 HDF_LOGE("%s: snprintf_s fail", __func__);
376 return HDF_FAILURE;
377 }
378 tmp = tmp + strlen(tmp) + 1;
379 }
380 if (!HdfSbufWriteBuffer(rspData, buffer, strlen(buffer) + 1) != 0) {
381 HDF_LOGE("%s: copy info failed", __func__);
382 return HDF_FAILURE;
383 }
384 return HDF_SUCCESS;
385 }
386
387 static BlCmdHandle g_blDevCmdHandle[] = {
388 HdfGetMinBrightness,
389 HdfGetCurrBrightness,
390 HdfGetDefBrightness,
391 HdfGetMaxBrightness,
392 HdfGetBlDevList,
393 HdfSetBrightness,
394 };
395
BacklightDispatch(struct HdfDeviceIoClient * client,int cmd,struct HdfSBuf * data,struct HdfSBuf * reply)396 static int32_t BacklightDispatch(struct HdfDeviceIoClient *client, int cmd, struct HdfSBuf *data,
397 struct HdfSBuf *reply)
398 {
399 BlCmdHandle blCmdHandle = NULL;
400
401 if (client == NULL) {
402 return HDF_ERR_INVALID_PARAM;
403 }
404 if ((cmd < 0) || (cmd >= sizeof(g_blDevCmdHandle) / sizeof(BlCmdHandle))) {
405 HDF_LOGE("%s: cmd is illegal", __func__);
406 return HDF_FAILURE;
407 }
408 blCmdHandle = g_blDevCmdHandle[cmd];
409 return blCmdHandle(client->device, data, reply);
410 }
411
BacklightBind(struct HdfDeviceObject * dev)412 static int BacklightBind(struct HdfDeviceObject *dev)
413 {
414 if (dev == NULL) {
415 return HDF_FAILURE;
416 }
417 static struct IDeviceIoService blService = {
418 .Dispatch = BacklightDispatch,
419 };
420 dev->service = &blService;
421 return HDF_SUCCESS;
422 }
423
BacklightInit(struct HdfDeviceObject * object)424 static int32_t BacklightInit(struct HdfDeviceObject *object)
425 {
426 if (object == NULL) {
427 HDF_LOGE("%s: object is null!", __func__);
428 return HDF_FAILURE;
429 }
430 HDF_LOGI("%s success", __func__);
431 return HDF_SUCCESS;
432 }
433
434 struct HdfDriverEntry g_blDevEntry = {
435 .moduleVersion = 1,
436 .moduleName = "HDF_BL",
437 .Init = BacklightInit,
438 .Bind = BacklightBind,
439 };
440
441 HDF_INIT(g_blDevEntry);
442