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_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 int32_t devNum;
85 struct BacklightDev *blDev = NULL;
86 struct BlDevManager *blDevManager = NULL;
87
88 if ((name == NULL) || (ops == NULL) || (props == NULL)) {
89 HDF_LOGE("%s: name , ops or props is null", __func__);
90 return NULL;
91 }
92 blDevManager = GetBlDevManager();
93 devNum = blDevManager->devNum;
94 if (devNum >= MAX_BL_DEV) {
95 HDF_LOGE("%s: number of backlight device registrations exceeded", __func__);
96 return NULL;
97 }
98 for (int32_t i = 0; i < devNum; i++) {
99 if (strcmp(name, blDevManager->blDev[i]->name) == 0) {
100 HDF_LOGE("%s: backlight name should be unique", __func__);
101 return NULL;
102 }
103 }
104 blDev = BlDevInstance(name, props, ops);
105 if (blDev == NULL) {
106 HDF_LOGE("%s: BlDevInstance fail", __func__);
107 return NULL;
108 }
109 blDev->priv = priv;
110 blDevManager->blDev[devNum] = blDev;
111 blDevManager->devNum++;
112 OsalMutexInit(&blDev->mutex);
113 HDF_LOGE("%s: success", __func__);
114 return blDev;
115 }
116
ToBlDevPriv(struct BacklightDev * blDev)117 void *ToBlDevPriv(struct BacklightDev *blDev)
118 {
119 if (blDev == NULL) {
120 HDF_LOGE("%s blDev is null", __func__);
121 return NULL;
122 }
123 return blDev->priv;
124 }
125
GetBacklightDev(const char * name)126 struct BacklightDev *GetBacklightDev(const char *name)
127 {
128 struct BlDevManager *blDevManager = NULL;
129
130 if (name == NULL) {
131 HDF_LOGE("%s name is null", __func__);
132 return NULL;
133 }
134 blDevManager = GetBlDevManager();
135 for (int32_t i = 0; i < blDevManager->devNum; i++) {
136 if (strcmp(name, blDevManager->blDev[i]->name) == 0) {
137 return blDevManager->blDev[i];
138 }
139 }
140 return NULL;
141 }
142
UpdateBacklightState(struct BacklightDev * blDev,enum FbPowerStatus status)143 int32_t UpdateBacklightState(struct BacklightDev *blDev, enum FbPowerStatus status)
144 {
145 if (blDev == NULL) {
146 HDF_LOGE("%s blDev is null", __func__);
147 return HDF_FAILURE;
148 }
149 if ((status < FB_POWER_ON) || (status > FB_POWER_OFF)) {
150 HDF_LOGE("%s the status is illegal", __func__);
151 return HDF_FAILURE;
152 }
153 OsalMutexLock(&blDev->mutex);
154 blDev->props.fbStatus = status;
155 OsalMutexUnlock(&blDev->mutex);
156 return HDF_SUCCESS;
157 }
158
UpdateBrightness(struct BacklightDev * blDev,uint32_t brightness)159 int32_t UpdateBrightness(struct BacklightDev *blDev, uint32_t brightness)
160 {
161 int32_t ret = HDF_FAILURE;
162
163 if (blDev == NULL) {
164 HDF_LOGE("%s blDev is null", __func__);
165 return HDF_FAILURE;
166 }
167 if (brightness > blDev->props.maxBrightness) {
168 brightness = blDev->props.maxBrightness;
169 }
170 if (brightness < blDev->props.minBrightness) {
171 brightness = blDev->props.minBrightness;
172 }
173 OsalMutexLock(&blDev->mutex);
174 if (brightness == blDev->props.brightness) {
175 HDF_LOGI("%s brightness does not change", __func__);
176 OsalMutexUnlock(&blDev->mutex);
177 return HDF_SUCCESS;
178 }
179 if ((blDev->props.fbStatus == FB_POWER_STANDBY) ||
180 (blDev->props.fbStatus == FB_POWER_SUSPEND) ||
181 (blDev->props.fbStatus == FB_POWER_OFF)) {
182 brightness = 0;
183 }
184 if (blDev->ops != NULL && blDev->ops->updateBrightness != NULL) {
185 ret = blDev->ops->updateBrightness(blDev, brightness);
186 if (ret == HDF_SUCCESS) {
187 blDev->props.brightness = brightness;
188 } else {
189 HDF_LOGE("%s: fail", __func__);
190 }
191 }
192 OsalMutexUnlock(&blDev->mutex);
193 return ret;
194 }
195
GetBlDevBrightness(struct BacklightDev * blDev,enum BrightnessType type)196 static uint32_t GetBlDevBrightness(struct BacklightDev *blDev, enum BrightnessType type)
197 {
198 uint32_t brightness;
199
200 OsalMutexLock(&blDev->mutex);
201 switch (type) {
202 case MIN_BRIGHTNESS:
203 brightness = blDev->props.minBrightness;
204 break;
205 case CURRENT_BRIGHTNESS:
206 if ((blDev->props.fbStatus == FB_POWER_STANDBY) ||
207 (blDev->props.fbStatus == FB_POWER_SUSPEND) ||
208 (blDev->props.fbStatus == FB_POWER_OFF)) {
209 blDev->props.brightness = 0;
210 }
211 if ((blDev->ops != NULL) && (blDev->ops->getBrightness != NULL)) {
212 brightness = blDev->ops->getBrightness(blDev);
213 } else {
214 brightness = blDev->props.brightness;
215 }
216 break;
217 case DEFAULT_BRIGHTNESS:
218 brightness = blDev->props.defBrightness;
219 break;
220 case MAX_BRIGHTNESS:
221 brightness = blDev->props.maxBrightness;
222 break;
223 }
224 OsalMutexUnlock(&blDev->mutex);
225 return brightness;
226 }
227
GetMinBrightness(struct BacklightDev * blDev,uint32_t * brightness)228 int32_t GetMinBrightness(struct BacklightDev *blDev, uint32_t *brightness)
229 {
230 if (blDev == NULL || brightness == NULL) {
231 HDF_LOGE("%s: blDev or brightness is null", __func__);
232 return HDF_FAILURE;
233 }
234 *brightness = GetBlDevBrightness(blDev, MIN_BRIGHTNESS);
235 return HDF_SUCCESS;
236 }
237
GetCurrBrightness(struct BacklightDev * blDev,uint32_t * brightness)238 int32_t GetCurrBrightness(struct BacklightDev *blDev, uint32_t *brightness)
239 {
240 if (blDev == NULL || brightness == NULL) {
241 HDF_LOGE("%s: blDev or brightness is null", __func__);
242 return HDF_FAILURE;
243 }
244 *brightness = GetBlDevBrightness(blDev, CURRENT_BRIGHTNESS);
245 return HDF_SUCCESS;
246 }
247
GetDefBrightness(struct BacklightDev * blDev,uint32_t * brightness)248 int32_t GetDefBrightness(struct BacklightDev *blDev, uint32_t *brightness)
249 {
250 if (blDev == NULL || brightness == NULL) {
251 HDF_LOGE("%s: blDev or brightness is null", __func__);
252 return HDF_FAILURE;
253 }
254 *brightness = GetBlDevBrightness(blDev, DEFAULT_BRIGHTNESS);
255 return HDF_SUCCESS;
256 }
257
GetMaxBrightness(struct BacklightDev * blDev,uint32_t * brightness)258 int32_t GetMaxBrightness(struct BacklightDev *blDev, uint32_t *brightness)
259 {
260 if (blDev == NULL || brightness == NULL) {
261 HDF_LOGE("%s: blDev or brightness is null", __func__);
262 return HDF_FAILURE;
263 }
264 *brightness = GetBlDevBrightness(blDev, MAX_BRIGHTNESS);
265 return HDF_SUCCESS;
266 }
267
HdfGetBrightness(enum BrightnessType type,struct HdfSBuf * reqData,struct HdfSBuf * rspData)268 static int32_t HdfGetBrightness(enum BrightnessType type,
269 struct HdfSBuf *reqData, struct HdfSBuf *rspData)
270 {
271 uint32_t devId;
272 uint32_t brightness;
273 struct BlDevManager *blDevManager = NULL;
274 struct BacklightDev *blDev = NULL;
275
276 if (reqData == NULL) {
277 return HDF_ERR_INVALID_PARAM;
278 }
279 if (!HdfSbufReadUint32(reqData, &devId)) {
280 HDF_LOGE("%s: HdfSbufReadBuffer failed", __func__);
281 return HDF_FAILURE;
282 }
283 blDevManager = GetBlDevManager();
284 if (devId >= blDevManager->devNum) {
285 HDF_LOGE("%s: devId is illegal", __func__);
286 return HDF_FAILURE;
287 }
288 blDev = blDevManager->blDev[devId];
289 brightness = GetBlDevBrightness(blDev, type);
290 if (!HdfSbufWriteUint32(rspData, brightness)) {
291 HDF_LOGE("%s: HdfSbufWriteUint32 failed", __func__);
292 return HDF_FAILURE;
293 }
294 return HDF_SUCCESS;
295 }
296
HdfGetMinBrightness(struct HdfDeviceObject * device,struct HdfSBuf * reqData,struct HdfSBuf * rspData)297 static int32_t HdfGetMinBrightness(struct HdfDeviceObject *device,
298 struct HdfSBuf *reqData, struct HdfSBuf *rspData)
299 {
300 (void)device;
301 return HdfGetBrightness(MIN_BRIGHTNESS, reqData, rspData);
302 }
303
HdfGetCurrBrightness(struct HdfDeviceObject * device,struct HdfSBuf * reqData,struct HdfSBuf * rspData)304 static int32_t HdfGetCurrBrightness(struct HdfDeviceObject *device,
305 struct HdfSBuf *reqData, struct HdfSBuf *rspData)
306 {
307 (void)device;
308 return HdfGetBrightness(CURRENT_BRIGHTNESS, reqData, rspData);
309 }
310
HdfGetDefBrightness(struct HdfDeviceObject * device,struct HdfSBuf * reqData,struct HdfSBuf * rspData)311 static int32_t HdfGetDefBrightness(struct HdfDeviceObject *device,
312 struct HdfSBuf *reqData, struct HdfSBuf *rspData)
313 {
314 (void)device;
315 return HdfGetBrightness(DEFAULT_BRIGHTNESS, reqData, rspData);
316 }
317
HdfGetMaxBrightness(struct HdfDeviceObject * device,struct HdfSBuf * reqData,struct HdfSBuf * rspData)318 static int32_t HdfGetMaxBrightness(struct HdfDeviceObject *device,
319 struct HdfSBuf *reqData, struct HdfSBuf *rspData)
320 {
321 (void)device;
322 return HdfGetBrightness(MAX_BRIGHTNESS, reqData, rspData);
323 }
324
HdfSetBrightness(struct HdfDeviceObject * device,struct HdfSBuf * reqData,struct HdfSBuf * rspData)325 static int32_t HdfSetBrightness(struct HdfDeviceObject *device,
326 struct HdfSBuf *reqData, struct HdfSBuf *rspData)
327 {
328 struct BlDevManager *blDevManager = NULL;
329 struct BacklightDev *blDev = NULL;
330
331 (void)device;
332 (void)rspData;
333 if (reqData == NULL) {
334 return HDF_ERR_INVALID_PARAM;
335 }
336 uint32_t para = 0;
337 if (!HdfSbufReadUint32(reqData, ¶)) {
338 HDF_LOGE("%s: HdfSbufReadBuffer failed", __func__);
339 return HDF_FAILURE;
340 }
341 uint32_t devId = (para >> OFFSET_TWO_BYTE) & 0xffff;
342 uint32_t level = para & 0xffff;
343 blDevManager = GetBlDevManager();
344 if (devId >= blDevManager->devNum) {
345 HDF_LOGE("%s: devId is illegal", __func__);
346 return HDF_FAILURE;
347 }
348 blDev = blDevManager->blDev[devId];
349 return UpdateBrightness(blDev, level);
350 }
351
HdfGetBlDevList(struct HdfDeviceObject * device,struct HdfSBuf * reqData,struct HdfSBuf * rspData)352 static int32_t HdfGetBlDevList(struct HdfDeviceObject *device,
353 struct HdfSBuf *reqData, struct HdfSBuf *rspData)
354 {
355 (void)device;
356 (void)reqData;
357 int32_t ret;
358 char *devName = NULL;
359 char *tmp = NULL;
360 char buffer[NAME_BUFFER_LEN] = {0};
361 struct BlDevManager *blDevManager = NULL;
362
363 blDevManager = GetBlDevManager();
364 tmp = buffer;
365 for (int32_t i = 0; i < blDevManager->devNum; i++) {
366 devName = blDevManager->blDev[i]->name;
367 if ((tmp + MAX_DEST_STRING_LEN) > &buffer[NAME_BUFFER_LEN]) {
368 HDF_LOGE("%s: Memory out of bounds", __func__);
369 break;
370 }
371 // strlen("%d : \n") = 6
372 ret = snprintf_s(tmp, MAX_DEST_STRING_LEN, strlen(devName) + 6, "%d : %s\n", i, devName);
373 if (ret < 0) {
374 HDF_LOGE("%s: snprintf_s fail", __func__);
375 return HDF_FAILURE;
376 }
377 tmp = tmp + strlen(tmp) + 1;
378 }
379 if (!HdfSbufWriteBuffer(rspData, buffer, strlen(buffer) + 1) != 0) {
380 HDF_LOGE("%s: copy info failed", __func__);
381 return HDF_FAILURE;
382 }
383 return HDF_SUCCESS;
384 }
385
386 static BlCmdHandle g_blDevCmdHandle[] = {
387 HdfGetMinBrightness,
388 HdfGetCurrBrightness,
389 HdfGetDefBrightness,
390 HdfGetMaxBrightness,
391 HdfGetBlDevList,
392 HdfSetBrightness,
393 };
394
BacklightDispatch(struct HdfDeviceIoClient * client,int cmd,struct HdfSBuf * data,struct HdfSBuf * reply)395 static int32_t BacklightDispatch(struct HdfDeviceIoClient *client, int cmd, struct HdfSBuf *data,
396 struct HdfSBuf *reply)
397 {
398 BlCmdHandle blCmdHandle = NULL;
399
400 if (client == NULL) {
401 return HDF_ERR_INVALID_PARAM;
402 }
403 if ((cmd < 0) || (cmd >= sizeof(g_blDevCmdHandle) / sizeof(BlCmdHandle))) {
404 HDF_LOGE("%s: cmd is illegal", __func__);
405 return HDF_FAILURE;
406 }
407 blCmdHandle = g_blDevCmdHandle[cmd];
408 return blCmdHandle(client->device, data, reply);
409 }
410
BacklightBind(struct HdfDeviceObject * dev)411 static int BacklightBind(struct HdfDeviceObject *dev)
412 {
413 if (dev == NULL) {
414 return HDF_FAILURE;
415 }
416 static struct IDeviceIoService blService = {
417 .Dispatch = BacklightDispatch,
418 };
419 dev->service = &blService;
420 return HDF_SUCCESS;
421 }
422
BacklightInit(struct HdfDeviceObject * object)423 static int32_t BacklightInit(struct HdfDeviceObject *object)
424 {
425 if (object == NULL) {
426 HDF_LOGE("%s: object is null!", __func__);
427 return HDF_FAILURE;
428 }
429 HDF_LOGI("%s success", __func__);
430 return HDF_SUCCESS;
431 }
432
433 struct HdfDriverEntry g_blDevEntry = {
434 .moduleVersion = 1,
435 .moduleName = "HDF_BL",
436 .Init = BacklightInit,
437 .Bind = BacklightBind,
438 };
439
440 HDF_INIT(g_blDevEntry);
441