sh: Add a simple interactive shell
This commit is contained in:
parent
7ec221c36d
commit
3c5c92c7c3
@ -1,4 +1,4 @@
|
|||||||
APPS := init sym
|
APPS := init sym sh
|
||||||
|
|
||||||
APPS_DIR := $(LUNA_ROOT)/apps
|
APPS_DIR := $(LUNA_ROOT)/apps
|
||||||
APPS_SRC := $(APPS_DIR)/src
|
APPS_SRC := $(APPS_DIR)/src
|
||||||
|
131
apps/src/init.c
131
apps/src/init.c
@ -46,116 +46,15 @@ int main()
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE* serial = fopen("/dev/serial", "r");
|
|
||||||
if (!serial)
|
|
||||||
{
|
|
||||||
perror("fopen");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (fputs("Hello from init!\n", serial) < 0)
|
|
||||||
{
|
|
||||||
perror("fputs");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (fclose(serial) < 0)
|
|
||||||
{
|
|
||||||
perror("fclose");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Welcome to Luna!\n");
|
printf("Welcome to Luna!\n");
|
||||||
|
|
||||||
printf("Running as PID %ld, PPID %ld\n\n", getpid(), getppid());
|
printf("Running as PID %ld\n", getpid());
|
||||||
|
|
||||||
sleep(1);
|
|
||||||
|
|
||||||
if (print_version()) return 1;
|
if (print_version()) return 1;
|
||||||
|
|
||||||
sleep(2);
|
sleep(1);
|
||||||
|
|
||||||
const char* filename = "/sys/config";
|
|
||||||
|
|
||||||
printf("Opening %s for reading...\n", filename);
|
|
||||||
|
|
||||||
FILE* config = fopen(filename, "r");
|
|
||||||
if (!config)
|
|
||||||
{
|
|
||||||
perror("fopen");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fseek(config, 0, SEEK_END) < 0)
|
|
||||||
{
|
|
||||||
perror("fseek");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
long offset = ftell(config);
|
|
||||||
if (offset < 0)
|
|
||||||
{
|
|
||||||
perror("ftell");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("%s is %ld bytes long\n", filename, offset);
|
|
||||||
|
|
||||||
rewind(config);
|
|
||||||
|
|
||||||
char buf[4096];
|
|
||||||
|
|
||||||
size_t nread = fread(buf, sizeof(buf), 1, config);
|
|
||||||
if (ferror(config)) { perror("fread"); }
|
|
||||||
else
|
|
||||||
{
|
|
||||||
buf[nread] = 0;
|
|
||||||
|
|
||||||
printf("Read %zd bytes\n\n", nread);
|
|
||||||
|
|
||||||
printf("%s", buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fclose(config) < 0) { perror("fclose"); }
|
|
||||||
|
|
||||||
printf("\n\nGot random number %d\n\n", rand());
|
|
||||||
|
|
||||||
sleep(2);
|
|
||||||
|
|
||||||
printf("Press any key to restart.\n\n");
|
|
||||||
|
|
||||||
int stderr_fd = fileno(stderr);
|
|
||||||
int new_stderr_fd = dup(stderr_fd);
|
|
||||||
if (new_stderr_fd < 0)
|
|
||||||
{
|
|
||||||
perror("dup");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
FILE* new_stderr = fdopen(new_stderr_fd, "rw");
|
|
||||||
if (!new_stderr)
|
|
||||||
{
|
|
||||||
perror("fdopen");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(new_stderr, "Bye!\n\n");
|
|
||||||
|
|
||||||
fclose(new_stderr);
|
|
||||||
|
|
||||||
const char* pathname = "/etc";
|
|
||||||
|
|
||||||
printf("Creating directory %s\n", pathname);
|
|
||||||
|
|
||||||
if (mkdir(pathname, 0) < 0)
|
|
||||||
{
|
|
||||||
perror("mkdir");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Success!!\n");
|
|
||||||
|
|
||||||
printf("Forking...\n");
|
|
||||||
|
|
||||||
pid_t child = fork();
|
pid_t child = fork();
|
||||||
|
|
||||||
if (child < 0)
|
if (child < 0)
|
||||||
{
|
{
|
||||||
perror("fork");
|
perror("fork");
|
||||||
@ -163,38 +62,16 @@ int main()
|
|||||||
}
|
}
|
||||||
if (child == 0)
|
if (child == 0)
|
||||||
{
|
{
|
||||||
sleep(1);
|
execv("/bin/sh", NULL);
|
||||||
pid_t child = fork();
|
|
||||||
printf("I am the child (PID %ld), my parent is PID %ld!!\n", getpid(), getppid());
|
|
||||||
if (child) execv("/bin/sym", NULL);
|
|
||||||
else
|
|
||||||
execv("/bin/init", NULL);
|
|
||||||
perror("execv");
|
perror("execv");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else { printf("Success!! Got PID %ld\n", child); }
|
|
||||||
|
|
||||||
child = fork();
|
|
||||||
if (child < 0)
|
|
||||||
{
|
|
||||||
perror("fork");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (child == 0) { *(int*)(0xdeadbeef) = 1234; }
|
|
||||||
|
|
||||||
int status;
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
pid_t result;
|
while (wait(NULL) == 0) // No child has exited yet
|
||||||
while ((result = wait(&status)) == 0) // No child has exited yet
|
|
||||||
{
|
{
|
||||||
msleep(100);
|
msleep(100);
|
||||||
}
|
}
|
||||||
if (result < 0)
|
|
||||||
{
|
|
||||||
perror("wait");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (WIFEXITED(status)) { printf("Child process %ld exited with code %d\n", result, WEXITSTATUS(status)); }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
134
apps/src/sh.c
Normal file
134
apps/src/sh.c
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
#include <luna.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char* buffer;
|
||||||
|
long size;
|
||||||
|
long capacity;
|
||||||
|
} command;
|
||||||
|
|
||||||
|
void show_prompt()
|
||||||
|
{
|
||||||
|
printf("> ");
|
||||||
|
}
|
||||||
|
|
||||||
|
void command_expand(command* cmd, long new_capacity)
|
||||||
|
{
|
||||||
|
char* buffer = realloc(cmd->buffer, new_capacity);
|
||||||
|
if (!buffer)
|
||||||
|
{
|
||||||
|
perror("realloc");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
cmd->buffer = buffer;
|
||||||
|
cmd->capacity = new_capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
void command_push(command* cmd, char c)
|
||||||
|
{
|
||||||
|
if (cmd->size == cmd->capacity) command_expand(cmd, cmd->capacity + 8);
|
||||||
|
cmd->buffer[cmd->size] = c;
|
||||||
|
cmd->size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void command_pop(command* cmd)
|
||||||
|
{
|
||||||
|
cmd->size--;
|
||||||
|
}
|
||||||
|
|
||||||
|
void command_init(command* cmd)
|
||||||
|
{
|
||||||
|
cmd->buffer = malloc(5);
|
||||||
|
cmd->capacity = 5;
|
||||||
|
cmd->size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void command_clear(command* cmd)
|
||||||
|
{
|
||||||
|
free(cmd->buffer);
|
||||||
|
return command_init(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void command_execute(command* cmd)
|
||||||
|
{
|
||||||
|
command_push(cmd, '\0');
|
||||||
|
pid_t child = fork();
|
||||||
|
if (child < 0)
|
||||||
|
{
|
||||||
|
perror(cmd->buffer);
|
||||||
|
command_clear(cmd);
|
||||||
|
show_prompt();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (child == 0)
|
||||||
|
{
|
||||||
|
execv(cmd->buffer, NULL);
|
||||||
|
perror(cmd->buffer);
|
||||||
|
exit(127);
|
||||||
|
}
|
||||||
|
int status;
|
||||||
|
pid_t result;
|
||||||
|
while ((result = waitpid(child, &status, 0)) == 0) { msleep(20); }
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
perror("waitpid");
|
||||||
|
command_clear(cmd);
|
||||||
|
show_prompt();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (WEXITSTATUS(status) != 0) { printf("Exited with code %d\n", WEXITSTATUS(status)); }
|
||||||
|
command_clear(cmd);
|
||||||
|
show_prompt();
|
||||||
|
}
|
||||||
|
|
||||||
|
void command_concat(command* cmd, const char* str)
|
||||||
|
{
|
||||||
|
while (*str)
|
||||||
|
{
|
||||||
|
putchar(*str);
|
||||||
|
if (*str == '\b') { command_pop(cmd); }
|
||||||
|
else if (*str == '\n') { command_execute(cmd); }
|
||||||
|
else
|
||||||
|
command_push(cmd, *str);
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
FILE* fp = fopen("/dev/kbd", "r");
|
||||||
|
if (!fp)
|
||||||
|
{
|
||||||
|
perror("fopen");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
show_prompt();
|
||||||
|
|
||||||
|
char buffer[33];
|
||||||
|
|
||||||
|
command shell_command;
|
||||||
|
command_init(&shell_command);
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
size_t nread = fread(buffer, sizeof(buffer) - 1, 1, fp);
|
||||||
|
if (ferror(fp))
|
||||||
|
{
|
||||||
|
perror("fread");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (feof(fp))
|
||||||
|
{
|
||||||
|
clearerr(fp);
|
||||||
|
msleep(20);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
buffer[nread] = 0;
|
||||||
|
command_concat(&shell_command, buffer);
|
||||||
|
}
|
||||||
|
}
|
11
kernel/include/fs/devices/Keyboard.h
Normal file
11
kernel/include/fs/devices/Keyboard.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "fs/VFS.h"
|
||||||
|
|
||||||
|
namespace KeyboardDevice
|
||||||
|
{
|
||||||
|
VFS::Node* create_new(const char* devname);
|
||||||
|
|
||||||
|
ssize_t read(VFS::Node* node, size_t offset, size_t size, char* buffer);
|
||||||
|
|
||||||
|
void append(char c);
|
||||||
|
}
|
6
kernel/include/misc/Scancodes.h
Normal file
6
kernel/include/misc/Scancodes.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// This should only be used for a keyboard TTY interface. Userspace should translate keyboard scancodes by themselves.
|
||||||
|
char translate_scancode(unsigned char scancode, bool* ignore);
|
||||||
|
|
||||||
|
bool scancode_filter_released(unsigned char* scancode);
|
@ -1,5 +1,6 @@
|
|||||||
#include "fs/devices/DeviceFS.h"
|
#include "fs/devices/DeviceFS.h"
|
||||||
#include "fs/devices/Console.h"
|
#include "fs/devices/Console.h"
|
||||||
|
#include "fs/devices/Keyboard.h"
|
||||||
#include "fs/devices/Random.h"
|
#include "fs/devices/Random.h"
|
||||||
#include "fs/devices/Serial.h"
|
#include "fs/devices/Serial.h"
|
||||||
#include "fs/devices/Version.h"
|
#include "fs/devices/Version.h"
|
||||||
@ -27,6 +28,7 @@ VFS::Node* DeviceFS::get()
|
|||||||
devfs_files[devfs_file_count++] = ConsoleDevice::create_new("console");
|
devfs_files[devfs_file_count++] = ConsoleDevice::create_new("console");
|
||||||
devfs_files[devfs_file_count++] = SerialDevice::create_new("serial");
|
devfs_files[devfs_file_count++] = SerialDevice::create_new("serial");
|
||||||
devfs_files[devfs_file_count++] = RandomDevice::create_new("random");
|
devfs_files[devfs_file_count++] = RandomDevice::create_new("random");
|
||||||
|
devfs_files[devfs_file_count++] = KeyboardDevice::create_new("kbd");
|
||||||
return devfs_root;
|
return devfs_root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
44
kernel/src/fs/devices/Keyboard.cpp
Normal file
44
kernel/src/fs/devices/Keyboard.cpp
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#define MODULE "kbd"
|
||||||
|
|
||||||
|
#include "fs/devices/Keyboard.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "log/Log.h"
|
||||||
|
#include "render/TextRenderer.h"
|
||||||
|
#include "std/stdio.h"
|
||||||
|
#include "std/stdlib.h"
|
||||||
|
#include "std/string.h"
|
||||||
|
|
||||||
|
char* kbd_buffer = nullptr;
|
||||||
|
uint64_t kbd_bufsize = 0;
|
||||||
|
|
||||||
|
VFS::Node* KeyboardDevice::create_new(const char* devname)
|
||||||
|
{
|
||||||
|
VFS::Node* dev = new VFS::Node;
|
||||||
|
dev->read_func = KeyboardDevice::read;
|
||||||
|
dev->inode = 0;
|
||||||
|
dev->length = 0;
|
||||||
|
dev->type = VFS_DEVICE;
|
||||||
|
dev->flags = 0;
|
||||||
|
strncpy(dev->name, devname, sizeof(dev->name));
|
||||||
|
return dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t KeyboardDevice::read(VFS::Node* node, size_t, size_t size, char* buffer)
|
||||||
|
{
|
||||||
|
if (!node) return -1;
|
||||||
|
if (!kbd_buffer) return 0;
|
||||||
|
if (size > kbd_bufsize) size = kbd_bufsize;
|
||||||
|
memcpy(buffer, kbd_buffer, size);
|
||||||
|
memmove(kbd_buffer, kbd_buffer + size, kbd_bufsize - size);
|
||||||
|
kbd_bufsize -= size;
|
||||||
|
kbd_buffer = (char*)krealloc(kbd_buffer, kbd_bufsize);
|
||||||
|
return (ssize_t)size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyboardDevice::append(char c)
|
||||||
|
{
|
||||||
|
kbd_bufsize++;
|
||||||
|
kbd_buffer = (char*)krealloc(
|
||||||
|
kbd_buffer, kbd_bufsize); // FIXME: We should probably not be calling realloc every time a key is pressed.
|
||||||
|
kbd_buffer[kbd_bufsize - 1] = c;
|
||||||
|
}
|
@ -1,10 +1,11 @@
|
|||||||
#define MODULE "irq"
|
#define MODULE "irq"
|
||||||
|
|
||||||
#include "interrupts/IRQ.h"
|
#include "interrupts/IRQ.h"
|
||||||
|
#include "fs/devices/Keyboard.h"
|
||||||
#include "io/IO.h"
|
#include "io/IO.h"
|
||||||
#include "io/PIC.h"
|
#include "io/PIC.h"
|
||||||
#include "log/Log.h"
|
#include "log/Log.h"
|
||||||
#include "misc/reboot.h"
|
#include "misc/Scancodes.h"
|
||||||
#include "rand/Init.h"
|
#include "rand/Init.h"
|
||||||
#include "std/stdio.h"
|
#include "std/stdio.h"
|
||||||
#include "thread/PIT.h"
|
#include "thread/PIT.h"
|
||||||
@ -19,10 +20,11 @@ void IRQ::interrupt_handler(Context* context)
|
|||||||
Scheduler::task_tick(context);
|
Scheduler::task_tick(context);
|
||||||
break;
|
break;
|
||||||
case 1: {
|
case 1: {
|
||||||
[[maybe_unused]] volatile unsigned char scancode = IO::inb(0x60);
|
unsigned char scancode = IO::inb(0x60);
|
||||||
kdbgln("Keyboard key pressed/released, seconds since boot: %ld.%ld", PIT::ms_since_boot / 1000,
|
bool ignore = false;
|
||||||
PIT::ms_since_boot % 1000);
|
char key = translate_scancode(scancode, &ignore);
|
||||||
reboot();
|
if (ignore) break;
|
||||||
|
KeyboardDevice::append(key);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: kwarnln("Unhandled IRQ: %ld", context->irq_number); break;
|
default: kwarnln("Unhandled IRQ: %ld", context->irq_number); break;
|
||||||
|
168
kernel/src/misc/Scancodes.cpp
Normal file
168
kernel/src/misc/Scancodes.cpp
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
#include "misc/Scancodes.h"
|
||||||
|
|
||||||
|
#define SCANCODE_EXTENDED 0xE0
|
||||||
|
|
||||||
|
bool scancode_filter_released(unsigned char* scancode)
|
||||||
|
{
|
||||||
|
if (*scancode > 0x80)
|
||||||
|
{
|
||||||
|
*scancode -= 0x80;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool next_key_ignored = false; // FIXME: Do not ignore extended scancodes.
|
||||||
|
|
||||||
|
static bool left_shifted = false;
|
||||||
|
static bool right_shifted = false;
|
||||||
|
static bool capslock = false;
|
||||||
|
|
||||||
|
static bool should_shift()
|
||||||
|
{
|
||||||
|
if (capslock) return !(left_shifted || right_shifted);
|
||||||
|
return left_shifted || right_shifted;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SCANCODE_LEFT_SHIFT 0x2A
|
||||||
|
#define SCANCODE_RIGHT_SHIFT 0x36
|
||||||
|
#define SCANCODE_CAPS_LOCK 0x3A
|
||||||
|
|
||||||
|
#define SCANCODE_LEFT_CONTROL 0x1D
|
||||||
|
#define SCANCODE_TAB 0x0F
|
||||||
|
#define SCANCODE_LEFT_ALT 0x38
|
||||||
|
#define SCANCODE_F11 0x57
|
||||||
|
#define SCANCODE_F12 0x58
|
||||||
|
|
||||||
|
static bool should_ignore_key(char scancode)
|
||||||
|
{
|
||||||
|
return (scancode > 0x3A && scancode < 0x47) || scancode == SCANCODE_LEFT_CONTROL || scancode == SCANCODE_TAB ||
|
||||||
|
scancode == SCANCODE_LEFT_ALT || scancode == SCANCODE_F11 || scancode == SCANCODE_F12;
|
||||||
|
}
|
||||||
|
|
||||||
|
char keys_normal[] = {
|
||||||
|
'\0',
|
||||||
|
'\1', // escape
|
||||||
|
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b',
|
||||||
|
'\0', // tab
|
||||||
|
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n',
|
||||||
|
'\0', // left ctrl
|
||||||
|
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`',
|
||||||
|
'\0', // left shift
|
||||||
|
'\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/',
|
||||||
|
'\0', // right shift
|
||||||
|
'*', // keypad *
|
||||||
|
'\0', // left alt
|
||||||
|
' ',
|
||||||
|
'\0', // caps lock
|
||||||
|
'\0', // f1
|
||||||
|
'\0', // f2
|
||||||
|
'\0', // f3
|
||||||
|
'\0', // f4
|
||||||
|
'\0', // f5
|
||||||
|
'\0', // f6
|
||||||
|
'\0', // f7
|
||||||
|
'\0', // f8
|
||||||
|
'\0', // f9
|
||||||
|
'\0', // f10
|
||||||
|
'\0', // num lock
|
||||||
|
'\0', // scroll lock
|
||||||
|
'7', // keypad 7
|
||||||
|
'8', // keypad 8
|
||||||
|
'9', // keypad 9
|
||||||
|
'-', // keypad -
|
||||||
|
'4', // keypad 4
|
||||||
|
'5', // keypad 5
|
||||||
|
'6', // keypad 6
|
||||||
|
'+', // keypad +
|
||||||
|
'1', // keypad 1
|
||||||
|
'2', // keypad 2
|
||||||
|
'3', // keypad 3
|
||||||
|
'0', // keypad 0
|
||||||
|
'.', // keypad .
|
||||||
|
};
|
||||||
|
|
||||||
|
char keys_shifted[] = {
|
||||||
|
'\0',
|
||||||
|
'\1', // escape
|
||||||
|
'!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '\b',
|
||||||
|
'\0', // tab
|
||||||
|
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n',
|
||||||
|
'\0', // left ctrl
|
||||||
|
'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~',
|
||||||
|
'\0', // left shift
|
||||||
|
'|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?',
|
||||||
|
'\0', // right shift
|
||||||
|
'*', // keypad *
|
||||||
|
'\0', // left alt
|
||||||
|
' ',
|
||||||
|
'\0', // caps lock
|
||||||
|
'\0', // f1
|
||||||
|
'\0', // f2
|
||||||
|
'\0', // f3
|
||||||
|
'\0', // f4
|
||||||
|
'\0', // f5
|
||||||
|
'\0', // f6
|
||||||
|
'\0', // f7
|
||||||
|
'\0', // f8
|
||||||
|
'\0', // f9
|
||||||
|
'\0', // f10
|
||||||
|
'\0', // num lock
|
||||||
|
'\0', // scroll lock
|
||||||
|
'7', // keypad 7
|
||||||
|
'8', // keypad 8
|
||||||
|
'9', // keypad 9
|
||||||
|
'-', // keypad -
|
||||||
|
'4', // keypad 4
|
||||||
|
'5', // keypad 5
|
||||||
|
'6', // keypad 6
|
||||||
|
'+', // keypad +
|
||||||
|
'1', // keypad 1
|
||||||
|
'2', // keypad 2
|
||||||
|
'3', // keypad 3
|
||||||
|
'0', // keypad 0
|
||||||
|
'.', // keypad .
|
||||||
|
};
|
||||||
|
|
||||||
|
char translate_scancode(unsigned char scancode, bool* ignore)
|
||||||
|
{
|
||||||
|
if (next_key_ignored)
|
||||||
|
{
|
||||||
|
next_key_ignored = false;
|
||||||
|
*ignore = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (scancode == SCANCODE_EXTENDED)
|
||||||
|
{
|
||||||
|
next_key_ignored = true;
|
||||||
|
*ignore = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
bool released = scancode_filter_released(&scancode);
|
||||||
|
if (scancode == SCANCODE_CAPS_LOCK)
|
||||||
|
{
|
||||||
|
if (!released) { capslock = !capslock; }
|
||||||
|
*ignore = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (scancode == SCANCODE_LEFT_SHIFT)
|
||||||
|
{
|
||||||
|
left_shifted = !released;
|
||||||
|
*ignore = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (scancode == SCANCODE_RIGHT_SHIFT)
|
||||||
|
{
|
||||||
|
right_shifted = !released;
|
||||||
|
*ignore = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (released || should_ignore_key(scancode))
|
||||||
|
{
|
||||||
|
*ignore = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*ignore = false;
|
||||||
|
if (should_shift()) { return keys_shifted[scancode]; }
|
||||||
|
return keys_normal[scancode];
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user