mirror of
https://github.com/hrvach/deskhop.git
synced 2024-11-21 23:33:33 +01:00
Updates and bugfixes
- Make MacOS multi-desktop workaround more reliable - Partial media keys support
This commit is contained in:
parent
35002c90eb
commit
2d93c01421
23
.clang-format
Normal file
23
.clang-format
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
BasedOnStyle: LLVM
|
||||||
|
BinPackParameters: 'false'
|
||||||
|
BinPackArguments: 'false'
|
||||||
|
AlignAfterOpenBracket: Align
|
||||||
|
AlignConsecutiveMacros: 'true'
|
||||||
|
AlignConsecutiveAssignments: 'true'
|
||||||
|
AlignConsecutiveDeclarations: 'false'
|
||||||
|
AlignEscapedNewlines: Left
|
||||||
|
AlignOperands: 'true'
|
||||||
|
AlignTrailingComments: 'true'
|
||||||
|
AllowAllArgumentsOnNextLine: 'true'
|
||||||
|
AllowShortFunctionsOnASingleLine: 'false'
|
||||||
|
BreakBeforeBinaryOperators: 'All'
|
||||||
|
ColumnLimit: '110'
|
||||||
|
IndentWidth: '4'
|
||||||
|
IndentCaseLabels: 'true'
|
||||||
|
IndentWrappedFunctionNames: 'false'
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: 'true'
|
||||||
|
MaxEmptyLinesToKeep: '2'
|
||||||
|
PointerAlignment: Right
|
||||||
|
ReflowComments: 'true'
|
||||||
|
Standard: Cpp11
|
||||||
|
UseTab: Never
|
Binary file not shown.
Binary file not shown.
@ -231,6 +231,11 @@ void handle_output_config_msg(uart_packet_t *packet, device_t *state) {
|
|||||||
save_config(state);
|
save_config(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Process consumer control keyboard message. Send immediately, w/o queing */
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
/**==================================================== *
|
/**==================================================== *
|
||||||
* ============== Output Switch Routines ============ *
|
* ============== Output Switch Routines ============ *
|
||||||
* ==================================================== */
|
* ==================================================== */
|
||||||
|
@ -74,6 +74,14 @@ typedef struct {
|
|||||||
bool uses_report_id;
|
bool uses_report_id;
|
||||||
} mouse_t;
|
} mouse_t;
|
||||||
|
|
||||||
|
/* Defines information about HID report format for the keyboard. */
|
||||||
|
typedef struct {
|
||||||
|
uint8_t keyboard_report_id;
|
||||||
|
uint8_t consumer_report_id;
|
||||||
|
uint8_t system_report_id;
|
||||||
|
uint8_t protocol;
|
||||||
|
} keyboard_t;
|
||||||
|
|
||||||
/* For each element type we're interested in there is an entry
|
/* For each element type we're interested in there is an entry
|
||||||
in an array of these, defining its usage and in case matched, where to
|
in an array of these, defining its usage and in case matched, where to
|
||||||
store the data. */
|
store the data. */
|
||||||
|
@ -181,6 +181,16 @@ 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);
|
||||||
|
state->last_activity[BOARD_ROLE] = time_us_64();
|
||||||
|
} else {
|
||||||
|
send_packet((uint8_t *)raw_report, CONSUMER_CONTROL_MSG, CONSUMER_CONTROL_LENGTH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ==================================================== *
|
/* ==================================================== *
|
||||||
* Parse and interpret the keys pressed on the keyboard
|
* Parse and interpret the keys pressed on the keyboard
|
||||||
* ==================================================== */
|
* ==================================================== */
|
||||||
@ -218,3 +228,20 @@ void process_keyboard_report(uint8_t *raw_report, int length, device_t *state) {
|
|||||||
/* This method will decide if the key gets queued locally or sent through UART */
|
/* This method will decide if the key gets queued locally or sent through UART */
|
||||||
send_key(keyboard_report, state);
|
send_key(keyboard_report, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void process_consumer_report(uint8_t *raw_report, int length, device_t *state) {
|
||||||
|
uint8_t new_report[CONSUMER_CONTROL_LENGTH] = {0};
|
||||||
|
|
||||||
|
/* We expect length not to be zero or bail out */
|
||||||
|
if (!length)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Consumer control report ID rewrite and forward */
|
||||||
|
if (raw_report[0] && raw_report[0] == global_state.kbd_dev.consumer_report_id) {
|
||||||
|
for (int i = 0; i < length - 1 || i < CONSUMER_CONTROL_LENGTH; i++) {
|
||||||
|
new_report[i] = raw_report[i + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
send_consumer_control(new_report, &global_state);
|
||||||
|
}
|
||||||
|
}
|
12
src/main.h
12
src/main.h
@ -109,6 +109,7 @@ enum packet_type_e {
|
|||||||
SWAP_OUTPUTS_MSG = 12,
|
SWAP_OUTPUTS_MSG = 12,
|
||||||
HEARTBEAT_MSG = 13,
|
HEARTBEAT_MSG = 13,
|
||||||
OUTPUT_CONFIG_MSG = 14,
|
OUTPUT_CONFIG_MSG = 14,
|
||||||
|
CONSUMER_CONTROL_MSG = 15,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -142,9 +143,10 @@ typedef struct {
|
|||||||
#define KBD_QUEUE_LENGTH 128
|
#define KBD_QUEUE_LENGTH 128
|
||||||
#define MOUSE_QUEUE_LENGTH 2048
|
#define MOUSE_QUEUE_LENGTH 2048
|
||||||
|
|
||||||
#define KEYS_IN_USB_REPORT 6
|
#define KEYS_IN_USB_REPORT 6
|
||||||
#define KBD_REPORT_LENGTH 8
|
#define KBD_REPORT_LENGTH 8
|
||||||
#define MOUSE_REPORT_LENGTH 7
|
#define MOUSE_REPORT_LENGTH 7
|
||||||
|
#define CONSUMER_CONTROL_LENGTH 4
|
||||||
|
|
||||||
/********* Screen **********/
|
/********* Screen **********/
|
||||||
#define MIN_SCREEN_COORD 0
|
#define MIN_SCREEN_COORD 0
|
||||||
@ -260,6 +262,7 @@ typedef struct {
|
|||||||
|
|
||||||
config_t config; // Device configuration, loaded from flash or defaults used
|
config_t config; // Device configuration, loaded from flash or defaults used
|
||||||
mouse_t mouse_dev; // Mouse device specifics, e.g. stores locations for keys in report
|
mouse_t mouse_dev; // Mouse device specifics, e.g. stores locations for keys in report
|
||||||
|
keyboard_t kbd_dev; // Keyboard device specifics, like report IDs
|
||||||
queue_t kbd_queue; // Queue that stores keyboard reports
|
queue_t kbd_queue; // Queue that stores keyboard reports
|
||||||
queue_t mouse_queue; // Queue that stores mouse reports
|
queue_t mouse_queue; // Queue that stores mouse reports
|
||||||
|
|
||||||
@ -288,11 +291,13 @@ void core1_main(void);
|
|||||||
/********* Keyboard **********/
|
/********* Keyboard **********/
|
||||||
bool check_specific_hotkey(hotkey_combo_t, const hid_keyboard_report_t *);
|
bool check_specific_hotkey(hotkey_combo_t, const hid_keyboard_report_t *);
|
||||||
void process_keyboard_report(uint8_t *, int, device_t *);
|
void process_keyboard_report(uint8_t *, int, device_t *);
|
||||||
|
void process_consumer_report(uint8_t *, int, device_t *);
|
||||||
void release_all_keys(device_t *);
|
void release_all_keys(device_t *);
|
||||||
void queue_kbd_report(hid_keyboard_report_t *, device_t *);
|
void queue_kbd_report(hid_keyboard_report_t *, device_t *);
|
||||||
void process_kbd_queue_task(device_t *);
|
void process_kbd_queue_task(device_t *);
|
||||||
void send_key(hid_keyboard_report_t *, device_t *);
|
void send_key(hid_keyboard_report_t *, device_t *);
|
||||||
bool key_in_report(uint8_t, const hid_keyboard_report_t *);
|
bool key_in_report(uint8_t, const hid_keyboard_report_t *);
|
||||||
|
void send_consumer_control(uint8_t *, device_t *);
|
||||||
|
|
||||||
/********* Mouse **********/
|
/********* Mouse **********/
|
||||||
bool tud_mouse_report(uint8_t mode, uint8_t buttons, int16_t x, int16_t y, int8_t wheel);
|
bool tud_mouse_report(uint8_t mode, uint8_t buttons, int16_t x, int16_t y, int8_t wheel);
|
||||||
@ -355,6 +360,7 @@ void handle_flash_led_msg(uart_packet_t *, device_t *);
|
|||||||
void handle_fw_upgrade_msg(uart_packet_t *, device_t *);
|
void handle_fw_upgrade_msg(uart_packet_t *, device_t *);
|
||||||
void handle_wipe_config_msg(uart_packet_t *, device_t *);
|
void handle_wipe_config_msg(uart_packet_t *, device_t *);
|
||||||
void handle_screensaver_msg(uart_packet_t *, device_t *);
|
void handle_screensaver_msg(uart_packet_t *, device_t *);
|
||||||
|
void handle_consumer_control_msg(uart_packet_t *, device_t *);
|
||||||
|
|
||||||
void switch_output(device_t *, uint8_t);
|
void switch_output(device_t *, uint8_t);
|
||||||
|
|
||||||
|
@ -139,9 +139,9 @@ void switch_desktop(device_t *state, output_t *output, int new_index, int direct
|
|||||||
|
|
||||||
switch (output->os) {
|
switch (output->os) {
|
||||||
case MACOS:
|
case MACOS:
|
||||||
/* Once doesn't seem reliable enough, do it twice */
|
/* Once isn't reliable enough, but repeating it does the trick */
|
||||||
output_mouse_report(&move_relative_one, state);
|
for (int move_cnt=0; move_cnt<5; move_cnt++)
|
||||||
output_mouse_report(&move_relative_one, state);
|
output_mouse_report(&move_relative_one, state);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WINDOWS:
|
case WINDOWS:
|
||||||
|
@ -57,6 +57,7 @@ const uart_handler_t uart_handler[] = {
|
|||||||
{.type = SCREENSAVER_MSG, .handler = handle_screensaver_msg},
|
{.type = SCREENSAVER_MSG, .handler = handle_screensaver_msg},
|
||||||
{.type = WIPE_CONFIG_MSG, .handler = handle_wipe_config_msg},
|
{.type = WIPE_CONFIG_MSG, .handler = handle_wipe_config_msg},
|
||||||
{.type = OUTPUT_CONFIG_MSG, .handler = handle_output_config_msg},
|
{.type = OUTPUT_CONFIG_MSG, .handler = handle_output_config_msg},
|
||||||
|
{.type = CONSUMER_CONTROL_MSG, .handler = handle_consumer_control_msg},
|
||||||
};
|
};
|
||||||
|
|
||||||
void process_packet(uart_packet_t *packet, device_t *state) {
|
void process_packet(uart_packet_t *packet, device_t *state) {
|
||||||
|
25
src/usb.c
25
src/usb.c
@ -87,6 +87,7 @@ void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) {
|
|||||||
switch (itf_protocol) {
|
switch (itf_protocol) {
|
||||||
case HID_ITF_PROTOCOL_KEYBOARD:
|
case HID_ITF_PROTOCOL_KEYBOARD:
|
||||||
global_state.keyboard_connected = false;
|
global_state.keyboard_connected = false;
|
||||||
|
memset(&global_state.kbd_dev, 0, sizeof(global_state.kbd_dev));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HID_ITF_PROTOCOL_MOUSE:
|
case HID_ITF_PROTOCOL_MOUSE:
|
||||||
@ -99,7 +100,9 @@ void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *desc_report, uint16_t desc_len) {
|
void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *desc_report, uint16_t desc_len) {
|
||||||
uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance);
|
uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance);
|
||||||
|
tuh_hid_report_info_t report_info[MAX_REPORT_ITEMS] = {0};
|
||||||
|
tuh_hid_report_info_t *info;
|
||||||
|
|
||||||
switch (itf_protocol) {
|
switch (itf_protocol) {
|
||||||
case HID_ITF_PROTOCOL_KEYBOARD:
|
case HID_ITF_PROTOCOL_KEYBOARD:
|
||||||
@ -120,13 +123,25 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *desc_re
|
|||||||
at least we get all the information we need (looking at you, mouse wheel) */
|
at least we get all the information we need (looking at you, mouse wheel) */
|
||||||
if (tuh_hid_get_protocol(dev_addr, instance) == HID_PROTOCOL_BOOT) {
|
if (tuh_hid_get_protocol(dev_addr, instance) == HID_PROTOCOL_BOOT) {
|
||||||
tuh_hid_set_protocol(dev_addr, instance, HID_PROTOCOL_REPORT);
|
tuh_hid_set_protocol(dev_addr, instance, HID_PROTOCOL_REPORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
global_state.mouse_dev.protocol = tuh_hid_get_protocol(dev_addr, instance);
|
global_state.mouse_dev.protocol = tuh_hid_get_protocol(dev_addr, instance);
|
||||||
parse_report_descriptor(&global_state.mouse_dev, MAX_REPORTS, desc_report, desc_len);
|
parse_report_descriptor(&global_state.mouse_dev, MAX_REPORTS, desc_report, desc_len);
|
||||||
|
|
||||||
global_state.mouse_connected = true;
|
global_state.mouse_connected = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case HID_ITF_PROTOCOL_NONE:
|
||||||
|
uint8_t num_parsed
|
||||||
|
= tuh_hid_parse_report_descriptor(&report_info[0], MAX_REPORT_ITEMS, desc_report, desc_len);
|
||||||
|
|
||||||
|
for (int report_num = 0; report_num < num_parsed; report_num++) {
|
||||||
|
info = &report_info[report_num];
|
||||||
|
|
||||||
|
if (info->usage == HID_USAGE_CONSUMER_CONTROL && info->usage_page == HID_USAGE_PAGE_CONSUMER)
|
||||||
|
global_state.kbd_dev.consumer_report_id = info->report_id;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
/* Flash local led to indicate a device was connected */
|
/* Flash local led to indicate a device was connected */
|
||||||
blink_led(&global_state);
|
blink_led(&global_state);
|
||||||
@ -134,7 +149,7 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *desc_re
|
|||||||
/* Also signal the other board to flash LED, to enable easy verification if serial works */
|
/* Also signal the other board to flash LED, to enable easy verification if serial works */
|
||||||
send_value(ENABLE, FLASH_LED_MSG);
|
send_value(ENABLE, FLASH_LED_MSG);
|
||||||
|
|
||||||
/* Kick off the report querying */
|
/* Kick off the report querying */
|
||||||
tuh_hid_receive_report(dev_addr, instance);
|
tuh_hid_receive_report(dev_addr, instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,6 +165,10 @@ void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t cons
|
|||||||
case HID_ITF_PROTOCOL_MOUSE:
|
case HID_ITF_PROTOCOL_MOUSE:
|
||||||
process_mouse_report((uint8_t *)report, len, &global_state);
|
process_mouse_report((uint8_t *)report, len, &global_state);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case HID_ITF_PROTOCOL_NONE:
|
||||||
|
process_consumer_report((uint8_t *)report, len, &global_state);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Continue requesting reports */
|
/* Continue requesting reports */
|
||||||
|
@ -62,7 +62,9 @@ uint8_t const *tud_descriptor_device_cb(void) {
|
|||||||
// Relative mouse is used to overcome limitations of multiple desktops on MacOS and Windows
|
// Relative mouse is used to overcome limitations of multiple desktops on MacOS and Windows
|
||||||
|
|
||||||
uint8_t const desc_hid_report[] = {TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(REPORT_ID_KEYBOARD)),
|
uint8_t const desc_hid_report[] = {TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(REPORT_ID_KEYBOARD)),
|
||||||
TUD_HID_REPORT_DESC_ABSMOUSE(HID_REPORT_ID(REPORT_ID_MOUSE))};
|
TUD_HID_REPORT_DESC_ABSMOUSE(HID_REPORT_ID(REPORT_ID_MOUSE)),
|
||||||
|
TUD_HID_REPORT_DESC_CONSUMER_CTRL(HID_REPORT_ID(REPORT_ID_CONSUMER))
|
||||||
|
};
|
||||||
|
|
||||||
uint8_t const desc_hid_report_relmouse[] = {TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(REPORT_ID_RELMOUSE))};
|
uint8_t const desc_hid_report_relmouse[] = {TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(REPORT_ID_RELMOUSE))};
|
||||||
|
|
||||||
|
@ -29,7 +29,8 @@ enum
|
|||||||
{
|
{
|
||||||
REPORT_ID_KEYBOARD = 1,
|
REPORT_ID_KEYBOARD = 1,
|
||||||
REPORT_ID_MOUSE,
|
REPORT_ID_MOUSE,
|
||||||
REPORT_ID_COUNT
|
REPORT_ID_COUNT,
|
||||||
|
REPORT_ID_CONSUMER
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
@ -86,4 +87,20 @@ HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\
|
|||||||
HID_COLLECTION_END , \
|
HID_COLLECTION_END , \
|
||||||
HID_COLLECTION_END \
|
HID_COLLECTION_END \
|
||||||
|
|
||||||
|
// Consumer Control Report Descriptor Template
|
||||||
|
#define TUD_HID_REPORT_DESC_CONSUMER_CTRL(...) \
|
||||||
|
HID_USAGE_PAGE ( HID_USAGE_PAGE_CONSUMER ) ,\
|
||||||
|
HID_USAGE ( HID_USAGE_CONSUMER_CONTROL ) ,\
|
||||||
|
HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\
|
||||||
|
/* Report ID if any */\
|
||||||
|
__VA_ARGS__ \
|
||||||
|
HID_LOGICAL_MIN ( 0x01 ) ,\
|
||||||
|
HID_LOGICAL_MAX_N( 0x0FFF, 2 ) ,\
|
||||||
|
HID_USAGE_MIN ( 0x01 ) ,\
|
||||||
|
HID_USAGE_MAX_N ( 0x0FFF, 2 ) ,\
|
||||||
|
HID_REPORT_SIZE ( 16 ) ,\
|
||||||
|
HID_REPORT_COUNT ( 2 ) ,\
|
||||||
|
HID_INPUT ( HID_DATA | HID_ARRAY | HID_ABSOLUTE ) ,\
|
||||||
|
HID_COLLECTION_END \
|
||||||
|
|
||||||
#endif /* USB_DESCRIPTORS_H_ */
|
#endif /* USB_DESCRIPTORS_H_ */
|
||||||
|
Loading…
Reference in New Issue
Block a user