diff --git a/legacy/firmware/Makefile b/legacy/firmware/Makefile index 1e94db790..15464c8e2 100644 --- a/legacy/firmware/Makefile +++ b/legacy/firmware/Makefile @@ -25,6 +25,7 @@ OBJS += recovery.o OBJS += reset.o OBJS += signing.o OBJS += crypto.o +OBJS += keyboard.o ifneq ($(BITCOIN_ONLY),1) OBJS += u2f.o diff --git a/legacy/firmware/keyboard.c b/legacy/firmware/keyboard.c new file mode 100644 index 000000000..ca39b884d --- /dev/null +++ b/legacy/firmware/keyboard.c @@ -0,0 +1,441 @@ +/* + * This file is part of the Trezor project, https://trezor.io/ + * + * Copyright (C) 2019 SatoshiLabs + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include "keyboard.h" +#include +#include "buttons.h" +#include "memzero.h" +#include "oled.h" +#include "usb.h" + +#define BTN_WIDTH 23 +#define BTN_HEIGHT 11 +#define BTN_X_SEP 4 +#define BTN_Y_SEP 3 +#define KBD_COLS 3 +#define KBD_ROWS 4 +#define KBD_SIZE (KBD_COLS * KBD_ROWS) +#define KBD_X_OFFSET 26 +#define KBD_Y_OFFSET 10 +#define KBD_HEIGHT (KBD_ROWS * (BTN_HEIGHT + BTN_Y_SEP) - BTN_Y_SEP + 1) +#define KBD_WIDTH (KBD_COLS * (BTN_WIDTH + BTN_X_SEP) - BTN_X_SEP + 1) +#define KBD_COUNT 4 +#define MAX_INPUT_LEN 50 +const char *KBD_LABELS[KBD_COUNT][KBD_SIZE] = { + {"abc", "def", "ghi", "jkl", "mno", "pqr", "stu", "vwx", "yz ", "", "*#", + ""}, + {"ABC", "DEF", "GHI", "JKL", "MNO", "PQR", "STU", "VWX", "YZ ", "", "*#", + ""}, + {"_<>", ".:@", "/|\\", "!()", "+%&", "-[]", "?{}", ",'`", ";\"~", "", + "$^=", ""}, + {"1", "2", "3", "4", "5", "6", "7", "8", "9", "", "0", ""}, +}; + +#define BTN_BACKSPACE 9 +#define BTN_DONE 11 +#define LABEL_BACKSPACE "Bksp" +#define LABEL_CANCEL "Exit" +#define LABEL_DONE "OK" + +#define CURSOR_WIDTH 5 +#define CURSOR_HEIGHT 2 +static int select_index = -1; +static int kbd_layout = 0; + +enum { + STATUS_IN_PROGRESS = 0, + STATUS_DONE = 1, + STATUS_CANCELLED = 2, +} status = STATUS_IN_PROGRESS; + +#define INPUT_OFFSET KBD_X_OFFSET +#define TEXT_OFFSET 0 +CONFIDENTIAL char input[MAX_INPUT_LEN + 1] = ""; + +static void drawBtn(int i, const char *text) { + int x = KBD_X_OFFSET + (i % KBD_COLS) * (BTN_WIDTH + BTN_X_SEP); + int y = KBD_Y_OFFSET + (i / KBD_COLS) * (BTN_HEIGHT + BTN_Y_SEP); + for (int j = 0; j < BTN_WIDTH; j++) { + oledDrawPixel(x + j, y - 1); + oledDrawPixel(x + j, y + BTN_HEIGHT); + } + for (int j = 0; j < BTN_HEIGHT; j++) { + oledDrawPixel(x - 1, y + j); + oledDrawPixel(x + BTN_WIDTH, y + j); + } + oledDrawStringCenter(x + BTN_WIDTH / 2 + 1, y + 2, text, FONT_STANDARD); +} + +static void drawBtnLeft(const char *label) { + int x = KBD_X_OFFSET - BTN_X_SEP; + oledBox(0, OLED_HEIGHT - 9, x, OLED_HEIGHT - 1, false); + if (label) + oledDrawStringCenter(KBD_X_OFFSET / 2 - 1, OLED_HEIGHT - 8, label, + FONT_STANDARD); + else + oledDrawBitmap(3, OLED_HEIGHT - 7, &bmp_btn_up); + oledInvert(0, OLED_HEIGHT - 9, x, OLED_HEIGHT - 1); +} + +static void drawBtnRight(const char *label) { + int x = KBD_X_OFFSET + KBD_COLS * (BTN_WIDTH + BTN_X_SEP) - 1; + oledBox(x, OLED_HEIGHT - 9, OLED_WIDTH - 1, OLED_HEIGHT - 1, false); + if (label) + oledDrawStringCenter((OLED_WIDTH + x + 1) / 2, OLED_HEIGHT - 8, label, + FONT_STANDARD); + else + oledDrawBitmap(OLED_WIDTH - 14, OLED_HEIGHT - 8, &bmp_btn_right); + oledInvert(x, OLED_HEIGHT - 9, OLED_WIDTH - 1, OLED_HEIGHT - 1); +} + +static void drawKeyboard(void) { + oledBox(KBD_X_OFFSET, KBD_Y_OFFSET, KBD_X_OFFSET + KBD_WIDTH - 1, + KBD_Y_OFFSET + KBD_HEIGHT - 1, false); + + for (int i = 0; i < KBD_SIZE; ++i) { + drawBtn(i, KBD_LABELS[kbd_layout][i]); + } + + int x = KBD_X_OFFSET + 0 * (BTN_WIDTH + BTN_X_SEP); + int y = KBD_Y_OFFSET + 3 * (BTN_HEIGHT + BTN_Y_SEP); + if (input[0] == '\0') { + oledDrawBitmap(x + 8, y + 2, &bmp_btn_cancel); + } else { + oledDrawBitmap(x + 3, y + 1, &bmp_btn_backspace); + } + + x = KBD_X_OFFSET + 2 * (BTN_WIDTH + BTN_X_SEP); + y = KBD_Y_OFFSET + 3 * (BTN_HEIGHT + BTN_Y_SEP); + oledDrawBitmap(x + 8, y + 2, &bmp_btn_confirm); +} + +static void drawCursor(void) { + int x = INPUT_OFFSET + oledStringWidth(input, FONT_STANDARD); + oledBox(x, FONT_HEIGHT - CURSOR_HEIGHT, x + CURSOR_WIDTH - 1, FONT_HEIGHT - 1, + true); +} + +static void invertBtn(int i, int j) { + int x = KBD_X_OFFSET + i * (BTN_WIDTH + BTN_X_SEP); + int y = KBD_Y_OFFSET + j * (BTN_HEIGHT + BTN_Y_SEP); + oledInvert(x, y, x + BTN_WIDTH - 1, y + BTN_HEIGHT - 1); + oledRefresh(); +} + +static void pressBtn(int btn) { + int len = strlen(input); + if (btn == BTN_DONE) { + status = STATUS_DONE; + } else if (btn == BTN_BACKSPACE) { + if (len > 0) { + input[len - 1] = '\0'; + if (len == 1) { + // Replace backspace with cancel button. + drawKeyboard(); + select_index = -2; // Avoid accidentally pressing the cancel button. + } + } else if (select_index == -1) { + // Cancel only if this is not a repeated pressing of backspace. + status = STATUS_CANCELLED; + } + } else { + int btn_len = strlen(KBD_LABELS[kbd_layout][btn]); + int pos = len; + if (select_index >= 0) { + pos -= 1; + select_index = (select_index + 1) % btn_len; + } else { + select_index = 0; + } + if (pos < MAX_INPUT_LEN) { + input[pos] = KBD_LABELS[kbd_layout][btn][select_index]; + input[pos + 1] = '\0'; + } + + if (len == 0 && pos == 0) { + // Replace cancel button with backspace. + drawKeyboard(); + } + + if (btn_len == 1) { + // If the button has only one symbol, then pressing it repeatedly should + // cause the symbol to be typed repeatedly. + select_index = -1; + } + } + oledBox(TEXT_OFFSET, 0, OLED_WIDTH - 1, FONT_HEIGHT, false); + oledDrawString(INPUT_OFFSET, 0, input, FONT_STANDARD); + if (select_index < 0) drawCursor(); +} + +const char *pin_keyboard(const char *text) { + input[0] = '\0'; + select_index = -1; + status = STATUS_IN_PROGRESS; + kbd_layout = 3; + + oledClear(); + oledDrawString(TEXT_OFFSET, 0, text, FONT_STANDARD); + drawKeyboard(); + drawBtnLeft(NULL); + drawBtnRight(NULL); + + int i = 0; + int j = 0; + bool left_shift = false; + bool right_shift = false; + invertBtn(i, j); + while (status == STATUS_IN_PROGRESS) { + usbSleep(5); + bool refresh = false; + + buttonUpdate(); + if (button.YesReleased) { + if (right_shift) { + right_shift = false; + select_index = -1; + drawCursor(); + drawBtnLeft(NULL); + drawBtnRight(NULL); + } else { + invertBtn(i, j); + if (button.YesDown > button.NoDown) { + // Right + if (i == KBD_COLS - 1) { + i = 0; + j = (j + 1) % KBD_ROWS; + } else { + i = i + 1; + } + select_index = -1; + drawCursor(); + drawBtnLeft(NULL); + drawBtnRight(NULL); + } else { + // Shift + Right + pressBtn(i + j * KBD_COLS); + left_shift = true; + drawBtnLeft(""); + } + invertBtn(i, j); + } + refresh = true; + } else if (button.NoReleased) { + if (left_shift) { + left_shift = false; + select_index = -1; + drawCursor(); + drawBtnLeft(NULL); + drawBtnRight(NULL); + } else { + invertBtn(i, j); + if (button.NoDown > button.YesDown) { + // Left + i = 0; + j = (j - 1 + KBD_ROWS) % KBD_ROWS; + select_index = -1; + drawCursor(); + drawBtnLeft(NULL); + drawBtnRight(NULL); + } else { + // Shift + Left + pressBtn(i + j * KBD_COLS); + right_shift = true; + drawBtnRight(""); + } + invertBtn(i, j); + } + refresh = true; + } + + if (button.NoDown == 1 && button.YesDown <= 1) { + int btn = i + j * KBD_COLS; + const char *label = NULL; + if (btn == BTN_BACKSPACE) { + if (input[0] == '\0') { + label = LABEL_CANCEL; + } else { + label = LABEL_BACKSPACE; + } + } else if (btn == BTN_DONE) { + label = LABEL_DONE; + } else { + label = KBD_LABELS[kbd_layout][btn]; + } + drawBtnRight(label); + refresh = true; + } + + if (button.YesDown == 1 && button.NoDown <= 1) { + int btn = i + j * KBD_COLS; + const char *label = NULL; + if (btn == BTN_BACKSPACE) { + if (input[0] == '\0') { + label = LABEL_CANCEL; + } else { + label = LABEL_BACKSPACE; + } + } else if (btn == BTN_DONE) { + label = LABEL_DONE; + } else { + label = KBD_LABELS[kbd_layout][btn]; + } + drawBtnLeft(label); + refresh = true; + } + + if (refresh) { + oledRefresh(); + } + } + + // Wait for buttons to be released. + while (button.NoDown || button.YesDown) { + usbSleep(5); + buttonUpdate(); + } + + if (status == STATUS_DONE) { + return input; + } else { + return NULL; + } +} + +const char *passphrase_keyboard(const char *text) { + input[0] = '\0'; + select_index = -1; + status = STATUS_IN_PROGRESS; + kbd_layout = 0; + + oledClear(); + oledDrawString(TEXT_OFFSET, 0, text, FONT_STANDARD); + drawKeyboard(); + drawBtnLeft(NULL); + drawBtnRight(NULL); + + int i = 0; + int j = 0; + bool left_shift = false; + bool right_shift = false; + invertBtn(i, j); + while (status == STATUS_IN_PROGRESS) { + usbSleep(5); + bool refresh = false; + + buttonUpdate(); + if (button.YesReleased) { + if (right_shift) { + right_shift = false; + select_index = -1; + drawCursor(); + drawBtnLeft(NULL); + drawBtnRight(NULL); + } else { + invertBtn(i, j); + if (button.YesDown > button.NoDown) { + // Right + if (i == KBD_COLS - 1) { + i = 0; + j = (j + 1) % KBD_ROWS; + } else { + i = i + 1; + } + select_index = -1; + drawCursor(); + drawBtnLeft(NULL); + drawBtnRight(NULL); + } else { + // Shift + Right + pressBtn(i + j * KBD_COLS); + left_shift = true; + drawBtnLeft(""); + } + invertBtn(i, j); + } + refresh = true; + } else if (button.NoReleased) { + if (left_shift) { + left_shift = false; + select_index = -1; + drawCursor(); + drawBtnLeft(NULL); + drawBtnRight(NULL); + } else { + invertBtn(i, j); + if (button.NoDown > button.YesDown) { + // Left + i = 0; + j = (j - 1 + KBD_ROWS) % KBD_ROWS; + select_index = -1; + drawCursor(); + drawBtnLeft(NULL); + drawBtnRight(NULL); + } else { + // Shift + Left + kbd_layout = (kbd_layout + 1) % KBD_COUNT; + drawKeyboard(); + right_shift = true; + drawBtnRight(""); + } + invertBtn(i, j); + } + refresh = true; + } + + if (button.NoDown == 1 && button.YesDown <= 1) { + int btn = i + j * KBD_COLS; + const char *label = NULL; + if (btn == BTN_BACKSPACE) { + if (input[0] == '\0') { + label = LABEL_CANCEL; + } else { + label = LABEL_BACKSPACE; + } + } else if (btn == BTN_DONE) { + label = LABEL_DONE; + } else { + label = KBD_LABELS[kbd_layout][btn]; + } + drawBtnRight(label); + refresh = true; + } + + if (button.YesDown == 1 && button.NoDown <= 1) { + drawBtnLeft("0aA!"); + refresh = true; + } + + if (refresh) { + oledRefresh(); + } + } + + // Wait for buttons to be released. + while (button.NoDown || button.YesDown) { + usbSleep(5); + buttonUpdate(); + } + + if (status == STATUS_DONE) { + return input; + } else { + return NULL; + } +} diff --git a/legacy/firmware/keyboard.h b/legacy/firmware/keyboard.h new file mode 100644 index 000000000..7d142c835 --- /dev/null +++ b/legacy/firmware/keyboard.h @@ -0,0 +1,26 @@ +/* + * This file is part of the Trezor project, https://trezor.io/ + * + * Copyright (C) 2019 SatoshiLabs + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#ifndef __KEYBOARD_H__ +#define __KEYBOARD_H__ + +const char *passphrase_keyboard(const char *text); +const char *pin_keyboard(const char *text); + +#endif diff --git a/legacy/firmware/protect.c b/legacy/firmware/protect.c index e58e8ac38..7df3e2c89 100644 --- a/legacy/firmware/protect.c +++ b/legacy/firmware/protect.c @@ -23,6 +23,7 @@ #include "debug.h" #include "fsm.h" #include "gettext.h" +#include "keyboard.h" #include "layout2.h" #include "memory.h" #include "memzero.h" @@ -33,8 +34,6 @@ #include "usb.h" #include "util.h" -#define MAX_WRONG_PINS 15 - bool protectAbortedByCancel = false; bool protectAbortedByInitialize = false; @@ -112,6 +111,7 @@ bool protectButton(ButtonRequestType type, bool confirm_only) { } const char *requestPin(PinMatrixRequestType type, const char *text) { + return pin_keyboard(text); PinMatrixRequest resp = {0}; memzero(&resp, sizeof(PinMatrixRequest)); resp.has_type = true; diff --git a/legacy/gen/bitmaps.c b/legacy/gen/bitmaps.c index f1da68e47..277d7b81e 100644 --- a/legacy/gen/bitmaps.c +++ b/legacy/gen/bitmaps.c @@ -1,8 +1,14 @@ // clang-format off #include "bitmaps.h" +const uint8_t bmp_btn_backspace_data[] = { 0x07, 0xfe, 0x0e, 0xee, 0x1c, 0x46, 0x3e, 0x0e, 0x7f, 0x1e, 0x3e, 0x0e, 0x1c, 0x46, 0x0e, 0xee, 0x07, 0xfe, }; const uint8_t bmp_btn_cancel_data[] = { 0x44, 0xee, 0x7c, 0x38, 0x7c, 0xee, 0x44, 0x00, }; const uint8_t bmp_btn_confirm_data[] = { 0x02, 0x04, 0x08, 0xd8, 0xf0, 0x60, 0x20, 0x00, }; +const uint8_t bmp_btn_down_data[] = { 0x08, 0x20, 0x1c, 0x70, 0x0e, 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01, 0x00, }; +const uint8_t bmp_btn_left_data[] = { 0x0e, 0x1c, 0x38, 0x70, 0x38, 0x1c, 0x0e, }; +const uint8_t bmp_btn_right_data[] = { 0x70, 0x38, 0x1c, 0x0e, 0x1c, 0x38, 0x70, }; +const uint8_t bmp_btn_up_data[] = { 0x00, 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0x70, 0x0e, 0x38, 0x04, 0x10, }; +const uint8_t bmp_btn_upleft_data[] = { 0xfe, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, }; const uint8_t bmp_digit0_data[] = { 0xff, 0xff, 0xf8, 0x1f, 0xf0, 0x0f, 0xe1, 0x87, 0xe1, 0x87, 0xe1, 0x87, 0xe1, 0x87, 0xe1, 0x87, 0xe1, 0x87, 0xe1, 0x87, 0xe1, 0x87, 0xe1, 0x87, 0xe1, 0x87, 0xf0, 0x0f, 0xf8, 0x1f, 0xff, 0xff, }; const uint8_t bmp_digit1_data[] = { 0xff, 0xff, 0xfc, 0x3f, 0xf8, 0x3f, 0xf0, 0x3f, 0xf0, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xff, 0xff, }; const uint8_t bmp_digit2_data[] = { 0xff, 0xff, 0xe0, 0x1f, 0xe0, 0x0f, 0xff, 0x87, 0xff, 0x87, 0xff, 0x87, 0xff, 0x87, 0xf8, 0x0f, 0xf0, 0x1f, 0xe1, 0xff, 0xe1, 0xff, 0xe1, 0xff, 0xe1, 0xff, 0xe0, 0x07, 0xe0, 0x07, 0xff, 0xff, }; @@ -28,8 +34,14 @@ const uint8_t bmp_logo64_data[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x const uint8_t bmp_logo64_empty_data[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x70, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10, 0x00, 0x00, 0x08, 0x07, 0xe0, 0x10, 0x00, 0x00, 0x10, 0x08, 0x10, 0x08, 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x20, 0x20, 0x04, 0x04, 0x00, 0x00, 0x20, 0x40, 0x02, 0x04, 0x00, 0x00, 0x40, 0x80, 0x01, 0x02, 0x00, 0x00, 0x40, 0x80, 0x01, 0x02, 0x00, 0x00, 0x40, 0x80, 0x01, 0x02, 0x00, 0x00, 0x40, 0x80, 0x01, 0x02, 0x00, 0x00, 0x40, 0x80, 0x01, 0x02, 0x00, 0x00, 0x40, 0x80, 0x01, 0x02, 0x00, 0x00, 0x40, 0x80, 0x01, 0x02, 0x00, 0x00, 0x40, 0x80, 0x01, 0x02, 0x00, 0x1f, 0xc0, 0xff, 0xff, 0x03, 0xf8, 0x10, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x3f, 0xff, 0xff, 0xfc, 0x08, 0x10, 0x20, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x04, 0x08, 0x10, 0x18, 0x00, 0x00, 0x18, 0x08, 0x10, 0x06, 0x00, 0x00, 0x60, 0x08, 0x10, 0x01, 0x80, 0x01, 0x80, 0x08, 0x10, 0x00, 0x60, 0x06, 0x00, 0x08, 0x18, 0x00, 0x18, 0x18, 0x00, 0x18, 0x06, 0x00, 0x06, 0x60, 0x00, 0x60, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0x60, 0x00, 0x00, 0x06, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x06, 0x00, 0x00, 0x60, 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; const uint8_t bmp_webauthn_data[] = { 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x01, 0xff, 0xf8, 0x00, 0x03, 0xfe, 0x1c, 0x00, 0x03, 0xfc, 0x0c, 0x00, 0x07, 0xf8, 0x06, 0x00, 0x07, 0xf8, 0x06, 0x00, 0x0f, 0xf8, 0x06, 0x00, 0x0f, 0xf8, 0x07, 0x00, 0x0f, 0xfc, 0x0f, 0x00, 0x0f, 0xfe, 0x1f, 0x00, 0x0f, 0xff, 0xff, 0x00, 0x0f, 0xff, 0xff, 0x00, 0x07, 0xff, 0xfe, 0x00, 0x0f, 0xff, 0xfe, 0x00, 0x1f, 0xff, 0xfc, 0x00, 0x3f, 0xff, 0xfc, 0x00, 0x7f, 0xff, 0xf8, 0x00, 0xff, 0xff, 0xe0, 0x01, 0xff, 0xdf, 0x80, 0x03, 0xff, 0x80, 0x00, 0x07, 0xff, 0x00, 0x00, 0x0f, 0xfe, 0x00, 0x00, 0x1f, 0xfc, 0x00, 0x00, 0x3f, 0xf8, 0x00, 0x00, 0x7f, 0x80, 0x00, 0x00, 0xff, 0x80, 0x00, 0x00, 0xff, 0x80, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, }; +const BITMAP bmp_btn_backspace = {16, 9, bmp_btn_backspace_data}; const BITMAP bmp_btn_cancel = {8, 8, bmp_btn_cancel_data}; const BITMAP bmp_btn_confirm = {8, 8, bmp_btn_confirm_data}; +const BITMAP bmp_btn_down = {16, 6, bmp_btn_down_data}; +const BITMAP bmp_btn_left = {8, 7, bmp_btn_left_data}; +const BITMAP bmp_btn_right = {8, 7, bmp_btn_right_data}; +const BITMAP bmp_btn_up = {16, 6, bmp_btn_up_data}; +const BITMAP bmp_btn_upleft = {8, 7, bmp_btn_upleft_data}; const BITMAP bmp_digit0 = {16, 16, bmp_digit0_data}; const BITMAP bmp_digit1 = {16, 16, bmp_digit1_data}; const BITMAP bmp_digit2 = {16, 16, bmp_digit2_data}; diff --git a/legacy/gen/bitmaps.h b/legacy/gen/bitmaps.h index 08809e118..c1810fbcb 100644 --- a/legacy/gen/bitmaps.h +++ b/legacy/gen/bitmaps.h @@ -8,8 +8,14 @@ typedef struct { const uint8_t *data; } BITMAP; +extern const BITMAP bmp_btn_backspace; extern const BITMAP bmp_btn_cancel; extern const BITMAP bmp_btn_confirm; +extern const BITMAP bmp_btn_down; +extern const BITMAP bmp_btn_left; +extern const BITMAP bmp_btn_right; +extern const BITMAP bmp_btn_up; +extern const BITMAP bmp_btn_upleft; extern const BITMAP bmp_digit0; extern const BITMAP bmp_digit1; extern const BITMAP bmp_digit2; diff --git a/legacy/gen/bitmaps/btn_backspace.png b/legacy/gen/bitmaps/btn_backspace.png new file mode 100644 index 000000000..d84ec1101 Binary files /dev/null and b/legacy/gen/bitmaps/btn_backspace.png differ diff --git a/legacy/gen/bitmaps/btn_down.png b/legacy/gen/bitmaps/btn_down.png new file mode 100644 index 000000000..16587b39b Binary files /dev/null and b/legacy/gen/bitmaps/btn_down.png differ diff --git a/legacy/gen/bitmaps/btn_left.png b/legacy/gen/bitmaps/btn_left.png new file mode 100644 index 000000000..f4a7dae12 Binary files /dev/null and b/legacy/gen/bitmaps/btn_left.png differ diff --git a/legacy/gen/bitmaps/btn_right.png b/legacy/gen/bitmaps/btn_right.png new file mode 100644 index 000000000..7429da4c3 Binary files /dev/null and b/legacy/gen/bitmaps/btn_right.png differ diff --git a/legacy/gen/bitmaps/btn_up.png b/legacy/gen/bitmaps/btn_up.png new file mode 100644 index 000000000..a74a3d938 Binary files /dev/null and b/legacy/gen/bitmaps/btn_up.png differ diff --git a/legacy/gen/bitmaps/btn_upleft.png b/legacy/gen/bitmaps/btn_upleft.png new file mode 100644 index 000000000..0b982a94e Binary files /dev/null and b/legacy/gen/bitmaps/btn_upleft.png differ