blob: d7a2beb835daaa013adce966b1b58d5e8a58941f [file] [log] [blame]
lijuangf55ad052018-04-23 18:30:50 +08001/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
lijuang7d235f42015-07-16 20:19:45 +08002*
3* Redistribution and use in source and binary forms, with or without
4* modification, are permitted provided that the following conditions are
5* met:
6* * Redistributions of source code must retain the above copyright
7* notice, this list of conditions and the following disclaimer.
8* * Redistributions in binary form must reproduce the above
9* copyright notice, this list of conditions and the following
10* disclaimer in the documentation and/or other materials provided
11* with the distribution.
12* * Neither the name of The Linux Foundation nor the names of its
13* contributors may be used to endorse or promote products derived
14* from this software without specific prior written permission.
15*
16* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27*/
28
29#include <debug.h>
30#include <reg.h>
31#include <stdlib.h>
32#include <pm8x41.h>
33#include <pm8x41_hw.h>
34#include <kernel/timer.h>
35#include <platform/timer.h>
36#include <kernel/thread.h>
37#include <dev/keys.h>
38#include <dev/fbcon.h>
39#include <menu_keys_detect.h>
40#include <display_menu.h>
41#include <platform/gpio.h>
42#include <platform/iomap.h>
43#include <platform.h>
lijuangf5045b52015-09-07 17:19:20 +080044#include <reboot.h>
lijuang9a7d3b92015-11-30 14:41:24 +080045#include <sys/types.h>
lijuang7d235f42015-07-16 20:19:45 +080046#include <../../../app/aboot/recovery.h>
lijuang4ece1e72015-08-14 21:02:36 +080047#include <../../../app/aboot/devinfo.h>
Kishor PK60a68212017-05-08 16:55:57 +053048#include <string.h>
lijuang7d235f42015-07-16 20:19:45 +080049
50#define KEY_DETECT_FREQUENCY 50
lijuang7d235f42015-07-16 20:19:45 +080051
lijuang9a7d3b92015-11-30 14:41:24 +080052static time_t before_time;
lijuang7d235f42015-07-16 20:19:45 +080053
Parth Dixit54ac3bb2017-03-07 15:52:48 +053054extern bool pwr_key_is_pressed;
lijuang7d235f42015-07-16 20:19:45 +080055extern int target_volume_up();
56extern uint32_t target_volume_down();
57extern void reboot_device(unsigned reboot_reason);
58extern void shutdown_device();
59
60typedef uint32_t (*keys_detect_func)(void);
lijuang9a7d3b92015-11-30 14:41:24 +080061typedef void (*keys_action_func)(struct select_msg_info* msg_info);
lijuang7d235f42015-07-16 20:19:45 +080062
63struct keys_stru {
64 int type;
65 keys_detect_func keys_pressed_func;
66};
67
68struct keys_stru keys[] = {
69 {VOLUME_UP, (uint32_t (*)(void))target_volume_up},
70 {VOLUME_DOWN, target_volume_down},
71 {POWER_KEY, pm8x41_get_pwrkey_is_pressed},
72};
73
74struct pages_action {
75 keys_action_func up_action_func;
76 keys_action_func down_action_func;
77 keys_action_func enter_action_func;
78};
79
lijuang9a7d3b92015-11-30 14:41:24 +080080static uint32_t verify_index_action[] = {
81 [0] = POWEROFF,
82 [1] = RESTART,
83 [2] = RECOVER,
84 [3] = FASTBOOT,
85 [4] = BACK,
86};
87
88static uint32_t fastboot_index_action[] = {
89 [0] = RESTART,
90 [1] = FASTBOOT,
91 [2] = RECOVER,
92 [3] = POWEROFF,
lijuang42aefaa2016-04-14 15:55:17 +080093 [4] = FFBM,
lijuang9a7d3b92015-11-30 14:41:24 +080094};
95
96static uint32_t unlock_index_action[] = {
lijuangf55ad052018-04-23 18:30:50 +080097 [0] = RESTART,
98 [1] = RECOVER,
lijuang9a7d3b92015-11-30 14:41:24 +080099};
100
lijuang7d235f42015-07-16 20:19:45 +0800101static int is_key_pressed(int keys_type)
102{
103 int count = 0;
104
105 if (keys[keys_type].keys_pressed_func()) {
106 /*if key is pressed, wait for 1 second to see if it is released*/
107 while(count++ < 10 && keys[keys_type].keys_pressed_func())
108 thread_sleep(100);
109 return 1;
110 }
111
112 return 0;
113}
114
lijuang9a7d3b92015-11-30 14:41:24 +0800115static void update_device_status(struct select_msg_info* msg_info, int reason)
lijuang7d235f42015-07-16 20:19:45 +0800116{
lijuang42aefaa2016-04-14 15:55:17 +0800117 char ffbm_page_buffer[FFBM_MODE_BUF_SIZE];
lijuang9a7d3b92015-11-30 14:41:24 +0800118 fbcon_clear();
119 switch (reason) {
120 case RECOVER:
lijuangf55ad052018-04-23 18:30:50 +0800121 reset_device_unlock_status(msg_info->info.msg_type);
lijuang9a7d3b92015-11-30 14:41:24 +0800122 reboot_device(RECOVERY_MODE);
123 break;
124 case RESTART:
125 reboot_device(0);
126 break;
127 case POWEROFF:
128 shutdown_device();
129 break;
130 case FASTBOOT:
131 reboot_device(FASTBOOT_MODE);
132 break;
133 case CONTINUE:
lijuang9a7d3b92015-11-30 14:41:24 +0800134 /* Continue boot, no need to detect the keys'status */
lijuangde34d502016-02-26 16:04:50 +0800135 msg_info->info.is_exit = true;
lijuang9a7d3b92015-11-30 14:41:24 +0800136 break;
137 case BACK:
138 display_bootverify_menu_renew(msg_info, msg_info->last_msg_type);
139 before_time = current_time();
140
141 break;
lijuang42aefaa2016-04-14 15:55:17 +0800142 case FFBM:
Kishor PK60a68212017-05-08 16:55:57 +0530143 memset(&ffbm_page_buffer, 0, sizeof(ffbm_page_buffer));
lijuang42aefaa2016-04-14 15:55:17 +0800144 snprintf(ffbm_page_buffer, sizeof(ffbm_page_buffer), "ffbm-00");
145 write_misc(0, ffbm_page_buffer, sizeof(ffbm_page_buffer));
146
147 reboot_device(0);
148 break;
lijuang7d235f42015-07-16 20:19:45 +0800149 }
150}
151
lijuang9a7d3b92015-11-30 14:41:24 +0800152/* msg_lock need to be holded when call this function. */
153static void update_volume_up_bg(struct select_msg_info* msg_info)
lijuang7d235f42015-07-16 20:19:45 +0800154{
lijuang9a7d3b92015-11-30 14:41:24 +0800155 if (msg_info->info.option_index == msg_info->info.option_num - 1) {
156 fbcon_draw_msg_background(msg_info->info.option_start[0],
157 msg_info->info.option_end[0],
158 msg_info->info.option_bg[0], 0);
lijuang7d235f42015-07-16 20:19:45 +0800159
lijuang9a7d3b92015-11-30 14:41:24 +0800160 fbcon_draw_msg_background(msg_info->info.option_start[msg_info->info.option_num - 1],
161 msg_info->info.option_end[msg_info->info.option_num - 1],
162 msg_info->info.option_bg[msg_info->info.option_num - 1], 1);
lijuang7d235f42015-07-16 20:19:45 +0800163 } else {
lijuang9a7d3b92015-11-30 14:41:24 +0800164 fbcon_draw_msg_background(msg_info->info.option_start[msg_info->info.option_index],
165 msg_info->info.option_end[msg_info->info.option_index],
166 msg_info->info.option_bg[msg_info->info.option_index], 1);
lijuang7d235f42015-07-16 20:19:45 +0800167
lijuang9a7d3b92015-11-30 14:41:24 +0800168 fbcon_draw_msg_background(msg_info->info.option_start[msg_info->info.option_index + 1],
169 msg_info->info.option_end[msg_info->info.option_index + 1],
170 msg_info->info.option_bg[msg_info->info.option_index + 1], 0);
lijuang7d235f42015-07-16 20:19:45 +0800171 }
172}
173
lijuang9a7d3b92015-11-30 14:41:24 +0800174/* msg_lock need to be holded when call this function. */
175static void update_volume_down_bg(struct select_msg_info* msg_info)
lijuang7d235f42015-07-16 20:19:45 +0800176{
lijuang9a7d3b92015-11-30 14:41:24 +0800177 if (msg_info->info.option_index == 0) {
178 fbcon_draw_msg_background(msg_info->info.option_start[0],
179 msg_info->info.option_end[0],
180 msg_info->info.option_bg[0], 1);
lijuang7d235f42015-07-16 20:19:45 +0800181
lijuang9a7d3b92015-11-30 14:41:24 +0800182 fbcon_draw_msg_background(msg_info->info.option_start[msg_info->info.option_num - 1],
183 msg_info->info.option_end[msg_info->info.option_num - 1],
184 msg_info->info.option_bg[msg_info->info.option_num - 1], 0);
lijuang7d235f42015-07-16 20:19:45 +0800185 } else {
lijuang9a7d3b92015-11-30 14:41:24 +0800186 fbcon_draw_msg_background(msg_info->info.option_start[msg_info->info.option_index],
187 msg_info->info.option_end[msg_info->info.option_index],
188 msg_info->info.option_bg[msg_info->info.option_index], 1);
lijuang7d235f42015-07-16 20:19:45 +0800189
lijuang9a7d3b92015-11-30 14:41:24 +0800190 fbcon_draw_msg_background(msg_info->info.option_start[msg_info->info.option_index - 1],
191 msg_info->info.option_end[msg_info->info.option_index - 1],
192 msg_info->info.option_bg[msg_info->info.option_index - 1], 0);
lijuang7d235f42015-07-16 20:19:45 +0800193 }
194}
195
196/* update select option's background when volume up key is pressed */
lijuang9a7d3b92015-11-30 14:41:24 +0800197static void menu_volume_up_func (struct select_msg_info* msg_info)
lijuang7d235f42015-07-16 20:19:45 +0800198{
lijuang9a7d3b92015-11-30 14:41:24 +0800199 if (msg_info->info.option_index == 0)
200 msg_info->info.option_index = msg_info->info.option_num - 1;
201 else
202 msg_info->info.option_index--;
203
204 if (msg_info->info.msg_type == DISPLAY_MENU_FASTBOOT) {
205 display_fastboot_menu_renew(msg_info);
206 } else {
207 update_volume_up_bg(msg_info);
lijuang7d235f42015-07-16 20:19:45 +0800208 }
lijuang7d235f42015-07-16 20:19:45 +0800209}
210
211/* update select option's background when volume down key is pressed */
lijuang9a7d3b92015-11-30 14:41:24 +0800212static void menu_volume_down_func (struct select_msg_info* msg_info)
lijuang7d235f42015-07-16 20:19:45 +0800213{
lijuang9a7d3b92015-11-30 14:41:24 +0800214 msg_info->info.option_index++;
215 if (msg_info->info.option_index >= msg_info->info.option_num)
216 msg_info->info.option_index = 0;
lijuang7d235f42015-07-16 20:19:45 +0800217
lijuang9a7d3b92015-11-30 14:41:24 +0800218 if (msg_info->info.msg_type == DISPLAY_MENU_FASTBOOT) {
219 display_fastboot_menu_renew(msg_info);
lijuang7d235f42015-07-16 20:19:45 +0800220 } else {
lijuang9a7d3b92015-11-30 14:41:24 +0800221 update_volume_down_bg(msg_info);
lijuang7d235f42015-07-16 20:19:45 +0800222 }
lijuang7d235f42015-07-16 20:19:45 +0800223}
224
lijuang9a7d3b92015-11-30 14:41:24 +0800225/* enter to boot verification option page if volume key is pressed */
226static void boot_warning_volume_keys_func (struct select_msg_info* msg_info)
lijuang4ece1e72015-08-14 21:02:36 +0800227{
lijuang9a7d3b92015-11-30 14:41:24 +0800228 msg_info->last_msg_type = msg_info->info.msg_type;
229 display_bootverify_option_menu_renew(msg_info);
lijuang4ece1e72015-08-14 21:02:36 +0800230}
231
232/* update device's status via select option */
lijuang9a7d3b92015-11-30 14:41:24 +0800233static void power_key_func(struct select_msg_info* msg_info)
lijuang4ece1e72015-08-14 21:02:36 +0800234{
lijuang9a7d3b92015-11-30 14:41:24 +0800235 int reason = -1;
Monika Singh05fff3b2019-09-16 16:00:33 +0530236 static boolean isreflash;
lijuang4ece1e72015-08-14 21:02:36 +0800237
lijuang9a7d3b92015-11-30 14:41:24 +0800238 switch (msg_info->info.msg_type) {
239 case DISPLAY_MENU_YELLOW:
240 case DISPLAY_MENU_ORANGE:
Monika Singh05fff3b2019-09-16 16:00:33 +0530241 if (!isreflash) {
242 /* If the power key is pressed for the first time:
243 * Update the warning message and recalculate the timeout
244 */
245 before_time = current_time();
246 display_bootverify_menu_update (msg_info);
247 isreflash = TRUE;
248 } else {
249 reason = CONTINUE;
250 }
251 break;
lijuangbdd9bb42016-03-01 18:22:17 +0800252 case DISPLAY_MENU_LOGGING:
Parth Dixit54ac3bb2017-03-07 15:52:48 +0530253 reason = CONTINUE;
254 break;
Channagoud Kadabi86b0c112016-03-16 19:23:16 -0700255 case DISPLAY_MENU_EIO:
Parth Dixit54ac3bb2017-03-07 15:52:48 +0530256 pwr_key_is_pressed = true;
lijuang9a7d3b92015-11-30 14:41:24 +0800257 reason = CONTINUE;
258 break;
259 case DISPLAY_MENU_MORE_OPTION:
260 if(msg_info->info.option_index < ARRAY_SIZE(verify_index_action))
261 reason = verify_index_action[msg_info->info.option_index];
262 break;
263 case DISPLAY_MENU_UNLOCK:
264 case DISPLAY_MENU_UNLOCK_CRITICAL:
lijuangf55ad052018-04-23 18:30:50 +0800265 case DISPLAY_MENU_LOCK:
266 case DISPLAY_MENU_LOCK_CRITICAL:
lijuang9a7d3b92015-11-30 14:41:24 +0800267 if(msg_info->info.option_index < ARRAY_SIZE(unlock_index_action))
268 reason = unlock_index_action[msg_info->info.option_index];
269 break;
270 case DISPLAY_MENU_FASTBOOT:
271 if(msg_info->info.option_index < ARRAY_SIZE(fastboot_index_action))
272 reason = fastboot_index_action[msg_info->info.option_index];
273 break;
274 default:
275 dprintf(CRITICAL,"Unsupported menu type\n");
276 break;
lijuang4ece1e72015-08-14 21:02:36 +0800277 }
278
lijuang9a7d3b92015-11-30 14:41:24 +0800279 if (reason != -1) {
280 update_device_status(msg_info, reason);
281 }
lijuang4ece1e72015-08-14 21:02:36 +0800282}
283
lijuang9a7d3b92015-11-30 14:41:24 +0800284/* Initialize different page's function
285 * DISPLAY_MENU_UNLOCK/DISPLAY_MENU_UNLOCK_CRITICAL
286 * DISPLAY_MENU_MORE_OPTION/DISPLAY_MENU_FASTBOOT:
lijuang7d235f42015-07-16 20:19:45 +0800287 * up_action_func: update select option's background when volume up
288 * is pressed
289 * down_action_func: update select option's background when volume up
290 * is pressed
291 * enter_action_func: update device's status via select option
lijuang9a7d3b92015-11-30 14:41:24 +0800292 * DISPLAY_MENU_YELLOW/DISPLAY_MENU_ORANGE/DISPLAY_MENU_RED:
lijuang7d235f42015-07-16 20:19:45 +0800293 * up_action_func/down_action_func: enter BOOT_VERIFY_PAGE2 when volume
294 * key is pressed
295 * enter_action_func: continue booting
296 */
297static struct pages_action menu_pages_action[] = {
lijuang9a7d3b92015-11-30 14:41:24 +0800298 [DISPLAY_MENU_UNLOCK] = {
lijuang7d235f42015-07-16 20:19:45 +0800299 menu_volume_up_func,
300 menu_volume_down_func,
lijuang9a7d3b92015-11-30 14:41:24 +0800301 power_key_func,
lijuang7d235f42015-07-16 20:19:45 +0800302 },
lijuang9a7d3b92015-11-30 14:41:24 +0800303 [DISPLAY_MENU_UNLOCK_CRITICAL] = {
lijuang7d235f42015-07-16 20:19:45 +0800304 menu_volume_up_func,
305 menu_volume_down_func,
lijuang9a7d3b92015-11-30 14:41:24 +0800306 power_key_func,
lijuang7d235f42015-07-16 20:19:45 +0800307 },
lijuangf55ad052018-04-23 18:30:50 +0800308 [DISPLAY_MENU_LOCK] = {
309 menu_volume_up_func,
310 menu_volume_down_func,
311 power_key_func,
312 },
313 [DISPLAY_MENU_LOCK_CRITICAL] = {
314 menu_volume_up_func,
315 menu_volume_down_func,
316 power_key_func,
317 },
lijuang9a7d3b92015-11-30 14:41:24 +0800318 [DISPLAY_MENU_YELLOW] = {
Monika Singh05fff3b2019-09-16 16:00:33 +0530319 NULL,
320 NULL,
lijuang9a7d3b92015-11-30 14:41:24 +0800321 power_key_func,
322 },
323 [DISPLAY_MENU_ORANGE] = {
Monika Singh05fff3b2019-09-16 16:00:33 +0530324 NULL,
325 NULL,
lijuang9a7d3b92015-11-30 14:41:24 +0800326 power_key_func,
327 },
328 [DISPLAY_MENU_RED] = {
Monika Singh05fff3b2019-09-16 16:00:33 +0530329 NULL,
330 NULL,
lijuang9a7d3b92015-11-30 14:41:24 +0800331 power_key_func,
332 },
lijuangbdd9bb42016-03-01 18:22:17 +0800333 [DISPLAY_MENU_LOGGING] = {
334 boot_warning_volume_keys_func,
335 boot_warning_volume_keys_func,
336 power_key_func,
337 },
Channagoud Kadabi86b0c112016-03-16 19:23:16 -0700338 [DISPLAY_MENU_EIO] = {
Monika Singh05fff3b2019-09-16 16:00:33 +0530339 NULL,
340 NULL,
Channagoud Kadabi86b0c112016-03-16 19:23:16 -0700341 power_key_func,
342 },
lijuang9a7d3b92015-11-30 14:41:24 +0800343 [DISPLAY_MENU_MORE_OPTION] = {
344 menu_volume_up_func,
345 menu_volume_down_func,
346 power_key_func,
347 },
348 [DISPLAY_MENU_FASTBOOT] = {
349 menu_volume_up_func,
350 menu_volume_down_func,
351 power_key_func,
lijuang4ece1e72015-08-14 21:02:36 +0800352 },
353
lijuang7d235f42015-07-16 20:19:45 +0800354};
355
356void keys_detect_init()
357{
lijuang86f46b42015-12-23 13:39:22 +0800358 /* Waiting for all keys are released */
359 while(1) {
360 if(!keys[VOLUME_UP].keys_pressed_func() &&
361 !keys[VOLUME_DOWN].keys_pressed_func() &&
362 !keys[POWER_KEY].keys_pressed_func()) {
363 break;
364 }
365 thread_sleep(KEY_DETECT_FREQUENCY);
366 }
lijuang9a7d3b92015-11-30 14:41:24 +0800367
368 before_time = current_time();
lijuang7d235f42015-07-16 20:19:45 +0800369}
370
371int select_msg_keys_detect(void *param) {
372 struct select_msg_info *msg_info = (struct select_msg_info*)param;
lijuang7d235f42015-07-16 20:19:45 +0800373
lijuang9a7d3b92015-11-30 14:41:24 +0800374 msg_lock_init();
lijuang7d235f42015-07-16 20:19:45 +0800375 keys_detect_init();
376 while(1) {
lijuang7d235f42015-07-16 20:19:45 +0800377 /* 1: update select option's index, default it is the total option number
378 * volume up: index decrease, the option will scroll up from
379 * the bottom to top if the key is pressed firstly.
380 * eg: 5->4->3->2->1->0
381 * volume down: index increase, the option will scroll down from
382 * the bottom to top if the key is pressed firstly.
383 * eg: 5->0
384 * 2: update device's status via select option's index
385 */
386 if (is_key_pressed(VOLUME_UP)) {
lijuang9a7d3b92015-11-30 14:41:24 +0800387 mutex_acquire(&msg_info->msg_lock);
388 menu_pages_action[msg_info->info.msg_type].up_action_func(msg_info);
389 mutex_release(&msg_info->msg_lock);
lijuang7d235f42015-07-16 20:19:45 +0800390 } else if (is_key_pressed(VOLUME_DOWN)) {
lijuang9a7d3b92015-11-30 14:41:24 +0800391 mutex_acquire(&msg_info->msg_lock);
392 menu_pages_action[msg_info->info.msg_type].down_action_func(msg_info);
393 mutex_release(&msg_info->msg_lock);
lijuang7d235f42015-07-16 20:19:45 +0800394 } else if (is_key_pressed(POWER_KEY)) {
lijuang9a7d3b92015-11-30 14:41:24 +0800395 mutex_acquire(&msg_info->msg_lock);
396 menu_pages_action[msg_info->info.msg_type].enter_action_func(msg_info);
397 mutex_release(&msg_info->msg_lock);
lijuang7d235f42015-07-16 20:19:45 +0800398 }
399
lijuang9a7d3b92015-11-30 14:41:24 +0800400 mutex_acquire(&msg_info->msg_lock);
lijuangde34d502016-02-26 16:04:50 +0800401 /* Never time out if the timeout_time is 0 */
lijuang9a7d3b92015-11-30 14:41:24 +0800402 if(msg_info->info.timeout_time) {
lijuangde34d502016-02-26 16:04:50 +0800403 if ((current_time() - before_time) > msg_info->info.timeout_time)
404 msg_info->info.is_exit = true;
405 }
lijuang9a7d3b92015-11-30 14:41:24 +0800406
lijuangde34d502016-02-26 16:04:50 +0800407 if (msg_info->info.is_exit) {
408 msg_info->info.rel_exit = true;
409 mutex_release(&msg_info->msg_lock);
410 break;
lijuang9a7d3b92015-11-30 14:41:24 +0800411 }
412 mutex_release(&msg_info->msg_lock);
lijuang7d235f42015-07-16 20:19:45 +0800413 thread_sleep(KEY_DETECT_FREQUENCY);
414 }
415
416 return 0;
417}