DocumentationDevice AppIntegration walkthroughsDesign guidelinesNano devicesLow-level display management

Low-level display management

Introduction

⚠️

This article only concerns about 1% of users who wish to get a deeper understanding and/or design more advanced flows. Feel free to skip it.

BAGLs and Ledger OS

The Ledger OS SDKs contain a toolkit for building GUIs called the BOLOS Application Graphics Library (BAGL). BAGL defines a few useful types, most notably bagl_element_t. This type defines a single display element, such as a rectangle or a line of text, etc. Therefore, a GUI consists of an entire array of such elements. As the device hardware, including the screen, is managed by the MCU, the BAGL elements need to be transported to the MCU over SEPROXYHAL in order to display them. This is done using a Display Status.

A Display Status may be used to send a single BAGL element to the MCU. However, due to the design of the E/Cs/S protocol, in order to send a sequence of BAGL elements, the application must:

  • asynchronously send Display Statuses and wait for Display Processed Events before sending the next one
  • handle the other Events that are received from the MCU in the mean time.

As this is something that must be done by every Ledger OS application, a set of utilities have been defined in the SDKs to facilitate this process. These utilities also simplify the process of handling user input events, such as button presses.

Asynchronous Display and Interaction Helpers

To facilitate the process of implementing an asynchronous display manager loop, a set of macros have been defined in the Ledger OS SDKs. All these macros have the prefix UX_, and use a global variable of type ux_state_t called ux to maintain the user interface state.

  • UX_INIT(...) must be called when initializing the application, prior to sending the first Display Status.

  • UX_DISPLAY(...) takes an array of BAGL elements to be displayed and renders them, asynchronously. It is called when a new screen is displayed over the current one. This macro only sends the first element of the given array using a Display Status. Therefore, further Commands and Statuses are prohibited until the Display Processed Event is sent by the MCU.

  • UX_REDISPLAY() restarts the process of drawing the current screen. It behaves like UX_DISPLAY(...), but takes no arguments.

  • UX_DISPLAYED() returns 0 when the array requested to be displayed by UX_DISPLAY(...) or UX_REDISPLAY() has not been displayed entirely, and it returns a non-zero value when the array has been displayed entirely.

  • UX_DISPLAYED_EVENT(...) is called to handle Display Processed Events (generally in the io_event(...) function). It displays the next element in the array given as a parameter to UX_DISPLAY(...). This macro sends a Display Status if an element in the given array remains to be displayed. Therefore, further Commands and Statuses are prohibited until the Display Processed Event is sent by the MCU.

  • UX_BUTTON_PUSH_EVENT(...) facilitates handling Button Push Events, by setting the button released flag and calling the button handler implicitly passed to UX_DISPLAY(...).

See the sample apps for examples of how to use these macros.

đź’ˇ

After a Display Status has been sent, the application must wait, asynchronously, for the Display Processed Event before being able to continue to display more elements of the GUI.

Ledger OS UX

The Ledger OS UX is the implementation of the device-wide user interface; it is a component of the dashboard application. Applications delegate certain jobs to the BOLOS UX in order to retain consistency across all apps for certain UI components, as well as to allow the operating system to override the application’s UI when necessary (for example, when locking the screen). The application interfaces with the Ledger OS UX using os_ux(...), which is a system call. However, applications don’t need to call this function as it is automatically called by the display interaction helpers (the UX_ macros).

Applications should delegate Events like Button Push Events to the Ledger OS UX (in this case, using UX_BUTTON_PUSH_EVENT(...)) instead of handling them directly, in case the Ledger OS UX needs to override the application’s UI. If the event is consumed by the Ledger OS UX (for example, a pressed button while the user is unlocking the screen) then the event is not passed on to the application.

Ledger
Copyright © Ledger SAS. All rights reserved. Ledger, Ledger Nano S, Ledger Vault, Ledger OS are registered trademarks of Ledger SAS