libjoybus
Joybus implementation for 32-bit MCUs
Loading...
Searching...
No Matches
Targets

Interfaces for implementing Joybus targets and N64 accessories. More...

Topics

 GameCube Controller Target
 Joybus target implementation for standard GameCube controllers and WaveBird receivers.
 N64 Controller Target
 Joybus target implementation for standard N64 controllers.
 PixelFX Game ID Target
 Joybus target which listens for the PixelFX game ID command.

Data Structures

struct  joybus_target_api
 API for implementing a Joybus target. More...
struct  joybus_target
 Interface for a Joybus target, a device on the Joybus which responds to commands from a host. More...

Macros

#define JOYBUS_TARGET(target)
 Macro to cast a concrete Joybus target instance to a generic Joybus target instance.

Typedefs

typedef void(* joybus_target_response_cb) (const uint8_t *response, uint8_t len, void *user_data)
 Callback type for sending responses from target command handlers.

Functions

static int joybus_target_byte_received (struct joybus_target *target, const uint8_t *command, uint8_t byte_idx, joybus_target_response_cb send_response, void *user_data)
 Handle a received command byte for a single Joybus target.
static bool joybus_target_is_attached (struct joybus_target *target)
 Check if a target is currently attached to a bus.

Detailed Description

Interfaces for implementing Joybus targets and N64 accessories.

A Joybus target is a device on the bus that responds to commands from a host (the console), such as an N64 or GameCube controller.

Commands arrive one byte at a time. As each byte is received, libjoybus calls the joybus_target_api::byte_received handler with the bytes accumulated so far. The handler inspects them to decide how many more bytes the command needs, returning the count of bytes still expected.

To send a response, the handler must call the "response ready" callback with a pointer to the (long-lived) response data and its length.

Handlers should call the response callback as soon as the response is ready, even if they are still expecting more command bytes. For many commands, the response data is fully determined by the first few bytes of the command. This allows the backend to start transmitting the response immediately after the last byte is received.

Handlers run in interrupt context, on the response critical path. Mark them with JOYBUS_RAM_FUNC so a flash fetch cannot delay the reply.

To create your own target, define a struct whose first member is a joybus_target (so it can be cast through JOYBUS_TARGET), point its api at a joybus_target_api table, and attach it to a bus with joybus_attach_target().

A bus accepts more than one target. Each command is offered to the attached targets in attachment order, and the first one that accepts it handles that command to the end. This places the following contract on a target:

  • A target decides on the first byte of a command. Returning -JOYBUS_ERR_NOT_SUPPORTED from the handler for the first byte declines the command, and the byte is then offered to the next target. Any other return claims the command, and the target receives every later byte of it. A target cannot claim a command later.
  • Declining has no side effects. A declined first byte must store nothing and send nothing, since another target may go on to handle the command.
  • Once a command is claimed, -JOYBUS_ERR_NOT_SUPPORTED from a later byte is an error in a command the target owns, and the bus returns to idle.
  • On the first byte, "not my opcode" and "my opcode, refused" are the same return, so a target cannot distinguish them.

Macro Definition Documentation

◆ JOYBUS_TARGET

#define JOYBUS_TARGET ( target)
Value:
((struct joybus_target *)(target))
Interface for a Joybus target, a device on the Joybus which responds to commands from a host.
Definition target.h:92

Macro to cast a concrete Joybus target instance to a generic Joybus target instance.

Typedef Documentation

◆ joybus_target_response_cb

typedef void(* joybus_target_response_cb) (const uint8_t *response, uint8_t len, void *user_data)

Callback type for sending responses from target command handlers.

Parameters
responsethe response data to send
lenthe length of the response data
user_datauser data passed to the command handler

Function Documentation

◆ joybus_target_byte_received()

int joybus_target_byte_received ( struct joybus_target * target,
const uint8_t * command,
uint8_t byte_idx,
joybus_target_response_cb send_response,
void * user_data )
inlinestatic

Handle a received command byte for a single Joybus target.

Backends do not call this directly. They call joybus_byte_received(), which offers the command to each target attached to the bus.

Parameters
targetthe target to handle the command
commandthe command buffer
byte_idxthe index of the byte that was just received
send_responsea callback function to send the response
user_datauser data to pass to the response callback
Returns
positive number of bytes still expected, 0 if no more bytes expected, a negative joybus_error on failure

◆ joybus_target_is_attached()

bool joybus_target_is_attached ( struct joybus_target * target)
inlinestatic

Check if a target is currently attached to a bus.

Parameters
targetthe target to check
Returns
true if the target is attached, false otherwise