Some keyboard related changes.

- Added new devices method register_default_keyboard() and handle keyboard
  events similar to the mouse stuff.
- Prepared removable keyboard support for the "paste bytes" feature.
- Store keyboard type in device object to avoid reading parameter at runtime.
- Related code cleanups.
- TODO #1: Extend USB keypad to full featured keyboard.
- TODO #2: Paste bytes support for USB keyboard.
This commit is contained in:
Volker Ruppert 2020-12-12 21:27:43 +00:00
parent 575ebe9cad
commit 520ca1459e
6 changed files with 79 additions and 50 deletions

View File

@ -72,7 +72,6 @@ void bx_devices_c::init_stubs()
pluginCmosDevice = &stubCmos;
pluginDmaDevice = &stubDma;
pluginHardDrive = &stubHardDrive;
pluginKeyboard = &stubKeyboard;
pluginPicDevice = &stubPic;
pluginPitDevice = &stubPit;
pluginSpeaker = &stubSpeaker;
@ -137,10 +136,13 @@ void bx_devices_c::init(BX_MEM_C *newmem)
}
// removable devices init
bx_keyboard.dev = NULL;
bx_keyboard.gen_scancode = NULL;
for (i=0; i < 2; i++) {
bx_keyboard[i].dev = NULL;
bx_keyboard[i].gen_scancode = NULL;
bx_keyboard[i].paste_bytes = NULL;
}
for (i = 0; i < BX_KEY_NBKEYS; i++) {
bx_keyboard.bxkey_state[i] = 0;
bx_keyboard[0].bxkey_state[i] = 0;
}
for (i=0; i < 2; i++) {
bx_mouse[i].dev = NULL;
@ -1127,19 +1129,32 @@ bx_bool bx_devices_c::is_usb_enabled(void)
}
// removable keyboard/mouse registration
void bx_devices_c::register_removable_keyboard(void *dev, bx_kbd_gen_scancode_t kbd_gen_scancode)
void bx_devices_c::register_default_keyboard(void *dev, bx_kbd_gen_scancode_t kbd_gen_scancode,
bx_kbd_paste_bytes_t kbd_paste_bytes)
{
if (bx_keyboard.dev == NULL) {
bx_keyboard.dev = dev;
bx_keyboard.gen_scancode = kbd_gen_scancode;
if (bx_keyboard[0].dev == NULL) {
bx_keyboard[0].dev = dev;
bx_keyboard[0].gen_scancode = kbd_gen_scancode;
bx_keyboard[0].paste_bytes = kbd_paste_bytes;
}
}
void bx_devices_c::register_removable_keyboard(void *dev, bx_kbd_gen_scancode_t kbd_gen_scancode,
bx_kbd_paste_bytes_t kbd_paste_bytes)
{
if (bx_keyboard[1].dev == NULL) {
bx_keyboard[1].dev = dev;
bx_keyboard[1].gen_scancode = kbd_gen_scancode;
bx_keyboard[1].paste_bytes = kbd_paste_bytes;
}
}
void bx_devices_c::unregister_removable_keyboard(void *dev)
{
if (dev == bx_keyboard.dev) {
bx_keyboard.dev = NULL;
bx_keyboard.gen_scancode = NULL;
if (dev == bx_keyboard[1].dev) {
bx_keyboard[1].dev = NULL;
bx_keyboard[1].gen_scancode = NULL;
bx_keyboard[1].paste_bytes = NULL;
}
}
@ -1177,25 +1192,36 @@ void bx_devices_c::gen_scancode(Bit32u key)
{
bx_bool ret = 0;
bx_keyboard.bxkey_state[key & 0xff] = ((key & BX_KEY_RELEASED) == 0);
if (bx_keyboard.dev != NULL) {
ret = bx_keyboard.gen_scancode(bx_keyboard.dev, key);
bx_keyboard[0].bxkey_state[key & 0xff] = ((key & BX_KEY_RELEASED) == 0);
if (bx_keyboard[1].dev != NULL) {
ret = bx_keyboard[1].gen_scancode(bx_keyboard[1].dev, key);
}
if (ret == 0) {
pluginKeyboard->gen_scancode(key);
if ((ret == 0) && (bx_keyboard[0].dev != NULL)) {
bx_keyboard[0].gen_scancode(bx_keyboard[1].dev, key);
}
}
void bx_devices_c::release_keys()
{
for (int i = 0; i < BX_KEY_NBKEYS; i++) {
if (bx_keyboard.bxkey_state[i]) {
if (bx_keyboard[0].bxkey_state[i]) {
gen_scancode(i | BX_KEY_RELEASED);
bx_keyboard.bxkey_state[i] = 0;
bx_keyboard[0].bxkey_state[i] = 0;
}
}
}
void bx_devices_c::paste_bytes(Bit8u *data, Bit32s length)
{
if ((bx_keyboard[1].dev != NULL) && (bx_keyboard[1].paste_bytes != NULL)) {
bx_keyboard[1].paste_bytes(bx_keyboard[1].dev, data, length);
return;
}
if ((bx_keyboard[0].dev != NULL) && (bx_keyboard[0].paste_bytes != NULL)) {
bx_keyboard[0].paste_bytes(bx_keyboard[0].dev, data, length);
}
}
// common mouse device handlers
void bx_devices_c::mouse_enabled_changed(bx_bool enabled)
{

View File

@ -46,6 +46,7 @@ typedef Bit32u (*bx_read_handler_t)(void *, Bit32u, unsigned);
typedef void (*bx_write_handler_t)(void *, Bit32u, Bit32u, unsigned);
typedef bx_bool (*bx_kbd_gen_scancode_t)(void *, Bit32u);
typedef void (*bx_kbd_paste_bytes_t)(void *, Bit8u *data, Bit32s length);
typedef void (*bx_mouse_enq_t)(void *, int, int, int, unsigned, bx_bool);
typedef void (*bx_mouse_enabled_changed_t)(void *, bx_bool);
@ -175,17 +176,6 @@ protected:
pluginlog->panic("%s called in %s stub. you must not have loaded the %s plugin", #dev, #method, #dev)
//////////////////////////////////////////////////////////////////////
class BOCHSAPI bx_keyb_stub_c : public bx_devmodel_c {
public:
// stubs for bx_keyb_c methods
virtual void gen_scancode(Bit32u key) {
STUBFUNC(keyboard, gen_scancode);
}
virtual void paste_bytes(Bit8u *data, Bit32s length) {
STUBFUNC(keyboard, paste_bytes);
}
};
class BOCHSAPI bx_hard_drive_stub_c : public bx_devmodel_c {
public:
virtual Bit32u virt_read_handler(Bit32u address, unsigned io_len) { return 0; }
@ -418,13 +408,15 @@ public:
Bit32u inp(Bit16u addr, unsigned io_len) BX_CPP_AttrRegparmN(2);
void outp(Bit16u addr, Bit32u value, unsigned io_len) BX_CPP_AttrRegparmN(3);
void register_removable_keyboard(void *dev, bx_kbd_gen_scancode_t kbd_gen_scancode);
void register_default_keyboard(void *dev, bx_kbd_gen_scancode_t kbd_gen_scancode, bx_kbd_paste_bytes_t kbd_paste_bytes);
void register_removable_keyboard(void *dev, bx_kbd_gen_scancode_t kbd_gen_scancode, bx_kbd_paste_bytes_t kbd_paste_bytes);
void unregister_removable_keyboard(void *dev);
void register_default_mouse(void *dev, bx_mouse_enq_t mouse_enq, bx_mouse_enabled_changed_t mouse_enabled_changed);
void register_removable_mouse(void *dev, bx_mouse_enq_t mouse_enq, bx_mouse_enabled_changed_t mouse_enabled_changed);
void unregister_removable_mouse(void *dev);
void gen_scancode(Bit32u key);
void release_keys(void);
void paste_bytes(Bit8u *data, Bit32s length);
void mouse_enabled_changed(bx_bool enabled);
void mouse_motion(int delta_x, int delta_y, int delta_z, unsigned button_state, bx_bool absxy);
@ -447,7 +439,6 @@ public:
bx_dma_stub_c *pluginDmaDevice;
bx_hard_drive_stub_c *pluginHardDrive;
bx_hdimage_ctl_stub_c *pluginHDImageCtl;
bx_keyb_stub_c *pluginKeyboard;
bx_pic_stub_c *pluginPicDevice;
bx_pit_stub_c *pluginPitDevice;
bx_speaker_stub_c *pluginSpeaker;
@ -473,7 +464,6 @@ public:
bx_dma_stub_c stubDma;
bx_hard_drive_stub_c stubHardDrive;
bx_hdimage_ctl_stub_c stubHDImage;
bx_keyb_stub_c stubKeyboard;
bx_pic_stub_c stubPic;
bx_pit_stub_c stubPit;
bx_speaker_stub_c stubSpeaker;
@ -542,8 +532,9 @@ private:
struct {
void *dev;
bx_kbd_gen_scancode_t gen_scancode;
bx_kbd_paste_bytes_t paste_bytes;
bx_bool bxkey_state[BX_KEY_NBKEYS];
} bx_keyboard;
} bx_keyboard[2];
struct {
bx_bool enabled;

View File

@ -2,7 +2,7 @@
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2002-2017 The Bochs Project
// Copyright (C) 2002-2020 The Bochs Project
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@ -60,9 +60,6 @@ int CDECL libkeyboard_LTX_plugin_init(plugin_t *plugin, plugintype_t type)
{
// Create one instance of the keyboard device object.
theKeyboard = new bx_keyb_c();
// Before this plugin was loaded, pluginKeyboard pointed to a stub.
// Now make it point to the real thing.
bx_devices.pluginKeyboard = theKeyboard;
// Register this device.
BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theKeyboard, BX_PLUGIN_KEYBOARD);
return 0; // Success
@ -152,6 +149,7 @@ void bx_keyb_c::init(void)
BX_KEY_THIS s.kbd_controller.inpb = 0;
BX_KEY_THIS s.kbd_controller.outb = 0;
BX_KEY_THIS s.kbd_controller.kbd_type = SIM->get_param_enum(BXPN_KBD_TYPE)->get();
BX_KEY_THIS s.kbd_controller.kbd_clock_enabled = 1;
BX_KEY_THIS s.kbd_controller.aux_clock_enabled = 0;
BX_KEY_THIS s.kbd_controller.allow_irq1 = 1;
@ -202,6 +200,7 @@ void bx_keyb_c::init(void)
BX_KEY_THIS statusbar_id[1] = bx_gui->register_statusitem("CAPS");
BX_KEY_THIS statusbar_id[2] = bx_gui->register_statusitem("SCRL");
DEV_register_default_keyboard(this, gen_scancode_static, paste_bytes_static);
if ((BX_KEY_THIS s.mouse.type == BX_MOUSE_TYPE_PS2) ||
(BX_KEY_THIS s.mouse.type == BX_MOUSE_TYPE_IMPS2)) {
DEV_register_default_mouse(this, mouse_enq_static, mouse_enabled_changed_static);
@ -740,6 +739,11 @@ void bx_keyb_c::service_paste_buf()
BX_KEY_THIS paste_service = 0;
}
void bx_keyb_c::paste_bytes_static(void *dev, Bit8u *bytes, Bit32s length)
{
((bx_keyb_c*)dev)->paste_bytes(bytes, length);
}
// paste_bytes schedules an arbitrary number of ASCII characters to be
// inserted into the hardware queue as it become available. Any previous
// paste which is still in progress will be thrown out. BYTES is a pointer
@ -759,6 +763,12 @@ void bx_keyb_c::paste_bytes(Bit8u *bytes, Bit32s length)
BX_KEY_THIS service_paste_buf();
}
bx_bool bx_keyb_c::gen_scancode_static(void *dev, Bit32u key)
{
((bx_keyb_c*)dev)->gen_scancode(key);
return 1;
}
void bx_keyb_c::gen_scancode(Bit32u key)
{
unsigned char *scancode;
@ -1060,9 +1070,9 @@ void bx_keyb_c::kbd_ctrl_to_kbd(Bit8u value)
// XT sends nothing, AT sends ACK
// MFII with translation sends ACK+ABh+41h
// MFII without translation sends ACK+ABh+83h
if (SIM->get_param_enum(BXPN_KBD_TYPE)->get() != BX_KBD_XT_TYPE) {
if (BX_KEY_THIS s.kbd_controller.kbd_type != BX_KBD_XT_TYPE) {
kbd_enQ(0xFA);
if (SIM->get_param_enum(BXPN_KBD_TYPE)->get() == BX_KBD_MF_TYPE) {
if (BX_KEY_THIS s.kbd_controller.kbd_type == BX_KBD_MF_TYPE) {
kbd_enQ(0xAB);
if(BX_KEY_THIS s.kbd_controller.scancodes_translate)

View File

@ -2,7 +2,7 @@
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2002-2017 The Bochs Project
// Copyright (C) 2002-2020 The Bochs Project
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@ -37,16 +37,13 @@
#define MOUSE_MODE_REMOTE 12
#define MOUSE_MODE_WRAP 13
class bx_keyb_c : public bx_keyb_stub_c {
class bx_keyb_c : public bx_devmodel_c {
public:
bx_keyb_c();
virtual ~bx_keyb_c();
// implement bx_devmodel_c interface
virtual void init(void);
virtual void reset(unsigned type);
// override stubs from bx_keyb_stub_c
virtual void gen_scancode(Bit32u key);
virtual void paste_bytes(Bit8u *data, Bit32s length);
virtual void register_state(void);
virtual void after_restore_state(void);
@ -55,8 +52,13 @@ public:
BX_KEY_SMF void paste_delay_changed(Bit32u value);
private:
static bx_bool gen_scancode_static(void *dev, Bit32u key);
BX_KEY_SMF void gen_scancode(Bit32u key);
static void paste_bytes_static(void *dev, Bit8u *data, Bit32s length);
BX_KEY_SMF void paste_bytes(Bit8u *data, Bit32s length);
BX_KEY_SMF Bit8u get_kbd_enable(void);
BX_KEY_SMF void service_paste_buf ();
BX_KEY_SMF void service_paste_buf();
BX_KEY_SMF void create_mouse_packet(bx_bool force_enq);
BX_KEY_SMF unsigned periodic(Bit32u usec_delta);
@ -100,6 +102,7 @@ private:
bx_bool expecting_scancodes_set;
Bit8u current_scancodes_set;
bx_bool bat_in_progress;
Bit8u kbd_type;
} kbd_controller;
struct mouseStruct {

View File

@ -693,7 +693,7 @@ usb_hid_device_c::usb_hid_device_c(usbdev_type type)
d.device_desc_size = sizeof(bx_keypad_dev_descriptor);
d.config_desc_size = sizeof(bx_keypad_config_descriptor);
}
DEV_register_removable_keyboard((void*)this, gen_scancode_static);
DEV_register_removable_keyboard((void*)this, gen_scancode_static, NULL);
// DEV_register_removable_mouse((void*)this, mouse_enq_static, mouse_enabled_changed);
}
d.vendor_desc = "BOCHS";

View File

@ -149,8 +149,8 @@ extern "C" {
#define DEV_register_timer(a,b,c,d,e,f) bx_pc_system.register_timer(a,b,c,d,e,f)
///////// Removable devices macros
#define DEV_optional_key_enq(a) (bx_devices.optional_key_enq(a))
#define DEV_register_removable_keyboard(a,b) (bx_devices.register_removable_keyboard(a,b))
#define DEV_register_default_keyboard(a,b,c) (bx_devices.register_default_keyboard(a,b,c))
#define DEV_register_removable_keyboard(a,b,c) (bx_devices.register_removable_keyboard(a,b,c))
#define DEV_unregister_removable_keyboard(a) (bx_devices.unregister_removable_keyboard(a))
#define DEV_register_default_mouse(a,b,c) (bx_devices.register_default_mouse(a,b,c))
#define DEV_register_removable_mouse(a,b,c) (bx_devices.register_removable_mouse(a,b,c))
@ -173,8 +173,7 @@ extern "C" {
///////// keyboard macros
#define DEV_kbd_gen_scancode(key) (bx_devices.gen_scancode(key))
#define DEV_kbd_paste_bytes(bytes, count) \
(bx_devices.pluginKeyboard->paste_bytes(bytes,count))
#define DEV_kbd_paste_bytes(bytes, count) (bx_devices.paste_bytes(bytes,count))
#define DEV_kbd_release_keys() (bx_devices.release_keys())
///////// mouse macros