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_event.h"
16 #include <cstdio>
17 #include <cstdlib>
18 #include "log/log.h"
19 #include "updater_ui_const.h"
20
21 namespace updater {
22 constexpr int TOUCH_LOW_TH = 50;
23 constexpr int TOUCH_HIGH_TH = 90;
24 constexpr int INIT_DEFAULT_VALUE = 255;
25 constexpr int LABEL_HEIGHT = 64;
26 constexpr int LABEL_OFFSET_2 = 2;
27 constexpr int LABEL_OFFSET_3 = 3;
28 constexpr int DIALOG_START_Y = 550;
29 IInputInterface *g_inputInterface;
30 InputEventCb g_callback;
31
32 bool g_touchSwiping = false;
33 bool g_touchFingerDown = false;
34
35 int g_touchX;
36 int g_touchY;
37 int g_touchStartX;
38 int g_touchStartY;
39 extern Frame *g_menuFrame;
40
41 enum SwipeDirection {
42 UP,
43 DOWN,
44 RIGHT,
45 LEFT
46 };
47
TouchToClickEvent(const int dx,const int dy,int event)48 void TouchToClickEvent(const int dx, const int dy, int event)
49 {
50 if (!g_menuFrame->IsVisiable()) {
51 LOG(INFO) << "menu page is not top";
52 return;
53 }
54 if (abs(dy) >= 0 && abs(dy) <= LABEL_HEIGHT) {
55 g_menuFrame->DispatchKeyEvent(LABEL_ID_0, event);
56 } else if (abs(dy) > LABEL_HEIGHT && abs(dy) <= LABEL_HEIGHT * LABEL_OFFSET_2) {
57 g_menuFrame->DispatchKeyEvent(LABEL_ID_1, event);
58 } else if (abs(dy) > LABEL_HEIGHT * LABEL_OFFSET_2 && abs(dy) <= LABEL_HEIGHT * LABEL_OFFSET_3) {
59 g_menuFrame->DispatchKeyEvent(LABEL_ID_2, event);
60 } else if (abs(dy) > WIDTH1 && abs(dy) <= DIALOG_START_Y) {
61 if (abs(dx) > 0 && abs(dx) <= DIALOG_OK_WIDTH) {
62 g_menuFrame->DispatchKeyEvent(DIALOG_OK_ID, event);
63 } else if (abs(dx) > DIALOG_CANCEL_X && abs(dx) <= WIDTH1) {
64 g_menuFrame->DispatchKeyEvent(DIALOG_CANCEL_ID, event);
65 }
66 }
67 return;
68 }
69
TouchToKey(const int dx,const int dy)70 void TouchToKey(const int dx, const int dy)
71 {
72 enum SwipeDirection direction;
73 if (abs(dy) < TOUCH_LOW_TH && abs(dx) > TOUCH_HIGH_TH) {
74 direction = (dx < 0) ? SwipeDirection::LEFT : SwipeDirection::RIGHT;
75 } else if (abs(dx) < TOUCH_LOW_TH && abs(dy) > TOUCH_HIGH_TH) {
76 direction = (dy < 0) ? SwipeDirection::UP : SwipeDirection::DOWN;
77 } else {
78 return;
79 }
80 switch (direction) {
81 case SwipeDirection::UP:
82 g_menuFrame->DispatchKeyEvent(KEY_UP);
83 break;
84 case SwipeDirection::DOWN:
85 g_menuFrame->DispatchKeyEvent(KEY_DOWN);
86 break;
87 case SwipeDirection::LEFT:
88 case SwipeDirection::RIGHT:
89 g_menuFrame->DispatchKeyEvent(KEY_POWER);
90 break;
91 default:
92 break;
93 }
94 return;
95 }
96
SwipEvent()97 void SwipEvent()
98 {
99 if (g_touchFingerDown && !g_touchSwiping) {
100 g_touchStartX = g_touchX;
101 g_touchStartY = g_touchY;
102 g_touchSwiping = true;
103 } else if (!g_touchFingerDown && g_touchSwiping) {
104 g_touchSwiping = false;
105 TouchToKey(g_touchX - g_touchStartX, g_touchY - g_touchStartY);
106 }
107 }
108
ClickEvent()109 void ClickEvent()
110 {
111 if (!g_menuFrame->IsVisiable()) {
112 LOG(INFO) << "click event";
113 TouchToClickEvent(g_touchX, g_touchY, -1);
114 return;
115 }
116 if (g_touchFingerDown) {
117 TouchToClickEvent(g_touchX, g_touchY, PRESS_EVENT);
118 } else if (!g_touchFingerDown) {
119 TouchToClickEvent(g_touchX, g_touchY, RELEASE_EVENT);
120 }
121 }
122
HandleInputEvent(const struct input_event * iev)123 int HandleInputEvent(const struct input_event *iev)
124 {
125 struct input_event ev {};
126 ev.type = iev->type;
127 ev.code = iev->code;
128 ev.value = iev->value;
129 if (ev.type == EV_SYN) {
130 if (ev.code == SYN_REPORT) {
131 // There might be multiple SYN_REPORT events. We should only detect
132 // a swipe after lifting the contact.
133 #ifdef CONVERT_RL_SLIDE_TO_CLICK
134 SwipEvent();
135 #else
136 ClickEvent();
137 #endif
138 }
139 return 0;
140 }
141 if (ev.type == EV_ABS) {
142 switch (ev.code) {
143 case ABS_MT_POSITION_X:
144 g_touchX = ev.value;
145 g_touchFingerDown = true;
146 break;
147 case ABS_MT_POSITION_Y:
148 g_touchY = ev.value;
149 g_touchFingerDown = true;
150 break;
151 case ABS_MT_TRACKING_ID:
152 // Protocol B: -1 marks lifting the contact.
153 if (ev.value < 0) {
154 g_touchFingerDown = false;
155 }
156 break;
157 default:
158 break;
159 }
160 return 0;
161 }
162 if (ev.type == EV_KEY && ev.code <= KEY_MAX) {
163 if (ev.code == BTN_TOUCH) {
164 g_touchFingerDown = (ev.value == 1);
165 }
166 if (ev.code == BTN_TOUCH || ev.code == BTN_TOOL_FINGER) {
167 return 0;
168 }
169 }
170 return 0;
171 }
172
ReportEventPkgCallback(const EventPackage ** pkgs,const uint32_t count,uint32_t devIndex)173 void ReportEventPkgCallback(const EventPackage **pkgs, const uint32_t count, uint32_t devIndex)
174 {
175 if (pkgs == nullptr || *pkgs == nullptr || !g_menuFrame->IsVisiable()) {
176 return;
177 }
178 for (uint32_t i = 0; i < count; i++) {
179 struct input_event ev = {
180 .type = static_cast<__u16>(pkgs[i]->type),
181 .code = static_cast<__u16>(pkgs[i]->code),
182 .value = pkgs[i]->value,
183 };
184 HandleInputEvent(&ev);
185 }
186 return;
187 }
HdfInit()188 int HdfInit()
189 {
190 int ret = GetInputInterface(&g_inputInterface);
191 if (ret != INPUT_SUCCESS) {
192 LOG(ERROR) << "get input driver interface failed";
193 return ret;
194 }
195 ret = g_inputInterface->iInputManager->OpenInputDevice(1);
196 if (ret) {
197 LOG(ERROR) << "open device1 failed";
198 return ret;
199 }
200 uint32_t devType = 0;
201 ret = g_inputInterface->iInputController->GetDeviceType(1, &devType);
202 if (ret) {
203 LOG(ERROR) << "get device1's type failed";
204 return ret;
205 }
206 g_callback.EventPkgCallback = ReportEventPkgCallback;
207 ret = g_inputInterface->iInputReporter->RegisterReportCallback(1, &g_callback);
208 if (ret) {
209 LOG(ERROR) << "register callback failed for device 1";
210 return ret;
211 }
212 devType = INIT_DEFAULT_VALUE;
213 ret = g_inputInterface->iInputController->GetDeviceType(1, &devType);
214 return 0;
215 }
216 } // namespace updater
217