Skip to content

Commit

Permalink
DeskHop 0.63 (Bugfixes, small features)
Browse files Browse the repository at this point in the history
- add gaming mode (use left shift + right shift + G to toggle)
- rework HID queue, smoother operation of rotary dials (no packets lost)
- fix dragging across multiple screens on the same output
- improve read reliability for UI
- move default keyboard hotkey for output switching to LCtrl + Caps Lock
- change default X/Y speed to match 16:9 geometry
  • Loading branch information
Hrvoje Cavrak committed Aug 18, 2024
1 parent 1fd0049 commit a249aa5
Show file tree
Hide file tree
Showing 25 changed files with 438 additions and 292 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.6)

set(VERSION_MAJOR 00)
set(VERSION_MINOR 147)
set(VERSION_MINOR 156)

set(PICO_SDK_FETCH_FROM_GIT off)
set(PICO_BOARD=pico)
Expand Down
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ The actual switch happens at the very moment when one arrow stops moving and the

## Keyboard

Acting as a USB Host and querying your keyboard periodically, it looks for a preconfigured hotkey in the hid report (usually Caps Lock for me). When found, it will forward all subsequent characters to the other output.
Acting as a USB Host and querying your keyboard periodically, it looks for a preconfigured hotkey in the hid report (usually Ctrl + Caps Lock for me). When found, it will forward all subsequent characters to the other output.

To have a visual indication which output you are using at any given moment, you can repurpose keyboard LEDs and have them provide the necessary feedback.

Expand Down Expand Up @@ -101,6 +101,10 @@ This will make sure you won't accidentally leave your current screen. To turn of
You can lock both computers at once by using ```RIGHT CTRL + L```.
To make use of this feature, first set up the OS for each output in config (since the shortcuts are different).

### Gaming Mode

If you're gaming, there is a chance your game might not work properly with absolute mouse mode. To address that issue, a **gaming mode** is introduced, toggled by ```LEFT SHIFT + RIGHT SHIFT + G```. When in gaming mode, you are locked to the current screen and your mouse behaves like a standard relative mouse. This should also fix various virtual machine issues, currently unsupported operating systems etc.

### Screensaver

Supposedly built in to prevent computer from entering standby, but truth be told - it is just fun to watch. **Off by default**, will make your mouse pointer bounce around the screen like a Pong ball. When enabled, it activates after a period of inactivity defined in user config header and automatically switches off as soon as you send any output towards that screen.
Expand Down Expand Up @@ -216,7 +220,8 @@ _Usage_
- ```Right CTRL + Right ALT``` - Toggle slower mouse mode
- ```Right CTRL + K``` - Lock/Unlock mouse desktop switching
- ```Right CTRL + L``` - Lock both outputs at once (set output OS before, see shortcuts below)
- ```Caps Lock``` - Switch between outputs
- ```Left Shift + Right Shift + G``` - Toggle gaming mode (lock to screen, act as standard mouse)
- ```Left CTRL + Caps Lock``` - Switch between outputs

### Switch cursor height calibration

Expand Down
Binary file modified disk/disk.img
Binary file not shown.
30 changes: 25 additions & 5 deletions src/handlers.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ void switchlock_hotkey_handler(device_t *state, hid_keyboard_report_t *report) {
send_value(state->switch_lock, SWITCH_LOCK_MSG);
}

/* This key combo toggles gaming mode */
void toggle_relative_mode_handler(device_t *state, hid_keyboard_report_t *report) {
state->relative_mouse ^= 1;
send_value(state->relative_mouse, RELATIVE_MODE_MSG);
};

/* This key combo locks both outputs simultaneously */
void screenlock_hotkey_handler(device_t *state, hid_keyboard_report_t *report) {
hid_keyboard_report_t lock_report = {0}, release_keys = {0};
Expand Down Expand Up @@ -199,9 +205,9 @@ void handle_wipe_config_msg(uart_packet_t *packet, device_t *state) {
load_config(state);
}

/* Process consumer control message, TODO: use queue instead of sending directly */
/* Process consumer control message */
void handle_consumer_control_msg(uart_packet_t *packet, device_t *state) {
tud_hid_n_report(0, REPORT_ID_CONSUMER, &packet->data[0], CONSUMER_CONTROL_LENGTH);
queue_cc_packet(packet->data, state);
}

/* Process request to store config to flash */
Expand All @@ -219,6 +225,11 @@ void handle_proxy_msg(uart_packet_t *packet, device_t *state) {
queue_packet(&packet->data[1], (enum packet_type_e)packet->data[0], PACKET_DATA_LENGTH - 1);
}

/* Process request to reboot the board */
void handle_toggle_relative_msg(uart_packet_t *packet, device_t *state) {
state->relative_mouse = packet->data[0];
}

/* Process api communication messages */
void handle_api_msgs(uart_packet_t *packet, device_t *state) {
uint8_t value_idx = packet->data[0];
Expand All @@ -239,15 +250,24 @@ void handle_api_msgs(uart_packet_t *packet, device_t *state) {
memcpy(ptr, &packet->data[1], map->len);
}
else if (packet->type == GET_VAL_MSG) {
uart_packet_t response = {.type=GET_VAL_MSG, .data={0}};
memcpy(response.data, ptr, map->len);
queue_try_add(&state->cfg_queue_out, &response);
uart_packet_t response = {.type=GET_VAL_MSG, .data={[0] = value_idx}};
memcpy(&response.data[1], ptr, map->len);
queue_cfg_packet(&response, state);
}

/* With each GET/SET message, we reset the configuration mode timeout */
reset_config_timer(state);
}

/* Handle the "read all" message by calling our "read one" handler for each type */
void handle_api_read_all_msg(uart_packet_t *packet, device_t *state) {
uart_packet_t result = {.type=GET_VAL_MSG};

for (int i = 0; i < get_field_map_length(); i++) {
result.data[0] = get_field_map_index(i)->idx;
handle_api_msgs(&result, state);
}
}

/* Process request packet and create a response */
void handle_request_byte_msg(uart_packet_t *packet, device_t *state) {
Expand Down
35 changes: 32 additions & 3 deletions src/include/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,14 @@ enum packet_type_e {
FLASH_LED_MSG = 9,
WIPE_CONFIG_MSG = 10,
HEARTBEAT_MSG = 12,
RELATIVE_MODE_MSG = 13,
CONSUMER_CONTROL_MSG = 14,
SYSTEM_CONTROL_MSG = 15,
SAVE_CONFIG_MSG = 18,
REBOOT_MSG = 19,
GET_VAL_MSG = 20,
SET_VAL_MSG = 21,
GET_ALL_VALS_MSG = 22,
PROXY_PACKET_MSG = 23,
REQUEST_BYTE_MSG = 24,
RESPONSE_BYTE_MSG = 25,
Expand Down Expand Up @@ -166,7 +168,7 @@ typedef struct {
#define RAW_PACKET_LENGTH (START_LENGTH + PACKET_LENGTH)

#define UART_QUEUE_LENGTH 256
#define CFG_QUEUE_LENGTH 128
#define HID_QUEUE_LENGTH 128
#define KBD_QUEUE_LENGTH 128
#define MOUSE_QUEUE_LENGTH 512

Expand Down Expand Up @@ -345,6 +347,25 @@ typedef struct TU_ATTR_PACKED {
uint8_t mode;
} mouse_report_t;

/* Used to work around OS issues with absolute coordinates on
multiple desktops (Windows/MacOS) */
typedef struct {
uint8_t tip_pressure;
uint8_t buttons; // Buttons
uint16_t x; // X coordinate (0-32767)
uint16_t y; // Y coordinate (0-32767)
} touch_report_t;

/* This stores various packets other than kbd/mouse to go out
(configuration, consumer control, system...) */
typedef struct {
uint8_t instance;
uint8_t report_id;
uint8_t type;
uint8_t len;
uint8_t data[RAW_PACKET_LENGTH];
} hid_generic_pkt_t;

typedef enum { IDLE, READING_PACKET, PROCESSING_PACKET } receiver_state_t;

typedef struct {
Expand All @@ -370,7 +391,7 @@ typedef struct {
int16_t mouse_buttons; // Store and update the state of mouse buttons

config_t config; // Device configuration, loaded from flash or defaults used
queue_t cfg_queue_out; // Queue that stores outgoing vendor config messages
queue_t hid_queue_out; // Queue that stores outgoing hid messages
queue_t kbd_queue; // Queue that stores keyboard reports
queue_t mouse_queue; // Queue that stores mouse reports
queue_t uart_tx_queue; // Queue that stores outgoing packets
Expand Down Expand Up @@ -427,6 +448,8 @@ void process_consumer_report(uint8_t *, int, uint8_t, hid_interface_t *);
void process_system_report(uint8_t *, int, uint8_t, hid_interface_t *);
void release_all_keys(device_t *);
void queue_kbd_report(hid_keyboard_report_t *, device_t *);
void queue_cc_packet(uint8_t *, device_t *);
void queue_system_packet(uint8_t *, device_t *);
void send_key(hid_keyboard_report_t *, device_t *);
void send_consumer_control(uint8_t *, device_t *);
bool key_in_report(uint8_t, const hid_keyboard_report_t *);
Expand Down Expand Up @@ -474,7 +497,7 @@ void reboot(void);
/********* Tasks **********/
void process_uart_tx_task(device_t *);
void process_mouse_queue_task(device_t *);
void process_cfg_queue_task(device_t *);
void process_hid_queue_task(device_t *);
void process_kbd_queue_task(device_t *);
void usb_device_task(device_t *);
void kick_watchdog_task(device_t *);
Expand All @@ -495,7 +518,10 @@ void reset_config_timer(device_t *);

extern const field_map_t api_field_map[];
const field_map_t* get_field_map_entry(uint32_t);
const field_map_t* get_field_map_index(uint32_t);
size_t get_field_map_length(void);
bool validate_packet(uart_packet_t *);
void queue_cfg_packet(uart_packet_t *, device_t *);

/********* Handlers **********/
void output_toggle_hotkey_handler(device_t *, hid_keyboard_report_t *);
Expand All @@ -505,6 +531,7 @@ void fw_upgrade_hotkey_handler_B(device_t *, hid_keyboard_report_t *);
void mouse_zoom_hotkey_handler(device_t *, hid_keyboard_report_t *);
void all_keys_released_handler(device_t *);
void switchlock_hotkey_handler(device_t *, hid_keyboard_report_t *);
void toggle_relative_mode_handler(device_t *, hid_keyboard_report_t *);
void screenlock_hotkey_handler(device_t *, hid_keyboard_report_t *);
void output_config_hotkey_handler(device_t *, hid_keyboard_report_t *);
void wipe_config_hotkey_handler(device_t *, hid_keyboard_report_t *);
Expand All @@ -530,6 +557,8 @@ void handle_response_byte_msg(uart_packet_t *, device_t *);
void handle_heartbeat_msg(uart_packet_t *, device_t *);
void handle_proxy_msg(uart_packet_t *, device_t *);
void handle_api_msgs(uart_packet_t *, device_t *);
void handle_api_read_all_msg(uart_packet_t *, device_t *);
void handle_toggle_relative_msg(uart_packet_t *, device_t *);

void switch_output(device_t *, uint8_t);

Expand Down
44 changes: 44 additions & 0 deletions src/include/usb_descriptors.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,4 +151,48 @@ HID_COLLECTION_END \
HID_OUTPUT ( HID_DATA | HID_ARRAY | HID_ABSOLUTE ) ,\
HID_COLLECTION_END \

#define TUD_HID_REPORT_DESC_MOUSEHELP(...) \
HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\
HID_USAGE ( HID_USAGE_DESKTOP_MOUSE ) ,\
HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\
/* Report ID if any */\
__VA_ARGS__ \
HID_USAGE ( HID_USAGE_DESKTOP_POINTER ) ,\
HID_COLLECTION ( HID_COLLECTION_PHYSICAL ) ,\
HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\
HID_USAGE_MIN ( 1 ) ,\
HID_USAGE_MAX ( 5 ) ,\
HID_LOGICAL_MIN ( 0 ) ,\
HID_LOGICAL_MAX ( 1 ) ,\
/* Left, Right, Middle, Backward, Forward buttons */ \
HID_REPORT_COUNT( 5 ) ,\
HID_REPORT_SIZE ( 1 ) ,\
HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\
/* 3 bit padding */ \
HID_REPORT_COUNT( 1 ) ,\
HID_REPORT_SIZE ( 3 ) ,\
HID_INPUT ( HID_CONSTANT ) ,\
HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\
/* X, Y position [-127, 127] */ \
HID_USAGE ( HID_USAGE_DESKTOP_X ) ,\
HID_USAGE ( HID_USAGE_DESKTOP_Y ) ,\
HID_LOGICAL_MIN_N ( 0x8000, 2 ) ,\
HID_LOGICAL_MAX_N ( 0x7fff, 2 ) ,\
HID_REPORT_SIZE ( 16 ) ,\
HID_REPORT_COUNT( 2 ) ,\
HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ) ,\
/* Vertical wheel scroll [-127, 127] */ \
HID_USAGE ( HID_USAGE_DESKTOP_WHEEL ) ,\
HID_LOGICAL_MIN ( 0x81 ) ,\
HID_LOGICAL_MAX ( 0x7f ) ,\
HID_REPORT_COUNT( 1 ) ,\
HID_REPORT_SIZE ( 8 ) ,\
HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ) ,\
/* Mouse mode (0 = absolute, 1 = relative) */ \
HID_REPORT_COUNT( 1 ), \
HID_REPORT_SIZE ( 8 ), \
HID_INPUT ( HID_CONSTANT ), \
HID_COLLECTION_END , \
HID_COLLECTION_END \

#endif /* USB_DESCRIPTORS_H_ */
14 changes: 9 additions & 5 deletions src/include/user_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
*
* defined as HID_KEY_<something>
*
* In addition, keyboard.c defines right ctrl as a modifier key required to
* activate this. So, the current shortcut is RIGHT CTRL + whatever is defined
* here.
*
* If you do not want to use a key for switching outputs, you may be tempted
* to select HID_KEY_NONE here; don't do that! That code appears in many HID
* messages and the result will be a non-functional keyboard. Instead, choose
Expand All @@ -32,7 +36,7 @@
*
* */

#define HOTKEY_TOGGLE HID_KEY_F24
#define HOTKEY_TOGGLE HID_KEY_CAPS_LOCK

/**================================================== *
* ============== Mouse Speed Factor ============== *
Expand All @@ -53,13 +57,13 @@
*
* */

/* Output A values */
/* Output A values, default is for the most common ~ 16:9 ratio screen */
#define MOUSE_SPEED_A_FACTOR_X 16
#define MOUSE_SPEED_A_FACTOR_Y 16
#define MOUSE_SPEED_A_FACTOR_Y 28

/* Output B values */
/* Output B values, default is for the most common ~ 16:9 ratio screen */
#define MOUSE_SPEED_B_FACTOR_X 16
#define MOUSE_SPEED_B_FACTOR_Y 16
#define MOUSE_SPEED_B_FACTOR_Y 28

#define JUMP_THRESHOLD 0

Expand Down
13 changes: 10 additions & 3 deletions src/keyboard.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

hotkey_combo_t hotkeys[] = {
/* Main keyboard switching hotkey */
{.modifier = 0,
{.modifier = KEYBOARD_MODIFIER_LEFTCTRL,
.keys = {HOTKEY_TOGGLE},
.key_count = 1,
.pass_to_os = false,
Expand Down Expand Up @@ -51,6 +51,13 @@ hotkey_combo_t hotkeys[] = {
.acknowledge = true,
.action_handler = &screenlock_hotkey_handler},

/* Toggle gaming mode */
{.modifier = KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT,
.keys = {HID_KEY_G},
.key_count = 1,
.acknowledge = true,
.action_handler = &toggle_relative_mode_handler},

/* Erase stored config */
{.modifier = KEYBOARD_MODIFIER_RIGHTSHIFT,
.keys = {HID_KEY_F12, HID_KEY_D},
Expand Down Expand Up @@ -185,7 +192,7 @@ void send_key(hid_keyboard_report_t *report, device_t *state) {
/* Decide if consumer control reports go local or to the other board */
void send_consumer_control(uint8_t *raw_report, device_t *state) {
if (CURRENT_BOARD_IS_ACTIVE_OUTPUT) {
tud_hid_n_report(0, REPORT_ID_CONSUMER, raw_report, CONSUMER_CONTROL_LENGTH);
queue_cc_packet(raw_report, state);
state->last_activity[BOARD_ROLE] = time_us_64();
} else {
queue_packet((uint8_t *)raw_report, CONSUMER_CONTROL_MSG, CONSUMER_CONTROL_LENGTH);
Expand All @@ -195,7 +202,7 @@ void send_consumer_control(uint8_t *raw_report, device_t *state) {
/* Decide if consumer control reports go local or to the other board */
void send_system_control(uint8_t *raw_report, device_t *state) {
if (CURRENT_BOARD_IS_ACTIVE_OUTPUT) {
tud_hid_n_report(0, REPORT_ID_SYSTEM, raw_report, SYSTEM_CONTROL_LENGTH);
queue_system_packet(raw_report, state);
state->last_activity[BOARD_ROLE] = time_us_64();
} else {
queue_packet((uint8_t *)raw_report, SYSTEM_CONTROL_MSG, SYSTEM_CONTROL_LENGTH);
Expand Down
2 changes: 1 addition & 1 deletion src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ int main(void) {
[1] = {.exec = &kick_watchdog_task, .frequency = _HZ(30)}, // | Verify core1 is still running and if so, reset watchdog timer
[2] = {.exec = &process_kbd_queue_task, .frequency = _HZ(2000)}, // | Check if there were any keypresses and send them
[3] = {.exec = &process_mouse_queue_task, .frequency = _HZ(2000)}, // | Check if there were any mouse movements and send them
[4] = {.exec = &process_cfg_queue_task, .frequency = _HZ(1000)}, // | Check if there are any packets to send over vendor link
[4] = {.exec = &process_hid_queue_task, .frequency = _HZ(1000)}, // | Check if there are any packets to send over vendor link
[5] = {.exec = &process_uart_tx_task, .frequency = _TOP()}, // | Check if there are any packets to send over UART
}; // `----- then go back and repeat forever
const int NUM_TASKS = ARRAY_SIZE(tasks_core0);
Expand Down
Loading

0 comments on commit a249aa5

Please sign in to comment.