blob: 6200eb56045c23cbf5d9b8e6264e13c8efb5f106 [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"
37
Reut Zysman18411272015-02-09 13:47:27 +020038// Image dimensions
39#define MDTP_ERROR_MSG_WIDTH (1412)
40#define MDTP_ERROR_MSG_HEIGHT (212)
41#define MDTP_MAIN_TEXT_WIDTH (1364)
42#define MDTP_MAIN_TEXT_HEIGHT (288)
43#define MDTP_PIN_DIGIT_WIDTH (180)
44#define MDTP_PIN_DIGIT_HEIGHT (180)
45#define MDTP_OK_BUTTON_WIDTH (644)
46#define MDTP_OK_BUTTON_HEIGHT (158)
47#define MDTP_DIGITS_INSTRUCTIONS_WIDTH (1384)
48#define MDTP_DIGITS_INSTRUCTIONS_HEIGHT (166)
49#define MDTP_PIN_INSTRUCTIONS_WIDTH (920)
50#define MDTP_PIN_INSTRUCTIONS_HEIGHT (204)
Amit Blay6281ebc2015-01-11 14:44:08 +020051
Reut Zysman18411272015-02-09 13:47:27 +020052// Image offsets
53#define MDTP_ERROR_MSG_OFFSET (0x1000)
54#define MDTP_INITIAL_DELAY_OFFSET (0xDD000)
55#define MDTP_ENTER_PIN_OFFSET (0x1FD000)
56#define MDTP_INVALID_PIN_OFFSET (0x31D000)
57#define MDTP_PIN_DIGIT_0_OFFSET (0x43D000)
58#define MDTP_PIN_DIGITS_OFFSET (0x18000)
59#define MDTP_PIN_SELECTED_DIGIT_0_OFFSET (MDTP_PIN_DIGIT_0_OFFSET + 10*MDTP_PIN_DIGITS_OFFSET) // (0x52D000)
60#define MDTP_OK_BUTTON_OFFSET (0x61D000)
61#define MDTP_SELECTED_OK_BUTTON_OFFSET (0x668000)
62#define MDTP_DIGITS_INSTRUCTIONS_OFFSET (0x6B3000)
63#define MDTP_PIN_INSTRUCTIONS_OFFSET (0x75C000)
64
65// Image releative locations
66#define ERROR_MESSAGE_RELATIVE_Y_LOCATION (0.18)
67#define MAIN_TEXT_RELATIVE_Y_LOCATION (0.33)
68#define PIN_RELATIVE_Y_LOCATION (0.47)
69#define PIN_TEXT_RELATIVE_Y_LOCATION (0.57)
70#define OK_BUTTON_RELATIVE_Y_LOCATION (0.75)
71#define OK_TEXT_RELATIVE_Y_LOCATION (0.82)
72
73#define DIGIT_SPACE (12)
74
75#define MDTP_PRESSING_DELAY_MSEC (400)
76#define MDTP_MAX_IMAGE_SIZE (1183000) //size in bytes, includes some extra bytes since we round up to block size in read
77#define RGB888_BLACK (0x000000)
78#define BITS_PER_BYTE (8)
79
80
Amit Blay8e2731c2015-04-28 21:54:55 +030081#define CENTER_IMAGE_ON_X_AXIS(image_width,screen_width) (((screen_width)-(image_width))/2)
Reut Zysman18411272015-02-09 13:47:27 +020082
Amit Blay6281ebc2015-01-11 14:44:08 +020083extern void mdelay(unsigned msecs);
Reut Zysman18411272015-02-09 13:47:27 +020084extern uint32_t target_volume_up();
85extern uint32_t target_volume_down();
Amit Blay6281ebc2015-01-11 14:44:08 +020086
Reut Zysman18411272015-02-09 13:47:27 +020087struct mdtp_fbimage {
88 uint32_t width;
89 uint32_t height;
90 uint8_t image[MDTP_MAX_IMAGE_SIZE];
91};
Amit Blay6281ebc2015-01-11 14:44:08 +020092
Reut Zysman18411272015-02-09 13:47:27 +020093/*----------------------------------------------------------------------------
94 * Global Variables
95 * -------------------------------------------------------------------------*/
Amit Blay6281ebc2015-01-11 14:44:08 +020096
Reut Zysman18411272015-02-09 13:47:27 +020097static uint32_t g_pin_frames_x_location[MDTP_MAX_PIN_LEN] = {0};
98static uint32_t g_pin_frames_y_location = 0;
99
100static bool g_initial_screen_displayed = false;
101
102static struct mdtp_fbimage g_mdtp_header;
103static struct fbcon_config *fb_config = NULL;
104
105/*----------------------------------------------------------------------------
106 * Local Functions
107 * -------------------------------------------------------------------------*/
108
109/**
110 * Load images from EMMC
111 */
112static struct mdtp_fbimage* mdtp_read_mmc_image(uint32_t offset, uint32_t width, uint32_t height)
Amit Blay6281ebc2015-01-11 14:44:08 +0200113{
114 int index = INVALID_PTN;
115 unsigned long long ptn = 0;
Reut Zysman18411272015-02-09 13:47:27 +0200116 struct mdtp_fbimage *logo = &g_mdtp_header;
Amit Blaydf42d2f2015-02-03 16:37:09 +0200117 uint32_t block_size = mmc_get_device_blocksize();
Amit Blay6281ebc2015-01-11 14:44:08 +0200118
119 index = partition_get_index("mdtp");
120 if (index == 0) {
121 dprintf(CRITICAL, "ERROR: mdtp Partition table not found\n");
122 return NULL;
123 }
124
125 ptn = partition_get_offset(index);
126 if (ptn == 0) {
127 dprintf(CRITICAL, "ERROR: mdtp Partition invalid\n");
128 return NULL;
129 }
130
Reut Zysman18411272015-02-09 13:47:27 +0200131 if (fb_config)
Amit Blay6281ebc2015-01-11 14:44:08 +0200132 {
Reut Zysman18411272015-02-09 13:47:27 +0200133 uint8_t *base = logo->image;
Amit Blay8e2731c2015-04-28 21:54:55 +0300134 unsigned bytes_per_bpp = ((fb_config->bpp) / BITS_PER_BYTE);
Amit Blay6281ebc2015-01-11 14:44:08 +0200135
Amit Blay8e2731c2015-04-28 21:54:55 +0300136 if (mmc_read(ptn+offset, (void*)base, ROUNDUP(width*height*bytes_per_bpp, block_size))) {
Amit Blay6281ebc2015-01-11 14:44:08 +0200137 fbcon_clear();
138 dprintf(CRITICAL, "ERROR: mdtp image read failed\n");
139 return NULL;
140 }
Amit Blay4418fb42015-05-05 08:45:13 +0300141
Reut Zysman18411272015-02-09 13:47:27 +0200142 logo->width = width;
143 logo->height = height;
Amit Blay6281ebc2015-01-11 14:44:08 +0200144 }
145
146 return logo;
147}
148
Reut Zysman18411272015-02-09 13:47:27 +0200149/**
150 * flush fbcon display
151 *
152 * The function is duplicated from fbcon.c
153 */
154static void fbcon_flush(void)
Amit Blay6281ebc2015-01-11 14:44:08 +0200155{
Reut Zysman18411272015-02-09 13:47:27 +0200156 if (fb_config->update_start)
157 fb_config->update_start();
158 if (fb_config->update_done)
159 while (!fb_config->update_done());
160}
Amit Blay6281ebc2015-01-11 14:44:08 +0200161
Reut Zysman18411272015-02-09 13:47:27 +0200162/**
163 * Clear complete section on the screen.
164 * The section is of section_height, and is located from the y
165 * coordinate and down.
166 */
167static void fbcon_clear_section(uint32_t y, uint32_t section_height)
168{
169 unsigned image_base;
170 unsigned bytes_per_bpp;
Amit Blay6281ebc2015-01-11 14:44:08 +0200171
Reut Zysman18411272015-02-09 13:47:27 +0200172 if (fb_config)
Amit Blay6281ebc2015-01-11 14:44:08 +0200173 {
Reut Zysman18411272015-02-09 13:47:27 +0200174 image_base = (y *(fb_config->width));
175 bytes_per_bpp = ((fb_config->bpp) / BITS_PER_BYTE);
Amit Blay6281ebc2015-01-11 14:44:08 +0200176
Reut Zysman18411272015-02-09 13:47:27 +0200177 unsigned count = fb_config->width*section_height;
178 memset(fb_config->base + image_base*bytes_per_bpp, RGB888_BLACK, count*bytes_per_bpp);
179
180 fbcon_flush();
Amit Blay6281ebc2015-01-11 14:44:08 +0200181 }
Reut Zysman18411272015-02-09 13:47:27 +0200182 else
Amit Blay6281ebc2015-01-11 14:44:08 +0200183 {
Reut Zysman18411272015-02-09 13:47:27 +0200184 dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300185 display_error_msg(); /* This will never return */
Amit Blay6281ebc2015-01-11 14:44:08 +0200186 }
Amit Blay6281ebc2015-01-11 14:44:08 +0200187}
188
Reut Zysman18411272015-02-09 13:47:27 +0200189/**
190 * Put image at a specific (x,y) location on the screen.
191 * Duplicated from fbcon.c, with modifications to allow (x,y) location (instead of a centered image),
192 * and display bmp images properly (order of copying the lines to the screen was reversed)
193 */
194static void fbcon_putImage_in_location(struct mdtp_fbimage *fbimg, uint32_t x, uint32_t y)
Amit Blay6281ebc2015-01-11 14:44:08 +0200195{
Reut Zysman18411272015-02-09 13:47:27 +0200196 unsigned i = 0;
197 unsigned bytes_per_bpp;
198 unsigned image_base;
199 unsigned width, pitch, height;
200 unsigned char *logo_base = NULL;
Amit Blay6281ebc2015-01-11 14:44:08 +0200201
Reut Zysman18411272015-02-09 13:47:27 +0200202 if (!fb_config) {
203 dprintf(CRITICAL,"ERROR: NULL configuration, image cannot be displayed\n");
204 return;
Amit Blay6281ebc2015-01-11 14:44:08 +0200205 }
206
Reut Zysman18411272015-02-09 13:47:27 +0200207 if(fbimg) {
208 width = pitch = fbimg->width;
209 height = fbimg->height;
210 logo_base = (unsigned char *)fbimg->image;
211 }
212 else {
213 dprintf(CRITICAL,"ERROR: invalid image struct\n");
214 return;
Amit Blay6281ebc2015-01-11 14:44:08 +0200215 }
216
Reut Zysman18411272015-02-09 13:47:27 +0200217 bytes_per_bpp = ((fb_config->bpp) / BITS_PER_BYTE);
218
219#if DISPLAY_TYPE_MIPI
220 if (bytes_per_bpp == 3)
Amit Blay6281ebc2015-01-11 14:44:08 +0200221 {
Reut Zysman18411272015-02-09 13:47:27 +0200222 if (fbimg->width == fb_config->width && fbimg->height == fb_config->height)
Reut Zysman18411272015-02-09 13:47:27 +0200223 {
Amit Blay8e2731c2015-04-28 21:54:55 +0300224 dprintf(CRITICAL,"ERROR: full screen image, cannot be displayed\n");
225 return;
226 }
227
228 if (fbimg->width > fb_config->width || fbimg->height > fb_config->height ||
229 (x > (fb_config->width - fbimg->width)) || (y > (fb_config->height - fbimg->height)))
230 {
231 dprintf(CRITICAL,"ERROR: invalid image size, larger than the screen or exceeds its margins\n");
Reut Zysman18411272015-02-09 13:47:27 +0200232 return;
Amit Blay6281ebc2015-01-11 14:44:08 +0200233 }
Reut Zysman18411272015-02-09 13:47:27 +0200234
235 image_base = ( (y *(fb_config->width)) + x);
236 for (i = 0; i < height; i++) {
237 memcpy (fb_config->base + ((image_base + (i * (fb_config->width))) * bytes_per_bpp),
238 logo_base + ((height - 1 - i) * pitch * bytes_per_bpp), width * bytes_per_bpp);
239 }
Amit Blay6281ebc2015-01-11 14:44:08 +0200240 }
Amit Blay8e2731c2015-04-28 21:54:55 +0300241 else
242 {
243 dprintf(CRITICAL,"ERROR: invalid bpp value\n");
244 display_error_msg(); /* This will never return */
245 }
Amit Blay6281ebc2015-01-11 14:44:08 +0200246
Amit Blay4418fb42015-05-05 08:45:13 +0300247 /* Flush the contents to memory before giving the data to dma */
248 arch_clean_invalidate_cache_range((addr_t) fb_config->base, (fb_config->height * fb_config->width * bytes_per_bpp));
249
Reut Zysman18411272015-02-09 13:47:27 +0200250 fbcon_flush();
251
252#if DISPLAY_MIPI_PANEL_NOVATEK_BLUE
253 if(is_cmd_mode_enabled())
254 mipi_dsi_cmd_mode_trigger();
255#endif
256
Reut Zysman18411272015-02-09 13:47:27 +0200257#endif
Amit Blay6281ebc2015-01-11 14:44:08 +0200258}
259
Reut Zysman18411272015-02-09 13:47:27 +0200260/**
261 * Display main error message
262 */
263static int display_error_message()
Amit Blay6281ebc2015-01-11 14:44:08 +0200264{
Reut Zysman18411272015-02-09 13:47:27 +0200265 struct mdtp_fbimage *fbimg;
Amit Blay6281ebc2015-01-11 14:44:08 +0200266
Reut Zysman18411272015-02-09 13:47:27 +0200267 if (fb_config)
268 {
269 uint32_t x = CENTER_IMAGE_ON_X_AXIS(MDTP_ERROR_MSG_WIDTH,fb_config->width);
270 uint32_t y = ((fb_config->height)*ERROR_MESSAGE_RELATIVE_Y_LOCATION);
271
272 fbimg = mdtp_read_mmc_image(MDTP_ERROR_MSG_OFFSET, MDTP_ERROR_MSG_WIDTH, MDTP_ERROR_MSG_HEIGHT);
273 if (NULL == fbimg)
274 {
275 dprintf(CRITICAL,"ERROR: failed to read error image from mmc\n");
276 return -1;
277 }
278
279 fbcon_putImage_in_location(fbimg, x, y);
280
281 return 0;
282 }
283 else
284 {
285 dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n");
286 return -1;
287 }
Amit Blay6281ebc2015-01-11 14:44:08 +0200288}
289
Reut Zysman18411272015-02-09 13:47:27 +0200290/**
291 * Read from mmc the image in the given offset, of the given width and height.
292 * Then, display the image on the screen in the given (x,y) location.
293 */
294static 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 +0200295{
Reut Zysman18411272015-02-09 13:47:27 +0200296 struct mdtp_fbimage *fbimg;
Amit Blay6281ebc2015-01-11 14:44:08 +0200297
Reut Zysman18411272015-02-09 13:47:27 +0200298 if (fb_config)
299 {
300 fbimg = mdtp_read_mmc_image(offset, width, height);
301 if (NULL == fbimg)
302 {
303 dprintf(CRITICAL,"ERROR: failed to read image from mmc\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300304 display_error_msg(); /* This will never return */
Reut Zysman18411272015-02-09 13:47:27 +0200305 }
Amit Blay6281ebc2015-01-11 14:44:08 +0200306
Reut Zysman18411272015-02-09 13:47:27 +0200307 fbcon_putImage_in_location(fbimg, x, y);
308 }
309 else
310 {
311 dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300312 display_error_msg(); /* This will never return */
Reut Zysman18411272015-02-09 13:47:27 +0200313 }
Amit Blay6281ebc2015-01-11 14:44:08 +0200314}
315
Reut Zysman18411272015-02-09 13:47:27 +0200316/**
317 * Display initial delay message
318 */
319static void display_initial_delay()
Amit Blay6281ebc2015-01-11 14:44:08 +0200320{
Reut Zysman18411272015-02-09 13:47:27 +0200321 uint32_t x = CENTER_IMAGE_ON_X_AXIS(MDTP_MAIN_TEXT_WIDTH,fb_config->width);
322 uint32_t y = (fb_config->height)*MAIN_TEXT_RELATIVE_Y_LOCATION;
Amit Blay6281ebc2015-01-11 14:44:08 +0200323
Reut Zysman18411272015-02-09 13:47:27 +0200324 display_image(MDTP_INITIAL_DELAY_OFFSET, MDTP_MAIN_TEXT_WIDTH, MDTP_MAIN_TEXT_HEIGHT, x, y);
Amit Blay6281ebc2015-01-11 14:44:08 +0200325}
326
Reut Zysman18411272015-02-09 13:47:27 +0200327/**
328 * Display "enter PIN" message
329 */
330static void display_enter_pin()
Amit Blay6281ebc2015-01-11 14:44:08 +0200331{
Reut Zysman18411272015-02-09 13:47:27 +0200332 uint32_t x = CENTER_IMAGE_ON_X_AXIS(MDTP_MAIN_TEXT_WIDTH,fb_config->width);
333 uint32_t y = (fb_config->height)*MAIN_TEXT_RELATIVE_Y_LOCATION;
Amit Blay6281ebc2015-01-11 14:44:08 +0200334
Reut Zysman18411272015-02-09 13:47:27 +0200335 display_image(MDTP_ENTER_PIN_OFFSET, MDTP_MAIN_TEXT_WIDTH, MDTP_MAIN_TEXT_HEIGHT, x, y);
Amit Blay6281ebc2015-01-11 14:44:08 +0200336}
337
Reut Zysman18411272015-02-09 13:47:27 +0200338/**
339 * Display invalid PIN message
340 */
341static void display_invalid_pin()
Amit Blay6281ebc2015-01-11 14:44:08 +0200342{
Reut Zysman18411272015-02-09 13:47:27 +0200343 uint32_t x = CENTER_IMAGE_ON_X_AXIS(MDTP_MAIN_TEXT_WIDTH,fb_config->width);
344 uint32_t y = (fb_config->height)*MAIN_TEXT_RELATIVE_Y_LOCATION;
Amit Blay6281ebc2015-01-11 14:44:08 +0200345
Reut Zysman18411272015-02-09 13:47:27 +0200346 display_image(MDTP_INVALID_PIN_OFFSET, MDTP_MAIN_TEXT_WIDTH, MDTP_MAIN_TEXT_HEIGHT, x, y);
Amit Blay6281ebc2015-01-11 14:44:08 +0200347}
348
Reut Zysman18411272015-02-09 13:47:27 +0200349/**
350 * Clear digits instructions
351 */
352static void display_digits_instructions()
Amit Blay6281ebc2015-01-11 14:44:08 +0200353{
Reut Zysman18411272015-02-09 13:47:27 +0200354 uint32_t x = CENTER_IMAGE_ON_X_AXIS(MDTP_DIGITS_INSTRUCTIONS_WIDTH,fb_config->width);
355 uint32_t y = (fb_config->height)*PIN_TEXT_RELATIVE_Y_LOCATION;
356
357 display_image(MDTP_DIGITS_INSTRUCTIONS_OFFSET, MDTP_DIGITS_INSTRUCTIONS_WIDTH, MDTP_DIGITS_INSTRUCTIONS_HEIGHT, x, y);
358}
359
360/**
361 * Clear digits instructions
362 */
363static void clear_digits_instructions()
364{
365 uint32_t y = (fb_config->height)*PIN_TEXT_RELATIVE_Y_LOCATION;
366
367 fbcon_clear_section(y, MDTP_DIGITS_INSTRUCTIONS_HEIGHT);
368}
369
370/**
371 * Display a digit as un-selected.
372 */
373static void display_digit(uint32_t x, uint32_t y, uint32_t digit)
374{
375 display_image(MDTP_PIN_DIGIT_0_OFFSET + digit*MDTP_PIN_DIGITS_OFFSET,
376 MDTP_PIN_DIGIT_WIDTH, MDTP_PIN_DIGIT_HEIGHT, x, y);
377}
378
379/**
380 * Display a digit as selected.
381 */
382static void display_selected_digit(uint32_t x, uint32_t y, uint32_t digit)
383{
384 display_image(MDTP_PIN_SELECTED_DIGIT_0_OFFSET + digit*MDTP_PIN_DIGITS_OFFSET,
385 MDTP_PIN_DIGIT_WIDTH, MDTP_PIN_DIGIT_HEIGHT, x, y);
386}
387
388/**
389 * Display OK button as un-selected.
390 */
391static void display_ok_button()
392{
393 uint32_t ok_x = CENTER_IMAGE_ON_X_AXIS(MDTP_OK_BUTTON_WIDTH,fb_config->width);
394 uint32_t ok_y = (fb_config->height)*OK_BUTTON_RELATIVE_Y_LOCATION;
395
396 display_image(MDTP_OK_BUTTON_OFFSET, MDTP_OK_BUTTON_WIDTH, MDTP_OK_BUTTON_HEIGHT, ok_x, ok_y);
397}
398
399/**
400 * Display OK button as selected.
401 */
402static void display_selected_ok_button()
403{
404 uint32_t ok_x = CENTER_IMAGE_ON_X_AXIS(MDTP_OK_BUTTON_WIDTH,fb_config->width);
405 uint32_t ok_y = (fb_config->height)*OK_BUTTON_RELATIVE_Y_LOCATION;
406
407 display_image(MDTP_SELECTED_OK_BUTTON_OFFSET, MDTP_OK_BUTTON_WIDTH, MDTP_OK_BUTTON_HEIGHT, ok_x, ok_y);
408}
409
410/**
411 * Display the instructions for the OK button.
412 */
413static void display_pin_instructions()
414{
415 uint32_t x = CENTER_IMAGE_ON_X_AXIS(MDTP_PIN_INSTRUCTIONS_WIDTH,fb_config->width);
416 uint32_t y = (fb_config->height)*OK_TEXT_RELATIVE_Y_LOCATION;
417
418 display_image(MDTP_PIN_INSTRUCTIONS_OFFSET, MDTP_PIN_INSTRUCTIONS_WIDTH, MDTP_PIN_INSTRUCTIONS_HEIGHT, x, y);
419}
420
421/**
422 * Clear the instructions for the OK button.
423 */
424static void clear_pin_message()
425{
426 uint32_t y = (fb_config->height)*OK_TEXT_RELATIVE_Y_LOCATION;
427
428 fbcon_clear_section(y, MDTP_PIN_INSTRUCTIONS_HEIGHT);
429}
430
431/**
432 * Display the basic layout of the screen (done only once).
433 */
434static void display_initial_screen(uint32_t pin_length)
435{
436 if (g_initial_screen_displayed == true)
437 return;
438
439 fb_config = fbcon_display();
440
441 if (fb_config)
442 {
443 fbcon_clear();
444
445 if (display_error_message())
Amit Blay8e2731c2015-04-28 21:54:55 +0300446 display_error_msg(); /* This will never return */
Reut Zysman18411272015-02-09 13:47:27 +0200447 display_initial_delay();
448
449 mdelay(INITIAL_DELAY_MSECONDS);
450
451 g_pin_frames_y_location = ((fb_config->height)*PIN_RELATIVE_Y_LOCATION);
452
453 uint32_t total_pin_length = pin_length*MDTP_PIN_DIGIT_WIDTH + DIGIT_SPACE*(pin_length - 1);
454 uint32_t complete_pin_centered = (fb_config->width - total_pin_length)/2;
455
Amit Blay8e2731c2015-04-28 21:54:55 +0300456 for (uint32_t i=0; i<pin_length; i++)
Reut Zysman18411272015-02-09 13:47:27 +0200457 {
458 g_pin_frames_x_location[i] = complete_pin_centered + i*(DIGIT_SPACE+MDTP_PIN_DIGIT_WIDTH);
459 }
460
Amit Blay8e2731c2015-04-28 21:54:55 +0300461 for (uint32_t i=0; i<pin_length; i++)
Reut Zysman18411272015-02-09 13:47:27 +0200462 {
463 display_digit(g_pin_frames_x_location[i], g_pin_frames_y_location, 0);
464 }
465
466 display_ok_button();
467
468 g_initial_screen_displayed = true;
469 }
470 else
471 {
472 dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300473 display_error_msg(); /* This will never return */
Reut Zysman18411272015-02-09 13:47:27 +0200474 }
475}
476
477/**
478 * Display the recovery PIN screen and set received buffer
479 * with the PIN the user has entered.
480 * The entered PIN will be validated by the calling function.
481 */
482static void display_get_pin_interface(char *entered_pin, uint32_t pin_length)
483{
484 uint32_t previous_position = 0, current_position = 0;
485
486 display_initial_screen(pin_length);
487 display_enter_pin();
488
489 // Convert ascii to digits
490 for (uint32_t i=0; i<pin_length; i++)
491 {
492 entered_pin[i] -= '0';
493 }
494 display_selected_digit(g_pin_frames_x_location[0], g_pin_frames_y_location, entered_pin[0]);
495 display_digits_instructions();
Amit Blay6281ebc2015-01-11 14:44:08 +0200496
497 while (1)
498 {
Reut Zysman18411272015-02-09 13:47:27 +0200499 if (target_volume_up())
Amit Blay6281ebc2015-01-11 14:44:08 +0200500 {
Reut Zysman18411272015-02-09 13:47:27 +0200501 // current position is the OK button
502 if (current_position == pin_length)
503 {
504 // Convert digits to ascii and
505 // validate entered PIN in the calling function
506 for (uint32_t i=0; i<pin_length; i++)
507 {
508 entered_pin[i] += '0';
509 }
510 return;
511 }
512
513 // current position is a PIN slot
514 entered_pin[current_position] = (entered_pin[current_position]+1) % 10;
515 display_selected_digit(g_pin_frames_x_location[current_position], g_pin_frames_y_location, entered_pin[current_position]);
516 mdelay(MDTP_PRESSING_DELAY_MSEC);
517 }
518 if (target_volume_down())
519 {
520 previous_position = current_position;
521 current_position = (current_position+1) % (pin_length+1);
522
523 // previous position was the OK button
524 if (previous_position == pin_length)
525 {
526 clear_pin_message();
527 display_ok_button();
528
529 display_digits_instructions();
530 display_selected_digit(g_pin_frames_x_location[current_position], g_pin_frames_y_location, entered_pin[current_position]);
531
532 }
533
534 // current position is the OK button
535 else if (current_position == pin_length)
536 {
537 display_digit(g_pin_frames_x_location[previous_position], g_pin_frames_y_location, entered_pin[previous_position]);
538 clear_digits_instructions();
539
540 display_selected_ok_button();
541 display_pin_instructions();
542 }
543
544 // both the previous and the current positions are PIN slots
545 else
546 {
547 display_digit(g_pin_frames_x_location[previous_position], g_pin_frames_y_location, entered_pin[previous_position]);
548
549 display_selected_digit(g_pin_frames_x_location[current_position], g_pin_frames_y_location, entered_pin[current_position]);
550 }
551
552 mdelay(MDTP_PRESSING_DELAY_MSEC);
Amit Blay6281ebc2015-01-11 14:44:08 +0200553 }
554 }
Reut Zysman18411272015-02-09 13:47:27 +0200555}
556
557/*----------------------------------------------------------------------------
558 * External Functions
559 * -------------------------------------------------------------------------*/
560
561/**
562 * Display the recovery PIN screen and set received buffer
563 * with the PIN the user has entered.
564 */
565void get_pin_from_user(char *entered_pin, uint32_t pin_length)
566{
567 display_get_pin_interface(entered_pin, pin_length);
Amit Blay6281ebc2015-01-11 14:44:08 +0200568
569 return;
570}
571
Reut Zysman18411272015-02-09 13:47:27 +0200572/**
573 * User has entered invalid PIN, display error message and
574 * allow the user to try again.
575 */
576void display_invalid_pin_msg()
Amit Blay6281ebc2015-01-11 14:44:08 +0200577{
Reut Zysman18411272015-02-09 13:47:27 +0200578 clear_pin_message();
579 display_ok_button();
580
581 display_invalid_pin();
582
583 mdelay(INVALID_PIN_DELAY_MSECONDS);
Amit Blay6281ebc2015-01-11 14:44:08 +0200584}
585
Reut Zysman18411272015-02-09 13:47:27 +0200586/**
587 * Display error message and stop boot process.
588 */
589void display_error_msg()
Amit Blay6281ebc2015-01-11 14:44:08 +0200590{
Amit Blay8e2731c2015-04-28 21:54:55 +0300591 fb_config = fbcon_display();
592
593 if (fb_config)
594 {
595 fbcon_clear();
596 display_error_message(); // No point in checking the return value here
597 }
Reut Zysman18411272015-02-09 13:47:27 +0200598
599 // Invalid state. Nothing to be done but contacting the OEM.
600 // Stop boot process.
601 dprintf(CRITICAL,"ERROR: blocking boot process\n");
Amit Blay8e2731c2015-04-28 21:54:55 +0300602 for(;;);
Amit Blay6281ebc2015-01-11 14:44:08 +0200603}
604