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