summaryrefslogtreecommitdiffstats
path: root/apps/plugins/test_usb.c
blob: 28ef8f7e5f5b79da4e1ee8a910ea4330d5f62a74 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/***************************************************************************
 *             __________               __   ___.
 *   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;
    }
}