Moved paste feature and keyboard / mouse runtime handlers to the devices code.

The paste feature now basically works with the USB keyboard.
Prepared improvements for the keyboard indicator handling.
This commit is contained in:
Volker Ruppert 2020-12-19 11:00:36 +00:00
parent 47f72f5ff7
commit fc39da7d55
7 changed files with 224 additions and 192 deletions

View File

@ -24,6 +24,7 @@
#include "iodev.h"
#include "gui/keymap.h"
#include "iodev/virt_timer.h"
#include "iodev/slowdown_timer.h"
@ -63,8 +64,13 @@ bx_devices_c::bx_devices_c()
bx_devices_c::~bx_devices_c()
{
// nothing needed for now
timer_handle = BX_NULL_TIMER_HANDLE;
// remove runtime parameter handlers
SIM->get_param_num(BXPN_KBD_PASTE_DELAY)->set_handler(NULL);
SIM->get_param_num(BXPN_MOUSE_ENABLED)->set_handler(NULL);
if (paste.buf != NULL) {
delete [] paste.buf;
}
}
void bx_devices_c::init_stubs()
@ -139,7 +145,7 @@ void bx_devices_c::init(BX_MEM_C *newmem)
for (i=0; i < 2; i++) {
bx_keyboard[i].dev = NULL;
bx_keyboard[i].gen_scancode = NULL;
bx_keyboard[i].paste_bytes = NULL;
bx_keyboard[i].led_mask = 0;
}
for (i = 0; i < BX_KEY_NBKEYS; i++) {
bx_keyboard[0].bxkey_state[i] = 0;
@ -153,6 +159,18 @@ void bx_devices_c::init(BX_MEM_C *newmem)
mouse_captured = SIM->get_param_bool(BXPN_MOUSE_ENABLED)->get();
mouse_type = SIM->get_param_enum(BXPN_MOUSE_TYPE)->get();
// initialize paste feature
paste.buf = NULL;
paste.buf_len = 0;
paste.buf_ptr = 0;
paste.service = 0;
paste.stop = 0;
paste_delay_changed(SIM->get_param_num(BXPN_KBD_PASTE_DELAY)->get());
// init runtime parameters
SIM->get_param_num(BXPN_KBD_PASTE_DELAY)->set_handler(param_handler);
SIM->get_param_num(BXPN_MOUSE_ENABLED)->set_handler(param_handler);
// register as soon as possible - the devices want to have their timers !
bx_virt_timer.init();
bx_slowdown_timer.init();
@ -391,6 +409,9 @@ void bx_devices_c::reset(unsigned type)
mem->disable_smram();
bx_reset_plugins(type);
release_keys();
if (paste.buf != NULL) {
paste.stop = 1;
}
}
void bx_devices_c::register_state()
@ -607,6 +628,12 @@ void bx_devices_c::timer_handler(void *this_ptr)
void bx_devices_c::timer()
{
if (++paste.counter >= paste.delay) {
// after the paste delay, consider adding moving more chars
// from the paste buffer to the keyboard buffer.
service_paste_buf();
paste.counter = 0;
}
SIM->periodic();
if (!bx_pc_system.kill_bochs_request)
bx_gui->handle_events();
@ -1130,12 +1157,13 @@ bx_bool bx_devices_c::is_usb_enabled(void)
// removable keyboard/mouse registration
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)
bx_kbd_get_elements_t kbd_get_elements)
{
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;
bx_keyboard[0].get_elements = kbd_get_elements;
bx_keyboard[0].led_mask = BX_KBD_LED_NUM | BX_KBD_LED_CAPS | BX_KBD_LED_SCRL;
// add keyboard LEDs to the statusbar
statusbar_id[BX_KBD_LED_NUM] = bx_gui->register_statusitem("NUM");
statusbar_id[BX_KBD_LED_CAPS] = bx_gui->register_statusitem("CAPS");
@ -1144,12 +1172,14 @@ void bx_devices_c::register_default_keyboard(void *dev, bx_kbd_gen_scancode_t kb
}
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)
bx_kbd_get_elements_t kbd_get_elements,
Bit8u led_mask)
{
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;
bx_keyboard[1].get_elements = kbd_get_elements;
bx_keyboard[1].led_mask = led_mask;
}
}
@ -1158,7 +1188,7 @@ void bx_devices_c::unregister_removable_keyboard(void *dev)
if (dev == bx_keyboard[1].dev) {
bx_keyboard[1].dev = NULL;
bx_keyboard[1].gen_scancode = NULL;
bx_keyboard[1].paste_bytes = NULL;
bx_keyboard[1].led_mask = 0;
}
}
@ -1197,6 +1227,10 @@ void bx_devices_c::gen_scancode(Bit32u key)
bx_bool ret = 0;
bx_keyboard[0].bxkey_state[key & 0xff] = ((key & BX_KEY_RELEASED) == 0);
if ((paste.buf != NULL) && (!paste.service)) {
paste.stop = 1;
return;
}
if (bx_keyboard[1].dev != NULL) {
ret = bx_keyboard[1].gen_scancode(bx_keyboard[1].dev, key);
}
@ -1205,6 +1239,17 @@ void bx_devices_c::gen_scancode(Bit32u key)
}
}
Bit8u bx_devices_c::kbd_get_elements(void)
{
if (bx_keyboard[1].dev != NULL) {
return bx_keyboard[1].get_elements(bx_keyboard[1].dev);
}
if (bx_keyboard[0].dev != NULL) {
return bx_keyboard[0].get_elements(bx_keyboard[0].dev);
}
return BX_KBD_ELEMENTS;
}
void bx_devices_c::release_keys()
{
for (int i = 0; i < BX_KEY_NBKEYS; i++) {
@ -1215,15 +1260,90 @@ void bx_devices_c::release_keys()
}
}
// service_paste_buf() transfers data from the paste buffer to the hardware
// keyboard buffer. It tries to transfer as many chars as possible at a
// time, but because different chars require different numbers of scancodes
// we have to be conservative. Note that this process depends on the
// keymap tables to know what chars correspond to what keys, and which
// chars require a shift or other modifier.
void bx_devices_c::service_paste_buf()
{
if (!paste.buf) return;
BX_DEBUG(("service_paste_buf: ptr at %d out of %d", paste.buf_ptr, paste.buf_len));
int fill_threshold = 8;
paste.service = 1;
while ((paste.buf_ptr < paste.buf_len) && !paste.stop) {
if (kbd_get_elements() >= fill_threshold) {
paste.service = 0;
return;
}
// there room in the buffer for a keypress and a key release.
// send one keypress and a key release.
Bit8u byte = paste.buf[paste.buf_ptr];
BXKeyEntry *entry = bx_keymap.findAsciiChar(byte);
if (!entry) {
BX_ERROR(("paste character 0x%02x ignored", byte));
} else {
BX_DEBUG(("pasting character 0x%02x. baseKey is %04x", byte, entry->baseKey));
if (entry->modKey != BX_KEYMAP_UNKNOWN)
gen_scancode(entry->modKey);
gen_scancode(entry->baseKey);
gen_scancode(entry->baseKey | BX_KEY_RELEASED);
if (entry->modKey != BX_KEYMAP_UNKNOWN)
gen_scancode(entry->modKey | BX_KEY_RELEASED);
}
paste.buf_ptr++;
}
// reached end of pastebuf. free the memory it was using.
delete [] paste.buf;
paste.buf = NULL;
paste.stop = 0;
paste.service = 0;
}
// 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
// to a region of memory containing the chars to be pasted. When the paste
// is complete, the keyboard code will call delete [] bytes;
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;
BX_DEBUG(("paste_bytes: %d bytes", length));
if (paste.buf) {
BX_ERROR(("previous paste was not completed! %d chars lost",
paste.buf_len - paste.buf_ptr));
delete [] paste.buf; // free the old paste buffer
}
if ((bx_keyboard[0].dev != NULL) && (bx_keyboard[0].paste_bytes != NULL)) {
bx_keyboard[0].paste_bytes(bx_keyboard[0].dev, data, length);
paste.buf = data;
paste.buf_ptr = 0;
paste.buf_len = length;
service_paste_buf();
}
Bit64s bx_devices_c::param_handler(bx_param_c *param, int set, Bit64s val)
{
if (set) {
char pname[BX_PATHNAME_LEN];
param->get_param_path(pname, BX_PATHNAME_LEN);
if (set) {
if (!strcmp(pname, BXPN_KBD_PASTE_DELAY)) {
bx_devices.paste_delay_changed((Bit32u)val);
} else if (!strcmp(pname, BXPN_MOUSE_ENABLED)) {
bx_gui->mouse_enabled_changed(val!=0);
bx_devices.mouse_enabled_changed(val!=0);
} else {
BX_PANIC(("param_handler called with unexpected parameter '%s'", pname));
}
}
}
return val;
}
void bx_devices_c::paste_delay_changed(Bit32u value)
{
paste.delay = value / BX_IODEV_HANDLER_PERIOD;
paste.counter = 0;
BX_INFO(("will paste characters every %d iodev timer ticks", paste.delay));
}
void bx_devices_c::kbd_set_indicator(Bit8u devid, Bit8u ledid, bx_bool state)

View File

@ -39,6 +39,9 @@
#define BX_KBD_LED_CAPS 1
#define BX_KBD_LED_SCRL 2
/* size of internal buffer for keyboard devices */
#define BX_KBD_ELEMENTS 16
/* size of internal buffer for mouse devices */
#define BX_MOUSE_BUFF_SIZE 48
@ -51,7 +54,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 Bit8u (*bx_kbd_get_elements_t)(void *);
typedef void (*bx_mouse_enq_t)(void *, int, int, int, unsigned, bx_bool);
typedef void (*bx_mouse_enabled_changed_t)(void *, bx_bool);
@ -413,13 +416,17 @@ 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_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 register_default_keyboard(void *dev, bx_kbd_gen_scancode_t kbd_gen_scancode,
bx_kbd_get_elements_t kbd_get_elements);
void register_removable_keyboard(void *dev, bx_kbd_gen_scancode_t kbd_gen_scancode,
bx_kbd_get_elements_t kbd_get_elements,
Bit8u led_mask);
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);
Bit8u kbd_get_elements(void);
void release_keys(void);
void paste_bytes(Bit8u *data, Bit32s length);
void kbd_set_indicator(Bit8u devid, Bit8u ledid, bx_bool state);
@ -528,6 +535,11 @@ private:
static Bit32u default_read_handler(void *this_ptr, Bit32u address, unsigned io_len);
static void default_write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
// runtime options / paste feature
static Bit64s param_handler(bx_param_c *param, int set, Bit64s val);
void paste_delay_changed(Bit32u value);
void service_paste_buf();
bx_bool mouse_captured; // host mouse capture enabled
Bit8u mouse_type;
struct {
@ -535,13 +547,46 @@ private:
bx_mouse_enq_t enq_event;
bx_mouse_enabled_changed_t enabled_changed;
} bx_mouse[2];
struct {
void *dev;
bx_kbd_gen_scancode_t gen_scancode;
bx_kbd_paste_bytes_t paste_bytes;
bx_kbd_get_elements_t get_elements;
Bit8u led_mask;
bx_bool bxkey_state[BX_KEY_NBKEYS];
} bx_keyboard[2];
// The paste buffer does NOT exist in the hardware. It is a bochs
// construction that allows the user to "paste" arbitrary length sequences of
// keystrokes into the emulated machine. Since the hardware buffer is only
// 16 bytes, a very small amount of data can be added to the hardware buffer
// at a time. The paste buffer keeps track of the bytes that have not yet
// been pasted.
//
// Lifetime of a paste buffer: The paste data comes from the system
// clipboard, which must be accessed using platform independent code in the
// gui. Because every gui has its own way of managing the clipboard memory
// (in X windows, you're supposed to call Xfree for example), in the platform
// specific code we make a copy of the clipboard buffer with
// "new Bit8u[length]". Then the pointer is passed into
// bx_device_c::paste_bytes, along with the length. The gui code never touches
// the pastebuf again, and does not free it. The devices code is
// responsible for deallocating the paste buffer using delete [] buf. The
// paste buffer is binary data, and it is probably NOT null terminated.
//
// Summary: A paste buffer is allocated (new) in the platform-specific gui
// code, passed to the devices code, and is freed (delete[]) when it is no
// longer needed.
struct {
Bit8u *buf; // ptr to bytes to be pasted, or NULL if none in progress
Bit32u buf_len; // length of pastebuf
Bit32u buf_ptr; // ptr to next byte to be added to hw buffer
Bit32u delay; // number of timer events before paste
Bit32u counter; // count before paste
bx_bool service; // set to 1 when gen_scancode() is called from paste service
bx_bool stop; // stop the current paste operation on keypress or hardware reset
} paste;
struct {
bx_bool enabled;
#if BX_SUPPORT_PCI

View File

@ -74,17 +74,10 @@ bx_keyb_c::bx_keyb_c()
{
put("keyboard", "KBD");
memset(&s, 0, sizeof(s));
pastebuf = NULL;
}
bx_keyb_c::~bx_keyb_c()
{
// remove runtime parameter handlers
SIM->get_param_num(BXPN_KBD_PASTE_DELAY)->set_handler(NULL);
SIM->get_param_num(BXPN_MOUSE_ENABLED)->set_handler(NULL);
if (pastebuf != NULL) {
delete [] pastebuf;
}
SIM->get_bochs_root()->remove("keyboard");
BX_DEBUG(("Exit"));
}
@ -184,33 +177,19 @@ void bx_keyb_c::init(void)
BX_KEY_THIS s.controller_Qsize = 0;
BX_KEY_THIS s.controller_Qsource = 0;
// clear paste buffer
BX_KEY_THIS pastebuf = NULL;
BX_KEY_THIS pastebuf_len = 0;
BX_KEY_THIS pastebuf_ptr = 0;
BX_KEY_THIS paste_delay_changed(SIM->get_param_num(BXPN_KBD_PASTE_DELAY)->get());
BX_KEY_THIS paste_service = 0;
BX_KEY_THIS stop_paste = 0;
// mouse port installed on system board
DEV_cmos_set_reg(0x14, DEV_cmos_get_reg(0x14) | 0x04);
DEV_register_default_keyboard(this, gen_scancode_static, paste_bytes_static);
DEV_register_default_keyboard(this, gen_scancode_static, get_elements_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);
}
// init runtime parameter
SIM->get_param_num(BXPN_KBD_PASTE_DELAY)->set_handler(kbd_param_handler);
SIM->get_param_num(BXPN_MOUSE_ENABLED)->set_handler(kbd_param_handler);
}
void bx_keyb_c::reset(unsigned type)
{
if (BX_KEY_THIS pastebuf != NULL) {
BX_KEY_THIS stop_paste = 1;
}
// Nothing here yet
}
void bx_keyb_c::register_state(void)
@ -285,31 +264,6 @@ void bx_keyb_c::after_restore_state(void)
}
}
Bit64s bx_keyb_c::kbd_param_handler(bx_param_c *param, int set, Bit64s val)
{
if (set) {
char pname[BX_PATHNAME_LEN];
param->get_param_path(pname, BX_PATHNAME_LEN);
if (!strcmp(pname, BXPN_KBD_PASTE_DELAY)) {
BX_KEY_THIS paste_delay_changed((Bit32u)val);
} else if (!strcmp(pname, BXPN_MOUSE_ENABLED)) {
if (set) {
bx_gui->mouse_enabled_changed(val!=0);
DEV_mouse_enabled_changed(val!=0);
}
} else {
BX_PANIC(("kbd_param_handler called with unexpected parameter '%s'", pname));
}
}
return val;
}
void bx_keyb_c::paste_delay_changed(Bit32u value)
{
BX_KEY_THIS pastedelay = value / SIM->get_param_num(BXPN_KBD_SERIAL_DELAY)->get();
BX_INFO(("will paste characters every %d keyboard ticks",BX_KEY_THIS pastedelay));
}
// static IO port read callback handler
// redirects to non-static class handler to avoid virtual functions
@ -693,71 +647,6 @@ void bx_keyb_c::write(Bit32u address, Bit32u value, unsigned io_len)
}
}
// service_paste_buf() transfers data from the paste buffer to the hardware
// keyboard buffer. It tries to transfer as many chars as possible at a
// time, but because different chars require different numbers of scancodes
// we have to be conservative. Note that this process depends on the
// keymap tables to know what chars correspond to what keys, and which
// chars require a shift or other modifier.
void bx_keyb_c::service_paste_buf()
{
if (!BX_KEY_THIS pastebuf) return;
BX_DEBUG(("service_paste_buf: ptr at %d out of %d", BX_KEY_THIS pastebuf_ptr, BX_KEY_THIS pastebuf_len));
int fill_threshold = BX_KBD_ELEMENTS - 8;
BX_KEY_THIS paste_service = 1;
while ((BX_KEY_THIS pastebuf_ptr < BX_KEY_THIS pastebuf_len) && !BX_KEY_THIS stop_paste) {
if (BX_KEY_THIS s.kbd_internal_buffer.num_elements >= fill_threshold) {
BX_KEY_THIS paste_service = 0;
return;
}
// there room in the buffer for a keypress and a key release.
// send one keypress and a key release.
Bit8u byte = BX_KEY_THIS pastebuf[BX_KEY_THIS pastebuf_ptr];
BXKeyEntry *entry = bx_keymap.findAsciiChar(byte);
if (!entry) {
BX_ERROR(("paste character 0x%02x ignored", byte));
} else {
BX_DEBUG(("pasting character 0x%02x. baseKey is %04x", byte, entry->baseKey));
if (entry->modKey != BX_KEYMAP_UNKNOWN)
BX_KEY_THIS gen_scancode(entry->modKey);
BX_KEY_THIS gen_scancode(entry->baseKey);
BX_KEY_THIS gen_scancode(entry->baseKey | BX_KEY_RELEASED);
if (entry->modKey != BX_KEYMAP_UNKNOWN)
BX_KEY_THIS gen_scancode(entry->modKey | BX_KEY_RELEASED);
}
BX_KEY_THIS pastebuf_ptr++;
}
// reached end of pastebuf. free the memory it was using.
delete [] BX_KEY_THIS pastebuf;
BX_KEY_THIS pastebuf = NULL;
BX_KEY_THIS stop_paste = 0;
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
// to a region of memory containing the chars to be pasted. When the paste
// is complete, the keyboard code will call delete [] bytes;
void bx_keyb_c::paste_bytes(Bit8u *bytes, Bit32s length)
{
BX_DEBUG(("paste_bytes: %d bytes", length));
if (BX_KEY_THIS pastebuf) {
BX_ERROR(("previous paste was not completed! %d chars lost",
BX_KEY_THIS pastebuf_len - BX_KEY_THIS pastebuf_ptr));
delete [] BX_KEY_THIS pastebuf; // free the old paste buffer
}
BX_KEY_THIS pastebuf = bytes;
BX_KEY_THIS pastebuf_ptr = 0;
BX_KEY_THIS pastebuf_len = 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);
@ -769,11 +658,6 @@ void bx_keyb_c::gen_scancode(Bit32u key)
unsigned char *scancode;
Bit8u i;
if ((BX_KEY_THIS pastebuf != NULL) && (!BX_KEY_THIS paste_service)) {
BX_KEY_THIS stop_paste = 1;
return;
}
BX_DEBUG(("gen_scancode(): %s %s", bx_keymap.getBXKeyName(key), (key >> 31)?"released":"pressed"));
if (!BX_KEY_THIS s.kbd_controller.scancodes_translate)
@ -815,6 +699,16 @@ void bx_keyb_c::gen_scancode(Bit32u key)
}
}
Bit8u bx_keyb_c::get_elements_static(void *dev)
{
return ((bx_keyb_c*)dev)->get_elements();
}
Bit8u bx_keyb_c::get_elements()
{
return BX_KEY_THIS s.kbd_internal_buffer.num_elements;
}
void BX_CPP_AttrRegparmN(1)
bx_keyb_c::set_kbd_clock_enable(Bit8u value)
@ -1153,20 +1047,10 @@ void bx_keyb_c::timer_handler(void *this_ptr)
unsigned bx_keyb_c::periodic(Bit32u usec_delta)
{
static unsigned count_before_paste=0;
Bit8u retval;
UNUSED(usec_delta);
if (BX_KEY_THIS s.kbd_controller.kbd_clock_enabled) {
if(++count_before_paste >= BX_KEY_THIS pastedelay) {
// after the paste delay, consider adding moving more chars
// from the paste buffer to the keyboard buffer.
BX_KEY_THIS service_paste_buf();
count_before_paste=0;
}
}
retval = BX_KEY_THIS s.kbd_controller.irq1_requested | (BX_KEY_THIS s.kbd_controller.irq12_requested << 1);
BX_KEY_THIS s.kbd_controller.irq1_requested = 0;
BX_KEY_THIS s.kbd_controller.irq12_requested = 0;

View File

@ -21,8 +21,6 @@
#ifndef _PCKEY_H
#define _PCKEY_H
#define BX_KBD_ELEMENTS 16
// these keywords should only be used in keyboard.cc
#if BX_USE_KEY_SMF
# define BX_KEY_SMF static
@ -47,18 +45,13 @@ public:
virtual void register_state(void);
virtual void after_restore_state(void);
// runtime options
static Bit64s kbd_param_handler(bx_param_c *param, int set, Bit64s val);
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);
static Bit8u get_elements_static(void *dev);
BX_KEY_SMF Bit8u get_elements(void);
BX_KEY_SMF Bit8u get_kbd_enable(void);
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);
@ -183,34 +176,6 @@ private:
unsigned controller_Qsource; // 0=keyboard, 1=mouse
} s; // State information for saving/loading
// The paste buffer does NOT exist in the hardware. It is a bochs
// construction that allows the user to "paste" arbitrary length sequences of
// keystrokes into the emulated machine. Since the hardware buffer is only
// 16 bytes, a very small amount of data can be added to the hardware buffer
// at a time. The paste buffer keeps track of the bytes that have not yet
// been pasted.
//
// Lifetime of a paste buffer: The paste data comes from the system
// clipboard, which must be accessed using platform independent code in the
// gui. Because every gui has its own way of managing the clipboard memory
// (in X windows, you're supposed to call Xfree for example), in the platform
// specific code we make a copy of the clipboard buffer with
// "new Bit8u[length]". Then the pointer is passed into
// bx_keyb_c::paste_bytes, along with the length. The gui code never touches
// the pastebuf again, and does not free it. The keyboard code is
// responsible for deallocating the paste buffer using delete [] buf. The
// paste buffer is binary data, and it is probably NOT null terminated.
//
// Summary: A paste buffer is allocated (new) in the platform-specific gui
// code, passed to the keyboard model, and is freed (delete[]) when it is no
// longer needed.
Bit8u *pastebuf; // ptr to bytes to be pasted, or NULL if none in progress
Bit32u pastebuf_len; // length of pastebuf
Bit32u pastebuf_ptr; // ptr to next byte to be added to hw buffer
Bit32u pastedelay; // count before paste
bx_bool paste_service; // set to 1 when gen_scancode() is called from paste service
bx_bool stop_paste; // stop the current paste operation on keypress or hardware reset
BX_KEY_SMF void resetinternals(bx_bool powerup);
BX_KEY_SMF void set_kbd_clock_enable(Bit8u value) BX_CPP_AttrRegparmN(1);
BX_KEY_SMF void set_aux_clock_enable(Bit8u value);

View File

@ -783,6 +783,7 @@ usb_hid_device_c::usb_hid_device_c(usbdev_type type)
DEV_register_removable_mouse((void*)this, mouse_enq_static, mouse_enabled_changed);
bx_gui->set_mouse_mode_absxy(1);
} else if ((d.type == USB_DEV_TYPE_KEYPAD) || (d.type == USB_DEV_TYPE_KEYBOARD)) {
Bit8u led_mask;
if (d.type == USB_DEV_TYPE_KEYPAD) {
strcpy(d.devname, "USB/PS2 Keypad");
} else {
@ -799,7 +800,13 @@ 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, NULL);
if (d.type == USB_DEV_TYPE_KEYPAD) {
led_mask = BX_KBD_LED_NUM;
} else {
led_mask = BX_KBD_LED_NUM | BX_KBD_LED_CAPS | BX_KBD_LED_SCRL;
}
DEV_register_removable_keyboard((void*)this, gen_scancode_static,
get_elements_static, led_mask);
// DEV_register_removable_mouse((void*)this, mouse_enq_static, mouse_enabled_changed);
}
d.vendor_desc = "BOCHS";
@ -843,7 +850,7 @@ void usb_hid_device_c::register_state_specific(bx_list_c *parent)
BXRS_PARAM_BOOL(list, kbd_count, s.kbd_count);
bx_list_c *buffer = new bx_list_c(list, "kbd_buffer", "");
char pname[16];
for (Bit8u i = 0; i < 16; i++) {
for (Bit8u i = 0; i < BX_KBD_ELEMENTS; i++) {
sprintf(pname, "%u", i);
new bx_shadow_num_c(buffer, pname, &s.kbd_buffer[i], BASE_HEX);
}
@ -1197,11 +1204,11 @@ bx_bool usb_hid_device_c::gen_scancode_static(void *dev, Bit32u key)
bx_bool usb_hid_device_c::gen_scancode(Bit32u key)
{
bx_bool released = (key & BX_KEY_RELEASED) != 0;
bx_bool modkey, released = (key & BX_KEY_RELEASED) != 0;
Bit8u code;
key &= ~BX_KEY_RELEASED;
code = usbkbd_conv[key].code;
code = usbkbd_conv[key & ~BX_KEY_RELEASED].code;
modkey = usbkbd_conv[key & ~BX_KEY_RELEASED].modkey;
if (d.type == USB_DEV_TYPE_KEYPAD) {
if ((code < 0x53) || (code > 0x63)) {
return 0;
@ -1210,12 +1217,12 @@ bx_bool usb_hid_device_c::gen_scancode(Bit32u key)
return 1;
}
if (s.has_events) {
if (s.kbd_count < 16) {
if (s.kbd_count < BX_KBD_ELEMENTS) {
s.kbd_buffer[s.kbd_count++] = key;
}
return 1;
}
if (usbkbd_conv[key].modkey) {
if (modkey) {
if (released) {
s.key_pad_packet[0] &= ~code;
} else {
@ -1235,4 +1242,14 @@ bx_bool usb_hid_device_c::gen_scancode(Bit32u key)
return 1;
}
Bit8u usb_hid_device_c::get_elements_static(void *dev)
{
return ((usb_hid_device_c*)dev)->get_elements();
}
Bit8u usb_hid_device_c::get_elements()
{
return s.kbd_count;
}
#endif // BX_SUPPORT_PCI && BX_SUPPORT_PCIUSB

View File

@ -57,11 +57,13 @@ private:
Bit8u indicators;
bx_bool has_events;
Bit8u kbd_count;
Bit32u kbd_buffer[16];
Bit32u kbd_buffer[BX_KBD_ELEMENTS];
} s;
static bx_bool gen_scancode_static(void *dev, Bit32u key);
bx_bool gen_scancode(Bit32u key);
static Bit8u get_elements_static(void *dev);
Bit8u get_elements(void);
static void mouse_enabled_changed(void *dev, bx_bool enabled);
static void mouse_enq_static(void *dev, int delta_x, int delta_y, int delta_z, unsigned button_state, bx_bool absxy);
void mouse_enq(int delta_x, int delta_y, int delta_z, unsigned button_state, bx_bool absxy);

View File

@ -150,7 +150,7 @@ extern "C" {
///////// Removable devices macros
#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_register_removable_keyboard(a,b,c,d) (bx_devices.register_removable_keyboard(a,b,c,d))
#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))
@ -177,8 +177,7 @@ extern "C" {
#define DEV_kbd_release_keys() (bx_devices.release_keys())
#define DEV_kbd_set_indicator(a,b,c) (bx_devices.kbd_set_indicator(a,b,c))
///////// mouse macros
#define DEV_mouse_enabled_changed(en) (bx_devices.mouse_enabled_changed(en))
///////// mouse macro
#define DEV_mouse_motion(dx, dy, dz, bs, absxy) (bx_devices.mouse_motion(dx, dy, dz, bs, absxy))
///////// hard drive macros