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