diff --git a/Controllers/CorsairDRAMController/CorsairDRAMController.cpp b/Controllers/CorsairDRAMController/CorsairDRAMController.cpp index a516020fd..191a18773 100644 --- a/Controllers/CorsairDRAMController/CorsairDRAMController.cpp +++ b/Controllers/CorsairDRAMController/CorsairDRAMController.cpp @@ -26,6 +26,7 @@ CorsairDRAMController::CorsairDRAMController(i2c_smbus_interface *bus, corsair_d this->bus = bus; this->dev = dev; device_index = 0; + direct_mode = true; pid = 0; vid = 0; protocol_version = 0; @@ -132,13 +133,79 @@ void CorsairDRAMController::SetColorsPerLED(RGBColor* colors) | bytes, use a second block write to the second | | block write address for the remaining data | \*-------------------------------------------------*/ - bus->i2c_smbus_write_block_data(dev, CORSAIR_DRAM_REG_COLOR_BUFFER_BLOCK_1, 32, direct_packet); + s32 ret = bus->i2c_smbus_write_block_data(dev, CORSAIR_DRAM_REG_COLOR_BUFFER_BLOCK_1, 32, direct_packet); - if(direct_packet_size > 32) + if((ret >= 0) && (direct_packet_size > 32)) { bus->i2c_smbus_write_block_data(dev, CORSAIR_DRAM_REG_COLOR_BUFFER_BLOCK_2, direct_packet_size - 32, direct_packet + 32); } + /*-------------------------------------------------*\ + | Corsair DRAM supports an alternate means of | + | writing block data without using SMBus block | + | operations. If block operations are not | + | available, fall back to this scheme. | + | | + | Blocks are split up into word data writes. | + | Some data bytes are packed into the lower nibble | + | of the register address byte. | + \*-------------------------------------------------*/ + if(ret < 0) + { + unsigned int block_index = 0; + bool even_frame = true; + bool first_frame = true; + + while(block_index < direct_packet_size) + { + unsigned char reg_value_0 = 0xA0; + unsigned char reg_value_1 = 0x00; + unsigned short word_value_0 = 0; + unsigned short word_value_1 = 0; + + if(block_index == 0) + { + reg_value_0 = 0x90; + } + + word_value_0 = (direct_packet[block_index]); + block_index++; + + if(block_index < direct_packet_size) + { + word_value_0 |= (direct_packet[block_index] << 8); + block_index++; + } + + if(block_index < direct_packet_size) + { + reg_value_1 = 0xA0; + reg_value_0 |= (direct_packet[block_index] & 0x0F); + reg_value_1 |= (direct_packet[block_index] & 0xF0) >> 4; + block_index++; + } + + if(block_index < direct_packet_size) + { + word_value_1 = (direct_packet[block_index]); + block_index++; + } + + if(block_index < direct_packet_size) + { + word_value_1 |= (direct_packet[block_index] << 8); + block_index++; + } + + bus->i2c_smbus_write_word_data(dev, reg_value_0, word_value_0); + + if(reg_value_1 > 0) + { + bus->i2c_smbus_write_word_data(dev, reg_value_1, word_value_1); + } + } + } + /*-------------------------------------------------*\ | Remember to delete the data buffer | \*-------------------------------------------------*/ diff --git a/Controllers/CorsairDRAMController/CorsairDRAMControllerDetect.cpp b/Controllers/CorsairDRAMController/CorsairDRAMControllerDetect.cpp index 8f47f6a10..1416ba962 100644 --- a/Controllers/CorsairDRAMController/CorsairDRAMControllerDetect.cpp +++ b/Controllers/CorsairDRAMController/CorsairDRAMControllerDetect.cpp @@ -24,18 +24,15 @@ using namespace std::chrono_literals; bool TestForCorsairDRAMController(i2c_smbus_interface *bus, unsigned char address) { - int res = bus->i2c_smbus_write_quick(address, I2C_SMBUS_WRITE); - LOG_DEBUG("[%s] Trying address %02X", CORSAIR_DRAM_NAME, address); + int res = bus->i2c_smbus_read_byte_data(address, 0x43); + if(res < 0) { - LOG_DEBUG("[%s] Failed: res was %04X", CORSAIR_DRAM_NAME, res); return false; } - res = bus->i2c_smbus_read_byte_data(address, 0x43); - if(!(res == 0x1A || res == 0x1B || res == 0x1C)) { LOG_DEBUG("[%s] Failed: expected 0x1A, 0x1B, or 0x1C, got %04X", CORSAIR_DRAM_NAME, res); diff --git a/Controllers/CrucialController/CrucialController.cpp b/Controllers/CrucialController/CrucialController.cpp index adbe14b2e..9f922b30a 100644 --- a/Controllers/CrucialController/CrucialController.cpp +++ b/Controllers/CrucialController/CrucialController.cpp @@ -134,7 +134,14 @@ void CrucialController::CrucialRegisterWriteBlock(crucial_register reg, unsigned bus->i2c_smbus_write_word_data(dev, 0x00, ((reg << 8) & 0xFF00) | ((reg >> 8) & 0x00FF)); //Write Crucial block data - bus->i2c_smbus_write_block_data(dev, 0x03, sz, data); + if(bus->i2c_smbus_write_block_data(dev, 0x03, sz, data) == -1) + { + //Fall back to individual byte operations if the block operation fails + for(unsigned int block_byte = 0; block_byte < sz; block_byte++) + { + bus->i2c_smbus_write_byte_data(dev, 0x01, data[block_byte]); + } + } } void CrucialController::SendEffectColor diff --git a/Controllers/CrucialController/CrucialControllerDetect.cpp b/Controllers/CrucialController/CrucialControllerDetect.cpp index d91b93203..fbb60c19e 100644 --- a/Controllers/CrucialController/CrucialControllerDetect.cpp +++ b/Controllers/CrucialController/CrucialControllerDetect.cpp @@ -27,12 +27,6 @@ using namespace std::chrono_literals; static const unsigned char crucial_addresses[] = { -/*-----------------------------------------------------*\ -| These addresses have been disabled due to conflict | -| with ASUS Aura DRAM. Since the detection scheme is | -| the same, Aura RAM will be detected as Crucial. | -| We need to improve the Crucial detection scheme. | -\*-----------------------------------------------------*/ 0x39, 0x3A, 0x3B, @@ -81,7 +75,7 @@ unsigned char CrucialRegisterRead(i2c_smbus_interface* bus, crucial_dev_id dev, * TestForCrucialController * * * * Tests the given address to see if an Crucial controller exists there. First does a* -* quick write to test for a response, and if so does a simple read at 0xA0 to test * +* byte read to test for a response, and if so does a simple read at 0xA0 to test * * for incrementing values 0...F which was observed at this location during data dump * * * \******************************************************************************************/ @@ -90,19 +84,19 @@ bool TestForCrucialController(i2c_smbus_interface* bus, unsigned char address) { bool pass = false; - int res = bus->i2c_smbus_write_quick(address, I2C_SMBUS_WRITE); + int res = bus->i2c_smbus_read_byte(address); - if (res >= 0) + if(res >= 0) { pass = true; LOG_DEBUG("[%s] Detected an I2C device at address %02X", CRUCIAL_CONTROLLER_NAME, address); - for (int i = 0xA0; i < 0xB0; i++) + for(int i = 0xA0; i < 0xB0; i++) { res = bus->i2c_smbus_read_byte_data(address, i); - if (res != (i - 0xA0)) + if(res != (i - 0xA0)) { LOG_VERBOSE("[%s] Detection failed testing register %02X. Expected %02X, got %02X.", CRUCIAL_CONTROLLER_NAME, i, (i - 0xA0), res); @@ -178,7 +172,7 @@ void DetectCrucialControllers(std::vector &busses) { for(unsigned int slot = 0; slot < 4; slot++) { - int res = busses[bus]->i2c_smbus_write_quick(0x27, I2C_SMBUS_WRITE); + int res = busses[bus]->i2c_smbus_read_byte(0x27); if(res < 0) { @@ -192,7 +186,7 @@ void DetectCrucialControllers(std::vector &busses) if(address_list_idx < CRUCIAL_ADDRESS_COUNT) { - res = busses[bus]->i2c_smbus_write_quick(crucial_addresses[address_list_idx], I2C_SMBUS_WRITE); + res = busses[bus]->i2c_smbus_read_byte(crucial_addresses[address_list_idx]); } else { diff --git a/Controllers/ENESMBusController/ENESMBusControllerDetect.cpp b/Controllers/ENESMBusController/ENESMBusControllerDetect.cpp index 729ab62ef..73d25289f 100644 --- a/Controllers/ENESMBusController/ENESMBusControllerDetect.cpp +++ b/Controllers/ENESMBusController/ENESMBusControllerDetect.cpp @@ -112,7 +112,7 @@ static void ENERegisterWrite(i2c_smbus_interface* bus, ene_dev_id dev, ene_regis * TestForENESMBusController * * * * Tests the given address to see if an ENE controller exists there. First does a * -* quick write to test for a response, and if so does a simple read at 0xA0 to test * +* byte read to test for a response, and if so does a simple read at 0xA0 to test * * for incrementing values 0...F which was observed at this location during data dump * * * * Also tests for the string "Micron" in the ENE register space. Crucial (Micron) * @@ -202,7 +202,7 @@ void DetectENESMBusDRAMControllers(std::vector &busses) for (unsigned int slot = 0; slot < 8; slot++) { - int res = busses[bus]->i2c_smbus_write_quick(0x77, I2C_SMBUS_WRITE); + int res = busses[bus]->i2c_smbus_read_byte(0x77); if(res < 0) { @@ -219,7 +219,7 @@ void DetectENESMBusDRAMControllers(std::vector &busses) { LOG_DEBUG("[ENE SMBus DRAM] Testing address %02X to see if there is a device there", ene_ram_addresses[address_list_idx]); - res = busses[bus]->i2c_smbus_write_quick(ene_ram_addresses[address_list_idx], I2C_SMBUS_WRITE); + res = busses[bus]->i2c_smbus_read_byte(ene_ram_addresses[address_list_idx]); } else { diff --git a/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_i2c_smbus.cpp b/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_i2c_smbus.cpp index fb30101c8..4bd4b290a 100644 --- a/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_i2c_smbus.cpp +++ b/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_i2c_smbus.cpp @@ -61,5 +61,12 @@ void ENESMBusInterface_i2c_smbus::ENERegisterWriteBlock(ene_dev_id dev, ene_regi bus->i2c_smbus_write_word_data(dev, 0x00, ((reg << 8) & 0xFF00) | ((reg >> 8) & 0x00FF)); //Write ENE block data - bus->i2c_smbus_write_block_data(dev, 0x03, sz, data); + if(bus->i2c_smbus_write_block_data(dev, 0x03, sz, data) == -1) + { + //Fall back to individual byte operations if the block operation fails + for(unsigned int block_byte = 0; block_byte < sz; block_byte++) + { + bus->i2c_smbus_write_byte_data(dev, 0x01, data[block_byte]); + } + } } diff --git a/Controllers/HyperXDRAMController/HyperXDRAMControllerDetect.cpp b/Controllers/HyperXDRAMController/HyperXDRAMControllerDetect.cpp index 263914b62..6d8620197 100644 --- a/Controllers/HyperXDRAMController/HyperXDRAMControllerDetect.cpp +++ b/Controllers/HyperXDRAMController/HyperXDRAMControllerDetect.cpp @@ -30,28 +30,9 @@ using namespace std::chrono_literals; bool TestForHyperXDRAMController(i2c_smbus_interface* bus, unsigned char address) { - bool pass = false; + int res = bus->i2c_smbus_read_byte(address); - int res = bus->i2c_smbus_write_quick(address, I2C_SMBUS_WRITE); - - LOG_DEBUG("[%s] Writing at address %02X, res=%02X", HYPERX_CONTROLLER_NAME, address, res); - - if (res >= 0) - { - pass = true; - - for (int i = 0xA0; i < 0xB0; i++) - { - res = bus->i2c_smbus_read_byte_data(address, i); - - if (res != i) - { - pass = false; - } - } - } - - return(pass); + return(res >= 0); } /* TestForHyperXDRAMController() */ diff --git a/SPDAccessor/DDR4DirectAccessor.cpp b/SPDAccessor/DDR4DirectAccessor.cpp index a593bcc78..d4139f618 100644 --- a/SPDAccessor/DDR4DirectAccessor.cpp +++ b/SPDAccessor/DDR4DirectAccessor.cpp @@ -23,27 +23,17 @@ DDR4DirectAccessor::~DDR4DirectAccessor() bool DDR4DirectAccessor::isAvailable(i2c_smbus_interface *bus, uint8_t spd_addr) { - /*-----------------------------------------------------*\ - | Perform i2c quick transfer to test if i2c address | - | responds | - \*-----------------------------------------------------*/ - int value = bus->i2c_smbus_write_quick(0x36, 0x00); - if(value < 0) - { - return false; - } - /*-----------------------------------------------------*\ | Select low page | \*-----------------------------------------------------*/ - bus->i2c_smbus_write_byte_data(0x36, 0x00, 0xFF); + bus->i2c_smbus_write_byte(0x36, 0x00); std::this_thread::sleep_for(SPD_IO_DELAY); /*-----------------------------------------------------*\ | Read value at address 0 in SPD device | \*-----------------------------------------------------*/ - value = bus->i2c_smbus_read_byte_data(spd_addr, 0x00); + s32 value = bus->i2c_smbus_read_byte_data(spd_addr, 0x00); /*-----------------------------------------------------*\ | DDR4 is available if value is 0x23 | diff --git a/i2c_smbus/Linux/i2c_smbus_linux.cpp b/i2c_smbus/Linux/i2c_smbus_linux.cpp index 3d4d9fee9..8abd19700 100644 --- a/i2c_smbus/Linux/i2c_smbus_linux.cpp +++ b/i2c_smbus/Linux/i2c_smbus_linux.cpp @@ -136,9 +136,15 @@ bool i2c_smbus_linux_detect() port_id = 0; bus_id = 0; + // Get port ID for AMD GPU aux bus + sscanf(device_string, "AMDGPU DM aux hw bus %hu", &port_id); + // Get port ID for Nvidia GPUs sscanf(device_string, "NVIDIA i2c adapter %hu at", &port_id); + // Get port ID for PIIX4 SMBus + sscanf(device_string, "SMBus PIIX4 adapter port %hu at", &port_id); + // Get the Linux Bus ID sscanf(ent->d_name, "i2c-%hu", &bus_id); diff --git a/qt/OpenRGBSystemInfoPage/OpenRGBSystemInfoPage.cpp b/qt/OpenRGBSystemInfoPage/OpenRGBSystemInfoPage.cpp index 22931e7be..bc65364ef 100644 --- a/qt/OpenRGBSystemInfoPage/OpenRGBSystemInfoPage.cpp +++ b/qt/OpenRGBSystemInfoPage/OpenRGBSystemInfoPage.cpp @@ -154,7 +154,7 @@ void OpenRGBSystemInfoPage::on_CommandButton_clicked() unsigned char address = ui->CommandAddressBox->value(); unsigned char regaddr = ui->CommandRegisterBox->value(); unsigned char size = ui->CommandSizeBox->value(); - unsigned short write_data = ui->CommandWriteDataLineEdit->text().toInt(nullptr, 16); + unsigned short write_data = ui->CommandWriteDataLineEdit->text().toInt(nullptr, 0); unsigned short read_data = 0xFFFF; ui->SMBusDataText->clear();