1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
/*
Fake86: A portable, open-source 8086 PC emulator.
Copyright (C)2010-2013 Mike Chambers
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.
*/
/* sermouse.c: functions to emulate a standard Microsoft-compatible serial mouse. */
#include "config.h"
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "sermouse.h"
extern void set_port_write_redirector (uint16_t startport, uint16_t endport, void *callback);
extern void set_port_read_redirector (uint16_t startport, uint16_t endport, void *callback);
extern void doirq (uint8_t irqnum);
struct sermouse_s sermouse;
void bufsermousedata (uint8_t value) {
if (sermouse.bufptr == 16) return;
if (sermouse.bufptr == 0 ) doirq (4);
sermouse.buf[sermouse.bufptr++] = value;
}
void outsermouse (uint16_t portnum, uint8_t value) {
uint8_t oldreg;
//printf("[DEBUG] Serial mouse, port %X out: %02X\n", portnum, value);
portnum &= 7;
oldreg = sermouse.reg[portnum];
sermouse.reg[portnum] = value;
switch (portnum) {
case 4: //modem control register
if ( (value & 1) != (oldreg & 1) ) { //software toggling of this register
sermouse.bufptr = 0; //causes the mouse to reset and fill the buffer
bufsermousedata ('M'); //with a bunch of ASCII 'M' characters.
bufsermousedata ('M'); //this is intended to be a way for
bufsermousedata ('M'); //drivers to verify that there is
bufsermousedata ('M'); //actually a mouse connected to the port.
bufsermousedata ('M');
bufsermousedata ('M');
}
break;
}
}
uint8_t insermouse (uint16_t portnum) {
uint8_t temp;
//printf("[DEBUG] Serial mouse, port %X in\n", portnum);
portnum &= 7;
switch (portnum) {
case 0: //data receive
temp = sermouse.buf[0];
memmove (sermouse.buf, &sermouse.buf[1], 15);
sermouse.bufptr--;
if (sermouse.bufptr < 0) sermouse.bufptr = 0;
if (sermouse.bufptr > 0) doirq (4);
sermouse.reg[4] = ~sermouse.reg[4] & 1;
return (temp);
case 5: //line status register (read-only)
if (sermouse.bufptr > 0) temp = 1;
else temp = 0;
return (0x1);
return (0x60 | temp);
}
return (sermouse.reg[portnum & 7]);
}
void initsermouse (uint16_t baseport, uint8_t irq) {
sermouse.bufptr = 0;
set_port_write_redirector (baseport, baseport + 7, &outsermouse);
set_port_read_redirector (baseport, baseport + 7, &insermouse);
}
void sermouseevent (uint8_t buttons, int8_t xrel, int8_t yrel) {
uint8_t highbits = 0;
if (xrel < 0) highbits = 3;
else highbits = 0;
if (yrel < 0) highbits |= 12;
bufsermousedata (0x40 | (buttons << 4) | highbits);
bufsermousedata (xrel & 63);
bufsermousedata (yrel & 63);
}
|