VirtualBox

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

Last change on this file since 83299 was 83299, checked in by vboxsync, 5 years ago

DevPS2: Discard input when device's serial line is disabled. Also discard queued mouse input if protocol changes.

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