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