forked from TylerWilley/flipper-f-com
-
Notifications
You must be signed in to change notification settings - Fork 0
/
scene_serial.c
159 lines (129 loc) · 5.16 KB
/
scene_serial.c
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/*
Initializes a text box window
Turns on USB serial
Wires up data streams between USB serial and dmcomm
Prints truncated output to text box
On exit, disconnects and shuts down USB serial
TODO: dmcomm outputs a lot of white space, we should
probably, at some point, filter the USB/Dmcomm stuff to
'interesting' data, so the screen isn't mostly blank
*/
#include "flipper.h"
#include "app_state.h"
#include "scenes.h"
#include "dmcomm-lib/fcom.h"
#include "scene_serial.h"
#include <furi_hal_cortex.h>
typedef struct {
UsbUartConfig cfg;
UsbUartState state;
} SceneUsbUartBridge;
static SceneUsbUartBridge* scene_usb_uart;
void usb_uart_tx(void* context, uint8_t* data, size_t len)
{
// USB -> dmcomm
App* app = context;
// Copy data into the flipper UI
char out[65];
memset(out, 0, 65);
memcpy(out, data, len);
furi_check(furi_mutex_acquire(app->text_box_mutex, FuriWaitForever) == FuriStatusOk);
furi_string_cat_str(app->text_box_store, out);
size_t l = furi_string_size(app->text_box_store);
// Trim if necessary
if(l > 128)
furi_string_right(app->text_box_store, l - 128);
furi_check(furi_mutex_release(app->text_box_mutex) == FuriStatusOk);
view_dispatcher_send_custom_event(app->view_dispatcher, SerialCustomEventTextUpdate);
// Send to dmcomm
dmcomm_senddata(app, data, len);
}
void dmcomm_tx(void* context)
{
// dmcomm -> USB
furi_assert(context);
App* app = context;
// Read data from the stream
char out[64];
size_t recieved = 0;
memset(out, 0, 64);
recieved = furi_stream_buffer_receive(
app->dmcomm_output_stream,
&out,
63,
0);
// Copy data into the flipper UI
furi_check(furi_mutex_acquire(app->text_box_mutex, FuriWaitForever) == FuriStatusOk);
furi_string_cat_str(app->text_box_store, out);
size_t len = furi_string_size(app->text_box_store);
// Trim if necessary
if(len > 128)
furi_string_right(app->text_box_store, len - 128);
furi_check(furi_mutex_release(app->text_box_mutex) == FuriStatusOk);
view_dispatcher_send_custom_event(app->view_dispatcher, SerialCustomEventTextUpdate);
// Send to USB
usb_uart_send(app->usb_uart_bridge, (uint8_t*)out, recieved);
}
void fcom_serial_scene_on_enter(void* context) {
FURI_LOG_I(TAG, "fcom_serial_scene_on_enter");
App* app = context;
// Initialize the UI
text_box_reset(app->text_box);
furi_string_reset(app->text_box_store);
furi_string_cat_printf(app->text_box_store, "Starting Serial");
furi_string_push_back(app->text_box_store, '\n');
furi_string_cat_printf(app->text_box_store, "....");
furi_string_push_back(app->text_box_store, '\n');
text_box_set_text(app->text_box, furi_string_get_cstr(app->text_box_store));
text_box_set_focus(app->text_box, TextBoxFocusEnd);
// Initialize USB UART
scene_usb_uart = malloc(sizeof(SceneUsbUartBridge));
scene_usb_uart->cfg.vcp_ch = 0; // 0 disables logging/CLI, 1 runs alongside
scene_usb_uart->cfg.baudrate_mode = 4;
scene_usb_uart->cfg.baudrate = 4; // 9600
scene_usb_uart->cfg.cb = usb_uart_tx;
scene_usb_uart->cfg.ctx = context;
app->usb_uart_bridge = usb_uart_enable(&scene_usb_uart->cfg);
usb_uart_get_config(app->usb_uart_bridge, &scene_usb_uart->cfg);
usb_uart_get_state(app->usb_uart_bridge, &scene_usb_uart->state);
// Link dmcomm output to our callback
set_serial_callback(dmcomm_tx);
// Keep screen on while we're in serial mode
notification_message(app->notification, &sequence_display_backlight_enforce_on);
// Start the UI
view_dispatcher_switch_to_view(app->view_dispatcher, FcomSerialView);
}
bool fcom_serial_scene_on_event(void* context, SceneManagerEvent event) {
FURI_LOG_I(TAG, "fcom_serial_scene_on_event");
App* app = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeTick) {
// Update serial state, we could reference these data counts too if we wanted
//uint32_t tx_cnt_last = scene_usb_uart->state.tx_cnt;
//uint32_t rx_cnt_last = scene_usb_uart->state.rx_cnt;
usb_uart_get_state(app->usb_uart_bridge, &scene_usb_uart->state);
}
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SerialCustomEventTextUpdate) {
// Either serial stream updated the UI text box data
furi_check(furi_mutex_acquire(app->text_box_mutex, FuriWaitForever) == FuriStatusOk);
text_box_set_text(app->text_box, furi_string_get_cstr(app->text_box_store));
furi_check(furi_mutex_release(app->text_box_mutex) == FuriStatusOk);
consumed = true;
}
}
return consumed; //consumed event
}
void fcom_serial_scene_on_exit(void* context) {
FURI_LOG_I(TAG, "fcom_serial_scene_on_exit");
App* app = context;
// Unlink dmcomm output
set_serial_callback(NULL);
// Shutdown the USB CDC device
usb_uart_disable(app->usb_uart_bridge);
free(scene_usb_uart);
// let screen darken
notification_message(app->notification, &sequence_display_backlight_enforce_auto);
// Cancel any command the usb serial user was sending
dmcomm_sendcommand(app, "0\n");
}