addin: improve stability by not blocking on reads
This commit is contained in:
parent
9e76db9e7e
commit
fb9174197f
|
@ -3,8 +3,15 @@
|
|||
#include <gint/usb.h>
|
||||
#include <gint/usb-ff-bulk.h>
|
||||
#include <gint/gint.h>
|
||||
#include <fxlibc/printf.h>
|
||||
#include <libprof.h>
|
||||
#include <fxlibc/printf.h>
|
||||
|
||||
/* Debug mode (uses gint perf counters not committed to repository) */
|
||||
// #define DEBUG
|
||||
|
||||
//---
|
||||
// Receiving and displaying video frames
|
||||
//---
|
||||
|
||||
static void process_usb_message(struct usb_fxlink_header const *header)
|
||||
{
|
||||
|
@ -18,59 +25,96 @@ static void process_usb_message(struct usb_fxlink_header const *header)
|
|||
dupdate();
|
||||
return;
|
||||
}
|
||||
#if 0
|
||||
|
||||
#ifdef DEBUG
|
||||
extern prof_t prof_round, prof_core;
|
||||
prof_round = prof_make();
|
||||
prof_core = prof_make();
|
||||
|
||||
uint32_t us = prof_exec({
|
||||
prof_t prof_read = prof_make();
|
||||
prof_enter(prof_read);
|
||||
#endif
|
||||
// TODO: async read for robustness
|
||||
usb_read_sync(usb_ff_bulk_input(), gint_vram, header->size, false);
|
||||
#if 0
|
||||
});
|
||||
|
||||
/* Read the message payload directly into VRAM. We set a timeout so the
|
||||
calculator doesn't freeze if the communication stops midway because the
|
||||
VNC client on the PC was interrupted. */
|
||||
timeout_t tm = timeout_make_ms(250);
|
||||
usb_read_sync_timeout(usb_ff_bulk_input(), gint_vram, header->size, false,
|
||||
&tm);
|
||||
|
||||
#ifdef DEBUG
|
||||
prof_leave(prof_read);
|
||||
dprint_opt(1, 1, C_WHITE, C_BLACK, DTEXT_LEFT, DTEXT_TOP,
|
||||
"%d ms (read %.1D ms, wait %.1D ms)\n",
|
||||
us / 1000,
|
||||
prof_time(prof_read) / 1000,
|
||||
prof_time(prof_round) / 100,
|
||||
prof_time(prof_core) / 100);
|
||||
#endif
|
||||
|
||||
dupdate();
|
||||
}
|
||||
|
||||
#define MAX_PRESSES 16
|
||||
//---
|
||||
// Sending keyboard events
|
||||
//---
|
||||
|
||||
static void handle_events(void)
|
||||
#define MAX_EVENTS_PER_MESSAGE 16
|
||||
struct key_event { uint8_t key; bool down; };
|
||||
|
||||
/* Keyboard data to be sent to the PC whenever a key is pressed */
|
||||
static struct key_event keyinfo[MAX_EVENTS_PER_MESSAGE];
|
||||
/* Whether there is such a transfer in progress */
|
||||
static bool keyinfo_frame = false;
|
||||
|
||||
static void send_keyboard_events_callback(void)
|
||||
{
|
||||
keyinfo_frame = false;
|
||||
}
|
||||
|
||||
static void send_keyboard_events(void)
|
||||
{
|
||||
static uint8_t keyinfo[MAX_PRESSES*2];
|
||||
int i = 0;
|
||||
|
||||
key_event_t ev;
|
||||
while((ev = pollevent()).type != KEYEV_NONE) {
|
||||
if((ev.type == KEYEV_DOWN || ev.type == KEYEV_UP) && i < MAX_PRESSES) {
|
||||
keyinfo[2*i] = ev.key;
|
||||
keyinfo[2*i+1] = (ev.type == KEYEV_DOWN);
|
||||
i++;
|
||||
}
|
||||
/* Filter out repeats and any events past the maximum number */
|
||||
if(ev.type != KEYEV_DOWN && ev.type != KEYEV_UP)
|
||||
continue;
|
||||
if(i >= MAX_EVENTS_PER_MESSAGE)
|
||||
continue;
|
||||
|
||||
keyinfo[i].key = ev.key;
|
||||
keyinfo[i].down = (ev.type == KEYEV_DOWN);
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Send keyboard update via fxlink */
|
||||
if(i > 0 && usb_is_open()) {
|
||||
/* Send keyboard updates via fxlink */
|
||||
if(i > 0 && usb_is_open() && !keyinfo_frame) {
|
||||
usb_fxlink_header_t header;
|
||||
usb_fxlink_fill_header(&header, "cgvm", "pressed-keys", 2*i);
|
||||
|
||||
// TODO: async commit for robustness (write fits in buffer)
|
||||
/* We don't need to use async writes because all of this clearly fits
|
||||
in a single buffer (2 kB) and only the commit communicates */
|
||||
int pipe = usb_ff_bulk_output();
|
||||
usb_write_sync(pipe, &header, sizeof header, false);
|
||||
usb_write_sync(pipe, keyinfo, 2*i, false);
|
||||
usb_commit_sync(pipe);
|
||||
usb_write_sync(pipe, keyinfo, i * sizeof *keyinfo, false);
|
||||
usb_commit_async(pipe, GINT_CALL(send_keyboard_events_callback));
|
||||
|
||||
/* Remember that a transfer is in progress */
|
||||
keyinfo_frame = true;
|
||||
}
|
||||
}
|
||||
|
||||
//--
|
||||
// Main loop
|
||||
//---
|
||||
|
||||
int main(void)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
prof_init();
|
||||
__printf_enable_fixed();
|
||||
#endif
|
||||
|
||||
dclear(C_WHITE);
|
||||
dprint(1, 1, C_BLACK, "Opening USB connection...");
|
||||
|
@ -86,7 +130,7 @@ int main(void)
|
|||
|
||||
struct usb_fxlink_header header;
|
||||
while(1) {
|
||||
handle_events();
|
||||
send_keyboard_events();
|
||||
if(keydown(KEY_MENU))
|
||||
gint_osmenu();
|
||||
if(keydown(KEY_EXIT))
|
||||
|
@ -97,6 +141,8 @@ int main(void)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
prof_quit();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue