#ifndef RUMBLE_H_INCLUDED
#define RUMBLE_H_INCLUDED

#include <stdint.h>

#include "kernel.h"

// Output to a device, and rumble. See doc.Rumble.

#define RUMBLE_MAX_PACKET   64   // largest packet sent to a device

// Joystick_Cap_Rumble if the slot's driver can rumble and its transport exists.
uint32_t rumble_capabilities(uint32_t slot);

// Raw bytes to the slot's interrupt OUT endpoint; the stream is opened on
// first use.
_kernel_oserror *rumble_send(uint32_t slot, const uint8_t *buf, uint32_t len);

// A HID output report over the control pipe. A non-zero report_id is also
// sent as the first data byte, as a numbered report requires.
_kernel_oserror *rumble_send_report(uint32_t slot, uint8_t report_id, const uint8_t *buf, uint32_t len);

// Run the slot's motors: low and high are 0..65535 strengths for the
// low- and high-frequency motors, both zero stops. duration_ms is the run
// time, 0 meaning until the next call.
_kernel_oserror *rumble_set(uint32_t slot, uint32_t low, uint32_t high, uint32_t duration_ms);

// Per-family packet builders (joy_rumble_fn): send joy_data[slot].output's
// strengths in the family's format.
_kernel_oserror *rumble_xbox360(uint32_t slot);
_kernel_oserror *rumble_xbox360wireless(uint32_t slot);
_kernel_oserror *rumble_psx(uint32_t slot);
_kernel_oserror *rumble_ps3(uint32_t slot);
_kernel_oserror *rumble_ps4(uint32_t slot);

// Device removed: drop its stream and pending stop without talking to it.
void rumble_detach(uint32_t slot);

// Module dying: stop running motors and close the streams.
void rumble_shutdown(void);

// Stop-timer veneers (CMHG generic veneers). The OS_CallAfter handler runs
// where no USB write is possible, so it only schedules the callback.
_kernel_oserror *rumble_timer_handler(_kernel_swi_regs *r, void *pw);
_kernel_oserror *rumble_callback_handler(_kernel_swi_regs *r, void *pw);

#endif
