Skip to content

Commit d23a69a

Browse files
committed
Keyboard: Implement Type clipboard text function
1 parent 5986d07 commit d23a69a

4 files changed

Lines changed: 216 additions & 13 deletions

File tree

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ MacHyperVSupport Changelog
1010
- Added support for guest restart via Restart-VM
1111
- Renamed hvshutdown daemon to hvutil to support all userspace-side functions
1212
- Added guest time synchronization support
13+
- Added support for "Type clipboard text" function
1314

1415
#### v0.9.1
1516
- Added initial PCI passthrough support

MacHyperVSupport/Keyboard/HyperVADBMap.hpp renamed to MacHyperVSupport/Keyboard/HyperVADBMaps.hpp

Lines changed: 159 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,25 @@
11
//
2-
// HyperVPS2ToADBMap.hpp
2+
// HyperVPS2ToADBMaps.hpp
33
// Hyper-V keyboard driver
44
//
5-
// Copyright © 2021 Goldfish64. All rights reserved.
5+
// Copyright © 2021-2022 Goldfish64. All rights reserved.
66
//
77

8-
#ifndef HyperVADBMap_h
9-
#define HyperVADBMap_h
8+
#ifndef HyperVADBMaps_hpp
9+
#define HyperVADBMaps_hpp
1010

1111
#define kADBDeadKey 0x80
1212

1313
#define kADBConverterLength 256 * 2 // 0x00~0xff : normal key , 0x100~0x1ff : extended key
1414
#define kADBConverterExStart 256
1515

16+
//
17+
// PS/2 to ADB mappings. Used for standard keyboard input.
18+
//
1619
// PS/2 scancode reference : USB HID to PS/2 Scan Code Translation Table PS/2 Set 1 columns
1720
// http://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/translate.pdf
18-
static const UInt8 PS2ToADBMapStock[kADBConverterLength] =
19-
{
21+
//
22+
static const UInt8 PS2ToADBMapStock[kADBConverterLength] = {
2023
/* ADB AT ANSI Key-Legend
2124
======================== */
2225
kADBDeadKey,// 00
@@ -533,4 +536,154 @@ static const UInt8 PS2ToADBMapStock[kADBConverterLength] =
533536
kADBDeadKey // e0 ff
534537
};
535538

539+
//
540+
// Unicode to ADB mappings. Used for Hyper-V's "type clipboard text" "feature".
541+
//
542+
#define kADBUnicodeShift 0xF000
543+
#define kADBKeyCodeShift 0x38
544+
545+
static const UInt16 UnicodeToADBMap[0x80] = {
546+
//
547+
// Control characters.
548+
//
549+
kADBDeadKey, // 00 NUL
550+
kADBDeadKey, // 01 SOH
551+
kADBDeadKey, // 02 STX
552+
kADBDeadKey, // 03 ETX
553+
kADBDeadKey, // 04 EOT
554+
kADBDeadKey, // 05 ENQ
555+
kADBDeadKey, // 06 ACK
556+
kADBDeadKey, // 07 BEL
557+
0x33, // 08 Backspace
558+
0x30, // 09 Tab
559+
kADBDeadKey, // 0A Line Feed
560+
kADBDeadKey, // 0B VT
561+
kADBDeadKey, // 0C Form Feed
562+
0x24, // 0D Carriage Return
563+
kADBDeadKey, // 0E SO
564+
kADBDeadKey, // 0F SI
565+
566+
kADBDeadKey, // 10 DLE
567+
kADBDeadKey, // 11 DC1
568+
kADBDeadKey, // 12 DC2
569+
kADBDeadKey, // 13 DC3
570+
kADBDeadKey, // 14 DC4
571+
kADBDeadKey, // 15 NAK
572+
kADBDeadKey, // 16 SYN
573+
kADBDeadKey, // 17 ETB
574+
kADBDeadKey, // 18 CAN
575+
kADBDeadKey, // 19 EM
576+
kADBDeadKey, // 1A SUB
577+
0x35, // 1B Escape
578+
kADBDeadKey, // 1C FS
579+
kADBDeadKey, // 1D GS
580+
kADBDeadKey, // 1E GS
581+
kADBDeadKey, // 1F US
582+
583+
//
584+
// ASCII characters.
585+
//
586+
0x31, // 20 Space
587+
0x12 | kADBUnicodeShift, // 21 !
588+
0x27 | kADBUnicodeShift, // 22 "
589+
0x14 | kADBUnicodeShift, // 23 #
590+
0x15 | kADBUnicodeShift, // 24 $
591+
0x17 | kADBUnicodeShift, // 25 %
592+
0x1A | kADBUnicodeShift, // 26 &
593+
0x27, // 27 '
594+
0x19 | kADBUnicodeShift, // 28 (
595+
0x1D | kADBUnicodeShift, // 29 )
596+
0x1C | kADBUnicodeShift, // 2A *
597+
0x18 | kADBUnicodeShift, // 2B +
598+
0x2B, // 2C ,
599+
0x1B, // 2D -
600+
0x2F, // 2E .
601+
0x2C, // 2F /
602+
603+
0x1D, // 30 0
604+
0x12, // 31 1
605+
0x13, // 32 2
606+
0x14, // 33 3
607+
0x15, // 34 4
608+
0x17, // 35 5
609+
0x16, // 36 6
610+
0x1A, // 37 7
611+
0x1C, // 38 8
612+
0x19, // 39 9
613+
0x29 | kADBUnicodeShift, // 3A :
614+
0x29, // 3B ;
615+
0x2B | kADBUnicodeShift, // 3C <
616+
0x18, // 3D =
617+
0x2F | kADBUnicodeShift, // 3E >
618+
0x2C | kADBUnicodeShift, // 3F ?
619+
620+
0x13 | kADBUnicodeShift, // 40 @
621+
0x00 | kADBUnicodeShift, // 41 A
622+
0x0B | kADBUnicodeShift, // 42 B
623+
0x08 | kADBUnicodeShift, // 43 C
624+
0x02 | kADBUnicodeShift, // 44 D
625+
0x0E | kADBUnicodeShift, // 45 E
626+
0x03 | kADBUnicodeShift, // 46 F
627+
0x05 | kADBUnicodeShift, // 47 G
628+
0x04 | kADBUnicodeShift, // 48 H
629+
0x22 | kADBUnicodeShift, // 49 I
630+
0x26 | kADBUnicodeShift, // 4A J
631+
0x28 | kADBUnicodeShift, // 4B K
632+
0x25 | kADBUnicodeShift, // 4C L
633+
0x2E | kADBUnicodeShift, // 4D M
634+
0x2D | kADBUnicodeShift, // 4E N
635+
0x1F | kADBUnicodeShift, // 4F O
636+
637+
0x23 | kADBUnicodeShift, // 50 P
638+
0x0C | kADBUnicodeShift, // 51 Q
639+
0x0F | kADBUnicodeShift, // 52 R
640+
0x01 | kADBUnicodeShift, // 53 S
641+
0x11 | kADBUnicodeShift, // 54 T
642+
0x20 | kADBUnicodeShift, // 55 U
643+
0x09 | kADBUnicodeShift, // 56 V
644+
0x0D | kADBUnicodeShift, // 57 W
645+
0x07 | kADBUnicodeShift, // 58 X
646+
0x10 | kADBUnicodeShift, // 59 Y
647+
0x06 | kADBUnicodeShift, // 5A Z
648+
0x21, // 5B [
649+
0x2A, // 5C \ Backslash
650+
0x1E, // 5D ]
651+
0x16 | kADBUnicodeShift, // 5E ^
652+
0x1B | kADBUnicodeShift, // 5F _
653+
654+
0x32, // 60 `
655+
0x00, // 61 a
656+
0x0B, // 62 b
657+
0x08, // 63 c
658+
0x02, // 64 d
659+
0x0E, // 65 e
660+
0x03, // 66 f
661+
0x05, // 67 g
662+
0x04, // 68 h
663+
0x22, // 69 i
664+
0x26, // 6A j
665+
0x28, // 6B k
666+
0x25, // 6C l
667+
0x2E, // 6D m
668+
0x2D, // 6E n
669+
0x1F, // 6F o
670+
671+
0x23, // 70 p
672+
0x0C, // 71 q
673+
0x0F, // 72 r
674+
0x01, // 73 s
675+
0x11, // 74 t
676+
0x20, // 75 u
677+
0x09, // 76 v
678+
0x0D, // 77 w
679+
0x07, // 78 x
680+
0x10, // 79 y
681+
0x06, // 7A z
682+
0x21 | kADBUnicodeShift, // 7B {
683+
0x2A | kADBUnicodeShift, // 7C |
684+
0x1E | kADBUnicodeShift, // 7D }
685+
0x32 | kADBUnicodeShift, // 7E ~
686+
0x75, // 7F DEL
687+
};
688+
536689
#endif

MacHyperVSupport/Keyboard/HyperVKeyboard.cpp

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
//
77

88
#include "HyperVKeyboard.hpp"
9-
#include "HyperVADBMap.hpp"
9+
#include "HyperVADBMaps.hpp"
1010

1111
OSDefineMetaClassAndStructors(HyperVKeyboard, super);
1212

@@ -97,6 +97,50 @@ IOReturn HyperVKeyboard::connectKeyboard() {
9797
return _hvDevice->writeInbandPacket(&requestMsg, sizeof (requestMsg), true);
9898
}
9999

100+
void HyperVKeyboard::dispatchUnicodeKeyboardEvent(UInt16 unicodeChar, bool isBreak) {
101+
UInt16 keyCode;
102+
UInt64 time;
103+
104+
//
105+
// Ignore break codes as the simulated key goes down and back up within this function.
106+
//
107+
if (isBreak) {
108+
return;
109+
}
110+
111+
if (unicodeChar > arrsize(UnicodeToADBMap)) {
112+
HVDBGLOG("Unknown Unicode character 0x%X break: %u", unicodeChar, isBreak);
113+
return;
114+
}
115+
keyCode = UnicodeToADBMap[unicodeChar];
116+
HVDBGLOG("Handling Unicode character 0x%X keycode: 0x%X shift: %u", unicodeChar,
117+
keyCode, (keyCode & kADBUnicodeShift) ? 1 : 0);
118+
119+
//
120+
// Simulate shift key press for shifted characters.
121+
//
122+
if (keyCode & kADBUnicodeShift) {
123+
clock_get_uptime(&time);
124+
dispatchKeyboardEvent(kADBKeyCodeShift, true, *(AbsoluteTime*)&time);
125+
}
126+
127+
//
128+
// Simulate key press and release for character.
129+
//
130+
clock_get_uptime(&time);
131+
dispatchKeyboardEvent((UInt8)keyCode, true, *(AbsoluteTime*)&time);
132+
clock_get_uptime(&time);
133+
dispatchKeyboardEvent((UInt8)keyCode, false, *(AbsoluteTime*)&time);
134+
135+
//
136+
// Simulate shift key release for shifted characters.
137+
//
138+
if (keyCode & kADBUnicodeShift) {
139+
clock_get_uptime(&time);
140+
dispatchKeyboardEvent(kADBKeyCodeShift, false, *(AbsoluteTime*)&time);
141+
}
142+
}
143+
100144
UInt32 HyperVKeyboard::deviceType() {
101145
//
102146
// Apple keyboard.
@@ -114,18 +158,22 @@ inline UInt32 getKeyCode(HyperVKeyboardMessageKeystroke *keyEvent) {
114158

115159
void HyperVKeyboard::handlePacket(VMBusPacketHeader *pktHeader, UInt32 pktHeaderLength, UInt8 *pktData, UInt32 pktDataLength) {
116160
HyperVKeyboardMessage *keyboardMsg = (HyperVKeyboardMessage*) pktData;
161+
UInt64 time;
117162

118163
switch (keyboardMsg->header.type) {
119164
case kHyperVKeyboardMessageTypeProtocolResponse:
120165
HVDBGLOG("Keyboard protocol status %u %u", keyboardMsg->protocolResponse.header.type, keyboardMsg->protocolResponse.status);
121166
break;
122167

123168
case kHyperVKeyboardMessageTypeEvent:
124-
UInt64 time;
125-
clock_get_uptime(&time);
126-
127-
HVDBGLOG("Got make code 0x%X (E0: %u, break: %u)", keyboardMsg->keystroke.makeCode, keyboardMsg->keystroke.isE0, keyboardMsg->keystroke.isBreak);
128-
dispatchKeyboardEvent(getKeyCode(&keyboardMsg->keystroke), !keyboardMsg->keystroke.isBreak, *(AbsoluteTime*)&time);
169+
HVDBGLOG("Got make code 0x%X (E0: %u, E1: %u, break: %u, Unicode: %u)", keyboardMsg->keystroke.makeCode,
170+
keyboardMsg->keystroke.isE0, keyboardMsg->keystroke.isE1, keyboardMsg->keystroke.isBreak, keyboardMsg->keystroke.isUnicode);
171+
if (keyboardMsg->keystroke.isUnicode) {
172+
dispatchUnicodeKeyboardEvent(keyboardMsg->keystroke.makeCode, keyboardMsg->keystroke.isBreak);
173+
} else {
174+
clock_get_uptime(&time);
175+
dispatchKeyboardEvent(getKeyCode(&keyboardMsg->keystroke), !keyboardMsg->keystroke.isBreak, *(AbsoluteTime*)&time);
176+
}
129177
break;
130178

131179
default:

MacHyperVSupport/Keyboard/HyperVKeyboard.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ class HyperVKeyboard : public IOHIKeyboard {
2222
HyperVVMBusDevice *_hvDevice = nullptr;
2323

2424
void handlePacket(VMBusPacketHeader *pktHeader, UInt32 pktHeaderLength, UInt8 *pktData, UInt32 pktDataLength);
25-
OSReturn connectKeyboard();
25+
IOReturn connectKeyboard();
26+
void dispatchUnicodeKeyboardEvent(UInt16 unicodeChar, bool isBreak);
2627

2728
protected:
2829
//

0 commit comments

Comments
 (0)