diff --git a/CHANGELOG.md b/CHANGELOG.md index b7e00c3c6..3356586b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ customers cannot upgrade their bootloader, its changes are recorded separately. - simulator: simulate a Nova device - Add API call to fetch multiple xpubs at once - Add the option for the simulator to write its memory to file. +- simulator: spin tasks at max speed instead of at the client poll interval ### 9.23.1 - EVM: add HyperEVM (HYPE) and SONIC (S) to known networks diff --git a/test/simulator/simulator.c b/test/simulator/simulator.c index 92edaee37..0c4dd607e 100644 --- a/test/simulator/simulator.c +++ b/test/simulator/simulator.c @@ -28,10 +28,12 @@ #include #include +#include #include #include #include #include +#include #include #include @@ -45,11 +47,6 @@ int commfd; static volatile sig_atomic_t sigint_called = false; static int sockfd; -static int get_usb_message_socket(uint8_t* input) -{ - return read(commfd, input, USB_HID_REPORT_OUT_SIZE); -} - static void send_usb_message_socket(void) { const uint8_t* data = queue_pull(queue_hww_queue()); @@ -63,14 +60,6 @@ static void send_usb_message_socket(void) } } -static void simulate_firmware_execution(const uint8_t* input) -{ - usb_packet_process((const USB_FRAME*)input); - rust_workflow_spin(); - rust_async_usb_spin(); - usb_processing_process(usb_processing_hww()); -} - static void _int_handler(int signum) { (void)signum; @@ -170,13 +159,44 @@ int main(int argc, char* argv[]) } printf("Socket connection setup success\n"); + // Set commfd to non-blocking + int flags = fcntl(commfd, F_GETFL, 0); + if (flags == -1 || fcntl(commfd, F_SETFL, flags | O_NONBLOCK) == -1) { + perror("fcntl"); + close(commfd); + continue; + } + // BitBox02 firmware loop uint8_t input[BUFFER_SIZE]; int temp_len; while (1) { // Simulator polls for USB messages from client and then processes them - if (!get_usb_message_socket(input)) break; - simulate_firmware_execution(input); + + fd_set readfds; + FD_ZERO(&readfds); + FD_SET(commfd, &readfds); + // 0.05ms timeout, so this loop does not lead to 100% CPU usage, but is also not + // unbearably slow. It is a trade-off as we don't have proper waking of our Rust tasks, + // just busy polling. + struct timeval timeout = {0, 500}; + + if (select(commfd + 1, &readfds, NULL, NULL, &timeout) < 0) { + break; + } + + if (FD_ISSET(commfd, &readfds)) { + int bytes_read = read(commfd, input, USB_HID_REPORT_OUT_SIZE); + if (bytes_read == 0) break; + else if (bytes_read > 0) { + usb_packet_process((const USB_FRAME*)input); + } + } + + + usb_processing_process(usb_processing_hww()); + rust_workflow_spin(); + rust_async_usb_spin(); // If the USB message to be sent from firmware is bigger than one packet, // then the simulator sends the message in multiple packets. Packets use