DeskHop v0.62 (Minor Bugfixes)

- Fixed screen lock regression bug
  - Cleaned up trailing spaces

Due to MacOS having issues:
  - Moved screen lock shortcut to right control + L
  - Moved switch lock shortcut to right control + K
This commit is contained in:
Hrvoje Cavrak 2024-08-03 19:03:38 +02:00
parent 7a0e7f31ff
commit 1fd0049039
24 changed files with 188 additions and 184 deletions

View File

@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.6)
set(VERSION_MAJOR 00)
set(VERSION_MINOR 139)
set(VERSION_MINOR 147)
set(PICO_SDK_FETCH_FROM_GIT off)
set(PICO_BOARD=pico)

View File

@ -93,9 +93,14 @@ Ever tried to move that YT video slider to a specific position but your mouse mo
### Switch Lock
If you want to lock yourself to one screen, use ```RIGHT CTRL + L```.
If you want to lock yourself to one screen, use ```RIGHT CTRL + K```.
This will make sure you won't accidentally leave your current screen. To turn off, press the same key combo again.
### Lock Both Screens
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).
### 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.
@ -209,8 +214,8 @@ _Config_
_Usage_
- ```Right CTRL + Right ALT``` - Toggle slower mouse mode
- ```Right CTRL + L``` - Lock/Unlock mouse desktop switching
- ```Right ALT + Right Shift + L``` - Lock both outputs at once (set output OS before, see shortcuts below)
- ```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
### Switch cursor height calibration

Binary file not shown.

View File

@ -21,9 +21,9 @@ const config_t default_config = {
.mode = SCREENSAVER_A_MODE,
.only_if_inactive = SCREENSAVER_A_ONLY_IF_INACTIVE,
.idle_time_us = SCREENSAVER_A_IDLE_TIME_SEC * 1000000,
.max_time_us = SCREENSAVER_A_MAX_TIME_SEC * 1000000,
.max_time_us = SCREENSAVER_A_MAX_TIME_SEC * 1000000,
}
},
},
.output[OUTPUT_B] =
{
.number = OUTPUT_B,
@ -41,7 +41,7 @@ const config_t default_config = {
.mode = SCREENSAVER_B_MODE,
.only_if_inactive = SCREENSAVER_B_ONLY_IF_INACTIVE,
.idle_time_us = SCREENSAVER_B_IDLE_TIME_SEC * 1000000,
.max_time_us = SCREENSAVER_B_MAX_TIME_SEC * 1000000,
.max_time_us = SCREENSAVER_B_MAX_TIME_SEC * 1000000,
}
},
.enforce_ports = ENFORCE_PORTS,

View File

@ -79,14 +79,14 @@ void screenlock_hotkey_handler(device_t *state, hid_keyboard_report_t *report) {
lock_report.keycode[0] = HID_KEY_L;
break;
case MACOS:
lock_report.modifier = KEYBOARD_MODIFIER_LEFTCTRL | KEYBOARD_MODIFIER_LEFTALT;
lock_report.modifier = KEYBOARD_MODIFIER_LEFTCTRL | KEYBOARD_MODIFIER_LEFTGUI;
lock_report.keycode[0] = HID_KEY_Q;
break;
default:
break;
}
if (global_state.active_output == out) {
if (BOARD_ROLE == out) {
queue_kbd_report(&lock_report, state);
release_all_keys(state);
} else {
@ -111,14 +111,14 @@ void mouse_zoom_hotkey_handler(device_t *state, hid_keyboard_report_t *report) {
/* Put the device into a special configuration mode */
void config_enable_hotkey_handler(device_t *state, hid_keyboard_report_t *report) {
void config_enable_hotkey_handler(device_t *state, hid_keyboard_report_t *report) {
/* If config mode is already active, skip this and reboot to return to normal mode */
if (!state->config_mode_active) {
watchdog_hw->scratch[5] = MAGIC_WORD_1;
watchdog_hw->scratch[6] = MAGIC_WORD_2;
}
release_all_keys(state);
release_all_keys(state);
state->reboot_requested = true;
};
@ -226,9 +226,9 @@ void handle_api_msgs(uart_packet_t *packet, device_t *state) {
/* If we don't have a valid map entry, return immediately */
if (map == NULL)
return;
return;
/* Create a pointer to the offset into the structure we need to access */
/* Create a pointer to the offset into the structure we need to access */
uint8_t *ptr = (((uint8_t *)&global_state) + map->offset);
if (packet->type == SET_VAL_MSG) {
@ -237,7 +237,7 @@ void handle_api_msgs(uart_packet_t *packet, device_t *state) {
return;
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);
@ -252,14 +252,14 @@ void handle_api_msgs(uart_packet_t *packet, device_t *state) {
/* Process request packet and create a response */
void handle_request_byte_msg(uart_packet_t *packet, device_t *state) {
uint32_t address = packet->data32[0];
if (address > STAGING_IMAGE_SIZE)
return;
/* Add requested data to bytes 4-7 in the packet and return it with a different type */
/* Add requested data to bytes 4-7 in the packet and return it with a different type */
uint32_t data = *(uint32_t *)&ADDR_FW_RUNNING[address];
packet->data32[1] = data;
queue_packet(packet->data, RESPONSE_BYTE_MSG, PACKET_DATA_LENGTH);
}
@ -279,27 +279,27 @@ void handle_response_byte_msg(uart_packet_t *packet, device_t *state) {
if((address & 0xfff) == 0x000)
toggle_led();
}
/* Update checksum as we receive each byte */
if (address < STAGING_IMAGE_SIZE - FLASH_SECTOR_SIZE)
for (int i=0; i<4; i++)
state->fw.checksum = crc32_iter(state->fw.checksum, packet->data[4 + i]);
memcpy(state->page_buffer + offset, &packet->data32[1], sizeof(uint32_t));
memcpy(state->page_buffer + offset, &packet->data32[1], sizeof(uint32_t));
/* Neeeeeeext byte, please! */
state->fw.address += sizeof(uint32_t);
state->fw.address += sizeof(uint32_t);
state->fw.byte_done = true;
}
/* Process a request to read a firmware package from flash */
void handle_heartbeat_msg(uart_packet_t *packet, device_t *state) {
void handle_heartbeat_msg(uart_packet_t *packet, device_t *state) {
uint16_t other_running_version = packet->data16[0];
if (state->fw.upgrade_in_progress)
return;
/* If the other board isn't running a newer version, we are done */
/* If the other board isn't running a newer version, we are done */
if (other_running_version <= state->_running_fw.version)
return;
@ -309,7 +309,7 @@ void handle_heartbeat_msg(uart_packet_t *packet, device_t *state) {
.byte_done = true,
.address = 0,
.checksum = 0xffffffff,
};
};
}

View File

@ -46,7 +46,7 @@ void update_usage(parser_state_t *parser, int i) {
*(parser->p_usage + i) = *(parser->p_usage + i - 1);
}
void store_element(parser_state_t *parser, report_val_t *val, int i, uint32_t data, uint16_t size, hid_interface_t *iface) {
void store_element(parser_state_t *parser, report_val_t *val, int i, uint32_t data, uint16_t size, hid_interface_t *iface) {
*val = (report_val_t){
.offset = parser->offset_in_bits,
.offset_idx = parser->offset_in_bits >> 3,
@ -68,9 +68,9 @@ void store_element(parser_state_t *parser, report_val_t *val, int i, uint32_t da
}
void handle_global_item(parser_state_t *parser, item_t *item) {
if (item->hdr.tag == RI_GLOBAL_REPORT_ID)
parser->report_id = item->val;
if (item->hdr.tag == RI_GLOBAL_REPORT_ID)
parser->report_id = item->val;
parser->globals[item->hdr.tag] = *item;
}
@ -80,7 +80,7 @@ void handle_local_item(parser_state_t *parser, item_t *item) {
parser->locals[item->hdr.tag] = *item;
if (item->hdr.tag == RI_LOCAL_USAGE) {
if(IS_BLOCK_END)
if(IS_BLOCK_END)
parser->global_usage = item->val;
else if (parser->usage_count < HID_MAX_USAGES - 1)
@ -94,20 +94,20 @@ void handle_main_input(parser_state_t *parser, item_t *item, hid_interface_t *if
report_val_t val = {0};
/* Swap count and size for 1-bit variables, it makes sense to process e.g. NKRO with
size = 1 and count = 240 in one go instead of doing 240 iterations
size = 1 and count = 240 in one go instead of doing 240 iterations
Don't do this if there are usages in the queue, though.
*/
*/
if (size == 1 && parser->usage_count <= 1) {
size = count;
count = 1;
count = 1;
}
for (int i = 0; i < count; i++) {
update_usage(parser, i);
store_element(parser, &val, i, item->val, size, iface);
/* Use the parsed data to populate internal device structures */
extract_data(iface, &val);
extract_data(iface, &val);
/* Iterate <count> times and increase offset by <size> amount, moving by <count> x <size> bits */
parser->offset_in_bits += size;
@ -152,7 +152,7 @@ void handle_main_item(parser_state_t *parser, item_t *item, hid_interface_t *ifa
parser_state_t parser_state = {0}; // Avoid placing it on the stack, it's large
void parse_report_descriptor(hid_interface_t *iface,
uint8_t const *report,
uint8_t const *report,
int desc_len
) {
item_t item = {0};
@ -181,5 +181,5 @@ void parse_report_descriptor(hid_interface_t *iface,
/* Move to the next position and decrement size by header length + data length */
report += SIZE_LOOKUP[item.hdr.size];
desc_len -= (SIZE_LOOKUP[item.hdr.size] + 1);
}
}
}

View File

@ -55,17 +55,17 @@ int32_t get_report_value(uint8_t *report, report_val_t *val) {
}
/* After processing the descriptor, assign the values so we can later use them to interpret reports */
void handle_consumer_control_values(report_val_t *src, report_val_t *dst, hid_interface_t *iface) {
void handle_consumer_control_values(report_val_t *src, report_val_t *dst, hid_interface_t *iface) {
if (src->offset > MAX_CC_BUTTONS) {
return;
}
if (src->data_type == VARIABLE) {
iface->keyboard.cc_array[src->offset] = src->usage;
iface->consumer.is_variable = true;
}
iface->consumer.is_array |= (src->data_type == ARRAY);
iface->consumer.is_array |= (src->data_type == ARRAY);
}
/* After processing the descriptor, assign the values so we can later use them to interpret reports */
@ -73,13 +73,13 @@ void handle_system_control_values(report_val_t *src, report_val_t *dst, hid_inte
if (src->offset > MAX_SYS_BUTTONS) {
return;
}
if (src->data_type == VARIABLE) {
iface->keyboard.sys_array[src->offset] = src->usage;
iface->system.is_variable = true;
}
iface->system.is_array |= (src->data_type == ARRAY);
iface->system.is_array |= (src->data_type == ARRAY);
}
/* After processing the descriptor, assign the values so we can later use them to interpret reports */
@ -143,54 +143,54 @@ void extract_data(hid_interface_t *iface, report_val_t *val) {
.id = &iface->mouse.report_id},
{.usage_page = HID_USAGE_PAGE_DESKTOP,
.global_usage = HID_USAGE_DESKTOP_MOUSE,
.global_usage = HID_USAGE_DESKTOP_MOUSE,
.usage = HID_USAGE_DESKTOP_X,
.handler = _store,
.receiver = process_mouse_report,
.dst = &iface->mouse.move_x,
.id = &iface->mouse.report_id},
{.usage_page = HID_USAGE_PAGE_DESKTOP,
.global_usage = HID_USAGE_DESKTOP_MOUSE,
.global_usage = HID_USAGE_DESKTOP_MOUSE,
.usage = HID_USAGE_DESKTOP_Y,
.handler = _store,
.receiver = process_mouse_report,
.dst = &iface->mouse.move_y,
.id = &iface->mouse.report_id},
{.usage_page = HID_USAGE_PAGE_DESKTOP,
.global_usage = HID_USAGE_DESKTOP_MOUSE,
.global_usage = HID_USAGE_DESKTOP_MOUSE,
.usage = HID_USAGE_DESKTOP_WHEEL,
.handler = _store,
.receiver = process_mouse_report,
.dst = &iface->mouse.wheel,
.id = &iface->mouse.report_id},
{.usage_page = HID_USAGE_PAGE_KEYBOARD,
.global_usage = HID_USAGE_DESKTOP_KEYBOARD,
.global_usage = HID_USAGE_DESKTOP_KEYBOARD,
.handler = handle_keyboard_descriptor_values,
.receiver = process_keyboard_report,
.id = &iface->keyboard.report_id},
{.usage_page = HID_USAGE_PAGE_CONSUMER,
.global_usage = HID_USAGE_CONSUMER_CONTROL,
.handler = handle_consumer_control_values,
.receiver = process_consumer_report,
.dst = &iface->consumer.val,
.id = &iface->consumer.report_id},
{.usage_page = HID_USAGE_PAGE_DESKTOP,
.global_usage = HID_USAGE_DESKTOP_SYSTEM_CONTROL,
.handler = _store,
.receiver = process_system_report,
.dst = &iface->system.val,
.id = &iface->system.report_id},
};
};
/* We extracted all we could find in the descriptor to report_values, now go through them and
match them up with the values in the table above, then store those values for later reference */
for (const usage_map_t *hay = map; hay != &map[ARRAY_SIZE(map)]; hay++) {
for (const usage_map_t *hay = map; hay != &map[ARRAY_SIZE(map)]; hay++) {
/* ---> If any condition is not defined, we consider it as matched <--- */
bool global_usages_match = (val->global_usage == hay->global_usage) || (hay->global_usage == 0);
bool usages_match = (val->usage == hay->usage) || (hay->usage == 0);
@ -236,7 +236,7 @@ int32_t _extract_kbd_other(uint8_t *raw_report, int len, hid_interface_t *iface,
uint8_t *src = raw_report;
keyboard_t *kb = &iface->keyboard;
if (iface->uses_report_id)
if (iface->uses_report_id)
src++;
report->modifier = src[kb->modifier.offset_idx];
@ -286,7 +286,7 @@ int32_t extract_kbd_data(
/* NKRO is a special case */
if (report_id > 0
&& report_id == iface->keyboard.nkro.report_id
&& report_id == iface->keyboard.nkro.report_id
&& iface->keyboard.is_nkro)
return _extract_kbd_nkro(raw_report, len, iface, report);

View File

@ -31,7 +31,7 @@ typedef struct {
int usage_page;
int usage;
uint8_t *id;
report_val_t *dst;
report_val_t *dst;
value_handler_f handler;
process_report_f receiver;
} usage_map_t;

View File

@ -255,7 +255,7 @@ typedef struct {
uint8_t enforce_ports;
uint16_t jump_treshold;
output_t output[NUM_SCREENS];
output_t output[NUM_SCREENS];
uint32_t _reserved;
// Keep checksum at the end of the struct
@ -402,7 +402,7 @@ typedef struct {
bool onboard_led_state; // True when LED is ON
bool relative_mouse; // True when relative mouse mode is used
bool config_mode_active; // True when config mode is active
/* Onboard LED blinky (provide feedback when e.g. mouse connected) */
int32_t blinks_left; // How many blink transitions are left
int32_t last_led_change; // Timestamp of the last time led state transitioned
@ -411,7 +411,7 @@ typedef struct {
typedef struct {
void (*exec)(device_t *state);
uint64_t frequency;
uint64_t next_run;
uint64_t next_run;
bool *enabled;
} task_t;

View File

@ -17,7 +17,7 @@ typedef enum {
typedef struct {
uint32_t idx;
bool readonly;
type_e type;
type_e type;
uint32_t len;
size_t offset;
} field_map_t;

View File

@ -1,4 +1,4 @@
/*
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)

View File

@ -29,7 +29,7 @@
* a key that is unlikely to ever appear on a keyboard that you will use.
* HID_KEY_F24 is probably a good choice as keyboards with 24 function keys
* are rare.
*
*
* */
#define HOTKEY_TOGGLE HID_KEY_F24
@ -50,7 +50,7 @@
* This is now configurable per-screen.
*
* ENABLE_ACCELERATION: [0-1], disables or enables mouse acceleration.
*
*
* */
/* Output A values */
@ -180,10 +180,10 @@
* ==================================================
*
* If enabled, fixes some device incompatibilities by
* enforcing the boot protocol (which is simpler to parse
* enforcing the boot protocol (which is simpler to parse
* and with less variation)
*
* ENFORCE_KEYBOARD_BOOT_PROTOCOL: [0, 1] - 1 means keyboard will forcefully use
* ENFORCE_KEYBOARD_BOOT_PROTOCOL: [0, 1] - 1 means keyboard will forcefully use
* the boot protocol
* - 0 means no such thing is enforced
*

View File

@ -39,13 +39,13 @@ hotkey_combo_t hotkeys[] = {
/* Switch lock */
{.modifier = KEYBOARD_MODIFIER_RIGHTCTRL,
.keys = {HID_KEY_L},
.keys = {HID_KEY_K},
.key_count = 1,
.acknowledge = true,
.action_handler = &switchlock_hotkey_handler},
/* Screen lock */
{.modifier = KEYBOARD_MODIFIER_RIGHTALT | KEYBOARD_MODIFIER_RIGHTSHIFT,
{.modifier = KEYBOARD_MODIFIER_RIGHTCTRL,
.keys = {HID_KEY_L},
.key_count = 1,
.acknowledge = true,
@ -162,7 +162,7 @@ void process_kbd_queue_task(device_t *state) {
void queue_kbd_report(hid_keyboard_report_t *report, device_t *state) {
/* It wouldn't be fun to queue up a bunch of messages and then dump them all on host */
if (!state->tud_connected)
return;
return;
queue_try_add(&state->kbd_queue, report);
}
@ -252,7 +252,7 @@ void process_consumer_report(uint8_t *raw_report, int length, uint8_t itf, hid_i
int byte_idx = i >> 3;
if ((raw_report[byte_idx + 1] >> bit_idx) & 1) {
report_ptr[0] = iface->keyboard.cc_array[i];
report_ptr[0] = iface->keyboard.cc_array[i];
}
}
}
@ -267,6 +267,6 @@ void process_consumer_report(uint8_t *raw_report, int length, uint8_t itf, hid_i
void process_system_report(uint8_t *raw_report, int length, uint8_t itf, hid_interface_t *iface) {
uint16_t new_report = raw_report[1];
uint8_t *report_ptr = (uint8_t *)&new_report;
send_system_control(report_ptr, &global_state);
}
}

View File

@ -63,7 +63,7 @@ void blink_led(device_t *state) {
void led_blinking_task(device_t *state) {
const int blink_interval_us = 80000; /* 80 ms off, 80 ms on */
static uint8_t leds;
/* If there is no more blinking to be done, exit immediately */
if (state->blinks_left == 0)
return;

View File

@ -52,7 +52,7 @@ int main(void) {
while (true) {
for (int i = 0; i < NUM_TASKS; i++)
task_scheduler(device, &tasks_core0[i]);
}
}
}
void core1_main() {
@ -64,14 +64,14 @@ void core1_main() {
[4] = {.exec = &firmware_upgrade_task, .frequency = _HZ(4000)}, // | Send firmware to the other board if needed
[5] = {.exec = &heartbeat_output_task, .frequency = _HZ(1)}, // | Output periodic heartbeats
}; // `----- then go back and repeat forever
const int NUM_TASKS = ARRAY_SIZE(tasks_core1);
const int NUM_TASKS = ARRAY_SIZE(tasks_core1);
while (true) {
// Update the timestamp, so core0 can figure out if we're dead
device->core1_last_loop_pass = time_us_64();
for (int i = 0; i < NUM_TASKS; i++)
task_scheduler(device, &tasks_core1[i]);
task_scheduler(device, &tasks_core1[i]);
}
}
/* ======= End of Main Program Loops ======= */

View File

@ -87,7 +87,7 @@ void output_mouse_report(mouse_report_t *report, device_t *state) {
state->last_activity[BOARD_ROLE] = time_us_64();
} else {
queue_packet((uint8_t *)report, MOUSE_REPORT_MSG, MOUSE_REPORT_LENGTH);
}
}
}
/* Calculate and return Y coordinate when moving from screen out_from to screen out_to */
@ -124,12 +124,12 @@ int16_t scale_y_coordinate(int screen_from, int screen_to, device_t *state) {
void switch_screen(
device_t *state, output_t *output, int new_x, int output_from, int output_to, int direction) {
uint8_t *mouse_park_pos = &state->config.output[state->active_output].mouse_park_pos;
int16_t mouse_y = (*mouse_park_pos == 0) ? MIN_SCREEN_COORD : /* Top */
(*mouse_park_pos == 1) ? MAX_SCREEN_COORD : /* Bottom */
state->pointer_y; /* Previous */
mouse_report_t hidden_pointer = {.y = mouse_y, .x = MAX_SCREEN_COORD};
mouse_report_t hidden_pointer = {.y = mouse_y, .x = MAX_SCREEN_COORD};
output_mouse_report(&hidden_pointer, state);
switch_output(state, output_to);
@ -138,7 +138,7 @@ void switch_screen(
}
void switch_desktop(device_t *state, output_t *output, int new_index, int direction) {
/* Fix for MACOS: Send relative mouse movement here, one or two pixels in the
/* Fix for MACOS: Send relative mouse movement here, one or two pixels in the
direction of movement, BEFORE absolute report sets X to 0 */
mouse_report_t move_relative_one
= {.x = (direction == LEFT) ? SCREEN_MIDPOINT - 2 : SCREEN_MIDPOINT + 2, .mode = RELATIVE};
@ -207,7 +207,7 @@ void check_screen_switch(const mouse_values_t *values, device_t *state) {
switch_desktop(state, output, output->screen_index + 1, direction);
}
void extract_report_values(uint8_t *raw_report, device_t *state, mouse_values_t *values, hid_interface_t *iface) {
void extract_report_values(uint8_t *raw_report, device_t *state, mouse_values_t *values, hid_interface_t *iface) {
/* Interpret values depending on the current protocol used. */
if (iface->protocol == HID_PROTOCOL_BOOT) {
hid_mouse_report_t *mouse_report = (hid_mouse_report_t *)raw_report;
@ -267,7 +267,7 @@ void process_mouse_report(uint8_t *raw_report, int len, uint8_t itf, hid_interfa
output_mouse_report(&report, state);
/* We use the mouse to switch outputs, the logic is in check_screen_switch() */
check_screen_switch(&values, state);
check_screen_switch(&values, state);
}
/* ==================================================== *

View File

@ -1,6 +1,6 @@
#include "main.h"
const field_map_t api_field_map[] = {
const field_map_t api_field_map[] = {
/* Index, Rdonly, Type, Len, Offset in struct */
{ 0, true, UINT8, 1, offsetof(device_t, active_output) },
{ 1, true, INT16, 2, offsetof(device_t, pointer_x) },
@ -22,7 +22,7 @@ const field_map_t api_field_map[] = {
/* Until we increase the payload size from 8 bytes, clamp to avoid exceeding the field size */
{ 21, false, UINT64, 7, offsetof(device_t, config.output[0].screensaver.idle_time_us) },
{ 22, false, UINT64, 7, offsetof(device_t, config.output[0].screensaver.max_time_us) },
{ 22, false, UINT64, 7, offsetof(device_t, config.output[0].screensaver.max_time_us) },
/* Output B */
{ 40, false, UINT32, 4, offsetof(device_t, config.output[1].number) },
@ -58,7 +58,7 @@ const field_map_t api_field_map[] = {
{ 82, true, UINT8, 1, offsetof(device_t, relative_mouse) },
};
const field_map_t* get_field_map_entry(uint32_t index) {
const field_map_t* get_field_map_entry(uint32_t index) {
for (unsigned int i = 0; i < ARRAY_SIZE(api_field_map); i++) {
if (api_field_map[i].idx == index) {
return &api_field_map[i];

View File

@ -50,12 +50,12 @@ int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void *buff
return -1;
/* We lie about the image size - actually it's 64 kB, not 512 kB, so if we're out of bounds, return zeros */
else if (lba >= ACTUAL_NUMBER_OF_BLOCKS)
else if (lba >= ACTUAL_NUMBER_OF_BLOCKS)
memset(buffer, 0x00, bufsize);
else
else
memcpy(buffer, addr, bufsize);
return (int32_t)bufsize;
}
@ -67,31 +67,31 @@ bool tud_msc_is_writable_cb(uint8_t lun) {
/* Simple firmware write routine, we get 512-byte uf2 blocks with 256 byte payload */
int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t *buffer, uint32_t bufsize) {
uf2_t *uf2 = (uf2_t *)&buffer[0];
bool is_final_block = uf2->blockNo == (STAGING_IMAGE_SIZE / FLASH_PAGE_SIZE) - 1;
uint32_t flash_addr = (uint32_t)ADDR_FW_RUNNING + uf2->blockNo * FLASH_PAGE_SIZE - XIP_BASE;
bool is_final_block = uf2->blockNo == (STAGING_IMAGE_SIZE / FLASH_PAGE_SIZE) - 1;
uint32_t flash_addr = (uint32_t)ADDR_FW_RUNNING + uf2->blockNo * FLASH_PAGE_SIZE - XIP_BASE;
if (lba >= NUMBER_OF_BLOCKS)
return -1;
/* If we're not detecting UF2 magic constants, we have nothing to do... */
if (uf2->magicStart0 != UF2_MAGIC_START0 || uf2->magicStart1 != UF2_MAGIC_START1 || uf2->magicEnd != UF2_MAGIC_END)
return (int32_t)bufsize;
if (uf2->blockNo == 0) {
global_state.fw.checksum = 0xffffffff;
/* Make sure nobody else touches the flash during this operation, otherwise we get empty pages */
global_state.fw.upgrade_in_progress = true;
}
}
/* Update checksum continuously as blocks are being received */
const uint32_t last_block_with_checksum = (STAGING_IMAGE_SIZE - FLASH_SECTOR_SIZE) / FLASH_PAGE_SIZE;
for (int i=0; i<FLASH_PAGE_SIZE && uf2->blockNo < last_block_with_checksum; i++)
global_state.fw.checksum = crc32_iter(global_state.fw.checksum, buffer[32 + i]);
global_state.fw.checksum = crc32_iter(global_state.fw.checksum, buffer[32 + i]);
write_flash_page(flash_addr, &buffer[32]);
if (is_final_block) {
if (is_final_block) {
global_state.fw.checksum = ~global_state.fw.checksum;
/* If checksums don't match, overwrite first sector and rely on ROM bootloader for recovery */
@ -102,18 +102,17 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t *
else {
global_state.reboot_requested = true;
}
}
}
/* Provide some visual indication that fw is being uploaded */
toggle_led();
toggle_led();
watchdog_update();
return (int32_t)bufsize;
}
/* This is a super-dumb, rudimentary disk, any other scsi command is simply rejected */
int32_t tud_msc_scsi_cb(uint8_t lun, uint8_t const scsi_cmd[16], void *buffer, uint16_t bufsize) {
int32_t tud_msc_scsi_cb(uint8_t lun, uint8_t const scsi_cmd[16], void *buffer, uint16_t bufsize) {
tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00);
return -1;
}

View File

@ -75,7 +75,7 @@ void pio_usb_host_config(device_t *state) {
and it will drive it either high or low at any given time
- Before uart setup, enable it as an input
- Go through a probing sequence of 8 values and pull either up or down
to that value
to that value
- Read out the value on the RX pin
- If the entire sequence of values match, we are definitely floating
so IC is not connected on BOARD_A_RX, and we're BOARD B
@ -84,22 +84,22 @@ int board_autoprobe(void) {
const bool probing_sequence[] = {true, false, false, true, true, false, true, false};
const int seq_len = ARRAY_SIZE(probing_sequence);
/* Set the pin as INPUT and initialize it */
/* Set the pin as INPUT and initialize it */
gpio_init(BOARD_A_RX);
gpio_set_dir(BOARD_A_RX, GPIO_IN);
for (int i=0; i<seq_len; i++) {
for (int i=0; i<seq_len; i++) {
if (probing_sequence[i])
gpio_pull_up(BOARD_A_RX);
else
gpio_pull_down(BOARD_A_RX);
/* Wait for value to settle */
sleep_ms(3);
/* Read the value */
bool value = gpio_get(BOARD_A_RX);
gpio_disable_pulls(BOARD_A_RX);
gpio_disable_pulls(BOARD_A_RX);
/* If values mismatch at any point, means IC is connected and we're board A */
if (probing_sequence[i] != value)
@ -122,7 +122,7 @@ bool is_config_mode_active(device_t *state) {
/* Remove, so next reboot it's no longer active */
if (is_active)
watchdog_hw->scratch[5] = 0;
watchdog_hw->scratch[5] = 0;
reset_config_timer(state);
@ -131,23 +131,23 @@ bool is_config_mode_active(device_t *state) {
/* ================================================== *
* Configure DMA for reliable UART transfers
* Configure DMA for reliable UART transfers
* ================================================== */
const uint8_t* uart_buffer_pointers[1] = {uart_rxbuf};
const uint8_t* uart_buffer_pointers[1] = {uart_rxbuf};
uint8_t uart_rxbuf[DMA_RX_BUFFER_SIZE] __attribute__((aligned(DMA_RX_BUFFER_SIZE))) ;
uint8_t uart_txbuf[DMA_TX_BUFFER_SIZE] __attribute__((aligned(DMA_TX_BUFFER_SIZE))) ;
static void configure_tx_dma(device_t *state) {
state->dma_tx_channel = dma_claim_unused_channel(true);
dma_channel_config tx_config = dma_channel_get_default_config(state->dma_tx_channel);
dma_channel_config tx_config = dma_channel_get_default_config(state->dma_tx_channel);
channel_config_set_transfer_data_size(&tx_config, DMA_SIZE_8);
/* Writing uart (always write the same address, but source addr changes as we read) */
channel_config_set_read_increment(&tx_config, true);
channel_config_set_write_increment(&tx_config, false);
// channel_config_set_ring(&tx_config, false, 4);
// channel_config_set_ring(&tx_config, false, 4);
channel_config_set_dreq(&tx_config, DREQ_UART0_TX);
/* Configure, but don't start immediately. We'll do this each time the outgoing
@ -167,7 +167,7 @@ static void configure_rx_dma(device_t *state) {
state->dma_rx_channel = dma_claim_unused_channel(true);
state->dma_control_channel = dma_claim_unused_channel(true);
dma_channel_config config = dma_channel_get_default_config(state->dma_rx_channel);
dma_channel_config config = dma_channel_get_default_config(state->dma_rx_channel);
dma_channel_config control_config = dma_channel_get_default_config(state->dma_control_channel);
channel_config_set_transfer_data_size(&config, DMA_SIZE_8);
@ -185,16 +185,16 @@ static void configure_rx_dma(device_t *state) {
// The UART signals when data is avaliable
channel_config_set_dreq(&config, DREQ_UART0_RX);
channel_config_set_chain_to(&config, state->dma_control_channel);
dma_channel_configure(
state->dma_rx_channel,
&config,
uart_rxbuf,
&uart0_hw->dr,
DMA_RX_BUFFER_SIZE,
false);
false);
dma_channel_configure(
state->dma_control_channel,
@ -204,14 +204,14 @@ static void configure_rx_dma(device_t *state) {
1,
false);
dma_channel_start(state->dma_control_channel);
dma_channel_start(state->dma_control_channel);
}
/* ================================================== *
* Perform initial board/usb setup
* ================================================== */
int board;
int board;
void initial_setup(device_t *state) {
/* PIO USB requires a clock multiple of 12 MHz, setting to 120 MHz */
@ -248,12 +248,12 @@ void initial_setup(device_t *state) {
multicore_launch_core1(core1_main);
/* Initialize and configure TinyUSB Device */
tud_init(BOARD_TUD_RHPORT);
tud_init(BOARD_TUD_RHPORT);
/* Initialize and configure TinyUSB Host */
pio_usb_host_config(state);
/* Initialize and configure DMA */
/* Initialize and configure DMA */
configure_tx_dma(state);
configure_rx_dma(state);
@ -262,7 +262,7 @@ void initial_setup(device_t *state) {
/* Update the core1 initial pass timestamp before enabling the watchdog */
state->core1_last_loop_pass = time_us_64();
/* Setup the watchdog so we reboot and recover from a crash */
watchdog_enable(WATCHDOG_TIMEOUT, WATCHDOG_PAUSE_ON_DEBUG);
}

View File

@ -19,7 +19,7 @@
void task_scheduler(device_t *state, task_t *task) {
uint64_t current_time = time_us_64();
if (current_time < task->next_run)
return;
@ -36,7 +36,7 @@ void kick_watchdog_task(device_t *state) {
so it doesn't get updated in the meantime. */
uint64_t core1_last_loop_pass = state->core1_last_loop_pass;
uint64_t current_time = time_us_64();
/* If a reboot is requested, we'll stop updating watchdog */
if (state->reboot_requested)
return;
@ -64,7 +64,7 @@ void screensaver_task(device_t *state) {
const int mouse_move_delay = 5000;
screensaver_t *screensaver = &state->config.output[BOARD_ROLE].screensaver;
uint64_t inactivity_period = time_us_64() - state->last_activity[BOARD_ROLE];
static mouse_report_t report = {0};
static int last_pointer_move = 0;
static int dx = 20, dy = 25, jitter = 1;
@ -119,11 +119,11 @@ void screensaver_task(device_t *state) {
}
/* Periodically emit heartbeat packets */
void heartbeat_output_task(device_t *state) {
void heartbeat_output_task(device_t *state) {
/* If firmware upgrade is in progress, don't touch flash_cs */
if (state->fw.upgrade_in_progress)
return;
if (state->config_mode_active) {
/* Leave config mode if timeout expired and user didn't click exit */
if (time_us_64() > state->config_mode_timer)
@ -140,12 +140,12 @@ void heartbeat_output_task(device_t *state) {
uart_packet_t packet = {
.type = HEARTBEAT_MSG,
.data16 = {
[0] = state->_running_fw.version,
[0] = state->_running_fw.version,
[2] = state->active_output,
},
};
queue_try_add(&global_state.uart_tx_queue, &packet);
queue_try_add(&global_state.uart_tx_queue, &packet);
}
/* Process outgoing config report messages. */
@ -194,14 +194,14 @@ void firmware_upgrade_task(device_t *state) {
}
}
/* If we're on the last element of the current page, page is done - write it. */
if (TU_U32_BYTE0(state->fw.address) == 0x00) {
/* If we're on the last element of the current page, page is done - write it. */
if (TU_U32_BYTE0(state->fw.address) == 0x00) {
uint32_t page_start_addr = (state->fw.address - 1) & 0xFFFFFF00;
write_flash_page((uint32_t)ADDR_FW_RUNNING + page_start_addr - XIP_BASE, state->page_buffer);
write_flash_page((uint32_t)ADDR_FW_RUNNING + page_start_addr - XIP_BASE, state->page_buffer);
}
request_byte(state, state->fw.address);
request_byte(state, state->fw.address);
}
void packet_receiver_task(device_t *state) {
@ -210,7 +210,7 @@ void packet_receiver_task(device_t *state) {
uint32_t delta = get_ptr_delta(current_pointer, state);
/* If we don't have enough characters for a packet, skip loop and return immediately */
while (delta >= RAW_PACKET_LENGTH) {
while (delta >= RAW_PACKET_LENGTH) {
if (is_start_of_packet(state)) {
fetch_packet(state);
process_packet(&state->in_packet, state);

View File

@ -22,15 +22,15 @@
* ================================================== */
/* Takes a packet as uart_packet_t struct, adds preamble, checksum and encodes it to a raw array. */
void write_raw_packet(uint8_t *dst, uart_packet_t *packet) {
void write_raw_packet(uint8_t *dst, uart_packet_t *packet) {
uint8_t pkt[RAW_PACKET_LENGTH] = {[0] = START1,
[1] = START2,
[2] = packet->type,
/* [3-10] is data, defaults to 0 */
[11] = calc_checksum(packet->data, PACKET_DATA_LENGTH)};
memcpy(&pkt[START_LENGTH + TYPE_LENGTH], packet->data, PACKET_DATA_LENGTH);
memcpy(dst, &pkt, RAW_PACKET_LENGTH);
memcpy(dst, &pkt, RAW_PACKET_LENGTH);
}
/* Schedule packet for sending to the other box */
@ -38,7 +38,7 @@ void queue_packet(const uint8_t *data, enum packet_type_e packet_type, int lengt
uart_packet_t packet = {.type = packet_type};
memcpy(packet.data, data, length);
queue_try_add(&global_state.uart_tx_queue, &packet);
queue_try_add(&global_state.uart_tx_queue, &packet);
}
/* Sends just one byte of a certain packet type to the other box. */
@ -56,7 +56,7 @@ void process_uart_tx_task(device_t *state) {
if (!queue_try_remove(&state->uart_tx_queue, &packet))
return;
write_raw_packet(uart_txbuf, &packet);
write_raw_packet(uart_txbuf, &packet);
dma_channel_transfer_from_buffer_now(state->dma_tx_channel, uart_txbuf, RAW_PACKET_LENGTH);
}
@ -69,7 +69,7 @@ const uart_handler_t uart_handler[] = {
{.type = KEYBOARD_REPORT_MSG, .handler = handle_keyboard_uart_msg},
{.type = MOUSE_REPORT_MSG, .handler = handle_mouse_abs_uart_msg},
{.type = OUTPUT_SELECT_MSG, .handler = handle_output_select_msg},
/* Box control */
{.type = MOUSE_ZOOM_MSG, .handler = handle_mouse_zoom_msg},
{.type = KBD_SET_REPORT_MSG, .handler = handle_set_report_msg},
@ -77,7 +77,7 @@ const uart_handler_t uart_handler[] = {
{.type = SYNC_BORDERS_MSG, .handler = handle_sync_borders_msg},
{.type = FLASH_LED_MSG, .handler = handle_flash_led_msg},
{.type = CONSUMER_CONTROL_MSG, .handler = handle_consumer_control_msg},
/* Config */
{.type = WIPE_CONFIG_MSG, .handler = handle_wipe_config_msg},
{.type = SAVE_CONFIG_MSG, .handler = handle_save_config_msg},
@ -90,7 +90,7 @@ const uart_handler_t uart_handler[] = {
{.type = RESPONSE_BYTE_MSG, .handler = handle_response_byte_msg},
{.type = FIRMWARE_UPGRADE_MSG, .handler = handle_fw_upgrade_msg},
{.type = HEARTBEAT_MSG, .handler = handle_heartbeat_msg},
{.type = HEARTBEAT_MSG, .handler = handle_heartbeat_msg},
{.type = PROXY_PACKET_MSG, .handler = handle_proxy_msg},
};

View File

@ -28,7 +28,7 @@ uint16_t tud_hid_get_report_cb(uint8_t instance,
uint8_t report_id,
hid_report_type_t report_type,
uint8_t *buffer,
uint16_t request_len) {
uint16_t request_len) {
return 0;
}
@ -46,15 +46,15 @@ void tud_hid_set_report_cb(uint8_t instance,
uint16_t bufsize) {
/* We received a report on the config report ID */
if (instance == ITF_NUM_HID_VENDOR && report_id == REPORT_ID_VENDOR) {
if (instance == ITF_NUM_HID_VENDOR && report_id == REPORT_ID_VENDOR) {
/* Security - only if config mode is enabled are we allowed to do anything. While the report_id
isn't even advertised when not in config mode, security must always be explicit and never assume */
isn't even advertised when not in config mode, security must always be explicit and never assume */
if (!global_state.config_mode_active)
return;
/* We insist on a fixed size packet. No overflows. */
if (bufsize != RAW_PACKET_LENGTH)
return;
return;
uart_packet_t *packet = (uart_packet_t *) (buffer + START_LENGTH);
@ -62,8 +62,8 @@ void tud_hid_set_report_cb(uint8_t instance,
if (!validate_packet(packet))
return;
process_packet(packet, &global_state);
}
process_packet(packet, &global_state);
}
/* Only other set report we care about is LED state change, and that's exactly 1 byte long */
if (report_id != REPORT_ID_KEYBOARD || bufsize != 1 || report_type != HID_REPORT_TYPE_OUTPUT)
@ -125,36 +125,36 @@ void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) {
memset(iface, 0, sizeof(hid_interface_t));
}
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 itf_protocol = tuh_hid_interface_protocol(dev_addr, instance);
if (dev_addr >= MAX_DEVICES || instance > MAX_INTERFACES)
return;
/* Get interface information */
hid_interface_t *iface = &global_state.iface[dev_addr-1][instance];
iface->protocol = tuh_hid_get_protocol(dev_addr, instance);
/* Safeguard against memory corruption in case the number of instances exceeds our maximum */
if (instance >= MAX_INTERFACES)
return;
/* Parse the report descriptor into our internal structure. */
parse_report_descriptor(iface, desc_report, desc_len);
parse_report_descriptor(iface, desc_report, desc_len);
switch (itf_protocol) {
case HID_ITF_PROTOCOL_KEYBOARD:
if (global_state.config.enforce_ports && BOARD_ROLE == OUTPUT_B)
return;
if (global_state.config.force_kbd_boot_protocol)
tuh_hid_set_protocol(dev_addr, instance, HID_PROTOCOL_BOOT);
/* Keeping this is required for setting leds from device set_report callback */
global_state.kbd_dev_addr = dev_addr;
global_state.kbd_instance = instance;
global_state.keyboard_connected = true;
global_state.keyboard_connected = true;
break;
case HID_ITF_PROTOCOL_MOUSE:
@ -167,8 +167,8 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *desc_re
tuh_hid_set_protocol(dev_addr, instance, HID_PROTOCOL_REPORT);
}
break;
case HID_ITF_PROTOCOL_NONE:
case HID_ITF_PROTOCOL_NONE:
break;
}
/* Flash local led to indicate a device was connected */
@ -177,7 +177,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 */
send_value(ENABLE, FLASH_LED_MSG);
/* Kick off the report querying */
/* Kick off the report querying */
tuh_hid_receive_report(dev_addr, instance);
}
@ -202,7 +202,7 @@ void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t cons
if (receiver != NULL)
receiver((uint8_t *)report, len, itf_protocol, iface);
}
}
}
else if (itf_protocol == HID_ITF_PROTOCOL_KEYBOARD) {
process_keyboard_report((uint8_t *)report, len, itf_protocol, iface);
@ -216,7 +216,7 @@ void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t cons
}
/* Set protocol in a callback. This is tied to an interface, not a specific report ID */
void tuh_hid_set_protocol_complete_cb(uint8_t dev_addr, uint8_t idx, uint8_t protocol) {
void tuh_hid_set_protocol_complete_cb(uint8_t dev_addr, uint8_t idx, uint8_t protocol) {
if (dev_addr >= MAX_DEVICES || idx > MAX_INTERFACES)
return;

View File

@ -33,14 +33,14 @@
// https://github.com/raspberrypi/usb-pid
tusb_desc_device_t const desc_device = DEVICE_DESCRIPTOR(0x2e8a, 0x107c);
// https://pid.codes/1209/C000/
tusb_desc_device_t const desc_device_config = DEVICE_DESCRIPTOR(0x1209, 0xc000);
// Invoked when received GET DEVICE DESCRIPTOR
// Application return pointer to descriptor
uint8_t const *tud_descriptor_device_cb(void) {
if (global_state.config_mode_active)
if (global_state.config_mode_active)
return (uint8_t const *)&desc_device_config;
else
return (uint8_t const *)&desc_device;
@ -75,10 +75,10 @@ uint8_t const *tud_hid_descriptor_report_cb(uint8_t instance) {
case ITF_NUM_HID:
return desc_hid_report;
case ITF_NUM_HID_REL_M:
return desc_hid_report_relmouse;
return desc_hid_report_relmouse;
default:
return desc_hid_report;
}
}
}
bool tud_mouse_report(uint8_t mode, uint8_t buttons, int16_t x, int16_t y, int8_t wheel) {
@ -253,14 +253,14 @@ uint8_t const desc_configuration_config[] = {
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
TUD_CDC_DESCRIPTOR(
ITF_NUM_CDC, STRID_DEBUG, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, CFG_TUD_CDC_EP_BUFSIZE),
#endif
#endif
};
uint8_t const *tud_descriptor_configuration_cb(uint8_t index) {
(void)index; // for multiple configurations
if (global_state.config_mode_active)
return desc_configuration_config;
if (global_state.config_mode_active)
return desc_configuration_config;
else
return desc_configuration;
}

View File

@ -37,7 +37,7 @@ bool verify_checksum(const uart_packet_t *packet) {
}
uint32_t crc32_iter(uint32_t crc, const uint8_t byte) {
return crc32_lookup_table[(byte ^ crc) & 0xff] ^ (crc >> 8);
return crc32_lookup_table[(byte ^ crc) & 0xff] ^ (crc >> 8);
}
/* TODO - use DMA sniffer's built-in CRC32 */
@ -69,12 +69,12 @@ void write_flash_page(uint32_t target_addr, uint8_t *buffer) {
/* Start of sector == first 256-byte page in a 4096 byte block */
bool is_sector_start = (target_addr & 0xf00) == 0;
uint32_t ints = save_and_disable_interrupts();
uint32_t ints = save_and_disable_interrupts();
if (is_sector_start)
flash_range_erase(target_addr, FLASH_SECTOR_SIZE);
flash_range_program(target_addr, buffer, FLASH_PAGE_SIZE);
restore_interrupts(ints);
flash_range_program(target_addr, buffer, FLASH_PAGE_SIZE);
restore_interrupts(ints);
}
void load_config(device_t *state) {
@ -82,8 +82,8 @@ void load_config(device_t *state) {
config_t *running_config = &state->config;
/* Load the flash config first, including the checksum */
memcpy(running_config, config, sizeof(config_t));
memcpy(running_config, config, sizeof(config_t));
/* Calculate and update checksum, size without checksum */
uint8_t checksum = calc_crc32((uint8_t *)running_config, sizeof(config_t) - sizeof(uint32_t));
@ -110,9 +110,9 @@ void save_config(device_t *state) {
/* Copy the config to buffer and pad the rest with zeros */
memcpy(state->page_buffer, raw_config, sizeof(config_t));
memset(state->page_buffer + sizeof(config_t), 0, FLASH_PAGE_SIZE - sizeof(config_t));
memset(state->page_buffer + sizeof(config_t), 0, FLASH_PAGE_SIZE - sizeof(config_t));
/* Write the new config to flash */
/* Write the new config to flash */
write_flash_page((uint32_t)ADDR_CONFIG - XIP_BASE, state->page_buffer);
}
@ -120,10 +120,10 @@ void reset_config_timer(device_t *state) {
/* Once this is reached, we leave the config mode */
state->config_mode_timer = time_us_64() + CONFIG_MODE_TIMEOUT;
}
void _configure_flash_cs(enum gpio_override gpo, uint pin_index) {
hw_write_masked(&ioqspi_hw->io[pin_index].ctrl,
gpo << IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_LSB,
hw_write_masked(&ioqspi_hw->io[pin_index].ctrl,
gpo << IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_LSB,
IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_BITS);
}
@ -152,11 +152,11 @@ void request_byte(device_t *state, uint32_t address) {
};
state->fw.byte_done = false;
queue_try_add(&global_state.uart_tx_queue, &packet);
queue_try_add(&global_state.uart_tx_queue, &packet);
}
void reboot(void) {
*((volatile uint32_t*)(PPB_BASE + 0x0ED0C)) = 0x5FA0004;
*((volatile uint32_t*)(PPB_BASE + 0x0ED0C)) = 0x5FA0004;
}
bool is_start_of_packet(device_t *state) {
@ -204,8 +204,8 @@ bool validate_packet(uart_packet_t *packet) {
uint8_t packet_type = packet->type;
/* Proxied packets are encapsulated in the data field, but same rules apply */
if (packet->type == PROXY_PACKET_MSG)
packet_type = packet->data[0];
if (packet->type == PROXY_PACKET_MSG)
packet_type = packet->data[0];
for (int i = 0; i < ARRAY_SIZE(ALLOWED_PACKETS); i++) {
if (ALLOWED_PACKETS[i] == packet_type)