Skip to content

Commit

Permalink
Configurable emulated device type
Browse files Browse the repository at this point in the history
This commit makes it possible to configure the report descriptor HID
Remapper uses when talking to the host.

The descriptor can be selected from a list of presets (can't be edited
directly in raw form).

This makes it possible to emulate different device types in addition
to regular mouse and keyboard.

Currently the following options are available:

* Normal mouse and keyboard (same as previously).
* Mouse with absolute cursor positioning and keyboard.
* Switch-compatible gamepad.
* PS4-compatible arcade stick (also compatible with some PS5 games).

Emulated device type can change the Vendor ID/Product ID used
(currently Switch gamepad mode does this).

PS4 mode includes the ability to connect a licensed controller to HID
Remapper, which will be used for authenticanting to the console.
Otherwise it stops working after 8 minutes.

Bumps config version to 9.
  • Loading branch information
jfedor2 committed Sep 27, 2023
1 parent 7d521d9 commit 2dba6e7
Show file tree
Hide file tree
Showing 32 changed files with 2,562 additions and 394 deletions.
181 changes: 113 additions & 68 deletions config-tool-web/code.js

Large diffs are not rendered by default.

884 changes: 884 additions & 0 deletions config-tool-web/examples.js

Large diffs are not rendered by default.

52 changes: 49 additions & 3 deletions config-tool-web/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,30 @@ <h1 class="mt-sm-5 mt-3">HID Remapper Configuration</h1>
</select>
</div>
</div>

<div class="row mt-3">
<div class="col-4 text-end">
<label for="our_descriptor_number_dropdown" class="col-form-label">Emulated device type</label>
</div>
<div class="col-auto">
<select class="form-select" id="our_descriptor_number_dropdown">
<option value="0">Mouse and keyboard</option>
<option value="1">Absolute mouse and keyboard</option>
<option value="2">Switch gamepad</option>
<option value="3">PS4 arcade stick</option>
</select>
</div>
</div>
<div class="row mt-3">
<div class="col-4 text-end">
<label for="ignore_auth_dev_inputs_checkbox" class="col-form-label">Ignore auth device inputs</label>
</div>
<div class="col-auto">
<input type="checkbox" id="ignore_auth_dev_inputs_checkbox" class="form-check-input align-middle">
</div>
</div>
<div class="row mt-3">
<em>Changes to the emulated device type become active after disconnecting and reconnecting the device.</em>
</div>
</div>

<div class="tab-pane" id="nav-macros" role="tabpanel" tabindex="0">
Expand Down Expand Up @@ -333,11 +356,34 @@ <h2 class="accordion-header">
</div>
</template>

<div id="usage_modal" class="modal fade" tabindex="-1">
<div id="source_usage_modal" class="modal fade" tabindex="-1">
<div class="modal-dialog modal-lg modal-dialog-scrollable modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title usage_modal_title">Select input</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="col mouse_usages">
</div>
<div class="col keyboard_usages mt-3">
</div>
<div class="col media_usages mt-3">
</div>
<div class="col other_usages mt-3">
</div>
<div class="col extra_usages mt-3">
</div>
</div>
</div>
</div>
</div>

<div id="target_usage_modal" class="modal fade" tabindex="-1">
<div class="modal-dialog modal-lg modal-dialog-scrollable modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title usage_modal_title"></h5>
<h5 class="modal-title usage_modal_title">Select output</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
Expand Down
615 changes: 414 additions & 201 deletions config-tool-web/usages.js

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions config-tool/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
CONFIG_USAGE_PAGE = 0xFF00
CONFIG_USAGE = 0x0020

CONFIG_VERSION = 8
CONFIG_VERSION = 9
CONFIG_SIZE = 32
REPORT_ID_CONFIG = 100

Expand Down Expand Up @@ -49,6 +49,8 @@
TAP_FLAG = 1 << 1
HOLD_FLAG = 1 << 2

IGNORE_AUTH_DEV_INPUTS_FLAG = 1 << 4

NMACROS = 32
NEXPRESSIONS = 8
MACRO_ITEMS_IN_PACKET = 6
Expand Down Expand Up @@ -105,7 +107,7 @@ def add_crc(buf):
def get_device():
devices = [
d
for d in hid.enumerate(VENDOR_ID, PRODUCT_ID)
for d in hid.enumerate()
if d["usage_page"] == CONFIG_USAGE_PAGE and d["usage"] == CONFIG_USAGE
]
if len(devices) == 0:
Expand Down
5 changes: 4 additions & 1 deletion config-tool/get_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@
interval_override,
tap_hold_threshold,
gpio_debounce_time_ms,
our_descriptor_number,
*_,
crc,
) = struct.unpack("<BBBLLLLBLB4BL", data)
) = struct.unpack("<BBBLLLLBLBB3BL", data)
check_crc(data, crc)

config = {
Expand All @@ -35,6 +36,8 @@
"interval_override": interval_override,
"tap_hold_threshold": tap_hold_threshold,
"gpio_debounce_time_ms": gpio_debounce_time_ms,
"our_descriptor_number": our_descriptor_number,
"ignore_auth_dev_inputs": bool(flags & IGNORE_AUTH_DEV_INPUTS_FLAG),
"mappings": [],
"macros": [],
"expressions": [],
Expand Down
9 changes: 6 additions & 3 deletions config-tool/set_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@
config.get("unmapped_passthrough_layers", list(range(NLAYERS)))
)
interval_override = config.get("interval_override", 0)
our_descriptor_number = config.get("our_descriptor_number", 0)
ignore_auth_dev_inputs = config.get("ignore_auth_dev_inputs", False)

flags = unmapped_passthrough_layer_mask
flags = unmapped_passthrough_layer_mask | (IGNORE_AUTH_DEV_INPUTS_FLAG if ignore_auth_dev_inputs else 0)

data = struct.pack(
"<BBBBLBLB15B",
"<BBBBLBLBB14B",
REPORT_ID_CONFIG,
CONFIG_VERSION,
SET_CONFIG,
Expand All @@ -43,7 +45,8 @@
interval_override,
tap_hold_threshold,
gpio_debounce_time_ms,
*([0] * 15)
our_descriptor_number,
*([0] * 14)
)
device.send_feature_report(add_crc(data))

Expand Down
1 change: 1 addition & 0 deletions firmware-bluetooth/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@ target_sources(app PRIVATE
${REMAPPER_SRC}/our_descriptor.cc
${REMAPPER_SRC}/quirks.cc
${REMAPPER_SRC}/remapper.cc
${REMAPPER_SRC}/ps_auth.cc
)
25 changes: 21 additions & 4 deletions firmware-bluetooth/src/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -557,7 +557,11 @@ static int set_report_cb(const struct device* dev, struct usb_setup_packet* setu
LOG_HEXDUMP_DBG((*data), (uint32_t) *len, "");

if ((request_value[0] > 0) && (*len > 0)) {
handle_set_report(request_value[0], (*data) + 1, (*len) - 1);
if (dev == hid_dev0) {
handle_set_report0(request_value[0], (*data) + 1, (*len) - 1);
} else if (dev == hid_dev1) {
handle_set_report1(request_value[0], (*data) + 1, (*len) - 1);
}
} else {
LOG_ERR("no report ID?");
}
Expand All @@ -573,7 +577,11 @@ static int get_report_cb(const struct device* dev, struct usb_setup_packet* setu
LOG_INF("report_id=%d, %d, len=%d", request_value[0], request_value[1], *len);

*data[0] = request_value[0];
*len = handle_get_report(request_value[0], (*data) + 1, CONFIG_SIZE);
if (dev == hid_dev0) {
*len = handle_get_report0(request_value[0], (*data) + 1, CONFIG_SIZE);
} else if (dev == hid_dev1) {
*len = handle_get_report1(request_value[0], (*data) + 1, CONFIG_SIZE);
}
(*len)++;

return 0;
Expand Down Expand Up @@ -661,7 +669,7 @@ static void usb_init() {
return;
}

usb_hid_register_device(hid_dev0, our_report_descriptor, our_report_descriptor_length, &ops0);
usb_hid_register_device(hid_dev0, our_descriptor->descriptor, our_descriptor->descriptor_length, &ops0);
usb_hid_register_device(hid_dev1, config_report_descriptor, config_report_descriptor_length, &ops1);
CHK(usb_hid_init(hid_dev0));
CHK(usb_hid_init(hid_dev1));
Expand Down Expand Up @@ -764,17 +772,26 @@ void queue_out_report(uint16_t interface, uint8_t report_id, const uint8_t* buff
// TODO
}

void queue_set_feature_report(uint16_t interface, uint8_t report_id, const uint8_t* buffer, uint8_t len) {
// TODO
}

void queue_get_feature_report(uint16_t interface, uint8_t report_id, uint8_t len) {
// TODO
}

int main() {
LOG_INF("HID Remapper Bluetooth");

my_mutexes_init();
button_init();
leds_init();
usb_init();
bt_init();
CHK(settings_subsys_init());
CHK(settings_register(&our_settings_handlers));
settings_load();
our_descriptor = &our_descriptors[our_descriptor_number];
usb_init();
scan_init();
parse_our_descriptor();
set_mapping_from_config();
Expand Down
3 changes: 3 additions & 0 deletions firmware/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ add_executable(remapper
src/out_report.cc
src/tick.cc
src/activity_led.cc
src/ps_auth.cc
)

if(PICO_BOARD STREQUAL "pico")
Expand Down Expand Up @@ -87,6 +88,7 @@ add_executable(remapper_dual_a
src/pico_debug/flash.c
src/pico_debug/adi.c
dual_b_binary.c
src/ps_auth.cc
)
target_include_directories(remapper_dual_a PRIVATE
src
Expand Down Expand Up @@ -144,6 +146,7 @@ add_executable(remapper_serial
src/interval_override.cc
src/tick.cc
src/activity_led.cc
src/ps_auth.cc
)
target_include_directories(remapper_serial PRIVATE
src
Expand Down
Loading

0 comments on commit 2dba6e7

Please sign in to comment.