USB: FF-Bulk
This interface (class code 0xff/0x77) implements a simple bidirectional communication channel running the fxlink protocol. It basically talks to fxlink’s interactive mode on the host, and can broadly be used for 4 things:
-
Sending standard messages to fxlink (screenshots, logs…). Convenient functions are provided in this header to minimize the overhead. fxlink running in interactive mode (fxlink -t) will handle these messages in a suitable way automatically (eg. save screenshots as PNG).
-
Sending custom messages to fxlink (bench results, memory dumps, crash reports…). fxlink running in interactive mode will forward the data to appropriate user-provided external programs to handle the messages.
-
Applications based around on data streams coming from the host (screen projector, web browser…). This can be achieved by modifying fxlink or using it as a library.
-
Remote control from the fxlink interactive mode (fxlink -t). This is based on fxlink’s ‘command’ and ‘keyboard’ protocols. This module will automatically handle commands and respond to them as long as the message handling function is called regularly.
Functions
Section titled “Functions”usb_fxlink_text
Section titled “usb_fxlink_text”usb_fxlink_text(): Send raw text Send a string; fxlink will display it in the terminal. This can be used to back stdout/stderr. Sending lots of small messages can be slow; if that’s a problem, fill in message manually. If size is 0, uses strlen(text).
void usb_fxlink_text(char const *text, int size)usb_fxlink_screenshot
Section titled “usb_fxlink_screenshot”usb_fxlink_screenshot(): Take a screenshot
This function sends a copy of the VRAM to fxlink. This is best used just before dupdate() since this ensures the image sent by USB is identical to the one displayed on screen.
If onscreen is set and there are two VRAMs (on fx-CG or when using the
gray engine on fx-9860G), sends a copy of the other VRAM. This is a bit more
intuitive when taking a screenshot of the last shown image as a result of a
key press. Note that this function never reads pixels directly from the
display (it’s usually slow and currently not even implemented).
void usb_fxlink_screenshot(bool onscreen)usb_fxlink_videocapture
Section titled “usb_fxlink_videocapture”usb_fxlink_videocapture(): Send a frame for a video recording
This function is essentially the same as usb_fxlink_screenshot(). It sends a capture of the VRAM to fxlink but uses the “video” type, which fxlink displays in real-time or saves as a video file. The meaning of the onscreen setting is identical to usb_fxlink_screenshot().
This function can be called with onscreen=false as a dupdate() hook to automatically send new frames to fxlink.
void usb_fxlink_videocapture(bool onscreen)usb_fxlink_handle_messages
Section titled “usb_fxlink_handle_messages”usb_fxlink_handle_messages(): Process and return incoming messages
This function processes incoming messages. It handles some types of messages internally (eg. fxlink commands) and returns the others to the caller by loading the provided header structure and returning true.
When this function returns true, the caller should read the message contents on the interface’s input pipe. Usually every read will return just a portion of the message (eg. 2048 bytes) so the contents should be read with a loop.
As long as this function returns true it should be called againt to process any other messages. When there is no more messages to process, this function returns false. It is important to call this function regularly from the main thread when quick responses are expected.
bool usb_fxlink_handle_messages(struct usb_fxlink_header *header)usb_fxlink_drop_transaction
Section titled “usb_fxlink_drop_transaction”usb_fxlink_drop_transaction(): Drop incoming data until end of transaction
When a message arrives on the USB port incoming data must be processed in order for the pipe to accept any further data in the future. This function can be used in error situations to drop data until the end of the transaction (which is usually the end of the message, at least with the fxSDK’s implementation of fxlink).
void usb_fxlink_drop_transaction(void)usb_fxlink_set_notifier
Section titled “usb_fxlink_set_notifier”usb_fxlink_set_notifier(): Set up a notification for incoming messages
Registers the provided function to be called when data arrives on the fxlink input pipe. This signals that usb_fxlink_handle_messages() should be called later from the main thread. Pass NULL to disable the notification.
void usb_fxlink_set_notifier(void (*notifier_function)(void))usb_ff_bulk_output
Section titled “usb_ff_bulk_output”usb_ff_bulk_output(): Pipe number for calculator -> host communication
int usb_ff_bulk_output(void)usb_ff_bulk_input
Section titled “usb_ff_bulk_input”usb_ff_bulk_input(): Pipe number for host -> calculator communication
int usb_ff_bulk_input(void)usb_fxlink_fill_header
Section titled “usb_fxlink_fill_header”usb_fxlink_fill_header(): Fill an fxlink message header
Fills an fxlink header’s fields with the provided. You need to specify the exact amount of data that the fxlink message will contain. Returns false if parameters are invalid or don’t fit the fields.
bool usb_fxlink_fill_header(usb_fxlink_header_t *header, char const *application, char const *type, uint32_t data_size)usb_fxlink_header_t: Message header for fxlink
Messages are categorized with an (application, type) pair; both are UTF-8 strings of up to 16 bytes (NUL not required). The application name “fxlink” is reserved for built-in types of messages. Other names can be used freely, and fxlink’s interactive mode on the host side will forward messages to external programs based on the application name.
The size of the data to be transferred must be specified upfront, but this restriction might be lifted in the future. As with the rest of the USB protocol, all the integer are encoded as little-endian.
typedef struct usb_fxlink_header{ /* Protocol version = 0x00000100 */ uint32_t version; /* Size of the data to transfer (excluding this header) */ uint32_t size; /* Size of individual transfers (related to the size of the FIFO) */ uint32_t transfer_size; /* Application name and message type, UTF-8 (need not be zero-terminated) */ char application[16]; char type[16];}usb_fxlink_header_tSubheader for the fxlink built-in “image” type
typedef struct{ /* Image size; storage is row-major */ uint32_t width; uint32_t height; /* Pixel format, see below */ int pixel_format;}usb_fxlink_image_tData structures
Section titled “Data structures”struct usb_fxlink_headerPixel formats
enum{ /* Image is an array of *big-endian* uint16_t with RGB565 format */ USB_FXLINK_IMAGE_RGB565 = 0, /* Image is an array of bits in mono format */ USB_FXLINK_IMAGE_MONO, /* Image is two consecutive mono arrays, one for light, one for dark */ USB_FXLINK_IMAGE_GRAY,}