// SPDX-License-Identifier: MPL-2.0
#ifndef SH_LIB_KBD_H
#define SH_LIB_KBD_H
#include "std/stdlib.h"
#include "devs/input/event.h"
// Keyboard driver handle structure, driver handles should only be owned by keyboards drivers
typedef struct sh_kbd_DRIVER_HANDLE sh_kbd_DRIVER_HANDLE;
// Keyboard consumer handle structure, used for requests made by consumer
typedef struct sh_kbd_CONSUMER_HANDLE sh_kbd_CONSUMER_HANDLE;
// Keyboard device structure
typedef struct {
  sh_uint8 kbd_id;
  sh_queue_KBD_EVENT *events_queue;
  sh_bool present;
  sh_bool ver_maj;
  sh_bool ver_num;
  sh_bool shift;
  sh_bool alt;
  sh_bool ctrl;
  sh_bool win;
  sh_SPIN_LOCK spinlock;
} sh_kbd_DEVICE;
// Initialize Keyboard input subsystem, should only be called one time
SH_STATUS sh_kbd_init_devs();
// Register the PS2 keyboard, completing the provided handle.
SH_STATUS sh_kbd_register_ps2(sh_bool is_present,sh_kbd_DRIVER_HANDLE **handle);
// Register any others keyboard, completing the provided handle, that should be used only by the keyboard driver for using the keyboard subsystem API
SH_STATUS sh_kbd_register(sh_bool is_present,sh_kbd_DRIVER_HANDLE **handle);
#define SH_KBD_FLAG_PRESENT 0U
#define SH_KBD_FLAG_VER_MAJ 1U
#define SH_KBD_FLAG_VER_NUM 2U
#define SH_KBD_FLAG_SHIFT 3U
#define SH_KBD_FLAG_ALT 4U
#define SH_KBD_FLAG_CTRL 5U
#define SH_KBD_FLAG_WIN 6U
// Set any flag in the sh_kbd_DEVICE struct, given that a correct handle has been provided
SH_STATUS sh_kbd_set_flag(sh_kbd_DRIVER_HANDLE *handle,sh_uint8 flag,sh_bool value);
// Push a keyboard event on the keyboard queue, given that a correct handle has been provided
SH_STATUS sh_kbd_push_events(sh_kbd_DRIVER_HANDLE *handle,sh_kbd_EVENT *event);
// Keyboard device enumeration structure
typedef struct {
  sh_uint64 bitmap[4];
} sh_kbd_ENUMERATION;
// Enumerate all keyboard devices id
SH_STATUS sh_kbd_enumerate_devices(sh_kbd_ENUMERATION *enumeration);
// Return a valid consumer handle for the provided keyboard device id
SH_STATUS sh_kbd_get_handle(sh_uint8 kbd_id,sh_kbd_CONSUMER_HANDLE **handle);
// Destroy the provided consumer handle and set the pointer to SH_NULLPTR
SH_STATUS sh_kbd_destroy_handle(sh_kbd_CONSUMER_HANDLE **handle);
// Read any flag in the sh_kbd_DEVICE struct, given that a correct handle has been provided. Accept either a driver or consumer handle, but fail if both handle are provided
SH_STATUS sh_kbd_read_flag(sh_kbd_DRIVER_HANDLE *d_handle,sh_kbd_CONSUMER_HANDLE *c_handle,sh_uint8 flag,sh_bool *value);
#endif
