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:
parent
47f72f5ff7
commit
fc39da7d55
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user