blob: 643ed730bef3d9b66c5c0431290f5cbbd74cb857 [file] [log] [blame]
Amit Blay6281ebc2015-01-11 14:44:08 +02001/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
2 *
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 <dev/fbcon.h>
31#include <target.h>
32#include <mmc.h>
33#include <partition_parser.h>
34#include <stdlib.h>
Reut Zysman18411272015-02-09 13:47:27 +020035#include <string.h>
Amit Blay6281ebc2015-01-11 14:44:08 +020036#include "mdtp.h"
Reut Zysman561d81a2015-08-26 17:37:28 +030037#include "mdtp_defs.h"
Reut Zysman18411272015-02-09 13:47:27 +020038
39// Image releative locations
40#define ERROR_MESSAGE_RELATIVE_Y_LOCATION (0.18)
41#define MAIN_TEXT_RELATIVE_Y_LOCATION (0.33)
42#define PIN_RELATIVE_Y_LOCATION (0.47)
43#define PIN_TEXT_RELATIVE_Y_LOCATION (0.57)
44#define OK_BUTTON_RELATIVE_Y_LOCATION (0.75)
45#define OK_TEXT_RELATIVE_Y_LOCATION (0.82)
46
Reut Zysman18411272015-02-09 13:47:27 +020047#define MDTP_PRESSING_DELAY_MSEC (400)
48#define MDTP_MAX_IMAGE_SIZE (1183000) //size in bytes, includes some extra bytes since we round up to block size in read
49#define RGB888_BLACK (0x000000)
50#define BITS_PER_BYTE (8)
51
52
Amit Blay8e2731c2015-04-28 21:54:55 +030053#define CENTER_IMAGE_ON_X_AXIS(image_width,screen_width) (((screen_width)-(image_width))/2)
Reut Zysman18411272015-02-09 13:47:27 +020054
Amit Blay6281ebc2015-01-11 14:44:08 +020055extern void mdelay(unsigned msecs);
Reut Zysman18411272015-02-09 13:47:27 +020056extern uint32_t target_volume_up();
57extern uint32_t target_volume_down();
Amit Blay6281ebc2015-01-11 14:44:08 +020058
Reut Zysman18411272015-02-09 13:47:27 +020059struct mdtp_fbimage {
60 uint32_t width;
61 uint32_t height;
62 uint8_t image[MDTP_MAX_IMAGE_SIZE];
63};
Amit Blay6281ebc2015-01-11 14:44:08 +020064
Reut Zysman18411272015-02-09 13:47:27 +020065/*----------------------------------------------------------------------------
66 * Global Variables
67 * -------------------------------------------------------------------------*/
Amit Blay6281ebc2015-01-11 14:44:08 +020068
Reut Zysman18411272015-02-09 13:47:27 +020069static uint32_t g_pin_frames_x_location[MDTP_MAX_PIN_LEN] = {0};
70static uint32_t g_pin_frames_y_location = 0;
71
72static bool g_initial_screen_displayed = false;
73
Rami Butsteinfaecf7f2015-06-04 16:39:30 +030074static struct mdtp_fbimage *g_mdtp_header = NULL;
Reut Zysman18411272015-02-09 13:47:27 +020075static struct fbcon_config *fb_config = NULL;
76
Reut Zysman561d81a2015-08-26 17:37:28 +030077struct mdtp_ui_defs mdtp_ui_defs_data;
78
Reut Zysman18411272015-02-09 13:47:27 +020079/*----------------------------------------------------------------------------
80 * Local Functions
81 * -------------------------------------------------------------------------*/
82
83/**
Rami Butsteinfaecf7f2015-06-04 16:39:30 +030084 * Allocate mdtp image
85 */
86static void alloc_mdtp_image() {
87 if (!g_mdtp_header) {
88 g_mdtp_header = (struct mdtp_fbimage *)malloc(sizeof(struct mdtp_fbimage));
89 ASSERT(g_mdtp_header);
90 }
91}
92
93/**
94 * Free mdtp image
95 */
96void free_mdtp_image() {
97 if (g_mdtp_header) {
98 free(g_mdtp_header);
99 g_mdtp_header = NULL;
100 }
101}
102
103/**
Reut Zysman18411272015-02-09 13:47:27 +0200104 * Load images from EMMC
105 */
106static struct mdtp_fbimage* mdtp_read_mmc_image(uint32_t offset, uint32_t width, uint32_t height)
Amit Blay6281ebc2015-01-11 14:44:08 +0200107{
108 int index = INVALID_PTN;
109 unsigned long long ptn = 0;
Rami Butsteinfaecf7f2015-06-04 16:39:30 +0300110 struct mdtp_fbimage *logo = g_mdtp_header;
Amit Blaydf42d2f2015-02-03 16:37:09 +0200111 uint32_t block_size = mmc_get_device_blocksize();
Amit Blay6281ebc2015-01-11 14:44:08 +0200112
113 index = partition_get_index("mdtp");
114 if (index == 0) {
115 dprintf(CRITICAL, "ERROR: mdtp Partition table not found\n");
116 return NULL;
117 }
118
119 ptn = partition_get_offset(index);
120 if (ptn == 0) {
121 dprintf(CRITICAL, "ERROR: mdtp Partition invalid\n");
122 return NULL;
123 }
124
Reut Zysman18411272015-02-09 13:47:27 +0200125 if (fb_config)
Amit Blay6281ebc2015-01-11 14:44:08 +0200126 {
Reut Zysman18411272015-02-09 13:47:27 +0200127 uint8_t *base = logo->image;
Amit Blay8e2731c2015-04-28 21:54:55 +0300128 unsigned bytes_per_bpp = ((fb_config->bpp) / BITS_PER_BYTE);
Amit Blay6281ebc2015-01-11 14:44:08 +0200129
Amit Blay8e2731c2015-04-28 21:54:55 +0300130 if (mmc_read(ptn+offset, (void*)base, ROUNDUP(width*height*bytes_per_bpp, block_size))) {
Amit Blay6281ebc2015-01-11 14:44:08 +0200131 fbcon_clear();
132 dprintf(CRITICAL, "ERROR: mdtp image read failed\n");
133 return NULL;
134 }
Amit Blay4418fb42015-05-05 08:45:13 +0300135
Reut Zysman18411272015-02-09 13:47:27 +0200136 logo->width = width;
137 logo->height = height;
Amit Blay6281ebc2015-01-11 14:44:08 +0200138 }
139
140 return logo;
141}
142
Reut Zysman18411272015-02-09 13:47:27 +0200143/**
144 * flush fbcon display
145 *
146 * The function is duplicated from fbcon.c
147 */
148static void fbcon_flush(void)
Amit Blay6281ebc2015-01-11 14:44:08 +0200149{
Reut Zysman18411272015-02-09 13:47:27 +0200150 if (fb_config->update_start)
151 fb_config->update_start();
152 if (fb_config->update_done)
153 while (!fb_config->update_done());
154}
Amit Blay6281ebc2015-01-11 14:44:08 +0200155
Reut Zysman18411272015-02-09 13:47:27 +0200156/**
157 * Clear complete section on the screen.
158 * The section is of section_height, and is located from the y
159 * coordinate and down.
160 */
161static void fbcon_clear_section(uint32_t y, uint32_t section_height)
162{
163 unsigned image_base;
164 unsigned bytes_per_bpp;
Amit Blay6281ebc2015-01-11 14:44:08 +0200165
Reut Zysman18411272015-02-09 13:47:27 +0200166 if (fb_config)
Amit Blay6281ebc2015-01-11 14:44:08 +0200167 {
Reut Zysman18411272015-02-09 13:47:27 +0200168 image_base = (y *(fb_config->width));
169 bytes_per_bpp = ((fb_config->bpp) / BITS_PER_BYTE);
Amit Blay6281ebc2015-01-11 14:44:08 +0200170
Reut Zysman18411272015-02-09 13:47:27 +0200171 unsigned count = fb_config->width*section_height;
172 memset(fb_config->base + image_base*bytes_per_bpp, RGB888_BLACK, count*bytes_per_bpp);
173
174 fbcon_flush();
Amit Blay6281ebc2015-01-11 14:44:08 +0200175 }
Reut Zysman18411272015-02-09 13:47:27 +0200176 else
Amit Blay6281ebc2015-01-11 14:44:08 +0200177 {
Reut Zysman18411272015-02-09 13:47:27 +0200178 dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300179 display_error_msg(); /* This will never return */
Amit Blay6281ebc2015-01-11 14:44:08 +0200180 }
Amit Blay6281ebc2015-01-11 14:44:08 +0200181}
182
Reut Zysman18411272015-02-09 13:47:27 +0200183/**
184 * Put image at a specific (x,y) location on the screen.
185 * Duplicated from fbcon.c, with modifications to allow (x,y) location (instead of a centered image),
186 * and display bmp images properly (order of copying the lines to the screen was reversed)
187 */
188static void fbcon_putImage_in_location(struct mdtp_fbimage *fbimg, uint32_t x, uint32_t y)
Amit Blay6281ebc2015-01-11 14:44:08 +0200189{
Reut Zysman18411272015-02-09 13:47:27 +0200190 unsigned i = 0;
191 unsigned bytes_per_bpp;
192 unsigned image_base;
193 unsigned width, pitch, height;
194 unsigned char *logo_base = NULL;
Amit Blay6281ebc2015-01-11 14:44:08 +0200195
Reut Zysman18411272015-02-09 13:47:27 +0200196 if (!fb_config) {
197 dprintf(CRITICAL,"ERROR: NULL configuration, image cannot be displayed\n");
198 return;
Amit Blay6281ebc2015-01-11 14:44:08 +0200199 }
200
Reut Zysman18411272015-02-09 13:47:27 +0200201 if(fbimg) {
202 width = pitch = fbimg->width;
203 height = fbimg->height;
204 logo_base = (unsigned char *)fbimg->image;
205 }
206 else {
207 dprintf(CRITICAL,"ERROR: invalid image struct\n");
208 return;
Amit Blay6281ebc2015-01-11 14:44:08 +0200209 }
210
Reut Zysman18411272015-02-09 13:47:27 +0200211 bytes_per_bpp = ((fb_config->bpp) / BITS_PER_BYTE);
212
213#if DISPLAY_TYPE_MIPI
214 if (bytes_per_bpp == 3)
Amit Blay6281ebc2015-01-11 14:44:08 +0200215 {
Reut Zysman18411272015-02-09 13:47:27 +0200216 if (fbimg->width == fb_config->width && fbimg->height == fb_config->height)
Reut Zysman18411272015-02-09 13:47:27 +0200217 {
Amit Blay8e2731c2015-04-28 21:54:55 +0300218 dprintf(CRITICAL,"ERROR: full screen image, cannot be displayed\n");
219 return;
220 }
221
222 if (fbimg->width > fb_config->width || fbimg->height > fb_config->height ||
223 (x > (fb_config->width - fbimg->width)) || (y > (fb_config->height - fbimg->height)))
224 {
225 dprintf(CRITICAL,"ERROR: invalid image size, larger than the screen or exceeds its margins\n");
Reut Zysman18411272015-02-09 13:47:27 +0200226 return;
Amit Blay6281ebc2015-01-11 14:44:08 +0200227 }
Reut Zysman18411272015-02-09 13:47:27 +0200228
229 image_base = ( (y *(fb_config->width)) + x);
230 for (i = 0; i < height; i++) {
231 memcpy (fb_config->base + ((image_base + (i * (fb_config->width))) * bytes_per_bpp),
232 logo_base + ((height - 1 - i) * pitch * bytes_per_bpp), width * bytes_per_bpp);
233 }
Amit Blay6281ebc2015-01-11 14:44:08 +0200234 }
Amit Blay8e2731c2015-04-28 21:54:55 +0300235 else
236 {
237 dprintf(CRITICAL,"ERROR: invalid bpp value\n");
238 display_error_msg(); /* This will never return */
239 }
Amit Blay6281ebc2015-01-11 14:44:08 +0200240
Amit Blay4418fb42015-05-05 08:45:13 +0300241 /* Flush the contents to memory before giving the data to dma */
242 arch_clean_invalidate_cache_range((addr_t) fb_config->base, (fb_config->height * fb_config->width * bytes_per_bpp));
243
Reut Zysman18411272015-02-09 13:47:27 +0200244 fbcon_flush();
245
246#if DISPLAY_MIPI_PANEL_NOVATEK_BLUE
247 if(is_cmd_mode_enabled())
248 mipi_dsi_cmd_mode_trigger();
249#endif
250
Reut Zysman18411272015-02-09 13:47:27 +0200251#endif
Amit Blay6281ebc2015-01-11 14:44:08 +0200252}
253
Reut Zysman18411272015-02-09 13:47:27 +0200254/**
255 * Display main error message
256 */
257static int display_error_message()
Amit Blay6281ebc2015-01-11 14:44:08 +0200258{
Reut Zysman18411272015-02-09 13:47:27 +0200259 struct mdtp_fbimage *fbimg;
Amit Blay6281ebc2015-01-11 14:44:08 +0200260
Reut Zysman18411272015-02-09 13:47:27 +0200261 if (fb_config)
262 {
Reut Zysman33512bc2015-08-09 19:17:09 +0300263 uint32_t x = CENTER_IMAGE_ON_X_AXIS(mdtp_ui_defs_data.error_msg_width,fb_config->width);
Reut Zysman18411272015-02-09 13:47:27 +0200264 uint32_t y = ((fb_config->height)*ERROR_MESSAGE_RELATIVE_Y_LOCATION);
265
Reut Zysman33512bc2015-08-09 19:17:09 +0300266 fbimg = mdtp_read_mmc_image(mdtp_ui_defs_data.error_msg_offset, mdtp_ui_defs_data.error_msg_width, mdtp_ui_defs_data.error_msg_height);
Reut Zysman18411272015-02-09 13:47:27 +0200267 if (NULL == fbimg)
268 {
269 dprintf(CRITICAL,"ERROR: failed to read error image from mmc\n");
270 return -1;
271 }
272
273 fbcon_putImage_in_location(fbimg, x, y);
274
275 return 0;
276 }
277 else
278 {
279 dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n");
280 return -1;
281 }
Amit Blay6281ebc2015-01-11 14:44:08 +0200282}
283
Reut Zysman18411272015-02-09 13:47:27 +0200284/**
285 * Read from mmc the image in the given offset, of the given width and height.
286 * Then, display the image on the screen in the given (x,y) location.
287 */
288static void display_image(uint32_t offset, uint32_t width, uint32_t height, uint32_t x, uint32_t y)
Amit Blay6281ebc2015-01-11 14:44:08 +0200289{
Reut Zysman18411272015-02-09 13:47:27 +0200290 struct mdtp_fbimage *fbimg;
Amit Blay6281ebc2015-01-11 14:44:08 +0200291
Reut Zysman18411272015-02-09 13:47:27 +0200292 if (fb_config)
293 {
294 fbimg = mdtp_read_mmc_image(offset, width, height);
295 if (NULL == fbimg)
296 {
297 dprintf(CRITICAL,"ERROR: failed to read image from mmc\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300298 display_error_msg(); /* This will never return */
Reut Zysman18411272015-02-09 13:47:27 +0200299 }
Amit Blay6281ebc2015-01-11 14:44:08 +0200300
Reut Zysman18411272015-02-09 13:47:27 +0200301 fbcon_putImage_in_location(fbimg, x, y);
302 }
303 else
304 {
305 dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300306 display_error_msg(); /* This will never return */
Reut Zysman18411272015-02-09 13:47:27 +0200307 }
Amit Blay6281ebc2015-01-11 14:44:08 +0200308}
309
Reut Zysman18411272015-02-09 13:47:27 +0200310/**
311 * Display initial delay message
312 */
313static void display_initial_delay()
Amit Blay6281ebc2015-01-11 14:44:08 +0200314{
Reut Zysman33512bc2015-08-09 19:17:09 +0300315 uint32_t x = CENTER_IMAGE_ON_X_AXIS(mdtp_ui_defs_data.main_text_width,fb_config->width);
Reut Zysman18411272015-02-09 13:47:27 +0200316 uint32_t y = (fb_config->height)*MAIN_TEXT_RELATIVE_Y_LOCATION;
Amit Blay6281ebc2015-01-11 14:44:08 +0200317
Reut Zysman33512bc2015-08-09 19:17:09 +0300318 display_image(mdtp_ui_defs_data.initial_delay_offset, mdtp_ui_defs_data.main_text_width, mdtp_ui_defs_data.main_text_height, x, y);
Amit Blay6281ebc2015-01-11 14:44:08 +0200319}
320
Reut Zysman18411272015-02-09 13:47:27 +0200321/**
322 * Display "enter PIN" message
323 */
324static void display_enter_pin()
Amit Blay6281ebc2015-01-11 14:44:08 +0200325{
Reut Zysman33512bc2015-08-09 19:17:09 +0300326 uint32_t x = CENTER_IMAGE_ON_X_AXIS(mdtp_ui_defs_data.main_text_width,fb_config->width);
Reut Zysman18411272015-02-09 13:47:27 +0200327 uint32_t y = (fb_config->height)*MAIN_TEXT_RELATIVE_Y_LOCATION;
Amit Blay6281ebc2015-01-11 14:44:08 +0200328
Reut Zysman33512bc2015-08-09 19:17:09 +0300329 display_image(mdtp_ui_defs_data.enter_pin_offset, mdtp_ui_defs_data.main_text_width, mdtp_ui_defs_data.main_text_height, x, y);
Amit Blay6281ebc2015-01-11 14:44:08 +0200330}
331
Reut Zysman18411272015-02-09 13:47:27 +0200332/**
333 * Display invalid PIN message
334 */
335static void display_invalid_pin()
Amit Blay6281ebc2015-01-11 14:44:08 +0200336{
Reut Zysman33512bc2015-08-09 19:17:09 +0300337 uint32_t x = CENTER_IMAGE_ON_X_AXIS(mdtp_ui_defs_data.main_text_width,fb_config->width);
Reut Zysman18411272015-02-09 13:47:27 +0200338 uint32_t y = (fb_config->height)*MAIN_TEXT_RELATIVE_Y_LOCATION;
Amit Blay6281ebc2015-01-11 14:44:08 +0200339
Reut Zysman33512bc2015-08-09 19:17:09 +0300340 display_image(mdtp_ui_defs_data.invalid_pin_offset, mdtp_ui_defs_data.main_text_width, mdtp_ui_defs_data.main_text_height, x, y);
Amit Blay6281ebc2015-01-11 14:44:08 +0200341}
342
Reut Zysman18411272015-02-09 13:47:27 +0200343/**
344 * Clear digits instructions
345 */
346static void display_digits_instructions()
Amit Blay6281ebc2015-01-11 14:44:08 +0200347{
Reut Zysman33512bc2015-08-09 19:17:09 +0300348 uint32_t x = CENTER_IMAGE_ON_X_AXIS(mdtp_ui_defs_data.digits_instructions_width,fb_config->width);
Reut Zysman18411272015-02-09 13:47:27 +0200349 uint32_t y = (fb_config->height)*PIN_TEXT_RELATIVE_Y_LOCATION;
350
Reut Zysman33512bc2015-08-09 19:17:09 +0300351 display_image(mdtp_ui_defs_data.digits_instructions_offset, mdtp_ui_defs_data.digits_instructions_width, mdtp_ui_defs_data.digits_instructions_height, x, y);
Reut Zysman18411272015-02-09 13:47:27 +0200352}
353
354/**
355 * Clear digits instructions
356 */
357static void clear_digits_instructions()
358{
359 uint32_t y = (fb_config->height)*PIN_TEXT_RELATIVE_Y_LOCATION;
360
Reut Zysman33512bc2015-08-09 19:17:09 +0300361 fbcon_clear_section(y, mdtp_ui_defs_data.digits_instructions_height);
Reut Zysman18411272015-02-09 13:47:27 +0200362}
363
364/**
365 * Display a digit as un-selected.
366 */
367static void display_digit(uint32_t x, uint32_t y, uint32_t digit)
368{
Reut Zysman33512bc2015-08-09 19:17:09 +0300369 display_image(mdtp_ui_defs_data.pin_digit_0_offset + digit*mdtp_ui_defs_data.pin_digits_offset,
370 mdtp_ui_defs_data.pin_digit_width, mdtp_ui_defs_data.pin_digit_height, x, y);
Reut Zysman18411272015-02-09 13:47:27 +0200371}
372
373/**
374 * Display a digit as selected.
375 */
376static void display_selected_digit(uint32_t x, uint32_t y, uint32_t digit)
377{
Reut Zysman33512bc2015-08-09 19:17:09 +0300378 display_image(mdtp_ui_defs_data.pin_selected_digit_0_offset + digit*mdtp_ui_defs_data.pin_digits_offset,
379 mdtp_ui_defs_data.pin_digit_width, mdtp_ui_defs_data.pin_digit_height, x, y);
Reut Zysman18411272015-02-09 13:47:27 +0200380}
381
382/**
383 * Display OK button as un-selected.
384 */
385static void display_ok_button()
386{
Reut Zysman33512bc2015-08-09 19:17:09 +0300387 uint32_t ok_x = CENTER_IMAGE_ON_X_AXIS(mdtp_ui_defs_data.ok_button_width,fb_config->width);
Reut Zysman18411272015-02-09 13:47:27 +0200388 uint32_t ok_y = (fb_config->height)*OK_BUTTON_RELATIVE_Y_LOCATION;
389
Reut Zysman33512bc2015-08-09 19:17:09 +0300390 display_image(mdtp_ui_defs_data.ok_button_offset, mdtp_ui_defs_data.ok_button_width, mdtp_ui_defs_data.ok_button_height, ok_x, ok_y);
Reut Zysman18411272015-02-09 13:47:27 +0200391}
392
393/**
394 * Display OK button as selected.
395 */
396static void display_selected_ok_button()
397{
Reut Zysman33512bc2015-08-09 19:17:09 +0300398 uint32_t ok_x = CENTER_IMAGE_ON_X_AXIS(mdtp_ui_defs_data.ok_button_width,fb_config->width);
Reut Zysman18411272015-02-09 13:47:27 +0200399 uint32_t ok_y = (fb_config->height)*OK_BUTTON_RELATIVE_Y_LOCATION;
400
Reut Zysman33512bc2015-08-09 19:17:09 +0300401 display_image(mdtp_ui_defs_data.selected_ok_button_offset, mdtp_ui_defs_data.ok_button_width, mdtp_ui_defs_data.ok_button_height, ok_x, ok_y);
Reut Zysman18411272015-02-09 13:47:27 +0200402}
403
404/**
405 * Display the instructions for the OK button.
406 */
407static void display_pin_instructions()
408{
Reut Zysman33512bc2015-08-09 19:17:09 +0300409 uint32_t x = CENTER_IMAGE_ON_X_AXIS(mdtp_ui_defs_data.pin_instructions_width,fb_config->width);
Reut Zysman18411272015-02-09 13:47:27 +0200410 uint32_t y = (fb_config->height)*OK_TEXT_RELATIVE_Y_LOCATION;
411
Reut Zysman33512bc2015-08-09 19:17:09 +0300412 display_image(mdtp_ui_defs_data.pin_instructions_offset, mdtp_ui_defs_data.pin_instructions_width, mdtp_ui_defs_data.pin_instructions_height, x, y);
Reut Zysman18411272015-02-09 13:47:27 +0200413}
414
415/**
416 * Clear the instructions for the OK button.
417 */
418static void clear_pin_message()
419{
420 uint32_t y = (fb_config->height)*OK_TEXT_RELATIVE_Y_LOCATION;
421
Reut Zysman33512bc2015-08-09 19:17:09 +0300422 fbcon_clear_section(y, mdtp_ui_defs_data.pin_instructions_height);
423}
424
425/**
426 * Initialize data structures required for MDTP UI.
427 */
428static void init_mdtp_ui_data()
429{
430 fb_config = fbcon_display();
431 alloc_mdtp_image();
432 mdtp_ui_defs_data = mdtp_get_target_ui_defs();
Reut Zysman18411272015-02-09 13:47:27 +0200433}
434
435/**
436 * Display the basic layout of the screen (done only once).
437 */
438static void display_initial_screen(uint32_t pin_length)
439{
Rami Butsteinfaecf7f2015-06-04 16:39:30 +0300440 if (g_initial_screen_displayed == true)
Reut Zysman18411272015-02-09 13:47:27 +0200441 return;
442
Reut Zysman33512bc2015-08-09 19:17:09 +0300443 init_mdtp_ui_data();
Reut Zysman18411272015-02-09 13:47:27 +0200444
Rami Butsteinfaecf7f2015-06-04 16:39:30 +0300445 if (fb_config)
Reut Zysman18411272015-02-09 13:47:27 +0200446 {
447 fbcon_clear();
448
449 if (display_error_message())
Amit Blay8e2731c2015-04-28 21:54:55 +0300450 display_error_msg(); /* This will never return */
Reut Zysman18411272015-02-09 13:47:27 +0200451 display_initial_delay();
452
453 mdelay(INITIAL_DELAY_MSECONDS);
454
455 g_pin_frames_y_location = ((fb_config->height)*PIN_RELATIVE_Y_LOCATION);
456
Reut Zysman33512bc2015-08-09 19:17:09 +0300457 uint32_t total_pin_length = pin_length*mdtp_ui_defs_data.pin_digit_width + mdtp_ui_defs_data.digit_space*(pin_length - 1);
Reut Zysman18411272015-02-09 13:47:27 +0200458 uint32_t complete_pin_centered = (fb_config->width - total_pin_length)/2;
459
Amit Blay8e2731c2015-04-28 21:54:55 +0300460 for (uint32_t i=0; i<pin_length; i++)
Reut Zysman18411272015-02-09 13:47:27 +0200461 {
Reut Zysman33512bc2015-08-09 19:17:09 +0300462 g_pin_frames_x_location[i] = complete_pin_centered + i*(mdtp_ui_defs_data.digit_space+mdtp_ui_defs_data.pin_digit_width);
Reut Zysman18411272015-02-09 13:47:27 +0200463 }
464
Amit Blay8e2731c2015-04-28 21:54:55 +0300465 for (uint32_t i=0; i<pin_length; i++)
Reut Zysman18411272015-02-09 13:47:27 +0200466 {
467 display_digit(g_pin_frames_x_location[i], g_pin_frames_y_location, 0);
468 }
469
470 display_ok_button();
471
472 g_initial_screen_displayed = true;
473 }
474 else
475 {
476 dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300477 display_error_msg(); /* This will never return */
Reut Zysman18411272015-02-09 13:47:27 +0200478 }
479}
480
481/**
482 * Display the recovery PIN screen and set received buffer
483 * with the PIN the user has entered.
484 * The entered PIN will be validated by the calling function.
485 */
486static void display_get_pin_interface(char *entered_pin, uint32_t pin_length)
487{
488 uint32_t previous_position = 0, current_position = 0;
489
490 display_initial_screen(pin_length);
491 display_enter_pin();
492
493 // Convert ascii to digits
494 for (uint32_t i=0; i<pin_length; i++)
495 {
496 entered_pin[i] -= '0';
497 }
498 display_selected_digit(g_pin_frames_x_location[0], g_pin_frames_y_location, entered_pin[0]);
499 display_digits_instructions();
Amit Blay6281ebc2015-01-11 14:44:08 +0200500
501 while (1)
502 {
Reut Zysman18411272015-02-09 13:47:27 +0200503 if (target_volume_up())
Amit Blay6281ebc2015-01-11 14:44:08 +0200504 {
Reut Zysman18411272015-02-09 13:47:27 +0200505 // current position is the OK button
506 if (current_position == pin_length)
507 {
508 // Convert digits to ascii and
509 // validate entered PIN in the calling function
510 for (uint32_t i=0; i<pin_length; i++)
511 {
512 entered_pin[i] += '0';
513 }
514 return;
515 }
516
517 // current position is a PIN slot
518 entered_pin[current_position] = (entered_pin[current_position]+1) % 10;
519 display_selected_digit(g_pin_frames_x_location[current_position], g_pin_frames_y_location, entered_pin[current_position]);
520 mdelay(MDTP_PRESSING_DELAY_MSEC);
521 }
522 if (target_volume_down())
523 {
524 previous_position = current_position;
525 current_position = (current_position+1) % (pin_length+1);
526
527 // previous position was the OK button
528 if (previous_position == pin_length)
529 {
530 clear_pin_message();
531 display_ok_button();
532
533 display_digits_instructions();
534 display_selected_digit(g_pin_frames_x_location[current_position], g_pin_frames_y_location, entered_pin[current_position]);
535
536 }
537
538 // current position is the OK button
539 else if (current_position == pin_length)
540 {
541 display_digit(g_pin_frames_x_location[previous_position], g_pin_frames_y_location, entered_pin[previous_position]);
542 clear_digits_instructions();
543
544 display_selected_ok_button();
545 display_pin_instructions();
546 }
547
548 // both the previous and the current positions are PIN slots
549 else
550 {
551 display_digit(g_pin_frames_x_location[previous_position], g_pin_frames_y_location, entered_pin[previous_position]);
552
553 display_selected_digit(g_pin_frames_x_location[current_position], g_pin_frames_y_location, entered_pin[current_position]);
554 }
555
556 mdelay(MDTP_PRESSING_DELAY_MSEC);
Amit Blay6281ebc2015-01-11 14:44:08 +0200557 }
558 }
Reut Zysman18411272015-02-09 13:47:27 +0200559}
560
561/*----------------------------------------------------------------------------
562 * External Functions
563 * -------------------------------------------------------------------------*/
564
565/**
566 * Display the recovery PIN screen and set received buffer
567 * with the PIN the user has entered.
568 */
569void get_pin_from_user(char *entered_pin, uint32_t pin_length)
570{
571 display_get_pin_interface(entered_pin, pin_length);
Amit Blay6281ebc2015-01-11 14:44:08 +0200572
573 return;
574}
575
Reut Zysman18411272015-02-09 13:47:27 +0200576/**
577 * User has entered invalid PIN, display error message and
578 * allow the user to try again.
579 */
580void display_invalid_pin_msg()
Amit Blay6281ebc2015-01-11 14:44:08 +0200581{
Reut Zysman18411272015-02-09 13:47:27 +0200582 clear_pin_message();
583 display_ok_button();
584
585 display_invalid_pin();
586
587 mdelay(INVALID_PIN_DELAY_MSECONDS);
Amit Blay6281ebc2015-01-11 14:44:08 +0200588}
589
Reut Zysman18411272015-02-09 13:47:27 +0200590/**
591 * Display error message and stop boot process.
592 */
593void display_error_msg()
Amit Blay6281ebc2015-01-11 14:44:08 +0200594{
Reut Zysman33512bc2015-08-09 19:17:09 +0300595 init_mdtp_ui_data();
Amit Blay8e2731c2015-04-28 21:54:55 +0300596
597 if (fb_config)
598 {
599 fbcon_clear();
600 display_error_message(); // No point in checking the return value here
601 }
Reut Zysman18411272015-02-09 13:47:27 +0200602
603 // Invalid state. Nothing to be done but contacting the OEM.
604 // Stop boot process.
605 dprintf(CRITICAL,"ERROR: blocking boot process\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300606 for(;;);
Amit Blay6281ebc2015-01-11 14:44:08 +0200607}
608