blob: 48d899ef8f66c42160d8cfd20470802b5a5de387 [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
81#define CENTER_IMAGE_ON_X_AXIS(image_width,screen_width) ((screen_width-image_width)/2)
82
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 Blay6281ebc2015-01-11 14:44:08 +0200134
Reut Zysman18411272015-02-09 13:47:27 +0200135 if (mmc_read(ptn+offset, (void*)base, ROUNDUP(width*height*3, block_size))) {
Amit Blay6281ebc2015-01-11 14:44:08 +0200136 fbcon_clear();
137 dprintf(CRITICAL, "ERROR: mdtp image read failed\n");
138 return NULL;
139 }
Reut Zysman18411272015-02-09 13:47:27 +0200140 logo->width = width;
141 logo->height = height;
Amit Blay6281ebc2015-01-11 14:44:08 +0200142 }
143
144 return logo;
145}
146
Reut Zysman18411272015-02-09 13:47:27 +0200147/**
148 * flush fbcon display
149 *
150 * The function is duplicated from fbcon.c
151 */
152static void fbcon_flush(void)
Amit Blay6281ebc2015-01-11 14:44:08 +0200153{
Reut Zysman18411272015-02-09 13:47:27 +0200154 if (fb_config->update_start)
155 fb_config->update_start();
156 if (fb_config->update_done)
157 while (!fb_config->update_done());
158}
Amit Blay6281ebc2015-01-11 14:44:08 +0200159
Reut Zysman18411272015-02-09 13:47:27 +0200160/**
161 * Clear complete section on the screen.
162 * The section is of section_height, and is located from the y
163 * coordinate and down.
164 */
165static void fbcon_clear_section(uint32_t y, uint32_t section_height)
166{
167 unsigned image_base;
168 unsigned bytes_per_bpp;
Amit Blay6281ebc2015-01-11 14:44:08 +0200169
Reut Zysman18411272015-02-09 13:47:27 +0200170 if (fb_config)
Amit Blay6281ebc2015-01-11 14:44:08 +0200171 {
Reut Zysman18411272015-02-09 13:47:27 +0200172 image_base = (y *(fb_config->width));
173 bytes_per_bpp = ((fb_config->bpp) / BITS_PER_BYTE);
Amit Blay6281ebc2015-01-11 14:44:08 +0200174
Reut Zysman18411272015-02-09 13:47:27 +0200175 unsigned count = fb_config->width*section_height;
176 memset(fb_config->base + image_base*bytes_per_bpp, RGB888_BLACK, count*bytes_per_bpp);
177
178 fbcon_flush();
Amit Blay6281ebc2015-01-11 14:44:08 +0200179 }
Reut Zysman18411272015-02-09 13:47:27 +0200180 else
Amit Blay6281ebc2015-01-11 14:44:08 +0200181 {
Reut Zysman18411272015-02-09 13:47:27 +0200182 dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n");
183 display_error_msg();
Amit Blay6281ebc2015-01-11 14:44:08 +0200184 }
Amit Blay6281ebc2015-01-11 14:44:08 +0200185}
186
Reut Zysman18411272015-02-09 13:47:27 +0200187/**
188 * Put image at a specific (x,y) location on the screen.
189 * Duplicated from fbcon.c, with modifications to allow (x,y) location (instead of a centered image),
190 * and display bmp images properly (order of copying the lines to the screen was reversed)
191 */
192static void fbcon_putImage_in_location(struct mdtp_fbimage *fbimg, uint32_t x, uint32_t y)
Amit Blay6281ebc2015-01-11 14:44:08 +0200193{
Reut Zysman18411272015-02-09 13:47:27 +0200194 unsigned i = 0;
195 unsigned bytes_per_bpp;
196 unsigned image_base;
197 unsigned width, pitch, height;
198 unsigned char *logo_base = NULL;
Amit Blay6281ebc2015-01-11 14:44:08 +0200199
Reut Zysman18411272015-02-09 13:47:27 +0200200 if (!fb_config) {
201 dprintf(CRITICAL,"ERROR: NULL configuration, image cannot be displayed\n");
202 return;
Amit Blay6281ebc2015-01-11 14:44:08 +0200203 }
204
Reut Zysman18411272015-02-09 13:47:27 +0200205 if(fbimg) {
206 width = pitch = fbimg->width;
207 height = fbimg->height;
208 logo_base = (unsigned char *)fbimg->image;
209 }
210 else {
211 dprintf(CRITICAL,"ERROR: invalid image struct\n");
212 return;
Amit Blay6281ebc2015-01-11 14:44:08 +0200213 }
214
Reut Zysman18411272015-02-09 13:47:27 +0200215 bytes_per_bpp = ((fb_config->bpp) / BITS_PER_BYTE);
216
217#if DISPLAY_TYPE_MIPI
218 if (bytes_per_bpp == 3)
Amit Blay6281ebc2015-01-11 14:44:08 +0200219 {
Reut Zysman18411272015-02-09 13:47:27 +0200220 if (fbimg->width == fb_config->width && fbimg->height == fb_config->height)
221 return;
Amit Blay6281ebc2015-01-11 14:44:08 +0200222
Reut Zysman18411272015-02-09 13:47:27 +0200223 if (fbimg->width > fb_config->width || fbimg->height > fb_config->height)
224 {
225 dprintf(CRITICAL,"ERROR: invalid image size, larger than the screen\n");
226 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 }
235
Reut Zysman18411272015-02-09 13:47:27 +0200236 fbcon_flush();
237
238#if DISPLAY_MIPI_PANEL_NOVATEK_BLUE
239 if(is_cmd_mode_enabled())
240 mipi_dsi_cmd_mode_trigger();
241#endif
242
243#else
244 if (bytes_per_bpp == 2)
245 {
246 for (i = 0; i < fbimg->width; i++)
247 {
248 memcpy (fb_config->base + ((image_base + (i * (fb_config->width))) * bytes_per_bpp),
249 fbimg->image + (i * fbimg->height * bytes_per_bpp),
250 fbimg->height * bytes_per_bpp);
251 }
252 }
253 fbcon_flush();
254#endif
Amit Blay6281ebc2015-01-11 14:44:08 +0200255}
256
Reut Zysman18411272015-02-09 13:47:27 +0200257/**
258 * Display main error message
259 */
260static int display_error_message()
Amit Blay6281ebc2015-01-11 14:44:08 +0200261{
Reut Zysman18411272015-02-09 13:47:27 +0200262 struct mdtp_fbimage *fbimg;
Amit Blay6281ebc2015-01-11 14:44:08 +0200263
Reut Zysman18411272015-02-09 13:47:27 +0200264 fb_config = fbcon_display();
Amit Blay6281ebc2015-01-11 14:44:08 +0200265
Reut Zysman18411272015-02-09 13:47:27 +0200266 if (fb_config)
267 {
268 uint32_t x = CENTER_IMAGE_ON_X_AXIS(MDTP_ERROR_MSG_WIDTH,fb_config->width);
269 uint32_t y = ((fb_config->height)*ERROR_MESSAGE_RELATIVE_Y_LOCATION);
270
271 fbimg = mdtp_read_mmc_image(MDTP_ERROR_MSG_OFFSET, MDTP_ERROR_MSG_WIDTH, MDTP_ERROR_MSG_HEIGHT);
272 if (NULL == fbimg)
273 {
274 dprintf(CRITICAL,"ERROR: failed to read error image from mmc\n");
275 return -1;
276 }
277
278 fbcon_putImage_in_location(fbimg, x, y);
279
280 return 0;
281 }
282 else
283 {
284 dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n");
285 return -1;
286 }
Amit Blay6281ebc2015-01-11 14:44:08 +0200287}
288
Reut Zysman18411272015-02-09 13:47:27 +0200289/**
290 * Read from mmc the image in the given offset, of the given width and height.
291 * Then, display the image on the screen in the given (x,y) location.
292 */
293static 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 +0200294{
Reut Zysman18411272015-02-09 13:47:27 +0200295 struct mdtp_fbimage *fbimg;
Amit Blay6281ebc2015-01-11 14:44:08 +0200296
Reut Zysman18411272015-02-09 13:47:27 +0200297 if (fb_config)
298 {
299 fbimg = mdtp_read_mmc_image(offset, width, height);
300 if (NULL == fbimg)
301 {
302 dprintf(CRITICAL,"ERROR: failed to read image from mmc\n");
303 display_error_msg();
304 }
Amit Blay6281ebc2015-01-11 14:44:08 +0200305
Reut Zysman18411272015-02-09 13:47:27 +0200306 fbcon_putImage_in_location(fbimg, x, y);
307 }
308 else
309 {
310 dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n");
311 display_error_msg();
312 }
Amit Blay6281ebc2015-01-11 14:44:08 +0200313}
314
Reut Zysman18411272015-02-09 13:47:27 +0200315/**
316 * Display initial delay message
317 */
318static void display_initial_delay()
Amit Blay6281ebc2015-01-11 14:44:08 +0200319{
Reut Zysman18411272015-02-09 13:47:27 +0200320 uint32_t x = CENTER_IMAGE_ON_X_AXIS(MDTP_MAIN_TEXT_WIDTH,fb_config->width);
321 uint32_t y = (fb_config->height)*MAIN_TEXT_RELATIVE_Y_LOCATION;
Amit Blay6281ebc2015-01-11 14:44:08 +0200322
Reut Zysman18411272015-02-09 13:47:27 +0200323 display_image(MDTP_INITIAL_DELAY_OFFSET, MDTP_MAIN_TEXT_WIDTH, MDTP_MAIN_TEXT_HEIGHT, x, y);
Amit Blay6281ebc2015-01-11 14:44:08 +0200324}
325
Reut Zysman18411272015-02-09 13:47:27 +0200326/**
327 * Display "enter PIN" message
328 */
329static void display_enter_pin()
Amit Blay6281ebc2015-01-11 14:44:08 +0200330{
Reut Zysman18411272015-02-09 13:47:27 +0200331 uint32_t x = CENTER_IMAGE_ON_X_AXIS(MDTP_MAIN_TEXT_WIDTH,fb_config->width);
332 uint32_t y = (fb_config->height)*MAIN_TEXT_RELATIVE_Y_LOCATION;
Amit Blay6281ebc2015-01-11 14:44:08 +0200333
Reut Zysman18411272015-02-09 13:47:27 +0200334 display_image(MDTP_ENTER_PIN_OFFSET, MDTP_MAIN_TEXT_WIDTH, MDTP_MAIN_TEXT_HEIGHT, x, y);
Amit Blay6281ebc2015-01-11 14:44:08 +0200335}
336
Reut Zysman18411272015-02-09 13:47:27 +0200337/**
338 * Display invalid PIN message
339 */
340static void display_invalid_pin()
Amit Blay6281ebc2015-01-11 14:44:08 +0200341{
Reut Zysman18411272015-02-09 13:47:27 +0200342 uint32_t x = CENTER_IMAGE_ON_X_AXIS(MDTP_MAIN_TEXT_WIDTH,fb_config->width);
343 uint32_t y = (fb_config->height)*MAIN_TEXT_RELATIVE_Y_LOCATION;
Amit Blay6281ebc2015-01-11 14:44:08 +0200344
Reut Zysman18411272015-02-09 13:47:27 +0200345 display_image(MDTP_INVALID_PIN_OFFSET, MDTP_MAIN_TEXT_WIDTH, MDTP_MAIN_TEXT_HEIGHT, x, y);
Amit Blay6281ebc2015-01-11 14:44:08 +0200346}
347
Reut Zysman18411272015-02-09 13:47:27 +0200348/**
349 * Clear digits instructions
350 */
351static void display_digits_instructions()
Amit Blay6281ebc2015-01-11 14:44:08 +0200352{
Reut Zysman18411272015-02-09 13:47:27 +0200353 uint32_t x = CENTER_IMAGE_ON_X_AXIS(MDTP_DIGITS_INSTRUCTIONS_WIDTH,fb_config->width);
354 uint32_t y = (fb_config->height)*PIN_TEXT_RELATIVE_Y_LOCATION;
355
356 display_image(MDTP_DIGITS_INSTRUCTIONS_OFFSET, MDTP_DIGITS_INSTRUCTIONS_WIDTH, MDTP_DIGITS_INSTRUCTIONS_HEIGHT, x, y);
357}
358
359/**
360 * Clear digits instructions
361 */
362static void clear_digits_instructions()
363{
364 uint32_t y = (fb_config->height)*PIN_TEXT_RELATIVE_Y_LOCATION;
365
366 fbcon_clear_section(y, MDTP_DIGITS_INSTRUCTIONS_HEIGHT);
367}
368
369/**
370 * Display a digit as un-selected.
371 */
372static void display_digit(uint32_t x, uint32_t y, uint32_t digit)
373{
374 display_image(MDTP_PIN_DIGIT_0_OFFSET + digit*MDTP_PIN_DIGITS_OFFSET,
375 MDTP_PIN_DIGIT_WIDTH, MDTP_PIN_DIGIT_HEIGHT, x, y);
376}
377
378/**
379 * Display a digit as selected.
380 */
381static void display_selected_digit(uint32_t x, uint32_t y, uint32_t digit)
382{
383 display_image(MDTP_PIN_SELECTED_DIGIT_0_OFFSET + digit*MDTP_PIN_DIGITS_OFFSET,
384 MDTP_PIN_DIGIT_WIDTH, MDTP_PIN_DIGIT_HEIGHT, x, y);
385}
386
387/**
388 * Display OK button as un-selected.
389 */
390static void display_ok_button()
391{
392 uint32_t ok_x = CENTER_IMAGE_ON_X_AXIS(MDTP_OK_BUTTON_WIDTH,fb_config->width);
393 uint32_t ok_y = (fb_config->height)*OK_BUTTON_RELATIVE_Y_LOCATION;
394
395 display_image(MDTP_OK_BUTTON_OFFSET, MDTP_OK_BUTTON_WIDTH, MDTP_OK_BUTTON_HEIGHT, ok_x, ok_y);
396}
397
398/**
399 * Display OK button as selected.
400 */
401static void display_selected_ok_button()
402{
403 uint32_t ok_x = CENTER_IMAGE_ON_X_AXIS(MDTP_OK_BUTTON_WIDTH,fb_config->width);
404 uint32_t ok_y = (fb_config->height)*OK_BUTTON_RELATIVE_Y_LOCATION;
405
406 display_image(MDTP_SELECTED_OK_BUTTON_OFFSET, MDTP_OK_BUTTON_WIDTH, MDTP_OK_BUTTON_HEIGHT, ok_x, ok_y);
407}
408
409/**
410 * Display the instructions for the OK button.
411 */
412static void display_pin_instructions()
413{
414 uint32_t x = CENTER_IMAGE_ON_X_AXIS(MDTP_PIN_INSTRUCTIONS_WIDTH,fb_config->width);
415 uint32_t y = (fb_config->height)*OK_TEXT_RELATIVE_Y_LOCATION;
416
417 display_image(MDTP_PIN_INSTRUCTIONS_OFFSET, MDTP_PIN_INSTRUCTIONS_WIDTH, MDTP_PIN_INSTRUCTIONS_HEIGHT, x, y);
418}
419
420/**
421 * Clear the instructions for the OK button.
422 */
423static void clear_pin_message()
424{
425 uint32_t y = (fb_config->height)*OK_TEXT_RELATIVE_Y_LOCATION;
426
427 fbcon_clear_section(y, MDTP_PIN_INSTRUCTIONS_HEIGHT);
428}
429
430/**
431 * Display the basic layout of the screen (done only once).
432 */
433static void display_initial_screen(uint32_t pin_length)
434{
435 if (g_initial_screen_displayed == true)
436 return;
437
438 fb_config = fbcon_display();
439
440 if (fb_config)
441 {
442 fbcon_clear();
443
444 if (display_error_message())
445 display_error_msg();
446 display_initial_delay();
447
448 mdelay(INITIAL_DELAY_MSECONDS);
449
450 g_pin_frames_y_location = ((fb_config->height)*PIN_RELATIVE_Y_LOCATION);
451
452 uint32_t total_pin_length = pin_length*MDTP_PIN_DIGIT_WIDTH + DIGIT_SPACE*(pin_length - 1);
453 uint32_t complete_pin_centered = (fb_config->width - total_pin_length)/2;
454
455 for (int i=0; i<(int)pin_length; i++)
456 {
457 g_pin_frames_x_location[i] = complete_pin_centered + i*(DIGIT_SPACE+MDTP_PIN_DIGIT_WIDTH);
458 }
459
460 for (int i=0; i<(int)pin_length; i++)
461 {
462 display_digit(g_pin_frames_x_location[i], g_pin_frames_y_location, 0);
463 }
464
465 display_ok_button();
466
467 g_initial_screen_displayed = true;
468 }
469 else
470 {
471 dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n");
472 display_error_msg();
473 return;
474 }
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{
Reut Zysman18411272015-02-09 13:47:27 +0200591 fbcon_clear();
592 display_error_message(); // No point in checking the return value here
593
594 // Invalid state. Nothing to be done but contacting the OEM.
595 // Stop boot process.
596 dprintf(CRITICAL,"ERROR: blocking boot process\n");
597 while(1)
598 {
599
600 }
Amit Blay6281ebc2015-01-11 14:44:08 +0200601}
602