diff --git a/OpenAuraSDK.sln b/OpenAuraSDK.sln
new file mode 100644
index 00000000..efc9459c
--- /dev/null
+++ b/OpenAuraSDK.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.27703.2026
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenAuraSDK", "OpenAuraSDK\OpenAuraSDK.vcxproj", "{6D22BFF3-C1DF-407A-8816-05D63919A991}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {6D22BFF3-C1DF-407A-8816-05D63919A991}.Debug|x64.ActiveCfg = Debug|x64
+ {6D22BFF3-C1DF-407A-8816-05D63919A991}.Debug|x64.Build.0 = Debug|x64
+ {6D22BFF3-C1DF-407A-8816-05D63919A991}.Debug|x86.ActiveCfg = Debug|Win32
+ {6D22BFF3-C1DF-407A-8816-05D63919A991}.Debug|x86.Build.0 = Debug|Win32
+ {6D22BFF3-C1DF-407A-8816-05D63919A991}.Release|x64.ActiveCfg = Release|x64
+ {6D22BFF3-C1DF-407A-8816-05D63919A991}.Release|x64.Build.0 = Release|x64
+ {6D22BFF3-C1DF-407A-8816-05D63919A991}.Release|x86.ActiveCfg = Release|Win32
+ {6D22BFF3-C1DF-407A-8816-05D63919A991}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {A2BB3E13-D506-413D-900E-F2B1323B3BB3}
+ EndGlobalSection
+EndGlobal
diff --git a/OpenAuraSDK/AuraController.cpp b/OpenAuraSDK/AuraController.cpp
new file mode 100644
index 00000000..8319df4a
--- /dev/null
+++ b/OpenAuraSDK/AuraController.cpp
@@ -0,0 +1,40 @@
+/*-----------------------------------------*\
+| AuraController.h |
+| |
+| Driver for ASUS Aura RGB lighting |
+| controller |
+| |
+| Adam Honse (CalcProgrammer1) 8/19/2018 |
+\*-----------------------------------------*/
+
+#include "AuraController.h"
+
+unsigned char AuraController::AuraRegisterRead(aura_register reg)
+{
+ //Write Aura register
+ bus->i2c_smbus_write_word_data(dev, 0x00, ((reg << 8) & 0xFF00) | ((reg >> 8) & 0x00FF));
+
+ //Read Aura value
+ return(bus->i2c_smbus_read_byte_data(dev, 0x81));
+
+}
+
+void AuraController::AuraRegisterWrite(aura_register reg, unsigned char val)
+{
+ //Write Aura register
+ bus->i2c_smbus_write_word_data(dev, 0x00, ((reg << 8) & 0xFF00) | ((reg >> 8) & 0x00FF));
+
+ //Write Aura value
+ bus->i2c_smbus_write_byte_data(dev, 0x01, val);
+
+}
+
+void AuraController::AuraRegisterWriteBlock(aura_register reg, unsigned char * data, unsigned char sz)
+{
+ //Write Aura register (0x8000 for colors)
+ bus->i2c_smbus_write_word_data(dev, 0x00, ((reg << 8) & 0xFF00) | ((reg >> 8) & 0x00FF));
+
+ //Write Aura block data
+ bus->i2c_smbus_write_block_data(dev, 0x03, 15, data);
+
+}
\ No newline at end of file
diff --git a/OpenAuraSDK/AuraController.h b/OpenAuraSDK/AuraController.h
new file mode 100644
index 00000000..626efcee
--- /dev/null
+++ b/OpenAuraSDK/AuraController.h
@@ -0,0 +1,58 @@
+/*-----------------------------------------*\
+| AuraController.h |
+| |
+| Definitions and types for ASUS Aura RGB |
+| lighting controller |
+| |
+| Adam Honse (CalcProgrammer1) 8/19/2018 |
+\*-----------------------------------------*/
+
+#include "i2c_smbus.h"
+
+#pragma once
+
+typedef unsigned char aura_dev_id;
+typedef unsigned short aura_register;
+
+#define AURA_APPLY_VAL 0x01 /* Value for Apply Changes Register */
+
+enum
+{
+ AURA_REG_COLORS_DIRECT = 0x8000, /* Colors for Direct Mode 15 bytes */
+ AURA_REG_COLORS_EFFECT = 0x8010, /* Colors for Internal Effects 15 bytes */
+ AURA_REG_DIRECT = 0x8020, /* "Direct Access" Selection Register */
+ AURA_REG_MODE = 0x8021, /* AURA Mode Selection Register */
+ AURA_REG_APPLY = 0x80A0 /* AURA Apply Changes Register */
+};
+
+enum
+{
+ AURA_MODE_OFF = 0, /* OFF mode */
+ AURA_MODE_STATIC = 1, /* Static color mode */
+ AURA_MODE_BREATHING = 2, /* Breathing effect mode */
+ AURA_MODE_FLASHING = 3, /* Flashing effect mode */
+ AURA_MODE_SPECTRUM_CYCLE = 4, /* Spectrum Cycle mode */
+ AURA_MODE_RAINBOW = 5, /* Rainbow effect mode */
+ AURA_MODE_SPECTRUM_CYCLE_BREATHING = 6, /* Rainbow Breathing effect mode */
+ AURA_MODE_CHASE_FADE = 7, /* Chase with Fade effect mode */
+ AURA_MODE_SPECTRUM_CYCLE_CHASE_FADE = 8, /* Chase with Fade, Rainbow effect mode */
+ AURA_MODE_CHASE = 9, /* Chase effect mode */
+ AURA_MODE_SPECTRUM_CYCLE_CHASE = 10, /* Chase with Rainbow effect mode */
+ AURA_MODE_SPECTRUM_CYCLE_WAVE = 11, /* Wave effect mode */
+ AURA_MODE_CHASE_RAINBOW_PULSE = 12, /* Chase with Rainbow Pulse effect mode*/
+ AURA_MODE_RANDOM_FLICKER = 13, /* Random flicker effect mode */
+};
+
+class AuraController
+{
+public:
+ unsigned char AuraRegisterRead(aura_register reg);
+ void AuraRegisterWrite(aura_register reg, unsigned char val);
+ void AuraRegisterWriteBlock(aura_register reg, unsigned char * data, unsigned char sz);
+ i2c_smbus_interface * bus;
+ aura_dev_id dev;
+
+private:
+
+
+};
\ No newline at end of file
diff --git a/OpenAuraSDK/OpenAuraSDK.cpp b/OpenAuraSDK/OpenAuraSDK.cpp
new file mode 100644
index 00000000..711a178e
Binary files /dev/null and b/OpenAuraSDK/OpenAuraSDK.cpp differ
diff --git a/OpenAuraSDK/OpenAuraSDK.h b/OpenAuraSDK/OpenAuraSDK.h
new file mode 100644
index 00000000..3f8cb34b
--- /dev/null
+++ b/OpenAuraSDK/OpenAuraSDK.h
@@ -0,0 +1,10 @@
+#pragma once
+
+typedef unsigned int AuraBusDriverType;
+
+enum
+{
+ I2C_DRIVER_SMBUS_PIIX4,
+ I2C_DRIVER_SMBUS_I801,
+ NUM_I2C_DRIVERS
+};
\ No newline at end of file
diff --git a/OpenAuraSDK/OpenAuraSDK.vcxproj b/OpenAuraSDK/OpenAuraSDK.vcxproj
new file mode 100644
index 00000000..351f9daa
--- /dev/null
+++ b/OpenAuraSDK/OpenAuraSDK.vcxproj
@@ -0,0 +1,186 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 15.0
+ {6D22BFF3-C1DF-407A-8816-05D63919A991}
+ Win32Proj
+ OpenAuraSDK
+ 10.0.17134.0
+
+
+
+ Application
+ true
+ v141
+ Unicode
+
+
+ Application
+ false
+ v141
+ true
+ Unicode
+
+
+ Application
+ true
+ v141
+ Unicode
+
+
+ Application
+ false
+ v141
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ .exe
+
+
+ true
+ .exe
+
+
+ false
+ .exe
+
+
+ false
+ .exe
+
+
+
+ NotUsing
+ Level3
+ Disabled
+ true
+ WIN32;_DEBUG;OPENAURASDK_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS
+ true
+ ..\dependencies\inpout32_1501\Win32;%(AdditionalIncludeDirectories)
+ true
+
+
+
+
+ Windows
+ true
+ ..\dependencies\inpout32_1501\Win32;%(AdditionalLibraryDirectories)
+
+
+
+
+ NotUsing
+ Level3
+ Disabled
+ true
+ _DEBUG;OPENAURASDK_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS
+ true
+
+
+
+
+ Windows
+ true
+
+
+
+
+ NotUsing
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+ WIN32;NDEBUG;OPENAURASDK_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS
+ true
+ ..\dependencies\inpout32_1501\Win32;%(AdditionalIncludeDirectories)
+ true
+
+
+
+
+ Windows
+ true
+ true
+ true
+ ..\dependencies\inpout32_1501\Win32;%(AdditionalLibraryDirectories)
+
+
+
+
+ NotUsing
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+ NDEBUG;OPENAURASDK_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS
+ true
+
+
+
+
+ Windows
+ true
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OpenAuraSDK/OpenAuraSDK.vcxproj.filters b/OpenAuraSDK/OpenAuraSDK.vcxproj.filters
new file mode 100644
index 00000000..d7d7b34d
--- /dev/null
+++ b/OpenAuraSDK/OpenAuraSDK.vcxproj.filters
@@ -0,0 +1,57 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;ipp;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
\ No newline at end of file
diff --git a/OpenAuraSDK/dllmain.cpp b/OpenAuraSDK/dllmain.cpp
new file mode 100644
index 00000000..44c1a0c4
Binary files /dev/null and b/OpenAuraSDK/dllmain.cpp differ
diff --git a/OpenAuraSDK/i2c_smbus.cpp b/OpenAuraSDK/i2c_smbus.cpp
new file mode 100644
index 00000000..c0ae78b5
--- /dev/null
+++ b/OpenAuraSDK/i2c_smbus.cpp
@@ -0,0 +1,121 @@
+#include "i2c_smbus.h"
+
+s32 i2c_smbus_interface::i2c_smbus_write_quick(u8 addr, u8 value)
+{
+ return i2c_smbus_xfer(addr, value, 0, I2C_SMBUS_QUICK, NULL);
+}
+
+s32 i2c_smbus_interface::i2c_smbus_read_byte(u8 addr)
+{
+ i2c_smbus_data data;
+ if (i2c_smbus_xfer(addr, I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE, &data))
+ {
+ return -1;
+ }
+ else
+ {
+ return data.byte;
+ }
+}
+
+s32 i2c_smbus_interface::i2c_smbus_write_byte(u8 addr, u8 value)
+{
+ return i2c_smbus_xfer(addr, I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL);
+}
+
+s32 i2c_smbus_interface::i2c_smbus_read_byte_data(u8 addr, u8 command)
+{
+ i2c_smbus_data data;
+ if (i2c_smbus_xfer(addr, I2C_SMBUS_READ, command, I2C_SMBUS_BYTE_DATA, &data))
+ {
+ return -1;
+ }
+ else
+ {
+ return data.byte;
+ }
+}
+
+s32 i2c_smbus_interface::i2c_smbus_write_byte_data(u8 addr, u8 command, u8 value)
+{
+ i2c_smbus_data data;
+ data.byte = value;
+ return i2c_smbus_xfer(addr, I2C_SMBUS_WRITE, command, I2C_SMBUS_BYTE_DATA, &data);
+}
+
+s32 i2c_smbus_interface::i2c_smbus_read_word_data(u8 addr, u8 command)
+{
+ i2c_smbus_data data;
+ if (i2c_smbus_xfer(addr, I2C_SMBUS_READ, command, I2C_SMBUS_WORD_DATA, &data))
+ {
+ return -1;
+ }
+ else
+ {
+ return data.word;
+ }
+}
+
+s32 i2c_smbus_interface::i2c_smbus_write_word_data(u8 addr, u8 command, u16 value)
+{
+ i2c_smbus_data data;
+ data.word = value;
+ return i2c_smbus_xfer(addr, I2C_SMBUS_WRITE, command, I2C_SMBUS_WORD_DATA, &data);
+}
+
+s32 i2c_smbus_interface::i2c_smbus_read_block_data(u8 addr, u8 command, u8 *values)
+{
+ i2c_smbus_data data;
+ if (i2c_smbus_xfer(addr, I2C_SMBUS_READ, command, I2C_SMBUS_BLOCK_DATA, &data))
+ {
+ return -1;
+ }
+ else
+ {
+ memcpy(values, &data.block[1], data.block[0]);
+ return data.block[0];
+ }
+}
+
+s32 i2c_smbus_interface::i2c_smbus_write_block_data(u8 addr, u8 command, u8 length, const u8 *values)
+{
+ i2c_smbus_data data;
+ if (length > I2C_SMBUS_BLOCK_MAX)
+ {
+ length = I2C_SMBUS_BLOCK_MAX;
+ }
+ data.block[0] = length;
+ memcpy(&data.block[1], values, length);
+ return i2c_smbus_xfer(addr, I2C_SMBUS_WRITE, command, I2C_SMBUS_BLOCK_DATA, &data);
+}
+
+s32 i2c_smbus_interface::i2c_smbus_read_i2c_block_data(u8 addr, u8 command, u8 length, u8 *values)
+{
+ i2c_smbus_data data;
+ if (length > I2C_SMBUS_BLOCK_MAX)
+ {
+ length = I2C_SMBUS_BLOCK_MAX;
+ }
+ data.block[0] = length;
+ if (i2c_smbus_xfer(addr, I2C_SMBUS_READ, command, I2C_SMBUS_I2C_BLOCK_DATA, &data))
+ {
+ return -1;
+ }
+ else
+ {
+ memcpy(values, &data.block[1], data.block[0]);
+ return data.block[0];
+ }
+}
+
+s32 i2c_smbus_interface::i2c_smbus_write_i2c_block_data(u8 addr, u8 command, u8 length, const u8 *values)
+{
+ i2c_smbus_data data;
+ if (length > I2C_SMBUS_BLOCK_MAX)
+ {
+ length = I2C_SMBUS_BLOCK_MAX;
+ }
+ data.block[0] = length;
+ memcpy(&data.block[1], values, length);
+ return i2c_smbus_xfer(addr, I2C_SMBUS_WRITE, command, I2C_SMBUS_I2C_BLOCK_DATA, &data);
+}
\ No newline at end of file
diff --git a/OpenAuraSDK/i2c_smbus.h b/OpenAuraSDK/i2c_smbus.h
new file mode 100644
index 00000000..e1d5e016
--- /dev/null
+++ b/OpenAuraSDK/i2c_smbus.h
@@ -0,0 +1,67 @@
+/*-----------------------------------------*\
+| i2c_smbus.h |
+| |
+| Definitions and types for SMBUS drivers |
+| |
+| Adam Honse (CalcProgrammer1) 8/8/2018 |
+| Portions based on Linux source code |
+| GNU GPL v2 |
+\*-----------------------------------------*/
+
+#include
+#include
+#include
+#include "inpout32.h"
+
+typedef UINT8 u8;
+typedef UINT16 u16;
+typedef UINT32 uint32_t;
+typedef INT32 s32;
+
+#pragma comment(lib, "inpout32.lib")
+#pragma once
+
+//Data for SMBus Messages
+#define I2C_SMBUS_BLOCK_MAX 32
+
+union i2c_smbus_data
+{
+ u8 byte;
+ u16 word;
+ u8 block[I2C_SMBUS_BLOCK_MAX + 2];
+};
+
+// i2c_smbus_xfer read or write markers
+#define I2C_SMBUS_READ 1
+#define I2C_SMBUS_WRITE 0
+
+// SMBus transaction types (size parameter in the above functions)
+#define I2C_SMBUS_QUICK 0
+#define I2C_SMBUS_BYTE 1
+#define I2C_SMBUS_BYTE_DATA 2
+#define I2C_SMBUS_WORD_DATA 3
+#define I2C_SMBUS_PROC_CALL 4
+#define I2C_SMBUS_BLOCK_DATA 5
+#define I2C_SMBUS_I2C_BLOCK_BROKEN 6
+#define I2C_SMBUS_BLOCK_PROC_CALL 7 /* SMBus 2.0 */
+#define I2C_SMBUS_I2C_BLOCK_DATA 8
+
+class i2c_smbus_interface
+{
+public:
+ //Functions derived from i2c-core.c
+ s32 i2c_smbus_write_quick(u8 addr, u8 value);
+ s32 i2c_smbus_read_byte(u8 addr);
+ s32 i2c_smbus_write_byte(u8 addr, u8 value);
+ s32 i2c_smbus_read_byte_data(u8 addr, u8 command);
+ s32 i2c_smbus_write_byte_data(u8 addr, u8 command, u8 value);
+ s32 i2c_smbus_read_word_data(u8 addr, u8 command);
+ s32 i2c_smbus_write_word_data(u8 addr, u8 command, u16 value);
+ s32 i2c_smbus_read_block_data(u8 addr, u8 command, u8 *values);
+ s32 i2c_smbus_write_block_data(u8 addr, u8 command, u8 length, const u8 *values);
+ s32 i2c_smbus_read_i2c_block_data(u8 addr, u8 command, u8 length, u8 *values);
+ s32 i2c_smbus_write_i2c_block_data(u8 addr, u8 command, u8 length, const u8 *values);
+
+ //Virtual function to be implemented by the driver
+ virtual s32 i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data) = 0;
+};
\ No newline at end of file
diff --git a/OpenAuraSDK/i2c_smbus_i801.cpp b/OpenAuraSDK/i2c_smbus_i801.cpp
new file mode 100644
index 00000000..267fc6bf
--- /dev/null
+++ b/OpenAuraSDK/i2c_smbus_i801.cpp
@@ -0,0 +1,478 @@
+/*-----------------------------------------*\
+| i2c_smbus_i801.cpp |
+| |
+| i801 SMBUS driver for Windows |
+| |
+| Adam Honse (CalcProgrammer1) 1/29/2019 |
+| Portions based on Linux source code |
+| GNU GPL v2 |
+\*-----------------------------------------*/
+
+#include "i2c_smbus_i801.h"
+
+/* Return negative errno on error. */
+s32 i2c_smbus_i801::i801_access(u16 addr, char read_write, u8 command, int size, i2c_smbus_data *data)
+{
+ int hwpec = 0;
+ int block = 0;
+ int ret = 0, xact = 0;
+ //struct i801_priv *priv = i2c_get_adapdata(adap);
+
+ //mutex_lock(&priv->acpi_lock);
+ //if (priv->acpi_reserved) {
+ // mutex_unlock(&priv->acpi_lock);
+ // return -EBUSY;
+ //}
+
+ //pm_runtime_get_sync(&priv->pci_dev->dev);
+
+ //hwpec = (priv->features & FEATURE_SMBUS_PEC) && (flags & I2C_CLIENT_PEC)
+ // && size != I2C_SMBUS_QUICK
+ // && size != I2C_SMBUS_I2C_BLOCK_DATA;
+
+ switch (size)
+ {
+ case I2C_SMBUS_QUICK:
+ Out32(SMBHSTADD, ((addr & 0x7f) << 1) | (read_write & 0x01));
+ xact = I801_QUICK;
+ break;
+ case I2C_SMBUS_BYTE:
+ Out32(SMBHSTADD, ((addr & 0x7f) << 1) | (read_write & 0x01));
+ if (read_write == I2C_SMBUS_WRITE)
+ Out32(SMBHSTCMD, command);
+ xact = I801_BYTE;
+ break;
+ case I2C_SMBUS_BYTE_DATA:
+ Out32(SMBHSTADD, ((addr & 0x7f) << 1) | (read_write & 0x01));
+ Out32(SMBHSTCMD, command);
+ if (read_write == I2C_SMBUS_WRITE)
+ Out32(SMBHSTDAT0, data->byte);
+ xact = I801_BYTE_DATA;
+ break;
+ case I2C_SMBUS_WORD_DATA:
+ Out32(SMBHSTADD, ((addr & 0x7f) << 1) | (read_write & 0x01));
+ Out32(SMBHSTCMD, command);
+ if (read_write == I2C_SMBUS_WRITE)
+ {
+ Out32(SMBHSTDAT0, data->word & 0xff);
+ Out32(SMBHSTDAT1, (data->word & 0xff00) >> 8);
+ }
+ xact = I801_WORD_DATA;
+ break;
+ case I2C_SMBUS_BLOCK_DATA:
+ Out32(SMBHSTADD, ((addr & 0x7f) << 1) | (read_write & 0x01));
+ Out32(SMBHSTCMD, command);
+ block = 1;
+ break;
+ case I2C_SMBUS_I2C_BLOCK_DATA:
+ /*
+ * NB: page 240 of ICH5 datasheet shows that the R/#W
+ * bit should be cleared here, even when reading.
+ * However if SPD Write Disable is set (Lynx Point and later),
+ * the read will fail if we don't set the R/#W bit.
+ */
+ Out32(SMBHSTADD, ((addr & 0x7f) << 1) | (read_write & 0x01));
+
+ if (read_write == I2C_SMBUS_READ)
+ {
+ /* NB: page 240 of ICH5 datasheet also shows
+ * that DATA1 is the cmd field when reading */
+ Out32(SMBHSTDAT1, command);
+ }
+ else
+ {
+ Out32(SMBHSTCMD, command);
+ }
+ block = 1;
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ goto out;
+ }
+
+ //if (hwpec) /* enable/disable hardware PEC */
+ // outb_p(inb_p(SMBAUXCTL(priv)) | SMBAUXCTL_CRC, SMBAUXCTL(priv));
+ //else
+ // outb_p(inb_p(SMBAUXCTL(priv)) & (~SMBAUXCTL_CRC),
+ // SMBAUXCTL(priv));
+
+ if (block)
+ ret = i801_block_transaction(data, read_write, size, hwpec);
+ else
+ ret = i801_transaction(xact);
+
+ /* Some BIOSes don't like it when PEC is enabled at reboot or resume
+ time, so we forcibly disable it after every transaction. Turn off
+ E32B for the same reason. */
+ //if (hwpec || block)
+ // outb_p(inb_p(SMBAUXCTL(priv)) &
+ // ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv));
+
+ if (block)
+ goto out;
+ if (ret)
+ goto out;
+ if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK))
+ goto out;
+
+ switch (xact & 0x7f)
+ {
+ case I801_BYTE: /* Result put in SMBHSTDAT0 */
+ case I801_BYTE_DATA:
+ data->byte = Inp32(SMBHSTDAT0);
+ break;
+ case I801_WORD_DATA:
+ data->word = Inp32(SMBHSTDAT0) + (Inp32(SMBHSTDAT1) << 8);
+ break;
+ }
+
+out:
+ //pm_runtime_mark_last_busy(&priv->pci_dev->dev);
+ //pm_runtime_put_autosuspend(&priv->pci_dev->dev);
+ //mutex_unlock(&priv->acpi_lock);
+ return ret;
+}
+
+/* Block transaction function */
+int i2c_smbus_i801::i801_block_transaction(i2c_smbus_data *data, char read_write, int command, int hwpec)
+{
+ int result = 0;
+ unsigned char hostc;
+
+ //if (command == I2C_SMBUS_I2C_BLOCK_DATA)
+ //{
+ // if (read_write == I2C_SMBUS_WRITE)
+ // {
+ // /* set I2C_EN bit in configuration register */
+ // pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &hostc);
+ // pci_write_config_byte(priv->pci_dev, SMBHSTCFG,
+ // hostc | SMBHSTCFG_I2C_EN);
+ // }
+ // else if (!(priv->features & FEATURE_I2C_BLOCK_READ)) {
+ // dev_err(&priv->pci_dev->dev,
+ // "I2C block read is unsupported!\n");
+ // return -EOPNOTSUPP;
+ // }
+ //}
+
+ if (read_write == I2C_SMBUS_WRITE || command == I2C_SMBUS_I2C_BLOCK_DATA)
+ {
+ if (data->block[0] < 1)
+ data->block[0] = 1;
+ if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
+ data->block[0] = I2C_SMBUS_BLOCK_MAX;
+ }
+ else
+ {
+ data->block[0] = 32; /* max for SMBus block reads */
+ }
+
+ /* Experience has shown that the block buffer can only be used for
+ SMBus (not I2C) block transactions, even though the datasheet
+ doesn't mention this limitation. */
+ //if ((priv->features & FEATURE_BLOCK_BUFFER)
+ // && command != I2C_SMBUS_I2C_BLOCK_DATA
+ // && i801_set_block_buffer_mode(priv) == 0)
+ // result = i801_block_transaction_by_block(priv, data,
+ // read_write, hwpec);
+ //else
+ result = i801_block_transaction_byte_by_byte(data, read_write, command, hwpec);
+
+ //if (command == I2C_SMBUS_I2C_BLOCK_DATA
+ // && read_write == I2C_SMBUS_WRITE) {
+ // /* restore saved configuration register value */
+ // pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hostc);
+ //}
+ return result;
+}
+
+/*
+* For "byte-by-byte" block transactions:
+* I2C write uses cmd=I801_BLOCK_DATA, I2C_EN=1
+* I2C read uses cmd=I801_I2C_BLOCK_DATA
+*/
+int i2c_smbus_i801::i801_block_transaction_byte_by_byte(i2c_smbus_data *data, char read_write, int command, int hwpec)
+{
+ int i, len;
+ int smbcmd;
+ int status;
+ int result;
+
+ result = i801_check_pre();
+ if (result < 0)
+ return result;
+
+ len = data->block[0];
+
+ if (read_write == I2C_SMBUS_WRITE)
+ {
+ Out32(SMBHSTDAT0, len);
+ Out32(SMBBLKDAT, data->block[1]);
+ }
+
+ if (command == I2C_SMBUS_I2C_BLOCK_DATA && read_write == I2C_SMBUS_READ)
+ smbcmd = I801_I2C_BLOCK_DATA;
+ else
+ smbcmd = I801_BLOCK_DATA;
+
+ //if (priv->features & FEATURE_IRQ) {
+ // priv->is_read = (read_write == I2C_SMBUS_READ);
+ // if (len == 1 && priv->is_read)
+ // smbcmd |= SMBHSTCNT_LAST_BYTE;
+ // priv->cmd = smbcmd | SMBHSTCNT_INTREN;
+ // priv->len = len;
+ // priv->count = 0;
+ // priv->data = &data->block[1];
+ //
+ // outb_p(priv->cmd | SMBHSTCNT_START, SMBHSTCNT(priv));
+ // result = wait_event_timeout(priv->waitq,
+ // (status = priv->status),
+ // adap->timeout);
+ // if (!result) {
+ // status = -ETIMEDOUT;
+ // dev_warn(&priv->pci_dev->dev,
+ // "Timeout waiting for interrupt!\n");
+ // }
+ // priv->status = 0;
+ // return i801_check_post(priv, status);
+ //}
+
+ for (i = 1; i <= len; i++)
+ {
+ if (i == len && read_write == I2C_SMBUS_READ)
+ smbcmd |= SMBHSTCNT_LAST_BYTE;
+ Out32(SMBHSTCNT, smbcmd);
+
+ if (i == 1)
+ Out32(SMBHSTCNT, Inp32(SMBHSTCNT) | SMBHSTCNT_START);
+
+ status = i801_wait_byte_done();
+ if (status)
+ goto exit;
+
+ if (i == 1 && read_write == I2C_SMBUS_READ && command != I2C_SMBUS_I2C_BLOCK_DATA)
+ {
+ len = Inp32(SMBHSTDAT0);
+ if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
+ {
+ /* Recover */
+ while (Inp32(SMBHSTSTS) & SMBHSTSTS_HOST_BUSY)
+ Out32(SMBHSTSTS, SMBHSTSTS_BYTE_DONE);
+ Out32(SMBHSTSTS, SMBHSTSTS_INTR);
+ return -EPROTO;
+ }
+ data->block[0] = len;
+ }
+
+ /* Retrieve/store value in SMBBLKDAT */
+ if (read_write == I2C_SMBUS_READ)
+ data->block[i] = Inp32(SMBBLKDAT);
+ if (read_write == I2C_SMBUS_WRITE && i + 1 <= len)
+ Out32(SMBBLKDAT, data->block[i + 1]);
+
+ /* signals SMBBLKDAT ready */
+ Out32(SMBHSTSTS, SMBHSTSTS_BYTE_DONE);
+ }
+
+ status = i801_wait_intr();
+exit:
+ return i801_check_post(status);
+}
+
+/*
+* Convert the status register to an error code, and clear it.
+* Note that status only contains the bits we want to clear, not the
+* actual register value.
+*/
+int i2c_smbus_i801::i801_check_post(int status)
+{
+ int result = 0;
+
+ /*
+ * If the SMBus is still busy, we give up
+ * Note: This timeout condition only happens when using polling
+ * transactions. For interrupt operation, NAK/timeout is indicated by
+ * DEV_ERR.
+ */
+ if (status < 0)
+ {
+ /* try to stop the current command */
+ Out32(SMBHSTCNT, Inp32(SMBHSTCNT) | SMBHSTCNT_KILL);
+ //usleep_range(1000, 2000);
+ Out32(SMBHSTCNT, Inp32(SMBHSTCNT) & (~SMBHSTCNT_KILL));
+
+ Out32(SMBHSTSTS, STATUS_FLAGS);
+ return -ETIMEDOUT;
+ }
+
+ if (status & SMBHSTSTS_FAILED)
+ {
+ result = -EIO;
+ }
+
+ if (status & SMBHSTSTS_DEV_ERR)
+ {
+ /*
+ * This may be a PEC error, check and clear it.
+ *
+ * AUXSTS is handled differently from HSTSTS.
+ * For HSTSTS, i801_isr() or i801_wait_intr()
+ * has already cleared the error bits in hardware,
+ * and we are passed a copy of the original value
+ * in "status".
+ * For AUXSTS, the hardware register is left
+ * for us to handle here.
+ * This is asymmetric, slightly iffy, but safe,
+ * since all this code is serialized and the CRCE
+ * bit is harmless as long as it's cleared before
+ * the next operation.
+ */
+ //if ((priv->features & FEATURE_SMBUS_PEC) &&
+ // (inb_p(SMBAUXSTS(priv)) & SMBAUXSTS_CRCE)) {
+ // outb_p(SMBAUXSTS_CRCE, SMBAUXSTS(priv));
+ // result = -EBADMSG;
+ // dev_dbg(&priv->pci_dev->dev, "PEC error\n");
+ //}
+ //else {
+ result = -ENXIO;
+ // dev_dbg(&priv->pci_dev->dev, "No response\n");
+ //}
+ }
+
+ if (status & SMBHSTSTS_BUS_ERR)
+ {
+ result = -EAGAIN;
+ }
+
+ /* Clear status flags except BYTE_DONE, to be cleared by caller */
+ Out32(SMBHSTSTS, status);
+
+ return result;
+}
+
+/* Make sure the SMBus host is ready to start transmitting.
+Return 0 if it is, -EBUSY if it is not. */
+int i2c_smbus_i801::i801_check_pre()
+{
+ int status;
+
+ status = Inp32(SMBHSTSTS);
+ if (status & SMBHSTSTS_HOST_BUSY)
+ {
+ return -EBUSY;
+ }
+
+ status &= STATUS_FLAGS;
+ if (status)
+ {
+ Out32(SMBHSTSTS, status);
+ status = Inp32(SMBHSTSTS) & STATUS_FLAGS;
+ if (status)
+ {
+ return -EBUSY;
+ }
+ }
+
+ /*
+ * Clear CRC status if needed.
+ * During normal operation, i801_check_post() takes care
+ * of it after every operation. We do it here only in case
+ * the hardware was already in this state when the driver
+ * started.
+ */
+ //if (priv->features & FEATURE_SMBUS_PEC) {
+ // status = inb_p(SMBAUXSTS(priv)) & SMBAUXSTS_CRCE;
+ // if (status) {
+ // dev_dbg(&priv->pci_dev->dev,
+ // "Clearing aux status flags (%02x)\n", status);
+ // outb_p(status, SMBAUXSTS(priv));
+ // status = inb_p(SMBAUXSTS(priv)) & SMBAUXSTS_CRCE;
+ // if (status) {
+ // dev_err(&priv->pci_dev->dev,
+ // "Failed clearing aux status flags (%02x)\n",
+ // status);
+ // return -EBUSY;
+ // }
+ // }
+ //}
+
+ return 0;
+}
+
+int i2c_smbus_i801::i801_transaction(int xact)
+{
+ int status;
+ int result;
+
+ result = i801_check_pre();
+ if (result < 0)
+ return result;
+
+ //if (priv->features & FEATURE_IRQ)
+ //{
+ // outb_p(xact | SMBHSTCNT_INTREN | SMBHSTCNT_START,
+ // SMBHSTCNT(priv));
+ // result = wait_event_timeout(priv->waitq,
+ // (status = priv->status),
+ // adap->timeout);
+ // if (!result) {
+ // status = -ETIMEDOUT;
+ // dev_warn(&priv->pci_dev->dev,
+ // "Timeout waiting for interrupt!\n");
+ // }
+ // priv->status = 0;
+ // return i801_check_post(priv, status);
+ //}
+
+ /* the current contents of SMBHSTCNT can be overwritten, since PEC,
+ * SMBSCMD are passed in xact */
+ Out32(SMBHSTCNT, xact | SMBHSTCNT_START);
+
+ status = i801_wait_intr();
+ return i801_check_post(status);
+}
+
+/* Wait for either BYTE_DONE or an error flag being set */
+int i2c_smbus_i801::i801_wait_byte_done()
+{
+ int timeout = 0;
+ int status;
+
+ /* We will always wait for a fraction of a second! */
+ do
+ {
+ //usleep_range(250, 500);
+ status = Inp32(SMBHSTSTS);
+ } while (!(status & (STATUS_ERROR_FLAGS | SMBHSTSTS_BYTE_DONE)) && (timeout++ < MAX_RETRIES));
+
+ if (timeout > MAX_RETRIES)
+ {
+ return -ETIMEDOUT;
+ }
+ return status & STATUS_ERROR_FLAGS;
+}
+
+/* Wait for BUSY being cleared and either INTR or an error flag being set */
+int i2c_smbus_i801::i801_wait_intr()
+{
+ int timeout = 0;
+ int status;
+
+ /* We will always wait for a fraction of a second! */
+ do
+ {
+ //usleep_range(250, 500);
+ status = Inp32(SMBHSTSTS);
+ } while (((status & SMBHSTSTS_HOST_BUSY) || !(status & (STATUS_ERROR_FLAGS | SMBHSTSTS_INTR))) && (timeout++ < MAX_RETRIES));
+
+ if (timeout > MAX_RETRIES)
+ {
+ return -ETIMEDOUT;
+ }
+ return status & (STATUS_ERROR_FLAGS | SMBHSTSTS_INTR);
+}
+
+s32 i2c_smbus_i801::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data)
+{
+ return i801_access(addr, read_write, command, size, data);
+}
\ No newline at end of file
diff --git a/OpenAuraSDK/i2c_smbus_i801.h b/OpenAuraSDK/i2c_smbus_i801.h
new file mode 100644
index 00000000..aeda780c
--- /dev/null
+++ b/OpenAuraSDK/i2c_smbus_i801.h
@@ -0,0 +1,87 @@
+/*-----------------------------------------*\
+| i2c_smbus_i801.h |
+| |
+| i801 SMBUS driver for Windows |
+| |
+| Adam Honse (CalcProgrammer1) 1/29/2019 |
+| Portions based on Linux source code |
+| GNU GPL v2 |
+\*-----------------------------------------*/
+
+#include "i2c_smbus.h"
+
+#pragma once
+
+/* BIT shifting macro */
+#define BIT(x) ( 1 << x )
+
+/* I801 SMBus address offsets */
+#define SMBHSTSTS (0 + i801_smba)
+#define SMBHSTCNT (2 + i801_smba)
+#define SMBHSTCMD (3 + i801_smba)
+#define SMBHSTADD (4 + i801_smba)
+#define SMBHSTDAT0 (5 + i801_smba)
+#define SMBHSTDAT1 (6 + i801_smba)
+#define SMBBLKDAT (7 + i801_smba)
+#define SMBPEC (8 + i801_smba) /* ICH3 and later */
+#define SMBAUXSTS (12 + i801_smba) /* ICH4 and later */
+#define SMBAUXCTL (13 + i801_smba) /* ICH4 and later */
+#define SMBSLVSTS (16 + i801_smba) /* ICH3 and later */
+#define SMBSLVCMD (17 + i801_smba) /* ICH3 and later */
+#define SMBNTFDADD (20 + i801_smba) /* ICH3 and later */
+
+/* Other settings */
+#define MAX_RETRIES 400
+
+/* I801 command constants */
+#define I801_QUICK 0x00
+#define I801_BYTE 0x04
+#define I801_BYTE_DATA 0x08
+#define I801_WORD_DATA 0x0C
+#define I801_PROC_CALL 0x10 /* unimplemented */
+#define I801_BLOCK_DATA 0x14
+#define I801_I2C_BLOCK_DATA 0x18 /* ICH5 and later */
+
+/* I801 Host Control register bits */
+#define SMBHSTCNT_INTREN BIT(0)
+#define SMBHSTCNT_KILL BIT(1)
+#define SMBHSTCNT_LAST_BYTE BIT(5)
+#define SMBHSTCNT_START BIT(6)
+#define SMBHSTCNT_PEC_EN BIT(7) /* ICH3 and later */
+
+/* I801 Hosts Status register bits */
+#define SMBHSTSTS_BYTE_DONE BIT(7)
+#define SMBHSTSTS_INUSE_STS BIT(6)
+#define SMBHSTSTS_SMBALERT_STS BIT(5)
+#define SMBHSTSTS_FAILED BIT(4)
+#define SMBHSTSTS_BUS_ERR BIT(3)
+#define SMBHSTSTS_DEV_ERR BIT(2)
+#define SMBHSTSTS_INTR BIT(1)
+#define SMBHSTSTS_HOST_BUSY BIT(0)
+
+/* Host Notify Status register bits */
+#define SMBSLVSTS_HST_NTFY_STS BIT(0)
+
+/* Host Notify Command register bits */
+#define SMBSLVCMD_HST_NTFY_INTREN BIT(0)
+
+#define STATUS_ERROR_FLAGS (SMBHSTSTS_FAILED | SMBHSTSTS_BUS_ERR | SMBHSTSTS_DEV_ERR)
+#define STATUS_FLAGS (SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR | STATUS_ERROR_FLAGS)
+
+class i2c_smbus_i801 : public i2c_smbus_interface
+{
+public:
+ u16 i801_smba = 0xF000;
+
+private:
+ s32 i801_access(u16 addr, char read_write, u8 command, int size, i2c_smbus_data *data);
+ int i801_block_transaction(i2c_smbus_data *data, char read_write, int command, int hwpec);
+ int i801_block_transaction_byte_by_byte(i2c_smbus_data *data, char read_write, int command, int hwpec);
+ int i801_check_post(int status);
+ int i801_check_pre();
+ int i801_transaction(int xact);
+ int i801_wait_byte_done();
+ int i801_wait_intr();
+ s32 i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data);
+
+};
\ No newline at end of file
diff --git a/OpenAuraSDK/i2c_smbus_piix4.cpp b/OpenAuraSDK/i2c_smbus_piix4.cpp
new file mode 100644
index 00000000..b762a5a8
--- /dev/null
+++ b/OpenAuraSDK/i2c_smbus_piix4.cpp
@@ -0,0 +1,168 @@
+/*-----------------------------------------*\
+| i2c_smbus_piix4.cpp |
+| |
+| PIIX4 SMBUS driver for Windows |
+| |
+| Adam Honse (CalcProgrammer1) 8/8/2018 |
+| Portions based on Linux source code |
+| GNU GPL v2 |
+\*-----------------------------------------*/
+
+#include "i2c_smbus_piix4.h"
+
+//Logic adapted from piix4_transaction() in i2c-piix4.c
+int i2c_smbus_piix4::piix4_transaction()
+{
+ int result = 0;
+ int temp;
+ int timeout = 0;
+
+ /* Make sure the SMBus host is ready to start transmitting */
+ temp = Inp32(SMBHSTSTS);
+
+ if (temp != 0x00)
+ {
+ Out32(SMBHSTSTS, temp);
+
+ temp = Inp32(SMBHSTSTS);
+
+ if (temp != 0x00)
+ {
+ return -EBUSY;
+ }
+ }
+
+ /* start the transaction by setting bit 6 */
+ temp = Inp32(SMBHSTCNT);
+ Out32(SMBHSTCNT, temp | 0x040);
+
+ /* We will always wait for a fraction of a second! (See PIIX4 docs errata) */
+ temp = 0;
+ while ((++timeout < MAX_TIMEOUT) && temp <= 1)
+ {
+ temp = Inp32(SMBHSTSTS);
+ }
+
+ /* If the SMBus is still busy, we give up */
+ if (timeout == MAX_TIMEOUT)
+ {
+ result = -ETIMEDOUT;
+ }
+
+ if (temp & 0x10)
+ {
+ result = -EIO;
+ }
+
+ if (temp & 0x08)
+ {
+ result = -EIO;
+ }
+
+ if (temp & 0x04)
+ {
+ result = -ENXIO;
+ }
+
+ temp = Inp32(SMBHSTSTS);
+ if (temp != 0x00)
+ {
+ Out32(SMBHSTSTS, temp);
+ }
+
+ return result;
+}
+
+//Logic adapted from piix4_access() in i2c-piix4.c
+s32 i2c_smbus_piix4::piix4_access(u16 addr, char read_write, u8 command, int size, i2c_smbus_data *data)
+{
+ int i, len, status;
+
+ switch (size)
+ {
+ case I2C_SMBUS_QUICK:
+ Out32(SMBHSTADD, (addr << 1) | read_write);
+ size = PIIX4_QUICK;
+ break;
+ case I2C_SMBUS_BYTE_DATA:
+ Out32(SMBHSTADD, (addr << 1) | read_write);
+ Out32(SMBHSTCMD, command);
+ if (read_write == I2C_SMBUS_WRITE)
+ {
+ Out32(SMBHSTDAT0, data->byte);
+ }
+ size = PIIX4_BYTE_DATA;
+ break;
+ case I2C_SMBUS_WORD_DATA:
+ Out32(SMBHSTADD, (addr << 1) | read_write);
+ Out32(SMBHSTCMD, command);
+ if (read_write == I2C_SMBUS_WRITE)
+ {
+ Out32(SMBHSTDAT0, data->word & 0xFF);
+ Out32(SMBHSTDAT1, (data->word & 0xFF00) >> 8);
+ }
+ size = PIIX4_WORD_DATA;
+ break;
+ case I2C_SMBUS_BLOCK_DATA:
+ Out32(SMBHSTADD, (addr << 1) | read_write);
+ Out32(SMBHSTCMD, command);
+ if (read_write == I2C_SMBUS_WRITE)
+ {
+ len = data->block[0];
+ if (len == 0 || len > I2C_SMBUS_BLOCK_MAX)
+ {
+ return -EINVAL;
+ }
+ Out32(SMBHSTDAT0, len);
+ Inp32(SMBHSTCNT);
+ for (i = 1; i <= len; i++)
+ {
+ Out32(SMBBLKDAT, data->block[i]);
+ }
+ }
+ size = PIIX4_BLOCK_DATA;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ Out32(SMBHSTCNT, (size & 0x1C));
+
+ status = piix4_transaction();
+
+ if (status)
+ return status;
+
+ if ((read_write == I2C_SMBUS_WRITE) || (size == PIIX4_QUICK))
+ return 0;
+
+ switch (size)
+ {
+ case PIIX4_BYTE:
+ case PIIX4_BYTE_DATA:
+ data->byte = (u8)Inp32(SMBHSTDAT0);
+ break;
+ case PIIX4_WORD_DATA:
+ data->word = Inp32(SMBHSTDAT0) + (Inp32(SMBHSTDAT1) << 8);
+ break;
+ case PIIX4_BLOCK_DATA:
+ data->block[0] = (u8)Inp32(SMBHSTDAT0);
+ if (data->block[0] == 0 || data->block[0] > I2C_SMBUS_BLOCK_MAX)
+ {
+ return -EPROTO;
+ }
+ Inp32(SMBHSTCNT);
+ for (i = 1; i <= data->block[0]; i++)
+ {
+ data->block[i] = (u8)Inp32(SMBBLKDAT);
+ }
+ break;
+ }
+
+ return 0;
+}
+
+s32 i2c_smbus_piix4::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data)
+{
+ return piix4_access(addr, read_write, command, size, data);
+}
\ No newline at end of file
diff --git a/OpenAuraSDK/i2c_smbus_piix4.h b/OpenAuraSDK/i2c_smbus_piix4.h
new file mode 100644
index 00000000..262e0c58
--- /dev/null
+++ b/OpenAuraSDK/i2c_smbus_piix4.h
@@ -0,0 +1,48 @@
+/*-----------------------------------------*\
+| i2c_smbus_piix4.h |
+| |
+| Definitions and types for PIIX4 SMBUS |
+| driver |
+| |
+| Adam Honse (CalcProgrammer1) 8/8/2018 |
+| Portions based on Linux source code |
+| GNU GPL v2 |
+\*-----------------------------------------*/
+
+#include "i2c_smbus.h"
+
+#pragma once
+
+// PIIX4 SMBus address offsets
+#define SMBHSTSTS (0 + piix4_smba)
+#define SMBHSLVSTS (1 + piix4_smba)
+#define SMBHSTCNT (2 + piix4_smba)
+#define SMBHSTCMD (3 + piix4_smba)
+#define SMBHSTADD (4 + piix4_smba)
+#define SMBHSTDAT0 (5 + piix4_smba)
+#define SMBHSTDAT1 (6 + piix4_smba)
+#define SMBBLKDAT (7 + piix4_smba)
+#define SMBSLVCNT (8 + piix4_smba)
+#define SMBSHDWCMD (9 + piix4_smba)
+#define SMBSLVEVT (0xA + piix4_smba)
+#define SMBSLVDAT (0xC + piix4_smba)
+
+#define MAX_TIMEOUT 5000
+
+// PIIX4 constants
+#define PIIX4_QUICK 0x00
+#define PIIX4_BYTE 0x04
+#define PIIX4_BYTE_DATA 0x08
+#define PIIX4_WORD_DATA 0x0C
+#define PIIX4_BLOCK_DATA 0x14
+
+class i2c_smbus_piix4 : public i2c_smbus_interface
+{
+public:
+ u16 piix4_smba = 0x0B00;
+
+private:
+ int piix4_transaction();
+ s32 piix4_access(u16 addr, char read_write, u8 command, int size, i2c_smbus_data *data);
+ s32 i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data);
+};
\ No newline at end of file
diff --git a/dependencies/inpout32_1501/Win32/inpout32.dll b/dependencies/inpout32_1501/Win32/inpout32.dll
new file mode 100644
index 00000000..88892800
Binary files /dev/null and b/dependencies/inpout32_1501/Win32/inpout32.dll differ
diff --git a/dependencies/inpout32_1501/Win32/inpout32.h b/dependencies/inpout32_1501/Win32/inpout32.h
new file mode 100644
index 00000000..65df0969
--- /dev/null
+++ b/dependencies/inpout32_1501/Win32/inpout32.h
@@ -0,0 +1,32 @@
+#pragma once
+
+//Functions exported from DLL.
+//For easy inclusion is user projects.
+//Original InpOut32 function support
+void _stdcall Out32(short PortAddress, short data);
+short _stdcall Inp32(short PortAddress);
+
+//My extra functions for making life easy
+BOOL _stdcall IsInpOutDriverOpen(); //Returns TRUE if the InpOut driver was opened successfully
+BOOL _stdcall IsXP64Bit(); //Returns TRUE if the OS is 64bit (x64) Windows.
+
+//DLLPortIO function support
+UCHAR _stdcall DlPortReadPortUchar (USHORT port);
+void _stdcall DlPortWritePortUchar(USHORT port, UCHAR Value);
+
+USHORT _stdcall DlPortReadPortUshort (USHORT port);
+void _stdcall DlPortWritePortUshort(USHORT port, USHORT Value);
+
+ULONG _stdcall DlPortReadPortUlong(ULONG port);
+void _stdcall DlPortWritePortUlong(ULONG port, ULONG Value);
+
+//WinIO function support (Untested and probably does NOT work - esp. on x64!)
+PBYTE _stdcall MapPhysToLin(PBYTE pbPhysAddr, DWORD dwPhysSize, HANDLE *pPhysicalMemoryHandle);
+BOOL _stdcall UnmapPhysicalMemory(HANDLE PhysicalMemoryHandle, PBYTE pbLinAddr);
+BOOL _stdcall GetPhysLong(PBYTE pbPhysAddr, PDWORD pdwPhysVal);
+BOOL _stdcall SetPhysLong(PBYTE pbPhysAddr, DWORD dwPhysVal);
+
+
+
+
+
diff --git a/dependencies/inpout32_1501/Win32/inpout32.lib b/dependencies/inpout32_1501/Win32/inpout32.lib
new file mode 100644
index 00000000..25b70560
Binary files /dev/null and b/dependencies/inpout32_1501/Win32/inpout32.lib differ