VirtualBox

source: vbox/trunk/src/VBox/Devices/Input/DevPS2.h@ 89935

Last change on this file since 89935 was 89935, checked in by vboxsync, 3 years ago

Keyboard: Reworked the release-all-keys mechanism, made sure it's used before switching active keyboard, avoided potential mix-ups when tracking depressed keys (see bugref:10045).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.6 KB
Line 
1/* $Id: DevPS2.h 89935 2021-06-29 06:38:48Z vboxsync $ */
2/** @file
3 * PS/2 devices - Internal header file.
4 */
5
6/*
7 * Copyright (C) 2007-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#ifndef VBOX_INCLUDED_SRC_Input_DevPS2_h
19#define VBOX_INCLUDED_SRC_Input_DevPS2_h
20#ifndef RT_WITHOUT_PRAGMA_ONCE
21# pragma once
22#endif
23
24/** @defgroup grp_devps2 PS/2 Device
25 * @{
26 */
27
28/** Pointer to the shared keyboard (PS/2) controller / device state. */
29typedef struct KBDSTATE *PKBDSTATE;
30
31
32/** @name PS/2 Input Queue Primitive
33 * @{ */
34typedef struct PS2QHDR
35{
36 uint32_t volatile rpos;
37 uint32_t volatile wpos;
38 uint32_t volatile cUsed;
39 uint32_t uPadding;
40 const char *pszDesc;
41} PS2QHDR;
42/** Pointer to a queue header. */
43typedef PS2QHDR *PPS2QHDR;
44
45/** Define a simple PS/2 input device queue. */
46#define DEF_PS2Q_TYPE(name, size) \
47 typedef struct { \
48 PS2QHDR Hdr; \
49 uint8_t abQueue[size]; \
50 } name
51
52void PS2CmnClearQueue(PPS2QHDR pQHdr, size_t cElements);
53void PS2CmnInsertQueue(PPS2QHDR pQHdr, size_t cElements, uint8_t *pbElements, uint8_t bValue);
54int PS2CmnRemoveQueue(PPS2QHDR pQHdr, size_t cElements, uint8_t const *pbElements, uint8_t *pbValue);
55void PS2CmnR3SaveQueue(PCPDMDEVHLPR3 pHlp, PSSMHANDLE pSSM, PPS2QHDR pQHdr, size_t cElements, uint8_t const *pbElements);
56int PS2CmnR3LoadQueue(PCPDMDEVHLPR3 pHlp, PSSMHANDLE pSSM, PPS2QHDR pQHdr, size_t cElements, uint8_t *pbElements);
57
58#define PS2Q_CLEAR(a_pQueue) \
59 PS2CmnClearQueue(&(a_pQueue)->Hdr, RT_ELEMENTS((a_pQueue)->abQueue))
60#define PS2Q_INSERT(a_pQueue, a_bValue) \
61 PS2CmnInsertQueue(&(a_pQueue)->Hdr, RT_ELEMENTS((a_pQueue)->abQueue), (a_pQueue)->abQueue, (a_bValue))
62#define PS2Q_REMOVE(a_pQueue, a_pbValue) \
63 PS2CmnRemoveQueue(&(a_pQueue)->Hdr, RT_ELEMENTS((a_pQueue)->abQueue), (a_pQueue)->abQueue, (a_pbValue))
64#define PS2Q_SAVE(a_pHlp, a_pSSM, a_pQueue) \
65 PS2CmnR3SaveQueue((a_pHlp), (a_pSSM), &(a_pQueue)->Hdr, RT_ELEMENTS((a_pQueue)->abQueue), (a_pQueue)->abQueue)
66#define PS2Q_LOAD(a_pHlp, a_pSSM, a_pQueue) \
67 PS2CmnR3LoadQueue((a_pHlp), (a_pSSM), &(a_pQueue)->Hdr, RT_ELEMENTS((a_pQueue)->abQueue), (a_pQueue)->abQueue)
68#define PS2Q_SIZE(a_pQueue) RT_ELEMENTS((a_pQueue)->abQueue)
69#define PS2Q_COUNT(a_pQueue) ((a_pQueue)->Hdr.cUsed)
70#define PS2Q_RD_POS(a_pQueue) ((a_pQueue)->Hdr.rpos)
71#define PS2Q_WR_POS(a_pQueue) ((a_pQueue)->Hdr.wpos)
72/** @} */
73
74
75/** @defgroup grp_devps2k DevPS2K - Keyboard
76 * @{
77 */
78
79/** @name HID modifier range.
80 * @{ */
81#define HID_MODIFIER_FIRST 0xE0
82#define HID_MODIFIER_LAST 0xE8
83/** @} */
84
85/** @name USB HID additional constants
86 * @{ */
87/** The highest USB usage code reported by VirtualBox. */
88#define VBOX_USB_MAX_USAGE_CODE 0xE7
89/** The size of an array needed to store all USB usage codes */
90#define VBOX_USB_USAGE_ARRAY_SIZE (VBOX_USB_MAX_USAGE_CODE + 1)
91/** @} */
92
93/* Internal keyboard queue sizes. The input queue doesn't need to be
94 * extra huge and the command queue only needs to handle a few bytes.
95 */
96#define KBD_KEY_QUEUE_SIZE 64
97#define KBD_CMD_QUEUE_SIZE 4
98
99DEF_PS2Q_TYPE(KbdKeyQ, KBD_KEY_QUEUE_SIZE);
100DEF_PS2Q_TYPE(KbdCmdQ, KBD_CMD_QUEUE_SIZE);
101
102/** Typematic state. */
103typedef enum {
104 KBD_TMS_IDLE = 0, /* No typematic key active. */
105 KBD_TMS_DELAY = 1, /* In the initial delay period. */
106 KBD_TMS_REPEAT = 2, /* Key repeating at set rate. */
107 KBD_TMS_32BIT_HACK = 0x7fffffff
108} tmatic_state_t;
109
110
111/**
112 * The shared PS/2 keyboard instance data.
113 */
114typedef struct PS2K
115{
116 /** Set if keyboard is enabled ('scans' for input). */
117 bool fScanning;
118 /** Set NumLock is on. */
119 bool fNumLockOn;
120 /** Selected scan set. */
121 uint8_t u8ScanSet;
122 /** Modifier key state. */
123 uint8_t u8Modifiers;
124 /** Currently processed command (if any). */
125 uint8_t u8CurrCmd;
126 /** Status indicator (LED) state. */
127 uint8_t u8LEDs;
128 /** Selected typematic delay/rate. */
129 uint8_t u8TypematicCfg;
130 uint8_t bAlignment1;
131 /** Usage code of current typematic key, if any. */
132 uint32_t u32TypematicKey;
133 /** Current typematic repeat state. */
134 tmatic_state_t enmTypematicState;
135 /** Buffer holding scan codes to be sent to the host. */
136 KbdKeyQ keyQ;
137 /** Command response queue (priority). */
138 KbdCmdQ cmdQ;
139 /** Currently depressed keys. */
140 uint8_t abDepressedKeys[VBOX_USB_USAGE_ARRAY_SIZE];
141 /** Typematic delay in milliseconds. */
142 uint32_t uTypematicDelay;
143 /** Typematic repeat period in milliseconds. */
144 uint32_t uTypematicRepeat;
145 /** Set if the throttle delay is currently active. */
146 bool fThrottleActive;
147 /** Set if the input rate should be throttled. */
148 bool fThrottleEnabled;
149 /** Set if the serial line is disabled on the KBC. */
150 bool fLineDisabled;
151 uint8_t abAlignment2[1];
152
153 /** Command delay timer. */
154 TMTIMERHANDLE hKbdDelayTimer;
155 /** Typematic timer. */
156 TMTIMERHANDLE hKbdTypematicTimer;
157 /** Input throttle timer. */
158 TMTIMERHANDLE hThrottleTimer;
159} PS2K;
160/** Pointer to the shared PS/2 keyboard instance data. */
161typedef PS2K *PPS2K;
162
163
164/**
165 * The PS/2 keyboard instance data for ring-3.
166 */
167typedef struct PS2KR3
168{
169 /** The device instance.
170 * @note Only for getting our bearings in interface methods. */
171 PPDMDEVINSR3 pDevIns;
172
173 /**
174 * Keyboard port - LUN#0.
175 *
176 * @implements PDMIBASE
177 * @implements PDMIKEYBOARDPORT
178 */
179 struct
180 {
181 /** The base interface for the keyboard port. */
182 PDMIBASE IBase;
183 /** The keyboard port base interface. */
184 PDMIKEYBOARDPORT IPort;
185
186 /** The base interface of the attached keyboard driver. */
187 R3PTRTYPE(PPDMIBASE) pDrvBase;
188 /** The keyboard interface of the attached keyboard driver. */
189 R3PTRTYPE(PPDMIKEYBOARDCONNECTOR) pDrv;
190 } Keyboard;
191} PS2KR3;
192/** Pointer to the PS/2 keyboard instance data for ring-3. */
193typedef PS2KR3 *PPS2KR3;
194
195
196int PS2KByteToKbd(PPDMDEVINS pDevIns, PPS2K pThis, uint8_t cmd);
197int PS2KByteFromKbd(PPDMDEVINS pDevIns, PPS2K pThis, uint8_t *pVal);
198
199void PS2KLineDisable(PPS2K pThis);
200void PS2KLineEnable(PPS2K pThis);
201
202int PS2KR3Construct(PPDMDEVINS pDevIns, PPS2K pThis, PPS2KR3 pThisCC, PCFGMNODE pCfg);
203int PS2KR3Attach(PPDMDEVINS pDevIns, PPS2KR3 pThisCC, unsigned iLUN, uint32_t fFlags);
204void PS2KR3Reset(PPDMDEVINS pDevIns, PPS2K pThis, PPS2KR3 pThisCC);
205void PS2KR3SaveState(PPDMDEVINS pDevIns, PPS2K pThis, PSSMHANDLE pSSM);
206int PS2KR3LoadState(PPDMDEVINS pDevIns, PPS2K pThis, PSSMHANDLE pSSM, uint32_t uVersion);
207int PS2KR3LoadDone(PPDMDEVINS pDevIns, PPS2K pThis, PPS2KR3 pThisCC);
208/** @} */
209
210
211/** @defgroup grp_devps2m DevPS2M - Auxiliary Device (Mouse)
212 * @{
213 */
214
215/* Internal mouse queue sizes. The input queue is relatively large,
216 * but the command queue only needs to handle a few bytes.
217 */
218#define AUX_EVT_QUEUE_SIZE 256
219#define AUX_CMD_QUEUE_SIZE 8
220
221DEF_PS2Q_TYPE(AuxEvtQ, AUX_EVT_QUEUE_SIZE);
222DEF_PS2Q_TYPE(AuxCmdQ, AUX_CMD_QUEUE_SIZE);
223
224/** Auxiliary device special modes of operation. */
225typedef enum {
226 AUX_MODE_STD, /* Standard operation. */
227 AUX_MODE_RESET, /* Currently in reset. */
228 AUX_MODE_WRAP /* Wrap mode (echoing input). */
229} PS2M_MODE;
230
231/** Auxiliary device operational state. */
232typedef enum {
233 AUX_STATE_RATE_ERR = RT_BIT(0), /* Invalid rate received. */
234 AUX_STATE_RES_ERR = RT_BIT(1), /* Invalid resolution received. */
235 AUX_STATE_SCALING = RT_BIT(4), /* 2:1 scaling in effect. */
236 AUX_STATE_ENABLED = RT_BIT(5), /* Reporting enabled in stream mode. */
237 AUX_STATE_REMOTE = RT_BIT(6) /* Remote mode (reports on request). */
238} PS2M_STATE;
239
240/** Externally visible state bits. */
241#define AUX_STATE_EXTERNAL (AUX_STATE_SCALING | AUX_STATE_ENABLED | AUX_STATE_REMOTE)
242
243/** Protocols supported by the PS/2 mouse. */
244typedef enum {
245 PS2M_PROTO_PS2STD = 0, /* Standard PS/2 mouse protocol. */
246 PS2M_PROTO_IMPS2 = 3, /* IntelliMouse PS/2 protocol. */
247 PS2M_PROTO_IMEX = 4, /* IntelliMouse Explorer protocol. */
248 PS2M_PROTO_IMEX_HORZ = 5 /* IntelliMouse Explorer with horizontal reports. */
249} PS2M_PROTO;
250
251/** Protocol selection 'knock' states. */
252typedef enum {
253 PS2M_KNOCK_INITIAL,
254 PS2M_KNOCK_1ST,
255 PS2M_KNOCK_IMPS2_2ND,
256 PS2M_KNOCK_IMEX_2ND,
257 PS2M_KNOCK_IMEX_HORZ_2ND
258} PS2M_KNOCK_STATE;
259
260/**
261 * The shared PS/2 auxiliary device instance data.
262 */
263typedef struct PS2M
264{
265 /** Operational state. */
266 uint8_t u8State;
267 /** Configured sampling rate. */
268 uint8_t u8SampleRate;
269 /** Configured resolution. */
270 uint8_t u8Resolution;
271 /** Currently processed command (if any). */
272 uint8_t u8CurrCmd;
273 /** Set if the serial line is disabled on the KBC. */
274 bool fLineDisabled;
275 /** Set if the throttle delay is active. */
276 bool fThrottleActive;
277 /** Set if the throttle delay is active. */
278 bool fDelayReset;
279 /** Operational mode. */
280 PS2M_MODE enmMode;
281 /** Currently used protocol. */
282 PS2M_PROTO enmProtocol;
283 /** Currently used protocol. */
284 PS2M_KNOCK_STATE enmKnockState;
285 /** Buffer holding mouse events to be sent to the host. */
286 AuxEvtQ evtQ;
287 /** Command response queue (priority). */
288 AuxCmdQ cmdQ;
289 /** Accumulated horizontal movement. */
290 int32_t iAccumX;
291 /** Accumulated vertical movement. */
292 int32_t iAccumY;
293 /** Accumulated Z axis (vertical scroll) movement. */
294 int32_t iAccumZ;
295 /** Accumulated W axis (horizontal scroll) movement. */
296 int32_t iAccumW;
297 /** Accumulated button presses. */
298 uint32_t fAccumB;
299 /** Instantaneous button data. */
300 uint32_t fCurrB;
301 /** Button state last sent to the guest. */
302 uint32_t fReportedB;
303 /** Throttling delay in milliseconds. */
304 uint32_t uThrottleDelay;
305
306 /** Command delay timer. */
307 TMTIMERHANDLE hDelayTimer;
308 /** Interrupt throttling timer. */
309 TMTIMERHANDLE hThrottleTimer;
310} PS2M;
311/** Pointer to the shared PS/2 auxiliary device instance data. */
312typedef PS2M *PPS2M;
313
314/**
315 * The PS/2 auxiliary device instance data for ring-3.
316 */
317typedef struct PS2MR3
318{
319 /** The device instance.
320 * @note Only for getting our bearings in interface methods. */
321 PPDMDEVINSR3 pDevIns;
322
323 /**
324 * Mouse port - LUN#1.
325 *
326 * @implements PDMIBASE
327 * @implements PDMIMOUSEPORT
328 */
329 struct
330 {
331 /** The base interface for the mouse port. */
332 PDMIBASE IBase;
333 /** The keyboard port base interface. */
334 PDMIMOUSEPORT IPort;
335
336 /** The base interface of the attached mouse driver. */
337 R3PTRTYPE(PPDMIBASE) pDrvBase;
338 /** The keyboard interface of the attached mouse driver. */
339 R3PTRTYPE(PPDMIMOUSECONNECTOR) pDrv;
340 } Mouse;
341} PS2MR3;
342/** Pointer to the PS/2 auxiliary device instance data for ring-3. */
343typedef PS2MR3 *PPS2MR3;
344
345int PS2MByteToAux(PPDMDEVINS pDevIns, PPS2M pThis, uint8_t cmd);
346int PS2MByteFromAux(PPS2M pThis, uint8_t *pVal);
347
348void PS2MLineDisable(PPS2M pThis);
349void PS2MLineEnable(PPS2M pThis);
350
351int PS2MR3Construct(PPDMDEVINS pDevIns, PPS2M pThis, PPS2MR3 pThisCC);
352int PS2MR3Attach(PPDMDEVINS pDevIns, PPS2MR3 pThisCC, unsigned iLUN, uint32_t fFlags);
353void PS2MR3Reset(PPS2M pThis);
354void PS2MR3SaveState(PPDMDEVINS pDevIns, PPS2M pThis, PSSMHANDLE pSSM);
355int PS2MR3LoadState(PPDMDEVINS pDevIns, PPS2M pThis, PPS2MR3 pThisCC, PSSMHANDLE pSSM, uint32_t uVersion);
356void PS2MR3FixupState(PPS2M pThis, PPS2MR3 pThisCC, uint8_t u8State, uint8_t u8Rate, uint8_t u8Proto);
357/** @} */
358
359
360/**
361 * The shared keyboard controller/device state.
362 *
363 * @note We use the default critical section for serialize data access.
364 */
365typedef struct KBDSTATE
366{
367 uint8_t write_cmd; /* if non zero, write data to port 60 is expected */
368 uint8_t status;
369 uint8_t mode;
370 uint8_t dbbout; /* data buffer byte */
371 /* keyboard state */
372 int32_t translate;
373 int32_t xlat_state;
374
375 /** I/O port 60h. */
376 IOMIOPORTHANDLE hIoPortData;
377 /** I/O port 64h. */
378 IOMIOPORTHANDLE hIoPortCmdStatus;
379
380 /** Shared keyboard state (implemented in separate PS2K module). */
381 PS2K Kbd;
382 /** Shared mouse state (implemented in separate PS2M module). */
383 PS2M Aux;
384} KBDSTATE;
385
386
387/**
388 * The ring-3 keyboard controller/device state.
389 */
390typedef struct KBDSTATER3
391{
392 /** Keyboard state for ring-3 (implemented in separate PS2K module). */
393 PS2KR3 Kbd;
394 /** Mouse state for ring-3 (implemented in separate PS2M module). */
395 PS2MR3 Aux;
396} KBDSTATER3;
397/** Pointer to the keyboard (PS/2) controller / device state for ring-3. */
398typedef KBDSTATER3 *PKBDSTATER3;
399
400
401/* Shared keyboard/aux internal interface. */
402void KBCUpdateInterrupts(PPDMDEVINS pDevIns);
403
404/** @} */
405
406#endif /* !VBOX_INCLUDED_SRC_Input_DevPS2_h */
407
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette