From 42df4c5026baaebf2cd51549e0711d8dfec2e67d Mon Sep 17 00:00:00 2001 From: Adam Honse Date: Tue, 7 Jan 2020 23:59:52 -0600 Subject: [PATCH] Make i2c thread safe --- Controllers/AuraController/AuraController.cpp | 15 ++++++ .../CorsairController/CorsairController.cpp | 12 +++++ .../CorsairProController.cpp | 12 +++++ .../HyperXController/HyperXController.cpp | 32 +++++++++++- .../PatriotViperController.cpp | 49 +++++++++++++++++++ .../RGBFusionController.cpp | 23 +++++++++ i2c_smbus/i2c_smbus.cpp | 26 ++++++++++ i2c_smbus/i2c_smbus.h | 6 +++ 8 files changed, 174 insertions(+), 1 deletion(-) diff --git a/Controllers/AuraController/AuraController.cpp b/Controllers/AuraController/AuraController.cpp index ebed105c..9567958f 100644 --- a/Controllers/AuraController/AuraController.cpp +++ b/Controllers/AuraController/AuraController.cpp @@ -244,30 +244,45 @@ void AuraController::AuraUpdateDeviceName() unsigned char AuraController::AuraRegisterRead(aura_register reg) { + //Lock SMBus interface + bus->i2c_smbus_wait_and_lock(); + //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)); + //Unlock SMBus interface + bus->i2c_smbus_unlock(); } void AuraController::AuraRegisterWrite(aura_register reg, unsigned char val) { + //Lock SMBus interface + bus->i2c_smbus_wait_and_lock(); + //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); + //Unlock SMBus interface + bus->i2c_smbus_unlock(); } void AuraController::AuraRegisterWriteBlock(aura_register reg, unsigned char * data, unsigned char sz) { + //Lock SMBus interface + bus->i2c_smbus_wait_and_lock(); + //Write Aura register 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, sz, data); + //Unlock SMBus interface + bus->i2c_smbus_unlock(); } diff --git a/Controllers/CorsairController/CorsairController.cpp b/Controllers/CorsairController/CorsairController.cpp index bcdc7f5d..0a03d3e0 100644 --- a/Controllers/CorsairController/CorsairController.cpp +++ b/Controllers/CorsairController/CorsairController.cpp @@ -46,14 +46,26 @@ unsigned int CorsairController::GetLEDCount() void CorsairController::SetLEDColor(unsigned char red, unsigned char green, unsigned char blue) { + //Lock SMBus interface + bus->i2c_smbus_wait_and_lock(); + bus->i2c_smbus_write_byte_data(dev, CORSAIR_VENGEANCE_RGB_CMD_FADE_TIME, 0x00); bus->i2c_smbus_write_byte_data(dev, CORSAIR_VENGEANCE_RGB_CMD_RED_VAL, red); bus->i2c_smbus_write_byte_data(dev, CORSAIR_VENGEANCE_RGB_CMD_GREEN_VAL, green); bus->i2c_smbus_write_byte_data(dev, CORSAIR_VENGEANCE_RGB_CMD_BLUE_VAL, blue); bus->i2c_smbus_write_byte_data(dev, CORSAIR_VENGEANCE_RGB_CMD_MODE, CORSAIR_VENGEANCE_RGB_MODE_SINGLE); + + //Unlock SMBus interface + bus->i2c_smbus_unlock(); } void CorsairController::SetMode(unsigned char /*mode*/) { + //Lock SMBus interface + bus->i2c_smbus_wait_and_lock(); + bus->i2c_smbus_write_byte_data(dev, CORSAIR_VENGEANCE_RGB_CMD_MODE, CORSAIR_VENGEANCE_RGB_MODE_SINGLE); + + //Unlock SMBus interface + bus->i2c_smbus_unlock(); } diff --git a/Controllers/CorsairProController/CorsairProController.cpp b/Controllers/CorsairProController/CorsairProController.cpp index b654f5dc..ecb52a71 100644 --- a/Controllers/CorsairProController/CorsairProController.cpp +++ b/Controllers/CorsairProController/CorsairProController.cpp @@ -81,6 +81,9 @@ void CorsairProController::SetLEDColor(unsigned int led, unsigned char red, unsi void CorsairProController::ApplyColors() { + //Lock SMBus interface + bus->i2c_smbus_wait_and_lock(); + bus->i2c_smbus_write_byte_data(dev, 0x26, 0x02); Sleep(1); bus->i2c_smbus_write_byte_data(dev, 0x21, 0x00); @@ -95,10 +98,16 @@ void CorsairProController::ApplyColors() } bus->i2c_smbus_write_byte_data(dev, 0x82, 0x02); + + //Unlock SMBus interface + bus->i2c_smbus_unlock(); } void CorsairProController::SetEffect(unsigned char mode) { + //Lock SMBus interface + bus->i2c_smbus_wait_and_lock(); + bus->i2c_smbus_write_byte_data(dev, 0x26, 0x01); Sleep(1); bus->i2c_smbus_write_byte_data(dev, 0x21, 0x00); @@ -127,6 +136,9 @@ void CorsairProController::SetEffect(unsigned char mode) bus->i2c_smbus_write_byte_data(dev, 0x82, 0x01); WaitReady(); + + //Unlock SMBus interface + bus->i2c_smbus_unlock(); } void CorsairProController::SetCustom() diff --git a/Controllers/HyperXController/HyperXController.cpp b/Controllers/HyperXController/HyperXController.cpp index 5a57a0b8..0311db22 100644 --- a/Controllers/HyperXController/HyperXController.cpp +++ b/Controllers/HyperXController/HyperXController.cpp @@ -78,6 +78,9 @@ unsigned int HyperXController::GetMode() void HyperXController::SetEffectColor(unsigned char red, unsigned char green, unsigned char blue) { + //Lock SMBus interface + bus->i2c_smbus_wait_and_lock(); + bus->i2c_smbus_write_byte_data(dev, HYPERX_REG_APPLY, 0x01); bus->i2c_smbus_write_byte_data(dev, HYPERX_REG_EFFECT_RED, red ); @@ -87,10 +90,16 @@ void HyperXController::SetEffectColor(unsigned char red, unsigned char green, un bus->i2c_smbus_write_byte_data(dev, HYPERX_REG_APPLY, 0x02); bus->i2c_smbus_write_byte_data(dev, HYPERX_REG_APPLY, 0x03); + + //Unlock SMBus interface + bus->i2c_smbus_unlock(); } void HyperXController::SetAllColors(unsigned char red, unsigned char green, unsigned char blue) { + //Lock SMBus interface + bus->i2c_smbus_wait_and_lock(); + bus->i2c_smbus_write_byte_data(dev, HYPERX_REG_APPLY, 0x01); /*-----------------------------------------------------*\ @@ -124,6 +133,9 @@ void HyperXController::SetAllColors(unsigned char red, unsigned char green, unsi bus->i2c_smbus_write_byte_data(dev, HYPERX_REG_APPLY, 0x02); bus->i2c_smbus_write_byte_data(dev, HYPERX_REG_APPLY, 0x03); + + //Unlock SMBus interface + bus->i2c_smbus_unlock(); } void HyperXController::SetLEDColor(unsigned int led, unsigned char red, unsigned char green, unsigned char blue) @@ -163,6 +175,9 @@ void HyperXController::SetLEDColor(unsigned int led, unsigned char red, unsigned unsigned char blue_base = base + 0x02; unsigned char bright_base = base + 0x10; + //Lock SMBus interface + bus->i2c_smbus_wait_and_lock(); + bus->i2c_smbus_write_byte_data(dev, HYPERX_REG_APPLY, 0x01); bus->i2c_smbus_write_byte_data(dev, red_base + (3 * led), red ); @@ -172,6 +187,9 @@ void HyperXController::SetLEDColor(unsigned int led, unsigned char red, unsigned bus->i2c_smbus_write_byte_data(dev, HYPERX_REG_APPLY, 0x02); bus->i2c_smbus_write_byte_data(dev, HYPERX_REG_APPLY, 0x03); + + //Unlock SMBus interface + bus->i2c_smbus_unlock(); } @@ -183,6 +201,9 @@ void HyperXController::SetLEDColor(unsigned int slot, unsigned int led, unsigned unsigned char blue_base = base + 0x02; unsigned char bright_base = base + 0x10; + //Lock SMBus interface + bus->i2c_smbus_wait_and_lock(); + bus->i2c_smbus_write_byte_data(dev, HYPERX_REG_APPLY, 0x01); bus->i2c_smbus_write_byte_data(dev, red_base + (3 * led), red ); @@ -192,12 +213,18 @@ void HyperXController::SetLEDColor(unsigned int slot, unsigned int led, unsigned bus->i2c_smbus_write_byte_data(dev, HYPERX_REG_APPLY, 0x02); bus->i2c_smbus_write_byte_data(dev, HYPERX_REG_APPLY, 0x03); + + //Unlock SMBus interface + bus->i2c_smbus_unlock(); } void HyperXController::SetMode(unsigned char new_mode) { mode = new_mode; - + + //Lock SMBus interface + bus->i2c_smbus_wait_and_lock(); + bus->i2c_smbus_write_byte_data(dev, HYPERX_REG_APPLY, 0x01); switch (mode) @@ -241,4 +268,7 @@ void HyperXController::SetMode(unsigned char new_mode) bus->i2c_smbus_write_byte_data(dev, HYPERX_REG_APPLY, 0x02); bus->i2c_smbus_write_byte_data(dev, HYPERX_REG_APPLY, 0x03); + + //Unlock SMBus interface + bus->i2c_smbus_unlock(); } diff --git a/Controllers/PatriotViperController/PatriotViperController.cpp b/Controllers/PatriotViperController/PatriotViperController.cpp index 36c0ff08..2c7eb41d 100644 --- a/Controllers/PatriotViperController/PatriotViperController.cpp +++ b/Controllers/PatriotViperController/PatriotViperController.cpp @@ -76,6 +76,9 @@ unsigned int PatriotViperController::GetMode() void PatriotViperController::SetEffectColor(unsigned char red, unsigned char green, unsigned char blue) { + //Lock SMBus interface + bus->i2c_smbus_wait_and_lock(); + ViperRegisterWrite(VIPER_REG_START, 0xFF, 0xFF, 0xFF); ViperRegisterWrite(VIPER_REG_STATIC, 0x04, 0x00, 0x00); @@ -88,10 +91,16 @@ void PatriotViperController::SetEffectColor(unsigned char red, unsigned char gre ViperRegisterWrite(VIPER_REG_MODE, mode, 0x00, 0x0C); ViperRegisterWrite(VIPER_REG_MODE, 0xAA, 0x00, 0x00); ViperRegisterWrite(VIPER_REG_MODE, 0xFA, 0x00, 0x00); + + //Unlock SMBus interface + bus->i2c_smbus_unlock(); } void PatriotViperController::SetAllColors(unsigned char red, unsigned char green, unsigned char blue) { + //Lock SMBus interface + bus->i2c_smbus_wait_and_lock(); + ViperRegisterWrite(VIPER_REG_START, 0xFF, 0xFF, 0xFF); ViperRegisterWrite(VIPER_REG_STATIC, 0x04, 0x00, 0x00); @@ -102,20 +111,32 @@ void PatriotViperController::SetAllColors(unsigned char red, unsigned char green ViperRegisterWrite(VIPER_REG_LED4_DIRECT_COLOR, red, blue, green); ViperRegisterWrite(VIPER_REG_APPLY, 0x01, 0x00, 0x00); + + //Unlock SMBus interface + bus->i2c_smbus_unlock(); } void PatriotViperController::SetLEDColor(unsigned int led, unsigned char red, unsigned char green, unsigned char blue) { + //Lock SMBus interface + bus->i2c_smbus_wait_and_lock(); + ViperRegisterWrite(VIPER_REG_START, 0xFF, 0xFF, 0xFF); ViperRegisterWrite(VIPER_REG_STATIC, 0x04, 0x00, 0x00); ViperRegisterWrite(VIPER_REG_LED0_DIRECT_COLOR + led, red, blue, green); ViperRegisterWrite(VIPER_REG_APPLY, 0x01, 0x00, 0x00); + + //Unlock SMBus interface + bus->i2c_smbus_unlock(); } void PatriotViperController::SetLEDEffectColor(unsigned int led, unsigned char red, unsigned char green, unsigned char blue) { + //Lock SMBus interface + bus->i2c_smbus_wait_and_lock(); + ViperRegisterWrite(VIPER_REG_START, 0xFF, 0xFF, 0xFF); ViperRegisterWrite(VIPER_REG_STATIC, 0x04, 0x00, 0x00); @@ -124,20 +145,32 @@ void PatriotViperController::SetLEDEffectColor(unsigned int led, unsigned char r ViperRegisterWrite(VIPER_REG_MODE, mode, 0x00, 0x0C); ViperRegisterWrite(VIPER_REG_MODE, 0xAA, 0x00, 0x00); ViperRegisterWrite(VIPER_REG_MODE, 0xFA, 0x00, 0x00); + + //Unlock SMBus interface + bus->i2c_smbus_unlock(); } void PatriotViperController::SetLEDColor(unsigned int slot, unsigned int led, unsigned char red, unsigned char green, unsigned char blue) { + //Lock SMBus interface + bus->i2c_smbus_wait_and_lock(); + ViperRegisterWrite(VIPER_REG_START, 0xFF, 0xFF, 0xFF); ViperRegisterWrite(VIPER_REG_STATIC, 0x04, 0x00, 0x00); ViperRegisterWrite(VIPER_REG_LED0_DIRECT_COLOR + led, red, blue, green); ViperRegisterWrite(VIPER_REG_APPLY, 0x01, 0x00, 0x00); + + //Unlock SMBus interface + bus->i2c_smbus_unlock(); } void PatriotViperController::SetLEDEffectColor(unsigned int slot, unsigned int led, unsigned char red, unsigned char green, unsigned char blue) { + //Lock SMBus interface + bus->i2c_smbus_wait_and_lock(); + ViperRegisterWrite(VIPER_REG_START, 0xFF, 0xFF, 0xFF); ViperRegisterWrite(VIPER_REG_STATIC, 0x04, 0x00, 0x00); @@ -146,6 +179,9 @@ void PatriotViperController::SetLEDEffectColor(unsigned int slot, unsigned int l ViperRegisterWrite(VIPER_REG_MODE, mode, 0x00, 0x0C); ViperRegisterWrite(VIPER_REG_MODE, 0xAA, 0x00, 0x00); ViperRegisterWrite(VIPER_REG_MODE, 0xFA, 0x00, 0x00); + + //Unlock SMBus interface + bus->i2c_smbus_unlock(); } void PatriotViperController::SetMode(unsigned char new_mode) @@ -153,19 +189,32 @@ void PatriotViperController::SetMode(unsigned char new_mode) direct = false; mode = new_mode; + //Lock SMBus interface + bus->i2c_smbus_wait_and_lock(); + ViperRegisterWrite(VIPER_REG_START, 0xFF, 0xFF, 0xFF); ViperRegisterWrite(VIPER_REG_STATIC, 0x04, 0x00, 0x00); ViperRegisterWrite(VIPER_REG_MODE, new_mode, 0x00, 0x0C); ViperRegisterWrite(VIPER_REG_MODE, 0xAA, 0x00, 0x00); ViperRegisterWrite(VIPER_REG_MODE, 0xFA, 0x00, 0x00); + + //Unlock SMBus interface + bus->i2c_smbus_unlock(); } void PatriotViperController::SetDirect() { direct = true; + + //Lock SMBus interface + bus->i2c_smbus_wait_and_lock(); + ViperRegisterWrite(VIPER_REG_START, 0xFF, 0xFF, 0xFF); ViperRegisterWrite(VIPER_REG_STATIC, 0x04, 0x00, 0x00); ViperRegisterWrite(VIPER_REG_APPLY, 0x01, 0x00, 0x00); + + //Unlock SMBus interface + bus->i2c_smbus_unlock(); } void PatriotViperController::ViperRegisterWrite(viper_register reg, unsigned char val0, unsigned char val1, unsigned char val2) diff --git a/Controllers/RGBFusionController/RGBFusionController.cpp b/Controllers/RGBFusionController/RGBFusionController.cpp index b42c08ca..7815af44 100644 --- a/Controllers/RGBFusionController/RGBFusionController.cpp +++ b/Controllers/RGBFusionController/RGBFusionController.cpp @@ -63,6 +63,9 @@ void RGBFusionController::SetAllColors(unsigned char red, unsigned char green, u { unsigned char mode_ch_0; unsigned char mode_ch_1; + + //Lock SMBus interface + bus->i2c_smbus_wait_and_lock(); switch_bank(1); set_color_ch_0(red, green, blue); @@ -74,6 +77,8 @@ void RGBFusionController::SetAllColors(unsigned char red, unsigned char green, u set_mode_ch_0(mode_ch_0); set_mode_ch_1(mode_ch_1); + //Unlock SMBus interface + bus->i2c_smbus_unlock(); } void RGBFusionController::SetLEDColor(unsigned int led, unsigned char red, unsigned char green, unsigned char blue) @@ -83,30 +88,48 @@ void RGBFusionController::SetLEDColor(unsigned int led, unsigned char red, unsig switch (led) { case 0: + //Lock SMBus interface + bus->i2c_smbus_wait_and_lock(); + switch_bank(1); set_color_ch_0(red, green, blue); switch_bank(0); mode = get_mode_ch_0(); set_mode_ch_0(mode); + + //Unlock SMBus interface + bus->i2c_smbus_unlock(); break; case 1: + //Lock SMBus interface + bus->i2c_smbus_wait_and_lock(); + switch_bank(1); set_color_ch_1(red, green, blue); switch_bank(0); mode = get_mode_ch_1(); set_mode_ch_1(mode); + + //Unlock SMBus interface + bus->i2c_smbus_unlock(); break; } } void RGBFusionController::SetMode(unsigned char mode) { + //Lock SMBus interface + bus->i2c_smbus_wait_and_lock(); + switch_bank(0); set_mode_ch_0(mode); set_mode_ch_1(mode); + + //Unlock SMBus interface + bus->i2c_smbus_unlock(); } void RGBFusionController::dump() diff --git a/i2c_smbus/i2c_smbus.cpp b/i2c_smbus/i2c_smbus.cpp index 982040b7..ba594693 100644 --- a/i2c_smbus/i2c_smbus.cpp +++ b/i2c_smbus/i2c_smbus.cpp @@ -9,6 +9,17 @@ #include "i2c_smbus.h" #include +#ifdef WIN32 +#include +#else +#include + +static void Sleep(unsigned int milliseconds) +{ + usleep(1000 * milliseconds); +} +#endif + s32 i2c_smbus_interface::i2c_smbus_write_quick(u8 addr, u8 value) { return i2c_smbus_xfer(addr, value, 0, I2C_SMBUS_QUICK, NULL); @@ -128,3 +139,18 @@ s32 i2c_smbus_interface::i2c_smbus_write_i2c_block_data(u8 addr, u8 command, u8 memcpy(&data.block[1], values, length); return i2c_smbus_xfer(addr, I2C_SMBUS_WRITE, command, I2C_SMBUS_I2C_BLOCK_DATA, &data); } + +void i2c_smbus_interface::i2c_smbus_wait_and_lock() +{ + while(lock == true) + { + Sleep(1); + } + + lock = true; +} + +void i2c_smbus_interface::i2c_smbus_unlock() +{ + lock = false; +} \ No newline at end of file diff --git a/i2c_smbus/i2c_smbus.h b/i2c_smbus/i2c_smbus.h index 460e1327..bae23d93 100644 --- a/i2c_smbus/i2c_smbus.h +++ b/i2c_smbus/i2c_smbus.h @@ -69,8 +69,14 @@ public: 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); + void i2c_smbus_wait_and_lock(); + void i2c_smbus_unlock(); + //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; + +private: + bool lock = false; }; #endif /* I2C_SMBUS_H */