diff --git a/include/button_map.h b/include/button_map.h index 8d79d80..ddd3f13 100644 --- a/include/button_map.h +++ b/include/button_map.h @@ -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], diff --git a/include/input_device.h b/include/input_device.h index fe5c983..e89fed4 100644 --- a/include/input_device.h +++ b/include/input_device.h @@ -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 diff --git a/include/usb_hid.h b/include/usb_hid.h index 5fcf37f..6a496bb 100644 --- a/include/usb_hid.h +++ b/include/usb_hid.h @@ -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; @@ -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; diff --git a/source/button_map.c b/source/button_map.c index 73d2457..4a8588c 100644 --- a/source/button_map.c +++ b/source/button_map.c @@ -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; -} diff --git a/source/fake_wiimote.c b/source/fake_wiimote.c index 17175df..fd6baa5 100644 --- a/source/fake_wiimote.c +++ b/source/fake_wiimote.c @@ -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)) @@ -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; @@ -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); } } } diff --git a/source/usb_driver_ds3.c b/source/usb_driver_ds3.c index 6ed7c68..b11b8b1 100644 --- a/source/usb_driver_ds3.c +++ b/source/usb_driver_ds3.c @@ -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; @@ -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) @@ -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, @@ -341,45 +349,35 @@ 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, @@ -387,8 +385,8 @@ int ds3_driver_ops_usb_async_resp(usb_input_device_t *device) 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); @@ -396,6 +394,21 @@ int ds3_driver_ops_usb_async_resp(usb_input_device_t *device) &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); } @@ -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, }; diff --git a/source/usb_driver_ds4.c b/source/usb_driver_ds4.c index dfb08eb..e980c0f 100644 --- a/source/usb_driver_ds4.c +++ b/source/usb_driver_ds4.c @@ -118,6 +118,15 @@ enum ds4_analog_axis_e { }; struct ds4_private_data_t { + struct { + u32 buttons; + u8 analog_axis[DS4_ANALOG_AXIS__NUM]; + s16 acc_x, acc_y, acc_z; + struct { + u16 x, y; + } fingers[2]; + u8 num_fingers; + } input; u8 mapping; u8 leds; bool rumble_on; @@ -191,9 +200,11 @@ static const struct { static inline void ds4_get_buttons(const struct ds4_input_report *report, u32 *buttons) { + u32 mask = 0; + #define MAP(field, button) \ if (report->field) \ - *buttons |= BIT(button); + mask |= BIT(button); MAP(triangle, DS4_BUTTON_TRIANGLE) MAP(circle, DS4_BUTTON_CIRCLE) @@ -201,13 +212,13 @@ static inline void ds4_get_buttons(const struct ds4_input_report *report, u32 *b MAP(square, DS4_BUTTON_SQUARE) if (report->dpad == 0 || report->dpad == 1 || report->dpad == 7) - *buttons |= BIT(DS4_BUTTON_UP); + mask |= BIT(DS4_BUTTON_UP); else if (report->dpad == 3 || report->dpad == 4 || report->dpad == 5) - *buttons |= BIT(DS4_BUTTON_DOWN); + mask |= BIT(DS4_BUTTON_DOWN); if (report->dpad == 5 || report->dpad == 6 || report->dpad == 7) - *buttons |= BIT(DS4_BUTTON_LEFT); + mask |= BIT(DS4_BUTTON_LEFT); else if (report->dpad == 1 || report->dpad == 2 || report->dpad == 3) - *buttons |= BIT(DS4_BUTTON_RIGHT); + mask |= BIT(DS4_BUTTON_RIGHT); MAP(r3, DS4_BUTTON_R3) MAP(l3, DS4_BUTTON_L3) @@ -219,8 +230,9 @@ static inline void ds4_get_buttons(const struct ds4_input_report *report, u32 *b MAP(l1, DS4_BUTTON_L1) MAP(tpad, DS4_BUTTON_TOUCHPAD) MAP(ps, DS4_BUTTON_PS) - #undef MAP + + *buttons = mask; } static inline void ds4_get_analog_axis(const struct ds4_input_report *report, @@ -330,81 +342,86 @@ int ds4_driver_ops_set_rumble(usb_input_device_t *device, bool rumble_on) return ds4_driver_update_leds_rumble(device); } -int ds4_driver_ops_usb_async_resp(usb_input_device_t *device) +bool ds4_report_input(usb_input_device_t *device) { struct ds4_private_data_t *priv = (void *)device->private_data; - struct ds4_input_report *report = (void *)device->usb_async_resp; - u32 ds4_buttons = 0; - u8 ds4_analog_axis[DS4_ANALOG_AXIS__NUM]; - s32 ds4_acc_x, ds4_acc_y, ds4_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; - int num_fingers = 0; - u16 finger_x[2], finger_y[2]; struct ir_dot_t ir_dots[IR_MAX_DOTS]; - if (report->report_id == 0x01) { - ds4_get_buttons(report, &ds4_buttons); - ds4_get_analog_axis(report, ds4_analog_axis); + 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; + } - if (bm_check_switch_mapping(&ds4_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); - } + bm_map_wiimote(DS4_BUTTON__NUM, priv->input.buttons, + input_mappings[priv->mapping].wiimote_button_map, + &wiimote_buttons); + + /* Normalize to accelerometer calibration configuration */ + acc_x = ACCEL_ZERO_G - ((s32)priv->input.acc_x * (ACCEL_ONE_G - ACCEL_ZERO_G)) / DS4_ACC_RES_PER_G; + acc_y = ACCEL_ZERO_G + ((s32)priv->input.acc_z * (ACCEL_ONE_G - ACCEL_ZERO_G)) / DS4_ACC_RES_PER_G; + acc_z = ACCEL_ZERO_G + ((s32)priv->input.acc_y * (ACCEL_ONE_G - ACCEL_ZERO_G)) / DS4_ACC_RES_PER_G; + + fake_wiimote_report_accelerometer(device->wiimote, acc_x, acc_y, acc_z); + + bm_calculate_ir(priv->input.num_fingers, &priv->input.fingers[0].x, &priv->input.fingers[0].y, + DS4_TOUCHPAD_W - 1, DS4_TOUCHPAD_H - 1, + ir_dots); + + fake_wiimote_report_ir_dots(device->wiimote, ir_dots); + + 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(DS4_BUTTON__NUM, priv->input.buttons, + DS4_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(DS4_BUTTON__NUM, priv->input.buttons, + DS4_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; +} - bm_map_wiimote(DS4_BUTTON__NUM, ds4_buttons, - input_mappings[priv->mapping].wiimote_button_map, - &wiimote_buttons); +int ds4_driver_ops_usb_async_resp(usb_input_device_t *device) +{ + struct ds4_private_data_t *priv = (void *)device->private_data; + struct ds4_input_report *report = (void *)device->usb_async_resp; - ds4_acc_x = (s32)(s16)le16toh(report->accel_x); - ds4_acc_y = (s32)(s16)le16toh(report->accel_y); - ds4_acc_z = (s32)(s16)le16toh(report->accel_z); + if (report->report_id == 0x01) { + ds4_get_buttons(report, &priv->input.buttons); + ds4_get_analog_axis(report, priv->input.analog_axis); - /* Normalize to accelerometer calibration configuration */ - acc_x = ACCEL_ZERO_G - (ds4_acc_x * (ACCEL_ONE_G - ACCEL_ZERO_G)) / DS4_ACC_RES_PER_G; - acc_y = ACCEL_ZERO_G + (ds4_acc_z * (ACCEL_ONE_G - ACCEL_ZERO_G)) / DS4_ACC_RES_PER_G; - acc_z = ACCEL_ZERO_G + (ds4_acc_y * (ACCEL_ONE_G - ACCEL_ZERO_G)) / DS4_ACC_RES_PER_G; + priv->input.acc_x = (s16)le16toh(report->accel_x); + priv->input.acc_y = (s16)le16toh(report->accel_y); + priv->input.acc_z = (s16)le16toh(report->accel_z); - fake_wiimote_report_accelerometer(device->wiimote, acc_x, acc_y, acc_z); + priv->input.num_fingers = 0; if (!report->finger1_nactive) { - finger_x[0] = report->finger1_x_lo | ((u16)report->finger1_x_hi << 8); - finger_y[0] = report->finger1_y_lo | ((u16)report->finger1_y_hi << 4); - num_fingers++; + priv->input.fingers[0].x = report->finger1_x_lo | ((u16)report->finger1_x_hi << 8); + priv->input.fingers[0].y = report->finger1_y_lo | ((u16)report->finger1_y_hi << 4); + priv->input.num_fingers++; } if (!report->finger2_nactive) { - finger_x[1] = report->finger2_x_lo | ((u16)report->finger2_x_hi << 8); - finger_y[1] = report->finger2_y_lo | ((u16)report->finger2_y_hi << 4); - num_fingers++; - } - - bm_calculate_ir(num_fingers, finger_x, finger_y, - DS4_TOUCHPAD_W - 1, DS4_TOUCHPAD_H - 1, - ir_dots); - - fake_wiimote_report_ir_dots(device->wiimote, ir_dots); - - 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(DS4_BUTTON__NUM, ds4_buttons, - DS4_ANALOG_AXIS__NUM, ds4_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(DS4_BUTTON__NUM, ds4_buttons, - DS4_ANALOG_AXIS__NUM, ds4_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)); + priv->input.fingers[1].x = report->finger2_x_lo | ((u16)report->finger2_x_hi << 8); + priv->input.fingers[1].y = report->finger2_y_lo | ((u16)report->finger2_y_hi << 4); + priv->input.num_fingers++; } } @@ -417,5 +434,6 @@ const usb_device_driver_t ds4_usb_device_driver = { .disconnect = ds4_driver_ops_disconnect, .slot_changed = ds4_driver_ops_slot_changed, .set_rumble = ds4_driver_ops_set_rumble, + .report_input = ds4_report_input, .usb_async_resp = ds4_driver_ops_usb_async_resp, }; diff --git a/source/usb_hid.c b/source/usb_hid.c index f04da03..9f55675 100644 --- a/source/usb_hid.c +++ b/source/usb_hid.c @@ -325,11 +325,21 @@ static int usb_device_ops_set_rumble(void *usrdata, bool rumble_on) return 0; } +static bool usb_device_ops_report_input(void *usrdata) +{ + usb_input_device_t *device = usrdata; + + DEBUG("usb_device_ops_report_input\n"); + + return device->driver->report_input(device); +} + static const input_device_ops_t input_device_usb_ops = { - .init = usb_device_ops_init, - .disconnect = usb_device_ops_disconnect, - .set_leds = usb_device_ops_set_leds, - .set_rumble = usb_device_ops_set_rumble + .init = usb_device_ops_init, + .disconnect = usb_device_ops_disconnect, + .set_leds = usb_device_ops_set_leds, + .set_rumble = usb_device_ops_set_rumble, + .report_input = usb_device_ops_report_input, }; static void handle_device_change_reply(int host_fd, areply *reply)