summaryrefslogtreecommitdiffstats
path: root/quantum/pointing_device.c
diff options
context:
space:
mode:
Diffstat (limited to 'quantum/pointing_device.c')
-rw-r--r--quantum/pointing_device.c389
1 files changed, 356 insertions, 33 deletions
diff --git a/quantum/pointing_device.c b/quantum/pointing_device.c
index 2fefdb67b6..23d93fa15f 100644
--- a/quantum/pointing_device.c
+++ b/quantum/pointing_device.c
@@ -18,24 +18,105 @@
#include "pointing_device.h"
#include <string.h>
+#include "timer.h"
#ifdef MOUSEKEY_ENABLE
# include "mousekey.h"
#endif
#if (defined(POINTING_DEVICE_ROTATION_90) + defined(POINTING_DEVICE_ROTATION_180) + defined(POINTING_DEVICE_ROTATION_270)) > 1
# error More than one rotation selected. This is not supported.
#endif
+#if defined(SPLIT_POINTING_ENABLE)
+# include "transactions.h"
+# include "keyboard.h"
-static report_mouse_t mouseReport = {};
+report_mouse_t shared_mouse_report = {};
+uint16_t shared_cpi = 0;
+
+/**
+ * @brief Sets the shared mouse report used be pointing device task
+ *
+ * NOTE : Only available when using SPLIT_POINTING_ENABLE
+ *
+ * @param[in] new_mouse_report report_mouse_t
+ */
+void pointing_device_set_shared_report(report_mouse_t new_mouse_report) { shared_mouse_report = new_mouse_report; }
+
+/**
+ * @brief Gets current pointing device CPI if supported
+ *
+ * Gets current cpi of the shared report and returns it as uint16_t
+ *
+ * NOTE : Only available when using SPLIT_POINTING_ENABLE
+ *
+ * @return cpi value as uint16_t
+ */
+uint16_t pointing_device_get_shared_cpi(void) { return shared_cpi; }
+
+# if defined(POINTING_DEVICE_LEFT)
+# define POINTING_DEVICE_THIS_SIDE is_keyboard_left()
+# elif defined(POINTING_DEVICE_RIGHT)
+# define POINTING_DEVICE_THIS_SIDE !is_keyboard_left()
+# elif defined(POINTING_DEVICE_COMBINED)
+# define POINTING_DEVICE_THIS_SIDE true
+# endif
+
+#endif // defined(SPLIT_POINTING_ENABLE)
+
+static report_mouse_t local_mouse_report = {};
extern const pointing_device_driver_t pointing_device_driver;
+/**
+ * @brief Compares 2 mouse reports for difference and returns result
+ *
+ * @param[in] new report_mouse_t
+ * @param[in] old report_mouse_t
+ * @return bool result
+ */
__attribute__((weak)) bool has_mouse_report_changed(report_mouse_t new, report_mouse_t old) { return memcmp(&new, &old, sizeof(new)); }
-__attribute__((weak)) void pointing_device_init_kb(void) {}
-__attribute__((weak)) void pointing_device_init_user(void) {}
+/**
+ * @brief Keyboard level code pointing device initialisation
+ *
+ */
+__attribute__((weak)) void pointing_device_init_kb(void) {}
+
+/**
+ * @brief User level code pointing device initialisation
+ *
+ */
+__attribute__((weak)) void pointing_device_init_user(void) {}
+
+/**
+ * @brief Weak function allowing for keyboard level mouse report modification
+ *
+ * Takes report_mouse_t struct allowing modification at keyboard level then returns report_mouse_t.
+ *
+ * @param[in] mouse_report report_mouse_t
+ * @return report_mouse_t
+ */
__attribute__((weak)) report_mouse_t pointing_device_task_kb(report_mouse_t mouse_report) { return pointing_device_task_user(mouse_report); }
+
+/**
+ * @brief Weak function allowing for user level mouse report modification
+ *
+ * Takes report_mouse_t struct allowing modification at user level then returns report_mouse_t.
+ *
+ * @param[in] mouse_report report_mouse_t
+ * @return report_mouse_t
+ */
__attribute__((weak)) report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) { return mouse_report; }
+/**
+ * @brief Handles pointing device buttons
+ *
+ * Returns modified button bitmask using bool pressed and selected pointing_device_buttons_t button in uint8_t buttons bitmask.
+ *
+ * @param buttons[in] uint8_t bitmask
+ * @param pressed[in] bool
+ * @param button[in] pointing_device_buttons_t value
+ * @return Modified uint8_t bitmask buttons
+ */
__attribute__((weak)) uint8_t pointing_device_handle_buttons(uint8_t buttons, bool pressed, pointing_device_buttons_t button) {
if (pressed) {
buttons |= 1 << (button);
@@ -45,7 +126,17 @@ __attribute__((weak)) uint8_t pointing_device_handle_buttons(uint8_t buttons, bo
return buttons;
}
+/**
+ * @brief Initialises pointing device
+ *
+ * Initialises pointing device, perform driver init and optional keyboard/user level code.
+ */
__attribute__((weak)) void pointing_device_init(void) {
+#if defined(SPLIT_POINTING_ENABLE)
+ if (!(POINTING_DEVICE_THIS_SIDE)) {
+ return;
+ }
+#endif
pointing_device_driver.init();
#ifdef POINTING_DEVICE_MOTION_PIN
setPinInputHigh(POINTING_DEVICE_MOTION_PIN);
@@ -54,67 +145,299 @@ __attribute__((weak)) void pointing_device_init(void) {
pointing_device_init_user();
}
+/**
+ * @brief Sends processed mouse report to host
+ *
+ * This sends the mouse report generated by pointing_device_task if changed since the last report. Once send zeros mouse report except buttons.
+ *
+ */
__attribute__((weak)) void pointing_device_send(void) {
static report_mouse_t old_report = {};
// If you need to do other things, like debugging, this is the place to do it.
- if (has_mouse_report_changed(mouseReport, old_report)) {
- host_mouse_send(&mouseReport);
+ if (has_mouse_report_changed(local_mouse_report, old_report)) {
+ host_mouse_send(&local_mouse_report);
}
// send it and 0 it out except for buttons, so those stay until they are explicity over-ridden using update_pointing_device
- mouseReport.x = 0;
- mouseReport.y = 0;
- mouseReport.v = 0;
- mouseReport.h = 0;
+ local_mouse_report.x = 0;
+ local_mouse_report.y = 0;
+ local_mouse_report.v = 0;
+ local_mouse_report.h = 0;
- memcpy(&old_report, &mouseReport, sizeof(mouseReport));
+ memcpy(&old_report, &local_mouse_report, sizeof(local_mouse_report));
}
-__attribute__((weak)) void pointing_device_task(void) {
- // Gather report info
-#ifdef POINTING_DEVICE_MOTION_PIN
- if (!readPin(POINTING_DEVICE_MOTION_PIN))
-#endif
- mouseReport = pointing_device_driver.get_report(mouseReport);
-
- // Support rotation of the sensor data
+/**
+ * @brief Adjust mouse report by any optional common pointing configuration defines
+ *
+ * This applies rotation or inversion to the mouse report as selected by the pointing device common configuration defines.
+ *
+ * @param mouse_report[in] takes a report_mouse_t to be adjusted
+ * @return report_mouse_t with adjusted values
+ */
+report_mouse_t pointing_device_adjust_by_defines(report_mouse_t mouse_report) {
+ // Support rotation of the sensor data
#if defined(POINTING_DEVICE_ROTATION_90) || defined(POINTING_DEVICE_ROTATION_180) || defined(POINTING_DEVICE_ROTATION_270)
- int8_t x = mouseReport.x, y = mouseReport.y;
+ int8_t x = mouse_report.x, y = mouse_report.y;
# if defined(POINTING_DEVICE_ROTATION_90)
- mouseReport.x = y;
- mouseReport.y = -x;
+ mouse_report.x = y;
+ mouse_report.y = -x;
# elif defined(POINTING_DEVICE_ROTATION_180)
- mouseReport.x = -x;
- mouseReport.y = -y;
+ mouse_report.x = -x;
+ mouse_report.y = -y;
# elif defined(POINTING_DEVICE_ROTATION_270)
- mouseReport.x = -y;
- mouseReport.y = x;
+ mouse_report.x = -y;
+ mouse_report.y = x;
# else
# error "How the heck did you get here?!"
# endif
#endif
// Support Inverting the X and Y Axises
#if defined(POINTING_DEVICE_INVERT_X)
- mouseReport.x = -mouseReport.x;
+ mouse_report.x = -mouse_report.x;
#endif
#if defined(POINTING_DEVICE_INVERT_Y)
- mouseReport.y = -mouseReport.y;
+ mouse_report.y = -mouse_report.y;
+#endif
+ return mouse_report;
+}
+
+/**
+ * @brief Retrieves and processes pointing device data.
+ *
+ * This function is part of the keyboard loop and retrieves the mouse report from the pointing device driver.
+ * It applies any optional configuration e.g. rotation or axis inversion and then initiates a send.
+ *
+ */
+__attribute__((weak)) void pointing_device_task(void) {
+#if defined(SPLIT_POINTING_ENABLE)
+ // Don't poll the target side pointing device.
+ if (!is_keyboard_master()) {
+ return;
+ };
+#endif
+
+#if defined(POINTING_DEVICE_TASK_THROTTLE_MS)
+ static uint32_t last_exec = 0;
+ if (timer_elapsed32(last_exec) < POINTING_DEVICE_TASK_THROTTLE_MS) {
+ return;
+ }
+ last_exec = timer_read32();
+#else
+# if defined(SPLIT_POINTING_ENABLE)
+# pragma message("It's recommended you enable a throttle when sharing pointing devices.")
+# endif
+#endif
+
+ // Gather report info
+#ifdef POINTING_DEVICE_MOTION_PIN
+# if defined(SPLIT_POINTING_ENABLE)
+# error POINTING_DEVICE_MOTION_PIN not supported when sharing the pointing device report between sides.
+# endif
+ if (!readPin(POINTING_DEVICE_MOTION_PIN))
#endif
+#if defined(SPLIT_POINTING_ENABLE)
+# if defined(POINTING_DEVICE_COMBINED)
+ static uint8_t old_buttons = 0;
+ local_mouse_report.buttons = old_buttons;
+ local_mouse_report = pointing_device_driver.get_report(local_mouse_report);
+ old_buttons = local_mouse_report.buttons;
+# elif defined(POINTING_DEVICE_LEFT) || defined(POINTING_DEVICE_RIGHT)
+ local_mouse_report = POINTING_DEVICE_THIS_SIDE ? pointing_device_driver.get_report(local_mouse_report) : shared_mouse_report;
+# else
+# error "You need to define the side(s) the pointing device is on. POINTING_DEVICE_COMBINED / POINTING_DEVICE_LEFT / POINTING_DEVICE_RIGHT"
+# endif
+#else
+ local_mouse_report = pointing_device_driver.get_report(local_mouse_report);
+#endif // defined(SPLIT_POINTING_ENABLE)
+
// allow kb to intercept and modify report
- mouseReport = pointing_device_task_kb(mouseReport);
+#if defined(SPLIT_POINTING_ENABLE) && defined(POINTING_DEVICE_COMBINED)
+ if (is_keyboard_left()) {
+ local_mouse_report = pointing_device_adjust_by_defines(local_mouse_report);
+ shared_mouse_report = pointing_device_adjust_by_defines_right(shared_mouse_report);
+ } else {
+ local_mouse_report = pointing_device_adjust_by_defines_right(local_mouse_report);
+ shared_mouse_report = pointing_device_adjust_by_defines(shared_mouse_report);
+ }
+ local_mouse_report = is_keyboard_left() ? pointing_device_task_combined_kb(local_mouse_report, shared_mouse_report) : pointing_device_task_combined_kb(shared_mouse_report, local_mouse_report);
+#else
+ local_mouse_report = pointing_device_adjust_by_defines(local_mouse_report);
+ local_mouse_report = pointing_device_task_kb(local_mouse_report);
+#endif
// combine with mouse report to ensure that the combined is sent correctly
#ifdef MOUSEKEY_ENABLE
report_mouse_t mousekey_report = mousekey_get_report();
- mouseReport.buttons = mouseReport.buttons | mousekey_report.buttons;
+ local_mouse_report.buttons = local_mouse_report.buttons | mousekey_report.buttons;
#endif
pointing_device_send();
}
-report_mouse_t pointing_device_get_report(void) { return mouseReport; }
+/**
+ * @brief Gets current mouse report used by pointing device task
+ *
+ * @return report_mouse_t
+ */
+report_mouse_t pointing_device_get_report(void) { return local_mouse_report; }
+
+/**
+ * @brief Sets mouse report used be pointing device task
+ *
+ * @param[in] new_mouse_report
+ */
+void pointing_device_set_report(report_mouse_t new_mouse_report) { local_mouse_report = new_mouse_report; }
+
+/**
+ * @brief Gets current pointing device CPI if supported
+ *
+ * Gets current cpi from pointing device driver if supported and returns it as uint16_t
+ *
+ * @return cpi value as uint16_t
+ */
+uint16_t pointing_device_get_cpi(void) {
+#if defined(SPLIT_POINTING_ENABLE)
+ return POINTING_DEVICE_THIS_SIDE ? pointing_device_driver.get_cpi() : shared_cpi;
+#else
+ return pointing_device_driver.get_cpi();
+#endif
+}
-void pointing_device_set_report(report_mouse_t newMouseReport) { mouseReport = newMouseReport; }
+/**
+ * @brief Set pointing device CPI if supported
+ *
+ * Takes a uint16_t value to set pointing device cpi if supported by driver.
+ *
+ * @param[in] cpi uint16_t value.
+ */
+void pointing_device_set_cpi(uint16_t cpi) {
+#if defined(SPLIT_POINTING_ENABLE)
+ if (POINTING_DEVICE_THIS_SIDE) {
+ pointing_device_driver.set_cpi(cpi);
+ } else {
+ shared_cpi = cpi;
+ }
+#else
+ pointing_device_driver.set_cpi(cpi);
+#endif
+}
-uint16_t pointing_device_get_cpi(void) { return pointing_device_driver.get_cpi(); }
+#if defined(SPLIT_POINTING_ENABLE) && defined(POINTING_DEVICE_COMBINED)
+/**
+ * @brief Set pointing device CPI if supported
+ *
+ * Takes a bool and uint16_t and allows setting cpi for a single side when using 2 pointing devices with a split keyboard.
+ *
+ * NOTE: Only available when using SPLIT_POINTING_ENABLE and POINTING_DEVICE_COMBINED
+ *
+ * @param[in] left true = left, false = right.
+ * @param[in] cpi uint16_t value.
+ */
+void pointing_device_set_cpi_on_side(bool left, uint16_t cpi) {
+ bool local = (is_keyboard_left() & left) ? true : false;
+ if (local) {
+ pointing_device_driver.set_cpi(cpi);
+ } else {
+ shared_cpi = cpi;
+ }
+}
-void pointing_device_set_cpi(uint16_t cpi) { pointing_device_driver.set_cpi(cpi); }
+/**
+ * @brief clamps int16_t to int8_t
+ *
+ * @param[in] int16_t value
+ * @return int8_t clamped value
+ */
+static inline int8_t pointing_device_movement_clamp(int16_t value) {
+ if (value < INT8_MIN) {
+ return INT8_MIN;
+ } else if (value > INT8_MAX) {
+ return INT8_MAX;
+ } else {
+ return value;
+ }
+}
+
+/**
+ * @brief combines 2 mouse reports and returns 2
+ *
+ * Combines 2 report_mouse_t structs, clamping movement values to int8_t and ignores report_id then returns the resulting report_mouse_t struct.
+ *
+ * NOTE: Only available when using SPLIT_POINTING_ENABLE and POINTING_DEVICE_COMBINED
+ *
+ * @param[in] left_report left report_mouse_t
+ * @param[in] right_report right report_mouse_t
+ * @return combined report_mouse_t of left_report and right_report
+ */
+report_mouse_t pointing_device_combine_reports(report_mouse_t left_report, report_mouse_t right_report) {
+ left_report.x = pointing_device_movement_clamp((int16_t)left_report.x + right_report.x);
+ left_report.y = pointing_device_movement_clamp((int16_t)left_report.y + right_report.y);
+ left_report.h = pointing_device_movement_clamp((int16_t)left_report.h + right_report.h);
+ left_report.v = pointing_device_movement_clamp((int16_t)left_report.v + right_report.v);
+ left_report.buttons |= right_report.buttons;
+ return left_report;
+}
+
+/**
+ * @brief Adjust mouse report by any optional right pointing configuration defines
+ *
+ * This applies rotation or inversion to the mouse report as selected by the pointing device common configuration defines.
+ *
+ * NOTE: Only available when using SPLIT_POINTING_ENABLE and POINTING_DEVICE_COMBINED
+ *
+ * @param[in] mouse_report report_mouse_t to be adjusted
+ * @return report_mouse_t with adjusted values
+ */
+report_mouse_t pointing_device_adjust_by_defines_right(report_mouse_t mouse_report) {
+ // Support rotation of the sensor data
+# if defined(POINTING_DEVICE_ROTATION_90_RIGHT) || defined(POINTING_DEVICE_ROTATION_RIGHT) || defined(POINTING_DEVICE_ROTATION_RIGHT)
+ int8_t x = mouse_report.x, y = mouse_report.y;
+# if defined(POINTING_DEVICE_ROTATION_90_RIGHT)
+ mouse_report.x = y;
+ mouse_report.y = -x;
+# elif defined(POINTING_DEVICE_ROTATION_180_RIGHT)
+ mouse_report.x = -x;
+ mouse_report.y = -y;
+# elif defined(POINTING_DEVICE_ROTATION_270_RIGHT)
+ mouse_report.x = -y;
+ mouse_report.y = x;
+# else
+# error "How the heck did you get here?!"
+# endif
+# endif
+ // Support Inverting the X and Y Axises
+# if defined(POINTING_DEVICE_INVERT_X_RIGHT)
+ mouse_report.x = -mouse_report.x;
+# endif
+# if defined(POINTING_DEVICE_INVERT_Y_RIGHT)
+ mouse_report.y = -mouse_report.y;
+# endif
+ return mouse_report;
+}
+
+/**
+ * @brief Weak function allowing for keyboard level mouse report modification
+ *
+ * Takes 2 report_mouse_t structs allowing individual modification of sides at keyboard level then returns pointing_device_task_combined_user.
+ *
+ * NOTE: Only available when using SPLIT_POINTING_ENABLE and POINTING_DEVICE_COMBINED
+ *
+ * @param[in] left_report report_mouse_t
+ * @param[in] right_report report_mouse_t
+ * @return pointing_device_task_combined_user(left_report, right_report) by default
+ */
+__attribute__((weak)) report_mouse_t pointing_device_task_combined_kb(report_mouse_t left_report, report_mouse_t right_report) { return pointing_device_task_combined_user(left_report, right_report); }
+
+/**
+ * @brief Weak function allowing for user level mouse report modification
+ *
+ * Takes 2 report_mouse_t structs allowing individual modification of sides at user level then returns pointing_device_combine_reports.
+ *
+ * NOTE: Only available when using SPLIT_POINTING_ENABLE and POINTING_DEVICE_COMBINED
+ *
+ * @param[in] left_report report_mouse_t
+ * @param[in] right_report report_mouse_t
+ * @return pointing_device_combine_reports(left_report, right_report) by default
+ */
+__attribute__((weak)) report_mouse_t pointing_device_task_combined_user(report_mouse_t left_report, report_mouse_t right_report) { return pointing_device_combine_reports(left_report, right_report); }
+#endif