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