diff options
author | Javier <dev.git@javispedro.com> | 2022-03-29 01:15:53 +0200 |
---|---|---|
committer | Javier <dev.git@javispedro.com> | 2022-03-29 01:15:53 +0200 |
commit | a816d1a09b1045fb5c155ac73f3231fcf9d93180 (patch) | |
tree | c4e31e850b9f2afb36acd6119483cf350c33f596 /mousew16.c | |
parent | 67ebca92621aef31ff97705013456e95e60f7fbe (diff) | |
download | vbados-a816d1a09b1045fb5c155ac73f3231fcf9d93180.tar.gz vbados-a816d1a09b1045fb5c155ac73f3231fcf9d93180.zip |
initial import of DOS mouse driver
Diffstat (limited to 'mousew16.c')
-rw-r--r-- | mousew16.c | 342 |
1 files changed, 0 insertions, 342 deletions
diff --git a/mousew16.c b/mousew16.c deleted file mode 100644 index 4d54175..0000000 --- a/mousew16.c +++ /dev/null @@ -1,342 +0,0 @@ -/* - * VBMouse - win16 mouse driver entry points - * Copyright (C) 2022 Javier S. Pedro - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include <windows.h> - -#include "vbox.h" -#include "vboxdev.h" -#include "ps2.h" -#include "int2fwin.h" -#include "mousew16.h" - -/** If 1, actually call VBox services. - * Thus, if 0, this should behave like a plain PS/2 mouse driver. */ -#define ENABLE_VBOX 1 -/** If 1, hook int2f to detect fullscreen DOSBoxes and auto-disable this driver. */ -#define HOOK_INT2F 1 - -/** Logging through the virtualbox backdoor. */ -#define log(...) vbox_logs(__VA_ARGS__) - -#define MOUSE_NUM_BUTTONS 2 - -/** The routine Windows gave us which we should use to report events. */ -static LPFN_MOUSEEVENT eventproc; -/** Current status of the mouse driver (see MOUSEFLAGS_*). */ -static unsigned char mouseflags; -enum { - MOUSEFLAGS_ENABLED = 1 << 0, - MOUSEFLAGS_HAS_VBOX = 1 << 1, - MOUSEFLAGS_VBOX_ENABLED = 1 << 2, - MOUSEFLAGS_HAS_WIN386 = 1 << 3, - MOUSEFLAGS_INT2F_HOOKED = 1 << 4 -}; -/** Last received pressed button status (to compare and see which buttons have been pressed). */ -static unsigned char mousebtnstatus; -/** Existing interrupt2f handler. */ -static LPFN prev_int2f_handler; - -/* This is how events are delivered to Windows */ - -static void send_event(unsigned short Status, short deltaX, short deltaY, short ButtonCount, short extra1, short extra2); -#pragma aux (MOUSEEVENTPROC) send_event = \ - "call dword ptr [eventproc]" - -/* PS/2 BIOS mouse callback. */ - -#pragma code_seg ( "CALLBACKS" ) -static void FAR ps2_mouse_callback(uint8_t status, uint8_t x, uint8_t y, uint8_t z) -{ -#pragma aux (PS2_CB) ps2_mouse_callback - - int sstatus = 0; - int sx = status & PS2M_STATUS_X_NEG ? 0xFF00 | x : x; - int sy = -(status & PS2M_STATUS_Y_NEG ? 0xFF00 | y : y); - - if (!(mouseflags & MOUSEFLAGS_ENABLED)) { - // Likely eventproc is invalid - return; - } - - if (sx || sy) { - sstatus |= SF_MOVEMENT; - } - -#if ENABLE_VBOX - if ((sstatus & SF_MOVEMENT) && (mouseflags & MOUSEFLAGS_VBOX_ENABLED)) { - bool abs; - uint16_t vbx, vby; - // Even if we are connected to VBox, the user may have selected to disable abs positioning - // So only report abs coordinates if it is still enabled. - if (vbox_get_mouse_locked(&abs, &vbx, &vby) == 0 && abs) { - sx = vbx; - sy = vby; - sstatus |= SF_ABSOLUTE; - } - } -#endif - - // Now proceed to see which buttons have been pressed down and/or released - if ((mousebtnstatus & PS2M_STATUS_BUTTON_1) && !(status & PS2M_STATUS_BUTTON_1)) { - sstatus |= SF_B1_UP; - } else if (!(mousebtnstatus & PS2M_STATUS_BUTTON_1) && (status & PS2M_STATUS_BUTTON_1)) { - sstatus |= SF_B1_DOWN; - } - - if ((mousebtnstatus & PS2M_STATUS_BUTTON_2) && !(status & PS2M_STATUS_BUTTON_2)) { - sstatus |= SF_B2_UP; - } else if (!(mousebtnstatus & PS2M_STATUS_BUTTON_2) && (status & PS2M_STATUS_BUTTON_2)) { - sstatus |= SF_B2_DOWN; - } - - mousebtnstatus = status & (PS2M_STATUS_BUTTON_1 | PS2M_STATUS_BUTTON_2); - - if (sstatus) { - send_event(sstatus, sx, sy, MOUSE_NUM_BUTTONS, 0, 0); - } -} - -#if HOOK_INT2F - -static void display_switch_handler(int function) -#pragma aux display_switch_handler parm caller [ax] modify [ax bx cx dx si di] -{ - if (!(mouseflags & MOUSEFLAGS_ENABLED) || !(mouseflags & MOUSEFLAGS_VBOX_ENABLED)) { - return; - } - - switch (function) { - case INT2F_NOTIFY_BACKGROUND_SWITCH: - vbox_logs("Going background\n"); - vbox_set_mouse_locked(false); - break; - case INT2F_NOTIFY_FOREGROUND_SWITCH: - vbox_logs("Going foreground\n"); - vbox_set_mouse_locked(true); - break; - } -} - -/** Interrupt 2F handler, which will be called on some Windows 386 mode events. - * This is more complicated than it should be becaused we have to fetch our DS - * without clobbering any registers whatsoever, and chain back to the previous handler. - * @todo OpenWatcom 2.x insists on calling GETDS from a different code segment, so we can't use __interrupt. */ -static void __declspec(naked) __far int2f_handler(void) -{ - _asm { - ; Preserve data segment - push ds - - ; Load our data segment - push ax - mov ax, SEG prev_int2f_handler ; Let's hope that Windows relocates segments with interrupts disabled - mov ds, ax - pop ax - - ; Check functions we are interested in hooking - cmp ax, 0x4001 ; Notify Background Switch - je handle_it - cmp ax, 0x4002 ; Notify Foreground Switch - je handle_it - - ; Otherwise directly jump to next handler - jmp next_handler - - handle_it: - pushad ; Save and restore 32-bit registers, we may clobber them from C - call display_switch_handler - popad - - next_handler: - ; Store the address of the previous handler - push dword ptr [prev_int2f_handler] - - ; Restore original data segment without touching the stack, - ; since we want to keep the prev handler address at the top - push bp - mov bp, sp - mov ds, [bp + 6] ; Stack looks like 0: bp, 2: prev_int2f_handler, 6: ds - pop bp - - retf 2 - } -} - -#endif /* HOOK_INT2F */ - -#pragma code_seg () - -/* Driver exported functions. */ - -/** DLL entry point (or driver initialization routine). - * The initialization routine should check whether a mouse exists. - * @return nonzero value indicates a mouse exists. - */ -#pragma off (unreferenced); -BOOL FAR PASCAL LibMain(HINSTANCE hInstance, WORD wDataSegment, - WORD wHeapSize, LPSTR lpszCmdLine) -#pragma pop (unreferenced); -{ - // We are not going to bother checking whether a PS2 mouse exists and just assume it does - -#if HOOK_INT2F - // Check now whether we are running under protected mode windows - if (windows_386_enhanced_mode()) { - mouseflags |= MOUSEFLAGS_HAS_WIN386; - } -#endif - -#if ENABLE_VBOX - // However we will check whether VirtualBox exists: - if (vbox_init() == 0) { - vbox_logs("VirtualBox found\n"); - - // VirtualBox connection was succesful, remember that - mouseflags |= MOUSEFLAGS_HAS_VBOX; - } -#endif - - // When running under protected mode Windows, let's tell VMD (the mouse virtualizer) - // what type of mouse we are going to be using - if (mouseflags & MOUSEFLAGS_HAS_WIN386) { - LPFN vmd_entry = win_get_vxd_api_entry(VMD_DEVICE_ID); - if (vmd_entry) { - vmd_set_mouse_type(&vmd_entry, VMD_TYPE_PS2, PS2_MOUSE_INT_VECTOR, 0); - } - } - - return 1; -} - -/** Called by Windows to retrieve information about the mouse hardware. */ -WORD FAR PASCAL Inquire(LPMOUSEINFO lpMouseInfo) -{ - lpMouseInfo->msExist = 1; - lpMouseInfo->msRelative = mouseflags & MOUSEFLAGS_HAS_VBOX ? 0 : 1; - lpMouseInfo->msNumButtons = MOUSE_NUM_BUTTONS; - lpMouseInfo->msRate = 40; - return sizeof(MOUSEINFO); -} - -/** Called by Windows to enable the mouse driver. - * @param lpEventProc Callback function to call when a mouse event happens. */ -VOID FAR PASCAL Enable(LPFN_MOUSEEVENT lpEventProc) -{ - // Store the windows-given callback - cli(); // Write to far pointer may not be atomic, and we could be interrupted mid-write - eventproc = lpEventProc; - sti(); - - if (!(mouseflags & MOUSEFLAGS_ENABLED)) { - // Configure the PS/2 bios and reset the mouse - int err; - if ((err = ps2m_init(PS2_MOUSE_PLAIN_PACKET_SIZE))) { - vbox_logs("PS2 init failure\n"); - return; - } - - // Configure mouse settings; just use the same defaults as Windows. - // Note that protected mode Windows just ignores all of these anyway. - ps2m_set_resolution(3); // 3 = 200 dpi, 8 counts per millimeter - ps2m_set_sample_rate(2); // 2 = 40 reports per second - ps2m_set_scaling_factor(1); // 1 = 1:1 scaling - // Don't check errors for these, we don't care much - - if ((err = ps2m_set_callback(ps2_mouse_callback))) { - vbox_logs("PS2 set handler failure\n"); - return; - } - - if ((err = ps2m_enable(true))) { - vbox_logs("PS2 enable failure\n"); - return; - } - - vbox_logs("PS/2 Enabled!\n"); - mouseflags |= MOUSEFLAGS_ENABLED; - -#if ENABLE_VBOX - if (mouseflags & MOUSEFLAGS_HAS_VBOX) { - if ((err = vbox_alloc_buffers())) { - vbox_logs("VBox alloc failure\n"); - return; - } - - vbox_report_guest_info(VBOXOSTYPE_Win31); - - if ((err = vbox_set_mouse(true))) { - vbox_logs("VBox enable failure\n"); - vbox_free_buffers(); - return; - } - - vbox_logs("VBOX Enabled!\n"); - mouseflags |= MOUSEFLAGS_VBOX_ENABLED; - } -#endif - -#if HOOK_INT2F - if ((mouseflags & MOUSEFLAGS_HAS_WIN386) && (mouseflags & MOUSEFLAGS_VBOX_ENABLED)) { - cli(); - hook_int2f(&prev_int2f_handler, int2f_handler); - sti(); - vbox_logs("int2F hooked!\n"); - mouseflags |= MOUSEFLAGS_INT2F_HOOKED; - } -#endif - } -} - -/** Called by Windows to disable the mouse driver. */ -VOID FAR PASCAL Disable(VOID) -{ - if (mouseflags & MOUSEFLAGS_ENABLED) { -#if HOOK_INT2F - if (mouseflags & MOUSEFLAGS_INT2F_HOOKED) { - cli(); - unhook_int2f(prev_int2f_handler); - sti(); - vbox_logs("int2F unhooked!\n"); - mouseflags &= ~MOUSEFLAGS_INT2F_HOOKED; - } -#endif - - ps2m_enable(false); - ps2m_set_callback(NULL); - vbox_logs("PS2 Disabled!\n"); - - mouseflags &= ~MOUSEFLAGS_ENABLED; - -#if ENABLE_VBOX - if (mouseflags & MOUSEFLAGS_VBOX_ENABLED) { - vbox_set_mouse(false); - vbox_free_buffers(); - vbox_logs("VBOX Disabled!\n"); - mouseflags &= ~MOUSEFLAGS_VBOX_ENABLED; - } -#endif - } -} - -/** Called by Window to retrieve the interrupt vector number used by this driver, or -1. */ -int FAR PASCAL MouseGetIntVect(VOID) -{ - return PS2_MOUSE_INT_VECTOR; -} - |