Skip to content

Commit

Permalink
Split controller polling and input reporting (fixed 200Hz reporting)
Browse files Browse the repository at this point in the history
Now input reporting runs at fixed 200Hz (Wiimote report rate), instead
of being driven by USB controller's report rate.
  • Loading branch information
xerpi committed Oct 28, 2021
1 parent c76617b commit dce4ca9
Show file tree
Hide file tree
Showing 8 changed files with 165 additions and 125 deletions.
12 changes: 11 additions & 1 deletion include/button_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,17 @@ void bm_calculate_ir(
/* Outputs */
struct ir_dot_t ir_dots[static IR_MAX_DOTS]);

bool bm_check_switch_mapping(u32 *buttons, bool *switch_mapping, u32 switch_mapping_combo);
static inline bool bm_check_switch_mapping(u32 buttons, bool *switch_mapping, u32 switch_mapping_combo)
{
bool switch_pressed = (buttons & switch_mapping_combo) == switch_mapping_combo;
bool ret = false;

if (switch_pressed && !*switch_mapping)
ret = true;

*switch_mapping = switch_pressed;
return ret;
}

static inline void bm_nunchuk_format(struct wiimote_extension_data_format_nunchuk_t *out,
u8 buttons, u8 analog_axis[static BM_NUNCHUK_ANALOG_AXIS__NUM],
Expand Down
1 change: 1 addition & 0 deletions include/input_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ typedef struct input_device_ops_t {
int (*disconnect)(void *usrdata);
int (*set_leds)(void *usrdata, int leds);
int (*set_rumble)(void *usrdata, bool rumble_on);
bool (*report_input)(void *usrdata);
} input_device_ops_t;

#endif
3 changes: 2 additions & 1 deletion include/usb_hid.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#include "types.h"
#include "fake_wiimote_mgr.h"

#define USB_INPUT_DEVICE_PRIVATE_DATA_SIZE 8
#define USB_INPUT_DEVICE_PRIVATE_DATA_SIZE 32

typedef struct usb_device_driver_t usb_device_driver_t;

Expand Down Expand Up @@ -35,6 +35,7 @@ typedef struct usb_device_driver_t {
int (*disconnect)(usb_input_device_t *device);
int (*slot_changed)(usb_input_device_t *device, u8 slot);
int (*set_rumble)(usb_input_device_t *device, bool rumble_on);
bool (*report_input)(usb_input_device_t *device);
int (*usb_async_resp)(usb_input_device_t *device);
} usb_device_driver_t;

Expand Down
15 changes: 0 additions & 15 deletions source/button_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,18 +98,3 @@ void bm_calculate_ir(
ir_dots[1].x = (IR_HIGH_X - dot.x) + IR_HORIZONTAL_OFFSET;
ir_dots[1].y = dot.y + vert_offset;
}

bool bm_check_switch_mapping(u32 *buttons, bool *switch_mapping, u32 switch_mapping_combo)
{
bool switch_pressed = (*buttons & switch_mapping_combo) == switch_mapping_combo;
bool ret = false;

if (switch_pressed && !*switch_mapping) {
/* Remove the mapping switch combo from the pressed buttons */
*buttons &= ~switch_mapping_combo;
ret = true;
}

*switch_mapping = switch_pressed;
return ret;
}
31 changes: 16 additions & 15 deletions source/fake_wiimote.c
Original file line number Diff line number Diff line change
Expand Up @@ -430,20 +430,6 @@ void fake_wiimote_report_input_ext(fake_wiimote_t *wiimote, u16 buttons, const v
}
}

static void check_send_config_for_new_channel(u16 hci_con_handle, l2cap_channel_info_t *info)
{
int ret;

if (l2cap_channel_is_accepted(info) &&
(info->state == L2CAP_CHANNEL_STATE_INACTIVE)) {
ret = inject_l2cap_config_req(hci_con_handle, info->remote_cid,
WII_REQUEST_MTU, L2CAP_FLUSH_TIMO_DEFAULT);
if (ret == IOS_OK) {
info->state = L2CAP_CHANNEL_STATE_CONFIG_PEND;
}
}
}

static inline bool ir_camera_read_data(fake_wiimote_t *wiimote, void *dst, u16 address, u16 size)
{
if (address + size > sizeof(wiimote->ir_regs))
Expand Down Expand Up @@ -684,6 +670,20 @@ static inline void fake_wiimote_update_rumble(fake_wiimote_t *wiimote, bool rumb
}
}

static void check_send_config_for_new_channel(u16 hci_con_handle, l2cap_channel_info_t *info)
{
int ret;

if (l2cap_channel_is_accepted(info) &&
(info->state == L2CAP_CHANNEL_STATE_INACTIVE)) {
ret = inject_l2cap_config_req(hci_con_handle, info->remote_cid,
WII_REQUEST_MTU, L2CAP_FLUSH_TIMO_DEFAULT);
if (ret == IOS_OK) {
info->state = L2CAP_CHANNEL_STATE_CONFIG_PEND;
}
}
}

void fake_wiimote_tick(fake_wiimote_t *wiimote)
{
int ret;
Expand Down Expand Up @@ -740,7 +740,8 @@ void fake_wiimote_tick(fake_wiimote_t *wiimote)
return;
}

fake_wiimote_send_data_report(wiimote);
if (wiimote->input_device_ops->report_input(wiimote->usrdata))
fake_wiimote_send_data_report(wiimote);
}
}
}
Expand Down
62 changes: 38 additions & 24 deletions source/usb_driver_ds3.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,11 @@ enum ds3_analog_axis_e {
};

struct ds3_private_data_t {
struct {
u32 buttons;
u8 analog_axis[DS3_ANALOG_AXIS__NUM];
s16 acc_x, acc_y, acc_z;
} input;
u8 mapping;
u8 leds;
bool rumble_on;
Expand Down Expand Up @@ -180,9 +185,11 @@ static const struct {

static inline void ds3_get_buttons(const struct ds3_input_report *report, u32 *buttons)
{
u32 mask = 0;

#define MAP(field, button) \
if (report->field) \
*buttons |= BIT(button);
mask |= BIT(button);

MAP(triangle, DS3_BUTTON_TRIANGLE)
MAP(circle, DS3_BUTTON_CIRCLE)
Expand All @@ -201,8 +208,9 @@ static inline void ds3_get_buttons(const struct ds3_input_report *report, u32 *b
MAP(r1, DS3_BUTTON_R1)
MAP(l1, DS3_BUTTON_L1)
MAP(ps, DS3_BUTTON_PS)

#undef MAP

*buttons = mask;
}

static inline void ds3_get_analog_axis(const struct ds3_input_report *report,
Expand Down Expand Up @@ -341,61 +349,66 @@ int ds3_driver_ops_set_rumble(usb_input_device_t *device, bool rumble_on)
return ds3_driver_update_leds_rumble(device);
}

int ds3_driver_ops_usb_async_resp(usb_input_device_t *device)
bool ds3_report_input(usb_input_device_t *device)
{
struct ds3_private_data_t *priv = (void *)device->private_data;
struct ds3_input_report *report = (void *)device->usb_async_resp;
u32 ds3_buttons = 0;
u8 ds3_analog_axis[DS3_ANALOG_AXIS__NUM];
s32 ds3_acc_x, ds3_acc_y, ds3_acc_z;
u16 acc_x, acc_y, acc_z;
u16 wiimote_buttons = 0;
u16 acc_x, acc_y, acc_z;
union wiimote_extension_data_t extension_data;

ds3_get_buttons(report, &ds3_buttons);
ds3_get_analog_axis(report, ds3_analog_axis);

if (bm_check_switch_mapping(&ds3_buttons, &priv->switch_mapping, SWITCH_MAPPING_COMBO)) {
if (bm_check_switch_mapping(priv->input.buttons, &priv->switch_mapping, SWITCH_MAPPING_COMBO)) {
priv->mapping = (priv->mapping + 1) % ARRAY_SIZE(input_mappings);
fake_wiimote_set_extension(device->wiimote, input_mappings[priv->mapping].extension);
return false;
}

bm_map_wiimote(DS3_BUTTON__NUM, ds3_buttons,
bm_map_wiimote(DS3_BUTTON__NUM, priv->input.buttons,
input_mappings[priv->mapping].wiimote_button_map,
&wiimote_buttons);

ds3_acc_x = (s32)report->acc_x - 511;
ds3_acc_y = 511 - (s32)report->acc_y;
ds3_acc_z = 511 - (s32)report->acc_z;

/* Normalize to accelerometer calibration configuration */
acc_x = ACCEL_ZERO_G - (ds3_acc_x * (ACCEL_ONE_G - ACCEL_ZERO_G)) / DS3_ACC_RES_PER_G;
acc_y = ACCEL_ZERO_G + (ds3_acc_y * (ACCEL_ONE_G - ACCEL_ZERO_G)) / DS3_ACC_RES_PER_G;
acc_z = ACCEL_ZERO_G + (ds3_acc_z * (ACCEL_ONE_G - ACCEL_ZERO_G)) / DS3_ACC_RES_PER_G;
acc_x = ACCEL_ZERO_G - ((s32)priv->input.acc_x * (ACCEL_ONE_G - ACCEL_ZERO_G)) / DS3_ACC_RES_PER_G;
acc_y = ACCEL_ZERO_G + ((s32)priv->input.acc_y * (ACCEL_ONE_G - ACCEL_ZERO_G)) / DS3_ACC_RES_PER_G;
acc_z = ACCEL_ZERO_G + ((s32)priv->input.acc_z * (ACCEL_ONE_G - ACCEL_ZERO_G)) / DS3_ACC_RES_PER_G;

fake_wiimote_report_accelerometer(device->wiimote, acc_x, acc_y, acc_z);

if (input_mappings[priv->mapping].extension == WIIMOTE_EXT_NONE) {
fake_wiimote_report_input(device->wiimote, wiimote_buttons);
} else if (input_mappings[priv->mapping].extension == WIIMOTE_EXT_NUNCHUK) {
bm_map_nunchuk(DS3_BUTTON__NUM, ds3_buttons,
DS3_ANALOG_AXIS__NUM, ds3_analog_axis,
bm_map_nunchuk(DS3_BUTTON__NUM, priv->input.buttons,
DS3_ANALOG_AXIS__NUM, priv->input.analog_axis,
0, 0, 0,
input_mappings[priv->mapping].nunchuk_button_map,
input_mappings[priv->mapping].nunchuk_analog_axis_map,
&extension_data.nunchuk);
fake_wiimote_report_input_ext(device->wiimote, wiimote_buttons,
&extension_data, sizeof(extension_data.nunchuk));
} else if (input_mappings[priv->mapping].extension == WIIMOTE_EXT_CLASSIC) {
bm_map_classic(DS3_BUTTON__NUM, ds3_buttons,
DS3_ANALOG_AXIS__NUM, ds3_analog_axis,
bm_map_classic(DS3_BUTTON__NUM, priv->input.buttons,
DS3_ANALOG_AXIS__NUM, priv->input.analog_axis,
input_mappings[priv->mapping].classic_button_map,
input_mappings[priv->mapping].classic_analog_axis_map,
&extension_data.classic);
fake_wiimote_report_input_ext(device->wiimote, wiimote_buttons,
&extension_data, sizeof(extension_data.classic));
}

return true;
}

int ds3_driver_ops_usb_async_resp(usb_input_device_t *device)
{
struct ds3_private_data_t *priv = (void *)device->private_data;
struct ds3_input_report *report = (void *)device->usb_async_resp;

ds3_get_buttons(report, &priv->input.buttons);
ds3_get_analog_axis(report, priv->input.analog_axis);

priv->input.acc_x = (s16)report->acc_x - 511;
priv->input.acc_y = 511 - (s16)report->acc_y;
priv->input.acc_z = 511 - (s16)report->acc_z;

return ds3_request_data(device);
}

Expand All @@ -405,5 +418,6 @@ const usb_device_driver_t ds3_usb_device_driver = {
.disconnect = ds3_driver_ops_disconnect,
.slot_changed = ds3_driver_ops_slot_changed,
.set_rumble = ds3_driver_ops_set_rumble,
.report_input = ds3_report_input,
.usb_async_resp = ds3_driver_ops_usb_async_resp,
};
Loading

0 comments on commit dce4ca9

Please sign in to comment.