gint/include/gint/usb-ff-bulk.h

168 lines
6.3 KiB
C

//---
// gint:usb-ff-bulk - A trivial bulk-based transfer class
//---
#ifndef GINT_USB_FF_BULK
#define GINT_USB_FF_BULK
#include <gint/usb.h>
/* The bulk transfer interface with class code 0xff provides a very simple
communication channel between the calculator and a host. There is
(currently) a single IN pipe that sends data from the calculator to the
host, at high-speed (USB 2.0).
The class code of this interface is 0xff, which means that the protocol is
custom and requires a custom program on the host to receive the data (unlike
for instance LINK on a Graph 90+E which behaves as a USB stick and can be
used with the file browser). fxlink can be used to the effect. */
extern usb_interface_t const usb_ff_bulk;
//---
// Direct bulk access
//
// The following functions can be used to access the bulk pipes directly. They
// provide the pipe numbers, which can be passed for instance to usb_write
// functions.
//---
/* usb_ff_bulk_output(): Pipe for calculator -> host communication */
int usb_ff_bulk_output(void);
//---
// fxlink protocol
//
// fxlink is a bulk-based communication tool in the fxSDK that can be used to
// conveniently transfer or manipulate information during the execution of an
// add-in. For instance, screenshots can be saved, files can be transferred,
// and text can be logged.
//
// Each communication with fxlink is a message that consists of:
// * A first write with a message header;
// * One or more writes with message data (of a size announced in the header);
// * A commit on the USB pipe (to ensure that everything is sent).
//
// There are two ways to use the fxlink protocol in this header; you can either
// use one of the convenience functions like usb_fxlink_screenshot() that do
// all the steps for you, or you can perform the writes and commits yourself to
// send custom messages.
//---
/* usb_fxlink_header_t: Message header for fxlink
fxlink supports a minimalistic protocol to receive data sent from the
calculator and automatically process it (such as save it to file, convert
to an image, etc). It is designed as a convenience feature, and it can be
extended with custom types rather easily.
A message is categorized with an (application, type) pair; both are UTF-8
strings of up to 16 characters. The application name "fxlink" is reserved
for built-in types supported by fxlink; any other custom application name
can be set (in which case fxlink will call a user-provided program to handle
the message).
The size of the data to be transferred must be specified in order of the
transfer to proceed correctly, as it cannot reliably be guessed on the other
side (and guessing wrong means all further messages will be in trouble).
As with the rest of the USB protocol, all the multi-byte integer fields in
this header are encoded as *little-endian*. */
typedef struct
{
/* 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, UTF-8 (might not be zero-terminated) */
char application[16];
/* Message type */
char type[16];
} usb_fxlink_header_t;
/* usb_fxlink_fill_header(): Fill an fxlink message header
This function will fill the specified fxlink header. You need to specify the
exact amount of data that the fxlink message will contain; if you cannot
determine it, consider splitting the message into several messages each with
their own header, and use the application-specific script on the host to
recombine them.
Returns false if the parameters are invalid or don't fit, in this case the
contents of the header are unchanged. */
bool usb_fxlink_fill_header(usb_fxlink_header_t *header, char *application,
char *type, uint32_t data_size);
//---
// Short functions for fxlink built-in types
//---
/* Subheader for the fxlink built-in "image" type */
typedef struct
{
uint32_t width;
uint32_t height;
/* Pixel format, see below */
int pixel_format;
} usb_fxlink_image_t;
/* Pixel formats */
typedef 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,
} usb_fxlink_image_format_t;
/* usb_fxlink_screenshot(): Take a screenshot
This function takes a screenshot. If (onscreen = false), it sends the
contents of the VRAM. This mode is best used just before dupdate(), since
the VRAM contents are exactly as they will appear on screen a moment later.
However, this is somewhat unintuitive for interactive GUI as the user has to
press a button after the option is present on-screen, therefore the contents
of the *next* frame are captured.
If (onscreen = true), this function tries to send the pixels that are
currently visible on-screen, with the following heuristic:
* If there is only one VRAM, the VRAM contents are used in the hope they
haven't changed since the last frame was presented with dupdate().
* If there are two VRAMs (on fx-CG 50 or using the gray engine) the contents
of the VRAM not currently being draw to are sent.
This function does not read pixels directly from the display, as this is
usually slow and currently not even implemented. */
void usb_fxlink_screenshot(bool onscreen);
#ifdef FX9860G
/* usb_fxlink_screenshot_gray(): Take a gray screenshot on fx-9860G
This function is similar to usb_fxlink_screenshot(), but it takes a gray
screenshot. It depends on the gray engine so if you use your add-in will
automatically have the gray engine, that's why it's separate. */
void usb_fxlink_screenshot_gray(bool onscreen);
#endif
/* usb_fxlink_text(): Send raw text
This function sends a string with the "text" type, which fxlink prints on
the terminal. It will send a full fxlink message (with a commit), which is
inefficient if there is a lot of text to send. For better speed, send the
message manually by filling the header and doing the writes and commit
manually.
This function sends the text by blocks of 4 bytes or 2 bytes when alignment
and size allow, and 1 byte otherwise. If size is 0, strlen(text) is used. */
void usb_fxlink_text(char const *text, int size);
#endif /* GINT_USB_FF_BULK */