blob: 924c4fe7b5666979529f1622aa61d199e1d9699e [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 Blayf43af752015-11-10 19:13:37 +020058extern int msm_display_on();
Amit Blay6281ebc2015-01-11 14:44:08 +020059
Reut Zysman18411272015-02-09 13:47:27 +020060struct mdtp_fbimage {
61 uint32_t width;
62 uint32_t height;
63 uint8_t image[MDTP_MAX_IMAGE_SIZE];
64};
Amit Blay6281ebc2015-01-11 14:44:08 +020065
Reut Zysman18411272015-02-09 13:47:27 +020066/*----------------------------------------------------------------------------
67 * Global Variables
68 * -------------------------------------------------------------------------*/
Amit Blay6281ebc2015-01-11 14:44:08 +020069
Reut Zysman18411272015-02-09 13:47:27 +020070static uint32_t g_pin_frames_x_location[MDTP_MAX_PIN_LEN] = {0};
71static uint32_t g_pin_frames_y_location = 0;
72
73static bool g_initial_screen_displayed = false;
74
Rami Butsteinfaecf7f2015-06-04 16:39:30 +030075static struct mdtp_fbimage *g_mdtp_header = NULL;
Reut Zysman18411272015-02-09 13:47:27 +020076static struct fbcon_config *fb_config = NULL;
77
Reut Zysman561d81a2015-08-26 17:37:28 +030078struct mdtp_ui_defs mdtp_ui_defs_data;
79
Reut Zysman18411272015-02-09 13:47:27 +020080/*----------------------------------------------------------------------------
81 * Local Functions
82 * -------------------------------------------------------------------------*/
83
84/**
Rami Butsteinfaecf7f2015-06-04 16:39:30 +030085 * Allocate mdtp image
86 */
87static void alloc_mdtp_image() {
88 if (!g_mdtp_header) {
89 g_mdtp_header = (struct mdtp_fbimage *)malloc(sizeof(struct mdtp_fbimage));
90 ASSERT(g_mdtp_header);
91 }
92}
93
94/**
95 * Free mdtp image
96 */
97void free_mdtp_image() {
98 if (g_mdtp_header) {
99 free(g_mdtp_header);
100 g_mdtp_header = NULL;
101 }
102}
103
104/**
Reut Zysman18411272015-02-09 13:47:27 +0200105 * Load images from EMMC
106 */
107static struct mdtp_fbimage* mdtp_read_mmc_image(uint32_t offset, uint32_t width, uint32_t height)
Amit Blay6281ebc2015-01-11 14:44:08 +0200108{
109 int index = INVALID_PTN;
110 unsigned long long ptn = 0;
Rami Butsteinfaecf7f2015-06-04 16:39:30 +0300111 struct mdtp_fbimage *logo = g_mdtp_header;
Amit Blaydf42d2f2015-02-03 16:37:09 +0200112 uint32_t block_size = mmc_get_device_blocksize();
Amit Blay6281ebc2015-01-11 14:44:08 +0200113
114 index = partition_get_index("mdtp");
115 if (index == 0) {
116 dprintf(CRITICAL, "ERROR: mdtp Partition table not found\n");
117 return NULL;
118 }
119
120 ptn = partition_get_offset(index);
121 if (ptn == 0) {
122 dprintf(CRITICAL, "ERROR: mdtp Partition invalid\n");
123 return NULL;
124 }
125
Reut Zysman18411272015-02-09 13:47:27 +0200126 if (fb_config)
Amit Blay6281ebc2015-01-11 14:44:08 +0200127 {
Reut Zysman18411272015-02-09 13:47:27 +0200128 uint8_t *base = logo->image;
Amit Blay8e2731c2015-04-28 21:54:55 +0300129 unsigned bytes_per_bpp = ((fb_config->bpp) / BITS_PER_BYTE);
Amit Blay6281ebc2015-01-11 14:44:08 +0200130
Amit Blay8e2731c2015-04-28 21:54:55 +0300131 if (mmc_read(ptn+offset, (void*)base, ROUNDUP(width*height*bytes_per_bpp, block_size))) {
Amit Blay6281ebc2015-01-11 14:44:08 +0200132 fbcon_clear();
133 dprintf(CRITICAL, "ERROR: mdtp image read failed\n");
134 return NULL;
135 }
Amit Blay4418fb42015-05-05 08:45:13 +0300136
Reut Zysman18411272015-02-09 13:47:27 +0200137 logo->width = width;
138 logo->height = height;
Amit Blay6281ebc2015-01-11 14:44:08 +0200139 }
140
141 return logo;
142}
143
Reut Zysman18411272015-02-09 13:47:27 +0200144/**
145 * flush fbcon display
146 *
147 * The function is duplicated from fbcon.c
148 */
149static void fbcon_flush(void)
Amit Blay6281ebc2015-01-11 14:44:08 +0200150{
Reut Zysman18411272015-02-09 13:47:27 +0200151 if (fb_config->update_start)
152 fb_config->update_start();
153 if (fb_config->update_done)
154 while (!fb_config->update_done());
155}
Amit Blay6281ebc2015-01-11 14:44:08 +0200156
Reut Zysman18411272015-02-09 13:47:27 +0200157/**
158 * Clear complete section on the screen.
159 * The section is of section_height, and is located from the y
160 * coordinate and down.
161 */
162static void fbcon_clear_section(uint32_t y, uint32_t section_height)
163{
164 unsigned image_base;
165 unsigned bytes_per_bpp;
Amit Blay6281ebc2015-01-11 14:44:08 +0200166
Reut Zysman18411272015-02-09 13:47:27 +0200167 if (fb_config)
Amit Blay6281ebc2015-01-11 14:44:08 +0200168 {
Reut Zysman18411272015-02-09 13:47:27 +0200169 image_base = (y *(fb_config->width));
170 bytes_per_bpp = ((fb_config->bpp) / BITS_PER_BYTE);
Amit Blay6281ebc2015-01-11 14:44:08 +0200171
Reut Zysman18411272015-02-09 13:47:27 +0200172 unsigned count = fb_config->width*section_height;
173 memset(fb_config->base + image_base*bytes_per_bpp, RGB888_BLACK, count*bytes_per_bpp);
174
175 fbcon_flush();
Amit Blay6281ebc2015-01-11 14:44:08 +0200176 }
Reut Zysman18411272015-02-09 13:47:27 +0200177 else
Amit Blay6281ebc2015-01-11 14:44:08 +0200178 {
Reut Zysman18411272015-02-09 13:47:27 +0200179 dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300180 display_error_msg(); /* This will never return */
Amit Blay6281ebc2015-01-11 14:44:08 +0200181 }
Amit Blay6281ebc2015-01-11 14:44:08 +0200182}
183
Reut Zysman18411272015-02-09 13:47:27 +0200184/**
185 * Put image at a specific (x,y) location on the screen.
186 * Duplicated from fbcon.c, with modifications to allow (x,y) location (instead of a centered image),
187 * and display bmp images properly (order of copying the lines to the screen was reversed)
188 */
189static void fbcon_putImage_in_location(struct mdtp_fbimage *fbimg, uint32_t x, uint32_t y)
Amit Blay6281ebc2015-01-11 14:44:08 +0200190{
Reut Zysman18411272015-02-09 13:47:27 +0200191 unsigned i = 0;
192 unsigned bytes_per_bpp;
193 unsigned image_base;
194 unsigned width, pitch, height;
195 unsigned char *logo_base = NULL;
Amit Blay6281ebc2015-01-11 14:44:08 +0200196
Reut Zysman18411272015-02-09 13:47:27 +0200197 if (!fb_config) {
198 dprintf(CRITICAL,"ERROR: NULL configuration, image cannot be displayed\n");
199 return;
Amit Blay6281ebc2015-01-11 14:44:08 +0200200 }
201
Reut Zysman18411272015-02-09 13:47:27 +0200202 if(fbimg) {
203 width = pitch = fbimg->width;
204 height = fbimg->height;
205 logo_base = (unsigned char *)fbimg->image;
206 }
207 else {
208 dprintf(CRITICAL,"ERROR: invalid image struct\n");
209 return;
Amit Blay6281ebc2015-01-11 14:44:08 +0200210 }
211
Reut Zysman18411272015-02-09 13:47:27 +0200212 bytes_per_bpp = ((fb_config->bpp) / BITS_PER_BYTE);
213
214#if DISPLAY_TYPE_MIPI
215 if (bytes_per_bpp == 3)
Amit Blay6281ebc2015-01-11 14:44:08 +0200216 {
Reut Zysman18411272015-02-09 13:47:27 +0200217 if (fbimg->width == fb_config->width && fbimg->height == fb_config->height)
Reut Zysman18411272015-02-09 13:47:27 +0200218 {
Amit Blay8e2731c2015-04-28 21:54:55 +0300219 dprintf(CRITICAL,"ERROR: full screen image, cannot be displayed\n");
220 return;
221 }
222
223 if (fbimg->width > fb_config->width || fbimg->height > fb_config->height ||
224 (x > (fb_config->width - fbimg->width)) || (y > (fb_config->height - fbimg->height)))
225 {
226 dprintf(CRITICAL,"ERROR: invalid image size, larger than the screen or exceeds its margins\n");
Reut Zysman18411272015-02-09 13:47:27 +0200227 return;
Amit Blay6281ebc2015-01-11 14:44:08 +0200228 }
Reut Zysman18411272015-02-09 13:47:27 +0200229
230 image_base = ( (y *(fb_config->width)) + x);
231 for (i = 0; i < height; i++) {
232 memcpy (fb_config->base + ((image_base + (i * (fb_config->width))) * bytes_per_bpp),
233 logo_base + ((height - 1 - i) * pitch * bytes_per_bpp), width * bytes_per_bpp);
234 }
Amit Blay6281ebc2015-01-11 14:44:08 +0200235 }
Amit Blay8e2731c2015-04-28 21:54:55 +0300236 else
237 {
238 dprintf(CRITICAL,"ERROR: invalid bpp value\n");
239 display_error_msg(); /* This will never return */
240 }
Amit Blay6281ebc2015-01-11 14:44:08 +0200241
Amit Blay4418fb42015-05-05 08:45:13 +0300242 /* Flush the contents to memory before giving the data to dma */
243 arch_clean_invalidate_cache_range((addr_t) fb_config->base, (fb_config->height * fb_config->width * bytes_per_bpp));
244
Reut Zysman18411272015-02-09 13:47:27 +0200245 fbcon_flush();
Amit Blayf43af752015-11-10 19:13:37 +0200246 msm_display_on();
Reut Zysman18411272015-02-09 13:47:27 +0200247
Reut Zysman18411272015-02-09 13:47:27 +0200248#endif
Amit Blay6281ebc2015-01-11 14:44:08 +0200249}
250
Reut Zysman18411272015-02-09 13:47:27 +0200251/**
252 * Display main error message
253 */
254static int display_error_message()
Amit Blay6281ebc2015-01-11 14:44:08 +0200255{
Reut Zysman18411272015-02-09 13:47:27 +0200256 struct mdtp_fbimage *fbimg;
Amit Blay6281ebc2015-01-11 14:44:08 +0200257
Reut Zysman18411272015-02-09 13:47:27 +0200258 if (fb_config)
259 {
Reut Zysman33512bc2015-08-09 19:17:09 +0300260 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 +0200261 uint32_t y = ((fb_config->height)*ERROR_MESSAGE_RELATIVE_Y_LOCATION);
262
Reut Zysman33512bc2015-08-09 19:17:09 +0300263 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 +0200264 if (NULL == fbimg)
265 {
266 dprintf(CRITICAL,"ERROR: failed to read error image from mmc\n");
267 return -1;
268 }
269
270 fbcon_putImage_in_location(fbimg, x, y);
271
272 return 0;
273 }
274 else
275 {
276 dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n");
277 return -1;
278 }
Amit Blay6281ebc2015-01-11 14:44:08 +0200279}
280
Reut Zysman18411272015-02-09 13:47:27 +0200281/**
282 * Read from mmc the image in the given offset, of the given width and height.
283 * Then, display the image on the screen in the given (x,y) location.
284 */
285static 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 +0200286{
Reut Zysman18411272015-02-09 13:47:27 +0200287 struct mdtp_fbimage *fbimg;
Amit Blay6281ebc2015-01-11 14:44:08 +0200288
Reut Zysman18411272015-02-09 13:47:27 +0200289 if (fb_config)
290 {
291 fbimg = mdtp_read_mmc_image(offset, width, height);
292 if (NULL == fbimg)
293 {
294 dprintf(CRITICAL,"ERROR: failed to read image from mmc\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300295 display_error_msg(); /* This will never return */
Reut Zysman18411272015-02-09 13:47:27 +0200296 }
Amit Blay6281ebc2015-01-11 14:44:08 +0200297
Reut Zysman18411272015-02-09 13:47:27 +0200298 fbcon_putImage_in_location(fbimg, x, y);
299 }
300 else
301 {
302 dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300303 display_error_msg(); /* This will never return */
Reut Zysman18411272015-02-09 13:47:27 +0200304 }
Amit Blay6281ebc2015-01-11 14:44:08 +0200305}
306
Reut Zysman18411272015-02-09 13:47:27 +0200307/**
308 * Display initial delay message
309 */
310static void display_initial_delay()
Amit Blay6281ebc2015-01-11 14:44:08 +0200311{
Reut Zysman33512bc2015-08-09 19:17:09 +0300312 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 +0200313 uint32_t y = (fb_config->height)*MAIN_TEXT_RELATIVE_Y_LOCATION;
Amit Blay6281ebc2015-01-11 14:44:08 +0200314
Reut Zysman33512bc2015-08-09 19:17:09 +0300315 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 +0200316}
317
Reut Zysman18411272015-02-09 13:47:27 +0200318/**
319 * Display "enter PIN" message
320 */
321static void display_enter_pin()
Amit Blay6281ebc2015-01-11 14:44:08 +0200322{
Reut Zysman33512bc2015-08-09 19:17:09 +0300323 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 +0200324 uint32_t y = (fb_config->height)*MAIN_TEXT_RELATIVE_Y_LOCATION;
Amit Blay6281ebc2015-01-11 14:44:08 +0200325
Reut Zysman33512bc2015-08-09 19:17:09 +0300326 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 +0200327}
328
Reut Zysman18411272015-02-09 13:47:27 +0200329/**
330 * Display invalid PIN message
331 */
332static void display_invalid_pin()
Amit Blay6281ebc2015-01-11 14:44:08 +0200333{
Reut Zysman33512bc2015-08-09 19:17:09 +0300334 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 +0200335 uint32_t y = (fb_config->height)*MAIN_TEXT_RELATIVE_Y_LOCATION;
Amit Blay6281ebc2015-01-11 14:44:08 +0200336
Reut Zysman33512bc2015-08-09 19:17:09 +0300337 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 +0200338}
339
Reut Zysman18411272015-02-09 13:47:27 +0200340/**
341 * Clear digits instructions
342 */
343static void display_digits_instructions()
Amit Blay6281ebc2015-01-11 14:44:08 +0200344{
Reut Zysman33512bc2015-08-09 19:17:09 +0300345 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 +0200346 uint32_t y = (fb_config->height)*PIN_TEXT_RELATIVE_Y_LOCATION;
347
Reut Zysman33512bc2015-08-09 19:17:09 +0300348 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 +0200349}
350
351/**
352 * Clear digits instructions
353 */
354static void clear_digits_instructions()
355{
356 uint32_t y = (fb_config->height)*PIN_TEXT_RELATIVE_Y_LOCATION;
357
Reut Zysman33512bc2015-08-09 19:17:09 +0300358 fbcon_clear_section(y, mdtp_ui_defs_data.digits_instructions_height);
Reut Zysman18411272015-02-09 13:47:27 +0200359}
360
361/**
362 * Display a digit as un-selected.
363 */
364static void display_digit(uint32_t x, uint32_t y, uint32_t digit)
365{
Reut Zysman33512bc2015-08-09 19:17:09 +0300366 display_image(mdtp_ui_defs_data.pin_digit_0_offset + digit*mdtp_ui_defs_data.pin_digits_offset,
367 mdtp_ui_defs_data.pin_digit_width, mdtp_ui_defs_data.pin_digit_height, x, y);
Reut Zysman18411272015-02-09 13:47:27 +0200368}
369
370/**
371 * Display a digit as selected.
372 */
373static void display_selected_digit(uint32_t x, uint32_t y, uint32_t digit)
374{
Reut Zysman33512bc2015-08-09 19:17:09 +0300375 display_image(mdtp_ui_defs_data.pin_selected_digit_0_offset + digit*mdtp_ui_defs_data.pin_digits_offset,
376 mdtp_ui_defs_data.pin_digit_width, mdtp_ui_defs_data.pin_digit_height, x, y);
Reut Zysman18411272015-02-09 13:47:27 +0200377}
378
379/**
380 * Display OK button as un-selected.
381 */
382static void display_ok_button()
383{
Reut Zysman33512bc2015-08-09 19:17:09 +0300384 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 +0200385 uint32_t ok_y = (fb_config->height)*OK_BUTTON_RELATIVE_Y_LOCATION;
386
Reut Zysman33512bc2015-08-09 19:17:09 +0300387 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 +0200388}
389
390/**
391 * Display OK button as selected.
392 */
393static void display_selected_ok_button()
394{
Reut Zysman33512bc2015-08-09 19:17:09 +0300395 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 +0200396 uint32_t ok_y = (fb_config->height)*OK_BUTTON_RELATIVE_Y_LOCATION;
397
Reut Zysman33512bc2015-08-09 19:17:09 +0300398 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 +0200399}
400
401/**
402 * Display the instructions for the OK button.
403 */
404static void display_pin_instructions()
405{
Reut Zysman33512bc2015-08-09 19:17:09 +0300406 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 +0200407 uint32_t y = (fb_config->height)*OK_TEXT_RELATIVE_Y_LOCATION;
408
Reut Zysman33512bc2015-08-09 19:17:09 +0300409 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 +0200410}
411
412/**
413 * Clear the instructions for the OK button.
414 */
415static void clear_pin_message()
416{
417 uint32_t y = (fb_config->height)*OK_TEXT_RELATIVE_Y_LOCATION;
418
Reut Zysman33512bc2015-08-09 19:17:09 +0300419 fbcon_clear_section(y, mdtp_ui_defs_data.pin_instructions_height);
420}
421
422/**
423 * Initialize data structures required for MDTP UI.
424 */
425static void init_mdtp_ui_data()
426{
427 fb_config = fbcon_display();
428 alloc_mdtp_image();
429 mdtp_ui_defs_data = mdtp_get_target_ui_defs();
Reut Zysman18411272015-02-09 13:47:27 +0200430}
431
432/**
433 * Display the basic layout of the screen (done only once).
434 */
435static void display_initial_screen(uint32_t pin_length)
436{
Rami Butsteinfaecf7f2015-06-04 16:39:30 +0300437 if (g_initial_screen_displayed == true)
Reut Zysman18411272015-02-09 13:47:27 +0200438 return;
439
Reut Zysman33512bc2015-08-09 19:17:09 +0300440 init_mdtp_ui_data();
Reut Zysman18411272015-02-09 13:47:27 +0200441
Rami Butsteinfaecf7f2015-06-04 16:39:30 +0300442 if (fb_config)
Reut Zysman18411272015-02-09 13:47:27 +0200443 {
444 fbcon_clear();
445
446 if (display_error_message())
Amit Blay8e2731c2015-04-28 21:54:55 +0300447 display_error_msg(); /* This will never return */
Reut Zysman18411272015-02-09 13:47:27 +0200448 display_initial_delay();
449
450 mdelay(INITIAL_DELAY_MSECONDS);
451
452 g_pin_frames_y_location = ((fb_config->height)*PIN_RELATIVE_Y_LOCATION);
453
Reut Zysman33512bc2015-08-09 19:17:09 +0300454 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 +0200455 uint32_t complete_pin_centered = (fb_config->width - total_pin_length)/2;
456
Amit Blay8e2731c2015-04-28 21:54:55 +0300457 for (uint32_t i=0; i<pin_length; i++)
Reut Zysman18411272015-02-09 13:47:27 +0200458 {
Reut Zysman33512bc2015-08-09 19:17:09 +0300459 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 +0200460 }
461
Amit Blay8e2731c2015-04-28 21:54:55 +0300462 for (uint32_t i=0; i<pin_length; i++)
Reut Zysman18411272015-02-09 13:47:27 +0200463 {
464 display_digit(g_pin_frames_x_location[i], g_pin_frames_y_location, 0);
465 }
466
467 display_ok_button();
468
469 g_initial_screen_displayed = true;
470 }
471 else
472 {
473 dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300474 display_error_msg(); /* This will never return */
Reut Zysman18411272015-02-09 13:47:27 +0200475 }
476}
477
478/**
479 * Display the recovery PIN screen and set received buffer
480 * with the PIN the user has entered.
481 * The entered PIN will be validated by the calling function.
482 */
483static void display_get_pin_interface(char *entered_pin, uint32_t pin_length)
484{
485 uint32_t previous_position = 0, current_position = 0;
486
487 display_initial_screen(pin_length);
488 display_enter_pin();
489
490 // Convert ascii to digits
491 for (uint32_t i=0; i<pin_length; i++)
492 {
493 entered_pin[i] -= '0';
494 }
495 display_selected_digit(g_pin_frames_x_location[0], g_pin_frames_y_location, entered_pin[0]);
496 display_digits_instructions();
Amit Blay6281ebc2015-01-11 14:44:08 +0200497
498 while (1)
499 {
Reut Zysman18411272015-02-09 13:47:27 +0200500 if (target_volume_up())
Amit Blay6281ebc2015-01-11 14:44:08 +0200501 {
Reut Zysman18411272015-02-09 13:47:27 +0200502 // current position is the OK button
503 if (current_position == pin_length)
504 {
505 // Convert digits to ascii and
506 // validate entered PIN in the calling function
507 for (uint32_t i=0; i<pin_length; i++)
508 {
509 entered_pin[i] += '0';
510 }
511 return;
512 }
513
514 // current position is a PIN slot
515 entered_pin[current_position] = (entered_pin[current_position]+1) % 10;
516 display_selected_digit(g_pin_frames_x_location[current_position], g_pin_frames_y_location, entered_pin[current_position]);
517 mdelay(MDTP_PRESSING_DELAY_MSEC);
518 }
519 if (target_volume_down())
520 {
521 previous_position = current_position;
522 current_position = (current_position+1) % (pin_length+1);
523
524 // previous position was the OK button
525 if (previous_position == pin_length)
526 {
527 clear_pin_message();
528 display_ok_button();
529
530 display_digits_instructions();
531 display_selected_digit(g_pin_frames_x_location[current_position], g_pin_frames_y_location, entered_pin[current_position]);
532
533 }
534
535 // current position is the OK button
536 else if (current_position == pin_length)
537 {
538 display_digit(g_pin_frames_x_location[previous_position], g_pin_frames_y_location, entered_pin[previous_position]);
539 clear_digits_instructions();
540
541 display_selected_ok_button();
542 display_pin_instructions();
543 }
544
545 // both the previous and the current positions are PIN slots
546 else
547 {
548 display_digit(g_pin_frames_x_location[previous_position], g_pin_frames_y_location, entered_pin[previous_position]);
549
550 display_selected_digit(g_pin_frames_x_location[current_position], g_pin_frames_y_location, entered_pin[current_position]);
551 }
552
553 mdelay(MDTP_PRESSING_DELAY_MSEC);
Amit Blay6281ebc2015-01-11 14:44:08 +0200554 }
555 }
Reut Zysman18411272015-02-09 13:47:27 +0200556}
557
558/*----------------------------------------------------------------------------
559 * External Functions
560 * -------------------------------------------------------------------------*/
561
562/**
563 * Display the recovery PIN screen and set received buffer
564 * with the PIN the user has entered.
565 */
566void get_pin_from_user(char *entered_pin, uint32_t pin_length)
567{
568 display_get_pin_interface(entered_pin, pin_length);
Amit Blay6281ebc2015-01-11 14:44:08 +0200569
570 return;
571}
572
Reut Zysman18411272015-02-09 13:47:27 +0200573/**
574 * User has entered invalid PIN, display error message and
575 * allow the user to try again.
576 */
577void display_invalid_pin_msg()
Amit Blay6281ebc2015-01-11 14:44:08 +0200578{
Reut Zysman18411272015-02-09 13:47:27 +0200579 clear_pin_message();
580 display_ok_button();
581
582 display_invalid_pin();
583
584 mdelay(INVALID_PIN_DELAY_MSECONDS);
Amit Blay6281ebc2015-01-11 14:44:08 +0200585}
586
Reut Zysman18411272015-02-09 13:47:27 +0200587/**
588 * Display error message and stop boot process.
589 */
590void display_error_msg()
Amit Blay6281ebc2015-01-11 14:44:08 +0200591{
Reut Zysman33512bc2015-08-09 19:17:09 +0300592 init_mdtp_ui_data();
Amit Blay8e2731c2015-04-28 21:54:55 +0300593
594 if (fb_config)
595 {
596 fbcon_clear();
597 display_error_message(); // No point in checking the return value here
598 }
Reut Zysman18411272015-02-09 13:47:27 +0200599
600 // Invalid state. Nothing to be done but contacting the OEM.
601 // Stop boot process.
602 dprintf(CRITICAL,"ERROR: blocking boot process\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300603 for(;;);
Amit Blay6281ebc2015-01-11 14:44:08 +0200604}
605