Skip to content

Commit

Permalink
Add useCase Keypad for Nano
Browse files Browse the repository at this point in the history
  • Loading branch information
cedelavergne-ledger committed Jan 15, 2025
1 parent 893e609 commit 254ee18
Show file tree
Hide file tree
Showing 5 changed files with 355 additions and 82 deletions.
8 changes: 8 additions & 0 deletions lib_nbgl/include/nbgl_layout.h
Original file line number Diff line number Diff line change
Expand Up @@ -757,6 +757,14 @@ int nbgl_layoutUpdateKeypad(nbgl_layout_t *layout,
bool enableBackspace);
int nbgl_layoutAddHiddenDigits(nbgl_layout_t *layout, uint8_t nbDigits);
int nbgl_layoutUpdateHiddenDigits(nbgl_layout_t *layout, uint8_t index, uint8_t nbActive);
int nbgl_layoutAddKeypadContent(nbgl_layout_t *layout,
bool hidden,
uint8_t nbDigits,
const char *text);
int nbgl_layoutUpdateKeypadContent(nbgl_layout_t *layout,
bool hidden,
uint8_t nbActiveDigits,
const char *text);
#endif // HAVE_SE_TOUCH
#endif // NBGL_KEYPAD

Expand Down
2 changes: 1 addition & 1 deletion lib_nbgl/include/nbgl_obj.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,11 @@ extern "C" {
#else
#define KEYPAD_KEY_HEIGHT 104
#endif
#define KEYPAD_MAX_DIGITS 12
#else // HAVE_SE_TOUCH
#define KEYPAD_WIDTH 114
#define KEYPAD_HEIGHT 18
#endif // HAVE_SE_TOUCH
#define KEYPAD_MAX_DIGITS 12

#ifdef HAVE_SE_TOUCH
// external margin in pixels
Expand Down
46 changes: 29 additions & 17 deletions lib_nbgl/include/nbgl_use_case.h
Original file line number Diff line number Diff line change
Expand Up @@ -431,30 +431,42 @@ DEPRECATED void nbgl_useCaseAddressConfirmationExt(const char
#define nbgl_useCaseAddressConfirmation(__address, __callback) \
nbgl_useCaseAddressConfirmationExt(__address, __callback, NULL)

#endif // HAVE_SE_TOUCH
#ifdef NBGL_KEYPAD
void nbgl_useCaseKeypadDigits(const char *title,
uint8_t minDigits,
uint8_t maxDigits,
uint8_t backToken,
bool shuffled,
#ifdef HAVE_PIEZO_SOUND
tune_index_e tuneId,
#endif
void nbgl_useCaseKeypadDigits(const char *title,
uint8_t minDigits,
uint8_t maxDigits,
uint8_t backToken,
bool shuffled,
tune_index_e tuneId,
nbgl_pinValidCallback_t validatePinCallback,
nbgl_layoutTouchCallback_t actionCallback);
void nbgl_useCaseKeypadPIN(const char *title,
uint8_t minDigits,
uint8_t maxDigits,
uint8_t backToken,
bool shuffled,
#ifdef HAVE_PIEZO_SOUND
tune_index_e tuneId,
#endif
void nbgl_useCaseKeypadPIN(const char *title,
uint8_t minDigits,
uint8_t maxDigits,
uint8_t backToken,
bool shuffled,
tune_index_e tuneId,
nbgl_pinValidCallback_t validatePinCallback,
nbgl_layoutTouchCallback_t actionCallback);
#endif // NBGL_KEYPAD

#else // HAVE_SE_TOUCH
#ifdef NBGL_KEYPAD
void nbgl_useCaseKeypadDigits(const char *title,
uint8_t minDigits,
uint8_t maxDigits,
bool shuffled,
nbgl_pinValidCallback_t validatePinCallback,
nbgl_callback_t backCallbackk);
void nbgl_useCaseKeypadPIN(const char *title,
uint8_t minDigits,
uint8_t maxDigits,
bool shuffled,
nbgl_pinValidCallback_t validatePinCallback,
nbgl_callback_t backCallback);
#endif // NBGL_KEYPAD
#endif // HAVE_SE_TOUCH

#ifdef __cplusplus
} /* extern "C" */
#endif
Expand Down
207 changes: 143 additions & 64 deletions lib_nbgl/src/nbgl_layout_keypad_nanos.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,109 +160,188 @@ int nbgl_layoutUpdateKeypad(nbgl_layout_t *layout,
* @return the index of digits set, to use in @ref nbgl_layoutUpdateHiddenDigits()
*/
int nbgl_layoutAddHiddenDigits(nbgl_layout_t *layout, uint8_t nbDigits)
{
return nbgl_layoutAddKeypadContent(layout, true, nbDigits, NULL);
}

/**
* @brief Updates an existing set of hidden digits, with the given configuration
*
* @param layout the current layout
* @param index index returned by @ref nbgl_layoutAddHiddenDigits()
* @param nbActive number of "active" digits (represented by discs instead of circles)
* @return >=0 if OK
*/
int nbgl_layoutUpdateHiddenDigits(nbgl_layout_t *layout, uint8_t index, uint8_t nbActive)
{
UNUSED(index);
if (nbgl_layoutUpdateKeypadContent(layout, true, nbActive, NULL) < 0) {
return -1;
}
return 0;
}

/**
* @brief Adds an area with a title and a placeholder for hidden digits on top of a keypad, to
* represent the entered digits as small discs.
*
* @note It must be the only object added in the layout, after the keypad itself
*
* @param layout the current layout
* @param hidden if set to true, digits appear as discs, otherwise as visible digits (given in text
* param)
* @param nbDigits number of digits to be displayed (only used if hidden is true)
* @param text only used if hidden is false
* @return the height of this area, if no error, < 0 otherwise
*/
int nbgl_layoutAddKeypadContent(nbgl_layout_t *layout,
bool hidden,
uint8_t nbDigits,
const char *text)
{
nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout;
nbgl_container_t *container;
nbgl_text_area_t *textArea;

LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddHiddenDigits():\n");
LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddKeypadContent():\n");
if (layout == NULL) {
return -1;
}

// create a container, invisible or bordered
container = (nbgl_container_t *) nbgl_objPoolGet(CONTAINER, layoutInt->layer);
container->nbChildren = nbDigits;
container->children = nbgl_containerPoolGet(container->nbChildren, layoutInt->layer);
// 1 pixel between each icon (knowing that the effective bullets are 8px large)
container->obj.area.width = nbDigits * C_pin_bullet_empty.width + (nbDigits - 1);
container->obj.area.height = C_pin_bullet_empty.height;
// distance from top to digits is fixed to 24 px
container->obj.alignmentMarginY = 24;
container->obj.alignTo = NULL;
container->obj.alignment = TOP_MIDDLE;

// set this new container as child of the main container
layoutAddObject(layoutInt, (nbgl_obj_t *) container);

// create children of the container, as images (empty circles)
nbgl_objPoolGetArray(IMAGE, nbDigits, layoutInt->layer, (nbgl_obj_t **) container->children);
for (int i = 0; i < nbDigits; i++) {
nbgl_image_t *image = (nbgl_image_t *) container->children[i];
image->buffer = &C_pin_bullet_empty;
image->foregroundColor = WHITE;
if (i > 0) {
image->obj.alignment = MID_RIGHT;
image->obj.alignTo = (nbgl_obj_t *) container->children[i - 1];
image->obj.alignmentMarginX = 1;
}
else {
image->obj.alignment = NO_ALIGNMENT;
if (hidden) {
// create a container, invisible
container = (nbgl_container_t *) nbgl_objPoolGet(CONTAINER, layoutInt->layer);
container->nbChildren = nbDigits;
container->children = nbgl_containerPoolGet(container->nbChildren, layoutInt->layer);
// 1 pixel between each icon (knowing that the effective bullets are 8px large)
container->obj.area.width = nbDigits * C_pin_bullet_empty.width + (nbDigits - 1);
container->obj.area.height = C_pin_bullet_empty.height;
// distance from top to digits is fixed to 24 px
container->obj.alignmentMarginY = 24;
container->obj.alignTo = NULL;
container->obj.alignment = TOP_MIDDLE;

// set this new container as child of the main container
layoutAddObject(layoutInt, (nbgl_obj_t *) container);

// create children of the container, as images (empty circles)
nbgl_objPoolGetArray(
IMAGE, nbDigits, layoutInt->layer, (nbgl_obj_t **) container->children);
for (int i = 0; i < nbDigits; i++) {
nbgl_image_t *image = (nbgl_image_t *) container->children[i];
image->buffer = &C_pin_bullet_empty;
image->foregroundColor = WHITE;
if (i > 0) {
image->obj.alignment = MID_RIGHT;
image->obj.alignTo = (nbgl_obj_t *) container->children[i - 1];
image->obj.alignmentMarginX = 1;
}
else {
image->obj.alignment = NO_ALIGNMENT;
}
}
}
// return index of container to be modified later on
return (layoutInt->nbChildren - 1);
else {
// create text area
textArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer);
textArea->textColor = WHITE;
textArea->text = text;
textArea->textAlignment = CENTER;
textArea->fontId = BAGL_FONT_OPEN_SANS_EXTRABOLD_11px_1bpp;
textArea->obj.area.width = AVAILABLE_WIDTH;
textArea->obj.area.height = nbgl_getFontLineHeight(textArea->fontId);
textArea->autoHideLongLine = true;
// distance from top to digits is fixed to 20 px
textArea->obj.alignmentMarginY = 20;
textArea->obj.alignTo = NULL;
textArea->obj.alignment = TOP_MIDDLE;
// set this new text area as child of the main container
layoutAddObject(layoutInt, (nbgl_obj_t *) textArea);
}

// return 0
return 0;
}

/**
* @brief Updates an existing set of hidden digits, with the given configuration
*
* @param layout the current layout
* @param index index returned by @ref nbgl_layoutAddHiddenDigits()
* @param nbActive number of "active" digits (represented by discs instead of circles)
* @param hidden if set to true, digits appear as discs, otherwise as visible digits (given in text
* param)
* @param nbActiveDigits number of "active" digits (represented by discs instead of circles) (only
* used if hidden is true)
* @param text only used if hidden is false
*
* @return >=0 if OK
*/
int nbgl_layoutUpdateHiddenDigits(nbgl_layout_t *layout, uint8_t index, uint8_t nbActive)
int nbgl_layoutUpdateKeypadContent(nbgl_layout_t *layout,
bool hidden,
uint8_t nbActiveDigits,
const char *text)
{
nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout;
nbgl_container_t *container;
nbgl_image_t *image;

LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutUpdateHiddenDigits(): nbActive = %d\n", nbActive);
LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutUpdateHiddenDigits(): nbActive = %d\n", nbActiveDigits);
if (layout == NULL) {
return -1;
}

// get container
container = (nbgl_container_t *) layoutInt->children[index];
// sanity check
if ((container == NULL) || (container->obj.type != CONTAINER)) {
return -1;
}
if (nbActive > container->nbChildren) {
return -1;
}
if (nbActive == 0) {
// deactivate the first digit
image = (nbgl_image_t *) container->children[0];
if ((image == NULL) || (image->obj.type != IMAGE)) {
if (hidden) {
// get container (3rd child of main container)
container = (nbgl_container_t *) layoutInt->children[2];
// sanity check
if ((container == NULL) || (container->obj.type != CONTAINER)) {
return -1;
}
image->buffer = &C_pin_bullet_empty;
}
else {
image = (nbgl_image_t *) container->children[nbActive - 1];
if ((image == NULL) || (image->obj.type != IMAGE)) {
if (nbActiveDigits > container->nbChildren) {
return -1;
}
// if the last "active" is already active, it means that we are decreasing the number of
// active otherwise we are increasing it
if (image->buffer == &C_pin_bullet_filled) {
// all digits are already active
if (nbActive == container->nbChildren) {
return 0;
if (nbActiveDigits == 0) {
// deactivate the first digit
image = (nbgl_image_t *) container->children[0];
if ((image == NULL) || (image->obj.type != IMAGE)) {
return -1;
}
// deactivate the next digit
image = (nbgl_image_t *) container->children[nbActive];
image->buffer = &C_pin_bullet_empty;
}
else {
image->buffer = &C_pin_bullet_filled;
image = (nbgl_image_t *) container->children[nbActiveDigits - 1];
if ((image == NULL) || (image->obj.type != IMAGE)) {
return -1;
}
// if the last "active" is already active, it means that we are decreasing the number of
// active otherwise we are increasing it
if (image->buffer == &C_pin_bullet_filled) {
// all digits are already active
if (nbActiveDigits == container->nbChildren) {
return 0;
}
// deactivate the next digit
image = (nbgl_image_t *) container->children[nbActiveDigits];
image->buffer = &C_pin_bullet_empty;
}
else {
image->buffer = &C_pin_bullet_filled;
}
}
}

nbgl_objDraw((nbgl_obj_t *) image);
nbgl_objDraw((nbgl_obj_t *) image);
}
else {
// update main text area (second child of the main container)
nbgl_text_area_t *textArea = (nbgl_text_area_t *) layoutInt->children[2];
if ((textArea == NULL) || (textArea->obj.type != TEXT_AREA)) {
return -1;
}
textArea->text = text;
nbgl_objDraw((nbgl_obj_t *) textArea);
}

return 0;
}

#endif // NBGL_KEYPAD
#endif // HAVE_SE_TOUCH
Loading

0 comments on commit 254ee18

Please sign in to comment.