rockbox/apps/plugins/test_usb.c
William Wilgus a2e5d9563f [Feature] resume TSR plugins after interruption WIP
save tsr plugin path for later

resume tsr plugin when user stops the interrupting plugin

expand return of tsr_exit function to allow
continue, suspend, terminate

tsr plugins check parameter at start to determine if
the plugin is being resumed

Change-Id: I6fc70de664c7771e7dbc9a1af7a831e7b50b1d15
2023-03-25 10:02:43 -04:00

137 lines
3.9 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2022 Aidan MacDonald
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "plugin.h"
#include "logf.h"
#undef DEBUGF
#define DEBUGF(...)
//#define DEBUGF printf
#define EV_EXIT MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 0xFF)
unsigned char stack[DEFAULT_STACK_SIZE];
struct event_queue queue;
int thread_id;
const char* state = "none";
const char* prev_state = "none";
static void main_loop(void)
{
bool exiting = false;
struct queue_event ev;
while(true) {
rb->queue_wait(&queue, &ev);
/* events that are handled whether exiting or not */
switch(ev.id) {
case EV_EXIT:
return;
}
if(exiting)
continue;
/* events handled only when not exiting */
switch(ev.id) {
case SYS_USB_CONNECTED:
prev_state = state;
state = "connected";
logf("test_usb: connect ack %ld", *rb->current_tick);
DEBUGF("test_usb: connect ack %ld\n", *rb->current_tick);
rb->usb_acknowledge(SYS_USB_CONNECTED_ACK);
break;
case SYS_USB_DISCONNECTED:
prev_state = state;
state = "disconnected";
logf("test_usb: disconnect %ld", *rb->current_tick);
DEBUGF("test_usb: disconnect %ld\n", *rb->current_tick);
break;
case SYS_POWEROFF:
case SYS_REBOOT:
prev_state = state;
state = "exiting";
exiting = true;
break;
}
}
}
static void kill_tsr(void)
{
rb->queue_post(&queue, EV_EXIT, 0);
rb->thread_wait(thread_id);
rb->queue_delete(&queue);
}
static int exit_tsr(bool reenter)
{
MENUITEM_STRINGLIST(menu, "USB test menu", NULL,
"Status", "Stop plugin", "Back");
while(true) {
int result = reenter ? rb->do_menu(&menu, NULL, NULL, false) : 1;
switch(result) {
case 0:
rb->splashf(HZ, "State: %s", state);
rb->splashf(HZ, "Prev: %s", prev_state);
break;
case 1:
rb->splashf(HZ, "Stopping USB test thread");
kill_tsr();
return (reenter ? PLUGIN_TSR_TERMINATE : PLUGIN_TSR_SUSPEND);
case 2:
return PLUGIN_TSR_CONTINUE;
}
}
}
static void run_tsr(void)
{
rb->queue_init(&queue, true);
thread_id = rb->create_thread(main_loop, stack, sizeof(stack),
0, "test_usb TSR"
IF_PRIO(, PRIORITY_BACKGROUND)
IF_COP(, CPU));
rb->plugin_tsr(exit_tsr);
}
enum plugin_status plugin_start(const void* parameter)
{
bool resume = (parameter == rb->plugin_tsr);
MENUITEM_STRINGLIST(menu, "USB test menu", NULL,
"Start", "Quit");
switch(!resume ? rb->do_menu(&menu, NULL, NULL, false) : 0) {
case 0:
run_tsr();
rb->splashf(HZ, "USB test thread started");
return PLUGIN_OK;
case 1:
return PLUGIN_OK;
default:
return PLUGIN_ERROR;
}
}