/* Calcite, src/user-apps/terminal/terminal.c
* Copyright 2026 Benji Dial
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
static struct flanterm_context *flanterm_context;
static ipc_dgram_receiver_handle_t input_handle;
static ipc_dgram_receiver_handle_t output_handle;
static struct dispatch_queue *queue;
struct got_output_param {
int dgram_bytes;
void *dgram;
};
static void got_output(void *x) {
struct got_output_param *param = x;
flanterm_write(flanterm_context, param->dgram, param->dgram_bytes);
heap_dealloc(param->dgram, param->dgram_bytes);
heap_dealloc(param, sizeof(struct got_output_param));
}
[[noreturn]] static void output_thread(uint64_t) {
while (1) {
int dgram_bytes = 0;
ipc_receive_dgram(output_handle, 0, &dgram_bytes);
void *dgram = heap_alloc(dgram_bytes);
ipc_receive_dgram(output_handle, dgram, &dgram_bytes);
struct got_output_param *param = heap_alloc(sizeof(struct got_output_param));
param->dgram_bytes = dgram_bytes;
param->dgram = dgram;
dispatch(queue, &got_output, param);
}
}
[[noreturn]] static void input_thread(uint64_t) {
//TODO
while (1)
sleep_ms(1000000000);
}
void main() {
uint64_t output_pipe = ipc_create_private_dgram_pipe();
uint64_t input_pipe = ipc_create_private_dgram_pipe();
ipc_create_private_dgram_receiver(output_pipe, &output_handle);
ipc_create_private_dgram_sender(input_pipe, &input_handle);
struct framebuffer_info fb;
map_framebuffer(&fb);
flanterm_context =
flanterm_fb_init(
&heap_alloc, &heap_dealloc, (void *)fb.fb_base, fb.fb_width,
fb.fb_height, fb.fb_pitch, 8, 16, 8,
8, 8, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0);
queue = create_dispatch_queue();
create_thread(&output_thread, 0);
create_thread(&input_thread, 0);
char input_pipe_hex[17];
to_hex(input_pipe, 16, input_pipe_hex);
input_pipe_hex[16] = 0;
char output_pipe_hex[17];
to_hex(output_pipe, 16, output_pipe_hex);
output_pipe_hex[16] = 0;
const char *envvars[4] = {
"TERMINAL_INPUT_PIPE_ID", input_pipe_hex,
"TERMINAL_OUTPUT_PIPE_ID", output_pipe_hex };
struct process_start_info psi;
psi.forwared_envvar_count = 0;
psi.set_envvar_count = 2;
psi.set_envvars = envvars;
start_elf("root://calcite/apps/shell/shell.elf", &psi);
dispatch_loop(queue);
}