[NTFS] - Add some fixes and improvements to attribute.c from CR-123:
[reactos.git] / 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 ID_STRINGS_MAX,
41 };
42
43 typedef struct _MATCHENTRY
44 {
45 ULONG Type;
46 PCHAR String;
47 } MATCHENTRY;
48
49 #define MAX_MATCH_ENTRIES 3
50 typedef struct _HARDWARE_TABLE
51 {
52 MATCHENTRY MatchEntries[MAX_MATCH_ENTRIES];
53 ULONG Flags;
54 } HARDWARE_TABLE;
55
56 const HARDWARE_TABLE i8042HardwareTable[] =
57 {
58 // { {{BOARD_VENDOR, "RIOWORKS"}, {BOARD_NAME, "HDAMB"}, {BOARD_VERSION, "Rev E"}}, FL_NOLOOP },
59 // { {{BOARD_VENDOR, "ASUSTeK Computer Inc."}, {BOARD_NAME, "G1S"}, {BOARD_VERSION, "1.0"}}, FL_NOLOOP },
60
61 { {{SYS_VENDOR, "Microsoft Corporation"}, {SYS_PRODUCT, "Virtual Machine"}}, FL_INITHACK },
62 { {{SYS_VENDOR, "Dell Inc."}, {SYS_PRODUCT, "Inspiron 6000 "}}, FL_INITHACK },
63 { {{SYS_VENDOR, "Dell Inc."}, {SYS_PRODUCT, "Latitude D430 "}}, FL_INITHACK },
64 { {{SYS_VENDOR, "Dell Inc."}, {SYS_PRODUCT, "Latitude D530 "}}, FL_INITHACK },
65 { {{SYS_VENDOR, "Dell Inc."}, {SYS_PRODUCT, "Latitude D531 "}}, FL_INITHACK },
66 { {{SYS_VENDOR, "Dell Inc."}, {SYS_PRODUCT, "Latitude D600 "}}, FL_INITHACK },
67 { {{SYS_VENDOR, "Dell Inc."}, {SYS_PRODUCT, "Latitude D620 "}}, FL_INITHACK },
68 { {{SYS_VENDOR, "Dell Inc."}, {SYS_PRODUCT, "Latitude D630 "}}, FL_INITHACK },
69 { {{SYS_VENDOR, "Dell Inc."}, {SYS_PRODUCT, "Latitude D810 "}}, FL_INITHACK },
70 { {{SYS_VENDOR, "Dell Inc."}, {SYS_PRODUCT, "Latitude E4300 "}}, FL_INITHACK },
71 { {{SYS_VENDOR, "Dell Inc."}, {SYS_PRODUCT, "Latitude E4310 "}}, FL_INITHACK },
72
73 };
74
75
76
77 static
78 PCHAR
79 GetDmiString(
80 _In_ PDMI_HEADER Header,
81 _In_ ULONG FieldOffset)
82 {
83 ULONG StringIndex;
84 PCHAR String;
85
86 StringIndex = ((PUCHAR)Header)[FieldOffset];
87 if (StringIndex == 0)
88 {
89 return NULL;
90 }
91
92 String = (PCHAR)Header + Header->Length;
93
94 while (--StringIndex != 0)
95 {
96 while (*String != 0)
97 String++;
98
99 String++;
100 }
101
102 return String;
103 }
104
105
106 static
107 VOID
108 i8042ParseSMBiosTables(
109 _In_reads_bytes_(TableSize) PVOID SMBiosTables,
110 _In_ ULONG TableSize)
111 {
112 PMSSmBios_RawSMBiosTables BiosTablesHeader = SMBiosTables;
113 PDMI_HEADER Header;
114 ULONG Remaining, i, j;
115 PCHAR Data;
116 PCHAR Strings[ID_STRINGS_MAX] = { 0 };
117
118 Header = (PDMI_HEADER)(&BiosTablesHeader->SMBiosData);
119 Remaining = BiosTablesHeader->Size;
120
121 while (Remaining >= sizeof(*Header))
122 {
123
124 if (Header->Type == DMI_ENTRY_END_OF_TABLE)
125 break;
126
127 switch (Header->Type)
128 {
129 case DMI_ENTRY_BIOS:
130 if (Remaining < DMI_BIOS_SIZE)
131 return;
132 Strings[BIOS_VENDOR] = GetDmiString(Header, DMI_BIOS_VENDOR);
133 Strings[BIOS_VERSION] = GetDmiString(Header, DMI_BIOS_VERSION);
134 Strings[BIOS_DATE] = GetDmiString(Header, DMI_BIOS_DATE);
135 break;
136
137 case DMI_ENTRY_SYSTEM:
138 if (Remaining < DMI_SYS_SIZE)
139 return;
140 Strings[SYS_VENDOR] = GetDmiString(Header, DMI_SYS_VENDOR);
141 Strings[SYS_PRODUCT] = GetDmiString(Header, DMI_SYS_PRODUCT);
142 Strings[SYS_VERSION] = GetDmiString(Header, DMI_SYS_VERSION);
143 Strings[SYS_SERIAL] = GetDmiString(Header, DMI_SYS_SERIAL);
144 break;
145
146 case DMI_ENTRY_BASEBOARD:
147 if (Remaining < DMI_BOARD_SIZE)
148 return;
149 Strings[BOARD_VENDOR] = GetDmiString(Header, DMI_BOARD_VENDOR);
150 Strings[BOARD_NAME] = GetDmiString(Header, DMI_BOARD_NAME);
151 Strings[BOARD_VERSION] = GetDmiString(Header, DMI_BOARD_VERSION);
152 Strings[BOARD_SERIAL] = GetDmiString(Header, DMI_BOARD_SERIAL);
153 Strings[BOARD_ASSET_TAG] = GetDmiString(Header, DMI_BOARD_ASSET_TAG);
154 break;
155
156 case DMI_ENTRY_CHASSIS:
157 case DMI_ENTRY_ONBOARD_DEVICE:
158 case DMI_ENTRY_OEMSTRINGS:
159 // DMI_ENTRY_IPMI_DEV?
160 // DMI_ENTRY_ONBOARD_DEV_EXT?
161 break;
162 }
163
164 Remaining -= Header->Length;
165 Data = (PCHAR)Header + Header->Length;
166
167 /* Now loop until we find 2 zeroes */
168 while ((Remaining >= 2) && ((Data[0] != 0) || (Data[1] != 0)))
169 {
170 Data++;
171 Remaining--;
172 }
173
174 if (Remaining < 2)
175 break;
176
177 /* Go to the next header */
178 Remaining -= 2;
179 Header = (PDMI_HEADER)((PUCHAR)Data + 2);
180 }
181
182 #if 0 // DBG
183 DbgPrint("i8042prt: Dumping DMI data:\n");
184 DbgPrint("BIOS_VENDOR: %s\n", Strings[BIOS_VENDOR]);
185 DbgPrint("BIOS_VERSION: %s\n", Strings[BIOS_VERSION]);
186 DbgPrint("BIOS_DATE: %s\n", Strings[BIOS_DATE]);
187 DbgPrint("SYS_VENDOR: %s\n", Strings[SYS_VENDOR]);
188 DbgPrint("SYS_PRODUCT: %s\n", Strings[SYS_PRODUCT]);
189 DbgPrint("SYS_VERSION: %s\n", Strings[SYS_VERSION]);
190 DbgPrint("SYS_SERIAL: %s\n", Strings[SYS_SERIAL]);
191 DbgPrint("BOARD_VENDOR: %s\n", Strings[BOARD_VENDOR]);
192 DbgPrint("BOARD_NAME: %s\n", Strings[BOARD_NAME]);
193 DbgPrint("BOARD_VERSION: %s\n", Strings[BOARD_VERSION]);
194 DbgPrint("BOARD_SERIAL: %s\n", Strings[BOARD_SERIAL]);
195 DbgPrint("BOARD_ASSET_TAG: %s\n", Strings[BOARD_ASSET_TAG]);
196 #endif
197
198 /* Now loop the hardware table to find a match */
199 for (i = 0; i < ARRAYSIZE(i8042HardwareTable); i++)
200 {
201 for (j = 0; j < MAX_MATCH_ENTRIES; j++)
202 {
203 ULONG Type = i8042HardwareTable[i].MatchEntries[j].Type;
204
205 if (Type != ID_NONE)
206 {
207 /* Check for a match */
208 if ((Strings[Type] == NULL) ||
209 strcmp(i8042HardwareTable[i].MatchEntries[j].String,
210 Strings[i8042HardwareTable[i].MatchEntries[j].Type]))
211 {
212 /* Does not match, try next entry */
213 break;
214 }
215 }
216 }
217
218 if (j == MAX_MATCH_ENTRIES)
219 {
220 /* All items matched! */
221 i8042HwFlags = i8042HardwareTable[i].Flags;
222 DPRINT("Found match for hw table index %u\n", i);
223 break;
224 }
225 }
226 }
227
228 VOID
229 NTAPI
230 i8042InitializeHwHacks(
231 VOID)
232 {
233 NTSTATUS Status;
234 PVOID DataBlockObject;
235 PWNODE_ALL_DATA AllData;
236 ULONG BufferSize;
237
238 /* Open the data block object for the SMBIOS table */
239 Status = IoWMIOpenBlock(&MSSmBios_RawSMBiosTables_GUID,
240 WMIGUID_QUERY,
241 &DataBlockObject);
242 if (!NT_SUCCESS(Status))
243 {
244 DPRINT1("IoWMIOpenBlock failed: 0x%08lx\n", Status);
245 return;
246 }
247
248 /* Query the required buffer size */
249 BufferSize = 0;
250 Status = IoWMIQueryAllData(DataBlockObject, &BufferSize, NULL);
251 if (!NT_SUCCESS(Status))
252 {
253 DPRINT1("IoWMIOpenBlock failed: 0x%08lx\n", Status);
254 return;
255 }
256
257 AllData = ExAllocatePoolWithTag(PagedPool, BufferSize, 'BTMS');
258 if (AllData == NULL)
259 {
260 DPRINT1("Failed to allocate %lu bytes for SMBIOS tables\n", BufferSize);
261 return;
262 }
263
264 /* Query the buffer data */
265 Status = IoWMIQueryAllData(DataBlockObject, &BufferSize, AllData);
266 if (!NT_SUCCESS(Status))
267 {
268 DPRINT1("IoWMIOpenBlock failed: 0x%08lx\n", Status);
269 ExFreePoolWithTag(AllData, 'BTMS');
270 return;
271 }
272
273 /* Parse the table */
274 i8042ParseSMBiosTables(AllData + 1,
275 AllData->WnodeHeader.BufferSize);
276
277 /* Free the buffer */
278 ExFreePoolWithTag(AllData, 'BTMS');
279 }
280