forked from rasteri/HIDman
-
Notifications
You must be signed in to change notification settings - Fork 0
/
mouse.c
190 lines (163 loc) · 4.61 KB
/
mouse.c
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
/*
mouse.c
Keeps track of a particular mouse output channel
*/
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "ch559.h"
#include "util.h"
#include "usbhost.h"
#include "uart.h"
#include "ps2.h"
#include "data.h"
#include "ps2protocol.h"
#include "menu.h"
#include "mouse.h"
int16_t Ps2MouseScalingTable[] = {-9, -6, -3, -1, -1, 0, 1, 1, 3, 6, 9};
MOUSE OutputMice[2];
void InitMice()
{
memset(OutputMice, 0x00, sizeof(OutputMice));
Ps2MouseSetType(MOUSE_PS2_TYPE_STANDARD);
Ps2MouseSetDefaults();
}
uint8_t updates = 0;
void MouseMove(int16_t DeltaX, int16_t DeltaY, int16_t DeltaZ)
{
for (int x = 0; x < 2; x++)
{
MOUSE *m = &OutputMice[x];
m->DeltaX += DeltaX;
m->DeltaY += DeltaY;
m->DeltaZ += DeltaZ;
m->NeedsUpdating = 1;
}
}
uint8_t GetMouseAxisUpdate(MOUSE *m, int16_t* Axis, int16_t* Value, int16_t Min, int16_t Max, uint8_t Downscale)
{
// assume update value won't exceed min/max limit
*Value = *Axis >> Downscale;
// but if it does then cap to limit
if (*Value < Min)
{
*Value = Min;
m->NeedsUpdating = 1;
}
else if (*Value > Max)
{
*Value = Max;
m->NeedsUpdating = 1;
}
// decrease delta by update value (delta is zeroed if limits were not exceeded, otherwise we have leftovers)
// note that we can do power of two downscaling just by two bit shifts, no floating point maths needed
*Axis -= *Value << Downscale;
}
uint8_t GetMouseUpdate(uint8_t MouseNo, int16_t Min, int16_t Max, int16_t *X, int16_t *Y, int16_t *Z, uint8_t *Buttons, bool Accelerate, uint8_t Downscale)
{
MOUSE *m = &OutputMice[MouseNo];
if (MouseNo == MOUSE_PORT_PS2 && m->Ps2DataReporting == MOUSE_PS2_REPORTING_OFF)
{
// ps2 mouse and data reporting is off - no matter if update is needed or not, we do not give one
return 0;
}
if (m->NeedsUpdating)
{
// assume it doesn't need updating after this, but can change if deltas exceeds min/max limit
m->NeedsUpdating = 0;
// get deltas for x and y (notice downscaling, this is for ps2 mouse resolution but would work with serial as well)
GetMouseAxisUpdate(m, &m->DeltaX, X, Min, Max, Downscale);
GetMouseAxisUpdate(m, &m->DeltaY, Y, Min, Max, Downscale);
// get delta for z also for ps2 intellimouse
if (MouseNo == MOUSE_PORT_PS2)
GetMouseAxisUpdate(m, &m->DeltaZ, Z, -8, 7, 0);
// get buttons
*Buttons = m->Buttons;
// apply acceleration (this is for ps2 mouse 2:1 scaling support but in theory could be used with serial mouse)
if (Accelerate)
{
*X = (abs(*X) < 6 ? Ps2MouseScalingTable[(*X)+5] : (*X)*2);
*Y = (abs(*Y) < 6 ? Ps2MouseScalingTable[(*Y)+5] : (*Y)*2);
}
return 1;
}
else
return 0;
}
void MouseClick(uint8_t Button)
{
for (int x = 0; x < 2; x++)
{
MOUSE *m = &OutputMice[x];
m->Buttons |= 1 << Button;
m->NeedsUpdating = 1;
}
}
void MouseUnclick(uint8_t Button)
{
for (int x = 0; x < 2; x++)
{
MOUSE *m = &OutputMice[x];
m->Buttons &= ~(1 << Button);
m->NeedsUpdating = 1;
}
}
void MouseSet(uint8_t Button, uint8_t value)
{
for (int x = 0; x < 2; x++)
{
MOUSE *m = &OutputMice[x];
if (value)
m->Buttons |= 1 << Button;
else
m->Buttons &= ~(1 << Button);
m->NeedsUpdating = 1;
}
}
void Ps2MouseSetDelta(uint8_t DeltaX, uint8_t DeltaY, uint8_t DeltaZ)
{
MOUSE *m = &OutputMice[MOUSE_PORT_PS2];
m->DeltaX = DeltaX;
m->DeltaY = DeltaY;
m->DeltaZ = DeltaZ;
}
void Ps2MouseSetType(uint8_t Type)
{
MOUSE *m = &OutputMice[MOUSE_PORT_PS2];
m->Ps2Type = Type;
}
void Ps2MouseSetMode(uint8_t Mode) {
// TODO: implement (does anything use remote or wrap mode?)
MOUSE *m = &OutputMice[MOUSE_PORT_PS2];
m->Ps2Mode = Mode;
Ps2MouseSetDelta(0, 0, 0);
}
void Ps2MouseSetRate(uint8_t Rate) {
// TODO: implement
MOUSE *m = &OutputMice[MOUSE_PORT_PS2];
m->Ps2Rate = Rate;
Ps2MouseSetDelta(0, 0, 0);
}
void Ps2MouseSetResolution(uint8_t Resolution) {
MOUSE *m = &OutputMice[MOUSE_PORT_PS2];
m->Ps2Resolution = Resolution;
Ps2MouseSetDelta(0, 0, 0);
}
void Ps2MouseSetScaling(uint8_t Scaling) {
MOUSE *m = &OutputMice[MOUSE_PORT_PS2];
m->Ps2Scaling = Scaling;
}
void Ps2MouseSetReporting(bool Reporting) {
MOUSE *m = &OutputMice[MOUSE_PORT_PS2];
m->Ps2DataReporting = Reporting;
Ps2MouseSetDelta(0, 0, 0);
}
void Ps2MouseSetDefaults() {
Ps2MouseSetRate(100);
Ps2MouseSetResolution(MOUSE_PS2_RESOLUTION_4CMM);
Ps2MouseSetScaling(MOUSE_PS2_SCALING_1X);
Ps2MouseSetReporting(MOUSE_PS2_REPORTING_OFF);
Ps2MouseSetMode(MOUSE_PS2_MODE_STREAM);
}