FreeRDP
Loading...
Searching...
No Matches
Keyboard.m
1
20#import "Keyboard.h"
21
22#include <CoreFoundation/CoreFoundation.h>
23
24#include <IOKit/IOKitLib.h>
25#include <IOKit/hid/IOHIDManager.h>
26
27#include <winpr/platform.h>
28
29typedef struct
30{
31 uint32_t ProductId;
32 enum APPLE_KEYBOARD_TYPE Type;
33} APPLE_KEYBOARD_DESC;
34
35/* VendorID: 0x05AC (Apple, Inc.) */
36
37static const APPLE_KEYBOARD_DESC APPLE_KEYBOARDS[] = {
38 { 0x200, APPLE_KEYBOARD_TYPE_ANSI },
39 { 0x201, APPLE_KEYBOARD_TYPE_ANSI }, /* USB Keyboard [Alps or Logitech, M2452] */
40 { 0x202, APPLE_KEYBOARD_TYPE_ANSI }, /* Keyboard [ALPS] */
41 { 0x203, APPLE_KEYBOARD_TYPE_ANSI },
42 { 0x204, APPLE_KEYBOARD_TYPE_ANSI },
43 { 0x205, APPLE_KEYBOARD_TYPE_ANSI }, /* Extended Keyboard [Mitsumi] */
44 { 0x206, APPLE_KEYBOARD_TYPE_ANSI }, /* Extended Keyboard [Mitsumi] */
45 { 0x207, APPLE_KEYBOARD_TYPE_ANSI },
46 { 0x208, APPLE_KEYBOARD_TYPE_ANSI },
47 { 0x209, APPLE_KEYBOARD_TYPE_ANSI },
48 { 0x20A, APPLE_KEYBOARD_TYPE_ANSI },
49 { 0x20B, APPLE_KEYBOARD_TYPE_ANSI }, /* Pro Keyboard [Mitsumi, A1048/US layout] */
50 { 0x20C, APPLE_KEYBOARD_TYPE_ANSI }, /* Extended Keyboard [Mitsumi] */
51 { 0x20D, APPLE_KEYBOARD_TYPE_ANSI }, /* Pro Keyboard [Mitsumi, A1048/JIS layout] */
52 { 0x20E, APPLE_KEYBOARD_TYPE_ANSI }, /* Internal Keyboard/Trackpad (ANSI) */
53 { 0x20F, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (ISO) */
54 { 0x210, APPLE_KEYBOARD_TYPE_ANSI },
55 { 0x211, APPLE_KEYBOARD_TYPE_ANSI },
56 { 0x212, APPLE_KEYBOARD_TYPE_ANSI },
57 { 0x213, APPLE_KEYBOARD_TYPE_ANSI },
58 { 0x214, APPLE_KEYBOARD_TYPE_ANSI }, /* Internal Keyboard/Trackpad (ANSI) */
59 { 0x215, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (ISO) */
60 { 0x216, APPLE_KEYBOARD_TYPE_JIS }, /* Internal Keyboard/Trackpad (JIS) */
61 { 0x217, APPLE_KEYBOARD_TYPE_ANSI }, /* Internal Keyboard/Trackpad (ANSI) */
62 { 0x218, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (ISO) */
63 { 0x219, APPLE_KEYBOARD_TYPE_JIS }, /* Internal Keyboard/Trackpad (JIS) */
64 { 0x21A, APPLE_KEYBOARD_TYPE_ANSI }, /* Internal Keyboard/Trackpad (ANSI) */
65 { 0x21B, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (ISO) */
66 { 0x21C, APPLE_KEYBOARD_TYPE_JIS }, /* Internal Keyboard/Trackpad (JIS) */
67 { 0x21D, APPLE_KEYBOARD_TYPE_ANSI }, /* Aluminum Mini Keyboard (ANSI) */
68 { 0x21E, APPLE_KEYBOARD_TYPE_ISO }, /* Aluminum Mini Keyboard (ISO) */
69 { 0x21F, APPLE_KEYBOARD_TYPE_JIS }, /* Aluminum Mini Keyboard (JIS) */
70 { 0x220, APPLE_KEYBOARD_TYPE_ANSI }, /* Aluminum Keyboard (ANSI) */
71 { 0x221, APPLE_KEYBOARD_TYPE_JIS }, /* Aluminum Keyboard (JIS) */
72 { 0x222, APPLE_KEYBOARD_TYPE_JIS }, /* Aluminum Keyboard (JIS) */
73 { 0x223, APPLE_KEYBOARD_TYPE_ANSI }, /* Internal Keyboard/Trackpad (ANSI) */
74 { 0x224, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (ISO) */
75 { 0x225, APPLE_KEYBOARD_TYPE_JIS }, /* Internal Keyboard/Trackpad (JIS) */
76 { 0x226, APPLE_KEYBOARD_TYPE_ANSI },
77 { 0x227, APPLE_KEYBOARD_TYPE_ANSI },
78 { 0x228, APPLE_KEYBOARD_TYPE_ANSI },
79 { 0x229, APPLE_KEYBOARD_TYPE_ANSI }, /* Internal Keyboard/Trackpad (MacBook Pro) (ANSI) */
80 { 0x22A, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (MacBook Pro) (ISO) */
81 { 0x22B, APPLE_KEYBOARD_TYPE_JIS }, /* Internal Keyboard/Trackpad (MacBook Pro) (JIS) */
82 { 0x22C, APPLE_KEYBOARD_TYPE_ANSI },
83 { 0x22D, APPLE_KEYBOARD_TYPE_ANSI },
84 { 0x22E, APPLE_KEYBOARD_TYPE_ANSI },
85 { 0x22F, APPLE_KEYBOARD_TYPE_ANSI },
86 { 0x230, APPLE_KEYBOARD_TYPE_ANSI }, /* Internal Keyboard/Trackpad (MacBook Pro 4,1) (ANSI) */
87 { 0x231, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (MacBook Pro 4,1) (ISO) */
88 { 0x232, APPLE_KEYBOARD_TYPE_JIS }, /* Internal Keyboard/Trackpad (MacBook Pro 4,1) (JIS) */
89 { 0x233, APPLE_KEYBOARD_TYPE_ANSI },
90 { 0x234, APPLE_KEYBOARD_TYPE_ANSI },
91 { 0x235, APPLE_KEYBOARD_TYPE_ANSI },
92 { 0x236, APPLE_KEYBOARD_TYPE_ANSI }, /* Internal Keyboard/Trackpad (ANSI) */
93 { 0x237, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (ISO) */
94 { 0x238, APPLE_KEYBOARD_TYPE_JIS }, /* Internal Keyboard/Trackpad (JIS) */
95 { 0x239, APPLE_KEYBOARD_TYPE_ANSI },
96 { 0x23A, APPLE_KEYBOARD_TYPE_ANSI },
97 { 0x23B, APPLE_KEYBOARD_TYPE_ANSI },
98 { 0x23C, APPLE_KEYBOARD_TYPE_ANSI },
99 { 0x23D, APPLE_KEYBOARD_TYPE_ANSI },
100 { 0x23E, APPLE_KEYBOARD_TYPE_ANSI },
101 { 0x23F, APPLE_KEYBOARD_TYPE_ANSI }, /* Internal Keyboard/Trackpad (ANSI) */
102 { 0x240, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (ISO) */
103 { 0x241, APPLE_KEYBOARD_TYPE_JIS }, /* Internal Keyboard/Trackpad (JIS) */
104 { 0x242, APPLE_KEYBOARD_TYPE_ANSI }, /* Internal Keyboard/Trackpad (ANSI) */
105 { 0x243, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (ISO) */
106 { 0x244, APPLE_KEYBOARD_TYPE_JIS }, /* Internal Keyboard/Trackpad (JIS) */
107 { 0x245, APPLE_KEYBOARD_TYPE_ANSI }, /* Internal Keyboard/Trackpad (ANSI) */
108 { 0x246, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (ISO) */
109 { 0x247, APPLE_KEYBOARD_TYPE_JIS }, /* Internal Keyboard/Trackpad (JIS) */
110 { 0x248, APPLE_KEYBOARD_TYPE_ANSI },
111 { 0x249, APPLE_KEYBOARD_TYPE_ANSI },
112 { 0x24A, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (MacBook Air) (ISO) */
113 { 0x24B, APPLE_KEYBOARD_TYPE_ANSI },
114 { 0x24C, APPLE_KEYBOARD_TYPE_ANSI },
115 { 0x24D, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (MacBook Air) (ISO) */
116 { 0x24E, APPLE_KEYBOARD_TYPE_ANSI },
117 { 0x24F, APPLE_KEYBOARD_TYPE_ANSI },
118 { 0x250, APPLE_KEYBOARD_TYPE_ISO }, /* Aluminium Keyboard (ISO) */
119 { 0x251, APPLE_KEYBOARD_TYPE_ANSI },
120 { 0x252, APPLE_KEYBOARD_TYPE_ANSI }, /* Internal Keyboard/Trackpad (ANSI) */
121 { 0x253, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (ISO) */
122 { 0x254, APPLE_KEYBOARD_TYPE_JIS }, /* Internal Keyboard/Trackpad (JIS) */
123 { 0x255, APPLE_KEYBOARD_TYPE_ANSI },
124 { 0x256, APPLE_KEYBOARD_TYPE_ANSI },
125 { 0x257, APPLE_KEYBOARD_TYPE_ANSI },
126 { 0x258, APPLE_KEYBOARD_TYPE_ANSI },
127 { 0x259, APPLE_KEYBOARD_TYPE_ANSI },
128 { 0x25A, APPLE_KEYBOARD_TYPE_ANSI },
129 { 0x25B, APPLE_KEYBOARD_TYPE_ANSI },
130 { 0x25C, APPLE_KEYBOARD_TYPE_ANSI },
131 { 0x25D, APPLE_KEYBOARD_TYPE_ANSI },
132 { 0x25E, APPLE_KEYBOARD_TYPE_ANSI },
133 { 0x25F, APPLE_KEYBOARD_TYPE_ANSI },
134 { 0x260, APPLE_KEYBOARD_TYPE_ANSI },
135 { 0x261, APPLE_KEYBOARD_TYPE_ANSI },
136 { 0x262, APPLE_KEYBOARD_TYPE_ANSI },
137 { 0x263, APPLE_KEYBOARD_TYPE_ANSI }, /* Apple Internal Keyboard / Trackpad (MacBook Retina) */
138 { 0x264, APPLE_KEYBOARD_TYPE_ANSI },
139 { 0x265, APPLE_KEYBOARD_TYPE_ANSI },
140 { 0x266, APPLE_KEYBOARD_TYPE_ANSI },
141 { 0x267, APPLE_KEYBOARD_TYPE_ANSI },
142 { 0x268, APPLE_KEYBOARD_TYPE_ANSI },
143 { 0x269, APPLE_KEYBOARD_TYPE_ANSI },
144 { 0x26A, APPLE_KEYBOARD_TYPE_ANSI }
145};
146
147static enum APPLE_KEYBOARD_TYPE mac_identify_keyboard_type(uint32_t vendorID, uint32_t productID)
148{
149 enum APPLE_KEYBOARD_TYPE type = APPLE_KEYBOARD_TYPE_ANSI;
150
151 if (vendorID != 0x05AC) /* Apple, Inc. */
152 return type;
153
154 if ((productID < 0x200) || (productID > 0x26A))
155 return type;
156
157 type = APPLE_KEYBOARDS[productID - 0x200].Type;
158 return type;
159}
160
161enum APPLE_KEYBOARD_TYPE mac_detect_keyboard_type(void)
162{
163 CFSetRef deviceCFSetRef = nullptr;
164 IOHIDDeviceRef inIOHIDDeviceRef = nullptr;
165 IOHIDManagerRef tIOHIDManagerRef = nullptr;
166 IOHIDDeviceRef *tIOHIDDeviceRefs = nil;
167 enum APPLE_KEYBOARD_TYPE type = APPLE_KEYBOARD_TYPE_ANSI;
168 tIOHIDManagerRef = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
169
170 if (!tIOHIDManagerRef)
171 return type;
172
173 IOHIDManagerSetDeviceMatching(tIOHIDManagerRef, nullptr);
174 IOReturn tIOReturn = IOHIDManagerOpen(tIOHIDManagerRef, kIOHIDOptionsTypeNone);
175
176 if (noErr != tIOReturn)
177 return type;
178
179 deviceCFSetRef = IOHIDManagerCopyDevices(tIOHIDManagerRef);
180
181 if (!deviceCFSetRef)
182 return type;
183
184 CFIndex deviceIndex, deviceCount = CFSetGetCount(deviceCFSetRef);
185 tIOHIDDeviceRefs = malloc(sizeof(IOHIDDeviceRef) * deviceCount);
186
187 if (!tIOHIDDeviceRefs)
188 return type;
189
190 CFSetGetValues(deviceCFSetRef, (const void **)tIOHIDDeviceRefs);
191 CFRelease(deviceCFSetRef);
192 deviceCFSetRef = nullptr;
193
194 for (deviceIndex = 0; deviceIndex < deviceCount; deviceIndex++)
195 {
196 CFTypeRef tCFTypeRef;
197 uint32_t vendorID = 0;
198 uint32_t productID = 0;
199 uint32_t countryCode = 0;
200 enum APPLE_KEYBOARD_TYPE ltype;
201
202 if (!tIOHIDDeviceRefs[deviceIndex])
203 continue;
204
205 inIOHIDDeviceRef = tIOHIDDeviceRefs[deviceIndex];
206 tCFTypeRef = IOHIDDeviceGetProperty(inIOHIDDeviceRef, CFSTR(kIOHIDVendorIDKey));
207
208 if (tCFTypeRef)
209 CFNumberGetValue((CFNumberRef)tCFTypeRef, kCFNumberSInt32Type, &vendorID);
210
211 tCFTypeRef = IOHIDDeviceGetProperty(inIOHIDDeviceRef, CFSTR(kIOHIDProductIDKey));
212
213 if (tCFTypeRef)
214 CFNumberGetValue((CFNumberRef)tCFTypeRef, kCFNumberSInt32Type, &productID);
215
216 tCFTypeRef = IOHIDDeviceGetProperty(inIOHIDDeviceRef, CFSTR(kIOHIDCountryCodeKey));
217
218 if (tCFTypeRef)
219 CFNumberGetValue((CFNumberRef)tCFTypeRef, kCFNumberSInt32Type, &countryCode);
220
221 ltype = mac_identify_keyboard_type(vendorID, productID);
222
223 if (ltype != APPLE_KEYBOARD_TYPE_ANSI)
224 {
225 type = ltype;
226 break;
227 }
228 }
229
230 free(tIOHIDDeviceRefs);
231
232 if (deviceCFSetRef)
233 {
234 CFRelease(deviceCFSetRef);
235 deviceCFSetRef = nullptr;
236 }
237
238 if (tIOHIDManagerRef)
239 CFRelease(tIOHIDManagerRef);
240
241 return type;
242}