1/*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15#include "input_manager.h"
16#include <stdio.h>
17#include <stdlib.h>
18#include <unistd.h>
19#include <limits.h>
20#include <fcntl.h>
21#include <malloc.h>
22#include <sys/ioctl.h>
23#include <securec.h>
24#include "hdf_io_service_if.h"
25#include "osal_time.h"
26#include "input_common.h"
27
28#define TOUCH_INDEX 1
29#define PLACEHOLDER_LENGTH 2
30#define PLACEHOLDER_LIMIT 10
31
32static InputDevManager *g_devManager;
33int32_t InstanceReporterHdi(InputReporter **hdi);
34int32_t InstanceControllerHdi(InputController **hdi);
35int32_t UpdateDevFullInfo(uint32_t devIndex);
36
37InputDevManager *GetDevManager(void)
38{
39    return g_devManager;
40}
41
42static int32_t GetInputDevice(uint32_t devIndex, InputDeviceInfo **devInfo)
43{
44    int32_t ret;
45    int32_t count = 3; // 3 : number of attempts
46    DeviceInfoNode *pos = NULL;
47    DeviceInfoNode *next = NULL;
48    InputDevManager *manager = NULL;
49
50    if (devIndex >= MAX_INPUT_DEV_NUM || devInfo == NULL) {
51        HDF_LOGE("%s: invalid param", __func__);
52        return INPUT_INVALID_PARAM;
53    }
54
55    while ((count--) > 0) {
56        ret = UpdateDevFullInfo(devIndex);
57        if (ret == INPUT_SUCCESS) {
58            break;
59        }
60        OsalMSleep(10); // 10 : delay time
61    }
62    if (count == 0) {
63        HDF_LOGE("%s: update dev info failed", __func__);
64        return ret;
65    }
66
67    GET_MANAGER_CHECK_RETURN(manager);
68
69    pthread_mutex_lock(&manager->mutex);
70    DLIST_FOR_EACH_ENTRY_SAFE(pos, next, &manager->devList, DeviceInfoNode, node) {
71        if (pos->payload.devIndex != devIndex) {
72            continue;
73        }
74        *devInfo = &pos->payload;
75        pthread_mutex_unlock(&manager->mutex);
76        HDF_LOGI("%s: device%u get dev info succ", __func__, devIndex);
77        return INPUT_SUCCESS;
78    }
79
80    pthread_mutex_unlock(&manager->mutex);
81    HDF_LOGE("%s: device%u doesn't exist, can't get device info", __func__, devIndex);
82    return INPUT_FAILURE;
83}
84
85static int32_t GetInputDeviceList(uint32_t *devNum, InputDeviceInfo **deviceList, uint32_t size)
86{
87    DeviceInfoNode *pos = NULL;
88    DeviceInfoNode *next = NULL;
89    InputDevManager *manager = NULL;
90    uint32_t tempSize = 0;
91    InputDeviceInfo **tempList = NULL;
92
93    if (devNum == NULL || deviceList == NULL) {
94        HDF_LOGE("%s: invalid param", __func__);
95        return INPUT_INVALID_PARAM;
96    }
97    tempList = deviceList;
98    GET_MANAGER_CHECK_RETURN(manager);
99
100    pthread_mutex_lock(&manager->mutex);
101    DLIST_FOR_EACH_ENTRY_SAFE(pos, next, &manager->devList, DeviceInfoNode, node) {
102        if (tempSize >= size) {
103            *devNum = manager->attachedDevNum;
104            pthread_mutex_unlock(&manager->mutex);
105            HDF_LOGE("%s: size is not enough, size = %u, devNum = %u", __func__,
106                size, *devNum);
107            return INPUT_FAILURE;
108        }
109        *tempList = &pos->payload;
110        tempList++;
111        tempSize++;
112    }
113    *devNum = manager->attachedDevNum;
114    pthread_mutex_unlock(&manager->mutex);
115    return INPUT_SUCCESS;
116}
117
118static int32_t CloseInputDevice(uint32_t devIndex)
119{
120    DeviceInfoNode *pos = NULL;
121    DeviceInfoNode *next = NULL;
122    InputDevManager *manager = NULL;
123
124    GET_MANAGER_CHECK_RETURN(manager);
125
126    pthread_mutex_lock(&manager->mutex);
127    DLIST_FOR_EACH_ENTRY_SAFE(pos, next, &manager->devList, DeviceInfoNode, node) {
128        if (pos->payload.devIndex != devIndex) {
129            continue;
130        }
131        HdfIoServiceRecycle(pos->service);
132        DListRemove(&pos->node);
133        free(pos);
134        manager->attachedDevNum--;
135        pthread_mutex_unlock(&manager->mutex);
136        return INPUT_SUCCESS;
137    }
138
139    pthread_mutex_unlock(&manager->mutex);
140    HDF_LOGE("%s: device%u doesn't exist", __func__, devIndex);
141    return INPUT_FAILURE;
142}
143
144static int32_t AddService(uint32_t index, const struct HdfIoService *service)
145{
146    InputDevManager *manager = NULL;
147    DeviceInfoNode *device = NULL;
148
149    GET_MANAGER_CHECK_RETURN(manager);
150    device = (DeviceInfoNode *)malloc(sizeof(DeviceInfoNode));
151    if (device == NULL) {
152        HDF_LOGE("%s: malloc fail", __func__);
153        return INPUT_NOMEM;
154    }
155    (void)memset_s(device, sizeof(DeviceInfoNode), 0, sizeof(DeviceInfoNode));
156
157    device->payload.devIndex = index;
158    device->service = (struct HdfIoService *)service;
159    pthread_mutex_lock(&manager->mutex);
160    DListInsertTail(&device->node, &manager->devList);
161    manager->attachedDevNum++;
162    pthread_mutex_unlock(&manager->mutex);
163    return INPUT_SUCCESS;
164}
165
166static int32_t CheckIndex(uint32_t devIndex)
167{
168    DeviceInfoNode *pos = NULL;
169    DeviceInfoNode *next = NULL;
170    InputDevManager *manager = NULL;
171
172    if (devIndex >= MAX_INPUT_DEV_NUM) {
173        HDF_LOGE("%s: invalid param", __func__);
174        return INPUT_INVALID_PARAM;
175    }
176
177    GET_MANAGER_CHECK_RETURN(manager);
178    pthread_mutex_lock(&manager->mutex);
179    DLIST_FOR_EACH_ENTRY_SAFE(pos, next, &manager->devList, DeviceInfoNode, node) {
180        if (pos->payload.devIndex == devIndex) {
181            pthread_mutex_unlock(&manager->mutex);
182            HDF_LOGE("%s: the device%u has existed", __func__, devIndex);
183            return INPUT_FAILURE;
184        }
185    }
186    pthread_mutex_unlock(&manager->mutex);
187    return INPUT_SUCCESS;
188}
189
190static int32_t OpenInputDevice(uint32_t devIndex)
191{
192    int32_t ret;
193    int32_t len;
194    struct HdfIoService *service = NULL;
195    char serviceName[SERVICE_NAME_LEN] = {0};
196
197    if (CheckIndex(devIndex) != INPUT_SUCCESS) {
198        return INPUT_FAILURE;
199    }
200
201    len = (devIndex < PLACEHOLDER_LIMIT) ? 1 : PLACEHOLDER_LENGTH;
202    ret = snprintf_s(serviceName, SERVICE_NAME_LEN, strlen("hdf_input_event") + len, "%s%u",
203        "hdf_input_event", devIndex);
204    if (ret == -1) {
205        HDF_LOGE("%s: snprintf_s fail", __func__);
206        return INPUT_FAILURE;
207    }
208
209    service = HdfIoServiceBind(serviceName);
210    if (service == NULL) {
211        HDF_LOGE("%s: fail to get io service: %s", __func__, serviceName);
212        return INPUT_NULL_PTR;
213    }
214
215    if (AddService(devIndex, service) < 0) {
216        HDF_LOGE("%s: add device%d failed", __func__, devIndex);
217        HdfIoServiceRecycle(service);
218        return INPUT_FAILURE;
219    }
220
221    HDF_LOGI("%s: open dev%u succ, service name = %s", __func__, devIndex, serviceName);
222    return INPUT_SUCCESS;
223}
224
225static int32_t ScanInputDevice(InputDevDesc *staArr, uint32_t arrLen)
226{
227    InputDevManager *manager = NULL;
228    struct HdfIoService *service = NULL;
229    struct HdfSBuf *reply = NULL;
230    char *data = {0};
231    uint32_t count = 0;
232    uint32_t replayDataSize = 0;
233    int32_t ret;
234
235    GET_MANAGER_CHECK_RETURN(manager);
236    pthread_mutex_lock(&manager->mutex);
237    if (manager->hostDev.service == NULL) {
238        manager->hostDev.service = HdfIoServiceBind(DEV_MANAGER_SERVICE_NAME);
239    }
240    service = manager->hostDev.service;
241    pthread_mutex_unlock(&manager->mutex);
242
243    if (service == NULL) {
244        HDF_LOGE("%s: HdfIoServiceBind failed", __func__);
245        return INPUT_FAILURE;
246    }
247    reply = HdfSbufObtainDefaultSize();
248    if (reply == NULL) {
249        HDF_LOGE("%s: fail to obtain sbuf data", __func__);
250        return INPUT_FAILURE;
251    }
252
253    ret = service->dispatcher->Dispatch(&service->object, 0, NULL, reply);
254    if (ret != INPUT_SUCCESS) {
255        HDF_LOGE("%s: dispatch fail", __func__);
256        HdfSbufRecycle(reply);
257        return INPUT_FAILURE;
258    }
259
260    while (count < arrLen) {
261        if (!HdfSbufReadBuffer(reply, (const void **)(&data), &replayDataSize) ||
262            replayDataSize != sizeof(InputDevDesc)) {
263            HDF_LOGE("%s: sbuf read failed", __func__);
264            break;
265        }
266        if (memcpy_s(&staArr[count], sizeof(InputDevDesc), data, replayDataSize) != EOK) {
267            HDF_LOGE("%s: memcpy failed, line: %d", __func__, __LINE__);
268            HdfSbufRecycle(reply);
269            return INPUT_FAILURE;
270        }
271        HDF_LOGI("%s: type = %d, id =%d", __func__, staArr[count].devType, staArr[count].devIndex);
272        count++;
273    }
274    HdfSbufRecycle(reply);
275    return INPUT_SUCCESS;
276}
277
278static int32_t InstanceManagerHdi(InputManager **manager)
279{
280    InputManager *managerHdi = (InputManager *)malloc(sizeof(InputManager));
281    if (managerHdi == NULL) {
282        HDF_LOGE("%s: malloc fail", __func__);
283        return INPUT_NOMEM;
284    }
285
286    (void)memset_s(managerHdi, sizeof(InputManager), 0, sizeof(InputManager));
287
288    managerHdi->ScanInputDevice = ScanInputDevice;
289    managerHdi->OpenInputDevice = OpenInputDevice;
290    managerHdi->CloseInputDevice = CloseInputDevice;
291    managerHdi->GetInputDevice = GetInputDevice;
292    managerHdi->GetInputDeviceList = GetInputDeviceList;
293    *manager = managerHdi;
294    return INPUT_SUCCESS;
295}
296
297static int32_t InitDevManager(void)
298{
299    InputDevManager *manager = (InputDevManager *)malloc(sizeof(InputDevManager));
300    if (manager == NULL) {
301        HDF_LOGE("%s: malloc fail", __func__);
302        return INPUT_NOMEM;
303    }
304
305    (void)memset_s(manager, sizeof(InputDevManager), 0, sizeof(InputDevManager));
306    DListHeadInit(&manager->devList);
307    pthread_mutex_init(&manager->mutex, NULL);
308    manager->attachedDevNum = 0;
309    manager->evtCallbackNum = 0;
310    g_devManager = manager;
311    return INPUT_SUCCESS;
312}
313
314static void FreeInputHdi(IInputInterface **hdi)
315{
316    if (hdi == NULL || *hdi == NULL) {
317        return;
318    }
319    if ((*hdi)->iInputManager != NULL) {
320        free((*hdi)->iInputManager);
321        (*hdi)->iInputManager = NULL;
322    }
323
324    if ((*hdi)->iInputController != NULL) {
325        free((*hdi)->iInputController);
326        (*hdi)->iInputController = NULL;
327    }
328
329    if ((*hdi)->iInputReporter != NULL) {
330        free((*hdi)->iInputReporter);
331        (*hdi)->iInputReporter = NULL;
332    }
333    free((*hdi));
334    *hdi = NULL;
335}
336
337static IInputInterface *InstanceInputHdi(void)
338{
339    int32_t ret;
340    IInputInterface *hdi = (IInputInterface *)malloc(sizeof(IInputInterface));
341    if (hdi == NULL) {
342        HDF_LOGE("%s: malloc fail", __func__);
343        return NULL;
344    }
345    (void)memset_s(hdi, sizeof(IInputInterface), 0, sizeof(IInputInterface));
346
347    ret = InstanceManagerHdi(&hdi->iInputManager);
348    if (ret != INPUT_SUCCESS) {
349        FreeInputHdi(&hdi);
350        return NULL;
351    }
352
353    ret = InstanceControllerHdi(&hdi->iInputController);
354    if (ret != INPUT_SUCCESS) {
355        FreeInputHdi(&hdi);
356        return NULL;
357    }
358
359    ret = InstanceReporterHdi(&hdi->iInputReporter);
360    if (ret != INPUT_SUCCESS) {
361        FreeInputHdi(&hdi);
362        return NULL;
363    }
364    return hdi;
365}
366
367int32_t GetInputInterface(IInputInterface **inputInterface)
368{
369    int32_t ret;
370    IInputInterface *inputHdi = NULL;
371
372    if (inputInterface == NULL) {
373        HDF_LOGE("%s: parameter is null", __func__);
374        return INPUT_INVALID_PARAM;
375    }
376
377    inputHdi = InstanceInputHdi();
378    if (inputHdi == NULL) {
379        HDF_LOGE("%s: failed to instance hdi", __func__);
380        return INPUT_NULL_PTR;
381    }
382
383    ret = InitDevManager();
384    if (ret != INPUT_SUCCESS) {
385        HDF_LOGE("%s: failed to initialize manager", __func__);
386        FreeInputHdi(&inputHdi);
387        return INPUT_FAILURE;
388    }
389
390    *inputInterface = inputHdi;
391    HDF_LOGI("%s: exit succ", __func__);
392    return INPUT_SUCCESS;
393}
394
395static void FreeDevManager(InputDevManager *manager)
396{
397    (void)HdfDeviceUnregisterEventListener(manager->hostDev.service, manager->hostDev.listener);
398    if (manager->hostDev.listener != NULL) {
399        free(manager->hostDev.listener);
400        manager->hostDev.listener = NULL;
401        manager->hostDev.hostCb = NULL;
402    }
403    (void)HdfIoServiceRecycle(manager->hostDev.service);
404    pthread_mutex_unlock(&manager->mutex);
405    pthread_mutex_destroy(&manager->mutex);
406    free(manager);
407    g_devManager = NULL;
408}
409
410void ReleaseInputInterface(IInputInterface **inputInterface)
411{
412    DeviceInfoNode *pos = NULL;
413    DeviceInfoNode *next = NULL;
414    InputDevManager *manager = NULL;
415
416    if (inputInterface == NULL) {
417        return;
418    }
419    FreeInputHdi(inputInterface);
420
421    if (g_devManager == NULL) {
422        return;
423    }
424    manager = g_devManager;
425    pthread_mutex_lock(&manager->mutex);
426    DLIST_FOR_EACH_ENTRY_SAFE(pos, next, &manager->devList, DeviceInfoNode, node) {
427        (void)HdfDeviceUnregisterEventListener(pos->service, pos->listener);
428        if (pos->listener != NULL) {
429            free(pos->listener);
430            pos->listener = NULL;
431            pos->eventCb = NULL;
432        }
433        (void)HdfIoServiceRecycle(pos->service);
434        DListRemove(&pos->node);
435        free(pos);
436    }
437    FreeDevManager(manager);
438}