[I8042PRT] Apply a workaround for Dell Latitude D630. By Thomas Faber. CORE-10797
[reactos.git] / reactos / drivers / input / i8042prt / hwhacks.c
1 /*
2 * PROJECT: ReactOS i8042 (ps/2 keyboard-mouse controller) driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/input/i8042prt/hwhacks.c
5 * PURPOSE: Mouse specific functions
6 * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org)
7 * REFERENCES: - http://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.0.0.pdf
8 * -
9 */
10
11 #include "i8042prt.h"
12 #include <wmiguid.h>
13 #include <wmidata.h>
14 #include <wmistr.h>
15 #include "dmi.h"
16
17 #define NDEBUG
18 #include <debug.h>
19
20 const GUID MSSmBios_RawSMBiosTables_GUID = SMBIOS_DATA_GUID;
21 PVOID i8042SMBiosTables;
22 ULONG i8042HwFlags;
23
24 enum _ID_STRINGS
25 {
26 ID_NONE = 0,
27 BIOS_VENDOR,
28 BIOS_VERSION,
29 BIOS_DATE,
30 SYS_VENDOR,
31 SYS_PRODUCT,
32 SYS_VERSION,
33 SYS_SERIAL,
34 BOARD_VENDOR,
35 BOARD_NAME,
36 BOARD_VERSION,
37 BOARD_SERIAL,
38 BOARD_ASSET_TAG,
39
40
41 ID_STRINGS_MAX,
42 };
43
44 typedef struct _MATCHENTRY
45 {
46 ULONG Type;
47 PCHAR String;
48 } MATCHENTRY;
49
50 #define MAX_MATCH_ENTRIES 3
51 typedef struct _HARDWARE_TABLE
52 {
53 MATCHENTRY MatchEntries[MAX_MATCH_ENTRIES];
54 ULONG Flags;
55 } HARDWARE_TABLE;
56
57 const HARDWARE_TABLE i8042HardwareTable[] =
58 {
59 // { {{BOARD_VENDOR, "RIOWORKS"}, {BOARD_NAME, "HDAMB"}, {BOARD_VERSION, "Rev E"}}, FL_NOLOOP },
60 // { {{BOARD_VENDOR, "ASUSTeK Computer Inc."}, {BOARD_NAME, "G1S"}, {BOARD_VERSION, "1.0"}}, FL_NOLOOP },
61
62 { {{SYS_VENDOR, "Microsoft Corporation"}, {SYS_PRODUCT, "Virtual Machine"}}, FL_INITHACK },
63 { {{SYS_VENDOR, "Dell Inc."}, {SYS_PRODUCT, "Latitude D530 "}}, FL_INITHACK },
64 { {{SYS_VENDOR, "Dell Inc."}, {SYS_PRODUCT, "Latitude D531 "}}, FL_INITHACK },
65 { {{SYS_VENDOR, "Dell Inc."}, {SYS_PRODUCT, "Latitude D600 "}}, FL_INITHACK },
66 { {{SYS_VENDOR, "Dell Inc."}, {SYS_PRODUCT, "Latitude D630 "}}, FL_INITHACK },
67
68 };
69
70
71
72 static
73 PCHAR
74 GetDmiString(
75 _In_ PDMI_HEADER Header,
76 _In_ ULONG FieldOffset)
77 {
78 ULONG StringIndex;
79 PCHAR String;
80
81 StringIndex = ((PUCHAR)Header)[FieldOffset];
82 if (StringIndex == 0)
83 {
84 return NULL;
85 }
86
87 String = (PCHAR)Header + Header->Length;
88
89 while (--StringIndex != 0)
90 {
91 while (*String != 0)
92 String++;
93
94 String++;
95 }
96
97 return String;
98 }
99
100
101 static
102 VOID
103 i8042ParseSMBiosTables(
104 _In_reads_bytes_(TableSize) PVOID SMBiosTables,
105 _In_ ULONG TableSize)
106 {
107 PMSSmBios_RawSMBiosTables BiosTablesHeader = SMBiosTables;
108 PDMI_HEADER Header;
109 ULONG Remaining, i, j;
110 PCHAR Data;
111 PCHAR Strings[ID_STRINGS_MAX] = { 0 };
112
113 Header = (PDMI_HEADER)(&BiosTablesHeader->SMBiosData);
114 Remaining = BiosTablesHeader->Size;
115
116 while (Remaining >= sizeof(*Header))
117 {
118
119 if (Header->Type == DMI_ENTRY_END_OF_TABLE)
120 break;
121
122 switch (Header->Type)
123 {
124 case DMI_ENTRY_BIOS:
125 if (Remaining < DMI_BIOS_SIZE)
126 return;
127 Strings[BIOS_VENDOR] = GetDmiString(Header, DMI_BIOS_VENDOR);
128 Strings[BIOS_VERSION] = GetDmiString(Header, DMI_BIOS_VERSION);
129 Strings[BIOS_DATE] = GetDmiString(Header, DMI_BIOS_DATE);
130 break;
131
132 case DMI_ENTRY_SYSTEM:
133 if (Remaining < DMI_SYS_SIZE)
134 return;
135 Strings[SYS_VENDOR] = GetDmiString(Header, DMI_SYS_VENDOR);
136 Strings[SYS_PRODUCT] = GetDmiString(Header, DMI_SYS_PRODUCT);
137 Strings[SYS_VERSION] = GetDmiString(Header, DMI_SYS_VERSION);
138 Strings[SYS_SERIAL] = GetDmiString(Header, DMI_SYS_SERIAL);
139 break;
140
141 case DMI_ENTRY_BASEBOARD:
142 if (Remaining < DMI_BOARD_SIZE)
143 return;
144 Strings[BOARD_VENDOR] = GetDmiString(Header, DMI_BOARD_VENDOR);
145 Strings[BOARD_NAME] = GetDmiString(Header, DMI_BOARD_NAME);
146 Strings[BOARD_VERSION] = GetDmiString(Header, DMI_BOARD_VERSION);
147 Strings[BOARD_SERIAL] = GetDmiString(Header, DMI_BOARD_SERIAL);
148 Strings[BOARD_ASSET_TAG] = GetDmiString(Header, DMI_BOARD_ASSET_TAG);
149 break;
150
151 case DMI_ENTRY_CHASSIS:
152 case DMI_ENTRY_ONBOARD_DEVICE:
153 case DMI_ENTRY_OEMSTRINGS:
154 // DMI_ENTRY_IPMI_DEV?
155 // DMI_ENTRY_ONBOARD_DEV_EXT?
156 break;
157 }
158
159 Remaining -= Header->Length;
160 Data = (PCHAR)Header + Header->Length;
161
162 /* Now loop until we find 2 zeroes */
163 while ((Remaining >= 2) && ((Data[0] != 0) || (Data[1] != 0)))
164 {
165 Data++;
166 Remaining--;
167 }
168
169 if (Remaining < 2)
170 break;
171
172 /* Go to the next header */
173 Remaining -= 2;
174 Header = (PDMI_HEADER)((PUCHAR)Data + 2);
175 }
176
177 #if 0 // DBG
178 DbgPrint("i8042prt: Dumping DMI data:\n");
179 DbgPrint("BIOS_VENDOR: %s\n", Strings[BIOS_VENDOR]);
180 DbgPrint("BIOS_VERSION: %s\n", Strings[BIOS_VERSION]);
181 DbgPrint("BIOS_DATE: %s\n", Strings[BIOS_DATE]);
182 DbgPrint("SYS_VENDOR: %s\n", Strings[SYS_VENDOR]);
183 DbgPrint("SYS_PRODUCT: %s\n", Strings[SYS_PRODUCT]);
184 DbgPrint("SYS_VERSION: %s\n", Strings[SYS_VERSION]);
185 DbgPrint("SYS_SERIAL: %s\n", Strings[SYS_SERIAL]);
186 DbgPrint("BOARD_VENDOR: %s\n", Strings[BOARD_VENDOR]);
187 DbgPrint("BOARD_NAME: %s\n", Strings[BOARD_NAME]);
188 DbgPrint("BOARD_VERSION: %s\n", Strings[BOARD_VERSION]);
189 DbgPrint("BOARD_SERIAL: %s\n", Strings[BOARD_SERIAL]);
190 DbgPrint("BOARD_ASSET_TAG: %s\n", Strings[BOARD_ASSET_TAG]);
191 #endif
192
193 /* Now loop the hardware table to find a match */
194 for (i = 0; i < ARRAYSIZE(i8042HardwareTable); i++)
195 {
196 for (j = 0; j < MAX_MATCH_ENTRIES; j++)
197 {
198 ULONG Type = i8042HardwareTable[i].MatchEntries[j].Type;
199
200 if (Type != ID_NONE)
201 {
202 /* Check for a match */
203 if ((Strings[Type] == NULL) ||
204 strcmp(i8042HardwareTable[i].MatchEntries[j].String,
205 Strings[i8042HardwareTable[i].MatchEntries[j].Type]))
206 {
207 /* Does not match, try next entry */
208 break;
209 }
210 }
211 }
212
213 if (j == MAX_MATCH_ENTRIES)
214 {
215 /* All items matched! */
216 i8042HwFlags = i8042HardwareTable[i].Flags;
217 DPRINT("Found match for hw table index %u\n", i);
218 break;
219 }
220 }
221 }
222
223 VOID
224 NTAPI
225 i8042InitializeHwHacks(
226 VOID)
227 {
228 NTSTATUS Status;
229 PVOID DataBlockObject;
230 PWNODE_ALL_DATA AllData;
231 ULONG BufferSize;
232
233 /* Open the data block object for the SMBIOS table */
234 Status = IoWMIOpenBlock(&MSSmBios_RawSMBiosTables_GUID,
235 WMIGUID_QUERY,
236 &DataBlockObject);
237 if (!NT_SUCCESS(Status))
238 {
239 DPRINT1("IoWMIOpenBlock failed: 0x%08lx\n", Status);
240 return;
241 }
242
243 /* Query the required buffer size */
244 BufferSize = 0;
245 Status = IoWMIQueryAllData(DataBlockObject, &BufferSize, NULL);
246 if (!NT_SUCCESS(Status))
247 {
248 DPRINT1("IoWMIOpenBlock failed: 0x%08lx\n", Status);
249 return;
250 }
251
252 AllData = ExAllocatePoolWithTag(PagedPool, BufferSize, 'BTMS');
253 if (AllData == NULL)
254 {
255 DPRINT1("Failed to allocate %lu bytes for SMBIOS tables\n", BufferSize);
256 return;
257 }
258
259 /* Query the buffer data */
260 Status = IoWMIQueryAllData(DataBlockObject, &BufferSize, AllData);
261 if (!NT_SUCCESS(Status))
262 {
263 DPRINT1("IoWMIOpenBlock failed: 0x%08lx\n", Status);
264 ExFreePoolWithTag(AllData, 'BTMS');
265 return;
266 }
267
268 /* Parse the table */
269 i8042ParseSMBiosTables(AllData + 1,
270 AllData->WnodeHeader.BufferSize);
271
272 /* Free the buffer */
273 ExFreePoolWithTag(AllData, 'BTMS');
274 }
275