Expand description
Applet-side of the applet API.
This api crate provides Rust bindings for the Wasm-side of the applet API.
Users should not directly use those bindings but instead use the prelude crate
that provides higher-level and more convenient access.
The bindings in this crate are automatically generated from a proc-macro based
on a procedural description of the applet API defined in the api-desc crate.
As such, they follow a precise convention:
- The module hierarchy in the applet API is mapped to the module hierarchy in this crate.
- Type definitions (like enums) are mapped to their definition. If an enum is
used as an error, it provides a
Error::to_result(isize) -> Result<usize, Error>method to convert signed integer results into RustResult. - Functions are mapped to their definition but also to a module of the same
name. This module defines 2 structs:
Paramsfor the parameters of the function andResultsfor the results of the function. If a struct is empty, then it is not used. - All parameters and results are 32-bits integers mapping to the
i32Wasm type, but their Rust type reflect their role. For example:usizefor unsigned integersisizefor signed integers (which may represent someResult<u31, u31>where the error type may be converted to some enum)*const u8and*mut u8for opaque/polymorphic pointers*const Tand*mut Tfor transparent pointers whereTis recursively definedextern "C" fn(data: *const u8, ...)for closures over some opaque data and possibly additional parameters
§WebAssembly-level documentation
§Applet functions
An applet must expose 3 functions to the platform:
init: () -> ()called exactly once before anything else. It cannot call any platform function exceptdp(akadebug::println()).main: () -> ()called exactly once afterinitreturns. It can call all platform functions.alloc: (size: u32, align: u32) -> (ptr: u32)may be called during any platform function afterinitreturned. It cannot call any platform function. A return value of zero indicates an error and will trap the applet. The applet may assume thatsizeis a non-zero multiple ofalignandalignis either 1, 2, or 4.
§Platform functions
The platform exposes many functions. Each function comes with its own documentation, which may omit the following general properties.
§Parameters and result
At WebAssembly level, all functions use u32 (more precisely i32) as
parameters and result (WebAssembly permits multiple results, but platform
functions never return more than one value). However, platform functions will be
documented with more specific types to better convey the intent.
Languages that compile to WebAssembly may use similar specific types when
binding platform functions. Those types should be compatible with u32 in
WebAssembly.
§Applet closures
Some functions (usually called register) may register a closure. There is
usually an associated function (usually called unregister) that unregisters
the registered closure. The register function takes fn { data: *const void, ... } (usually called handler_func) and a *const void (usually called
handler_data) as arguments. The unregister function (if it exists) doesn’t
have any particular parameters.
After the closure is registered (the register function is called) and as long as
it stays registered (the unregister function is not called), the platform may
call this closure any time sw (aka scheduling::wait_for_callback()) is
called. Note that if main returns and there are registered closures, the
applet behaves as if sw is called indefinitely.
An applet closure may call any platform function unless explicitly documented by the register function.
§Reading and writing memory
Some functions take pointers as argument (usually *const u8 or *mut u8).
They either document the expected size or take an associated length argument.
The platform may read and write (only for *mut T pointers) the designated
region of the WebAssembly memory during the function call. Otherwise (and by
default), platform functions don’t read or write the WebAssembly memory.
§Allocating memory
Finally, some functions take nested pointers as argument (usually *mut *mut u8). They either return a usize or take a *mut usize as argument.
Those functions may call alloc (at most once per such nested pointer argument)
with a dynamic size but fixed alignment (usually 1). If they do, they will store
the non-null result in the *mut *mut u8 argument. Regardless of whether they
allocate or not, they store the size in the *mut usize argument (if it exists)
or return it (otherwise).
Note that alloc will not be called with a size of zero. So if the size is zero
after the function returns, this signifies that alloc was not called (and the
*mut *mut u8 not written) and the output is empty (unless otherwise documented
like in the case of an absence of output, in which case the size may not be
written).
The caller is responsible for managing the allocation after the function returns
and the size is non-zero. To avoid memory leaks, the applet should initialize
the *mut usize argument (if it exists) to zero and consider having ownership
of the *mut *mut u8 pointee if the size is non-zero after the call.
Modules§
- button
- Button and touch operations.
- clock
- Clock operations.
- crypto
- Cryptographic operations.
- debug
- Debugging operations.
- fingerprint
- Fingerprint operations.
- gpio
- Low-level GPIO operations.
- led
- LED operations.
- platform
- Platform operations.
- rng
- Random number generators.
- scheduling
- store
- Persistent storage operations.
- timer
- Timer operations.
- uart
- usb
- USB operations.
- vendor
- Vendor interface.