From fa312c462de18b25a67f08c8f7be51f9fbdc4df5 Mon Sep 17 00:00:00 2001
From: wangjue <jue.wang2@luxshare-ict.com>
Date: Thu, 19 Sep 2024 15:11:18 +0800
Subject: [PATCH] Implement power reset control

Signed-off-by: wangjue <jue.wang2@luxshare-ict.com>
---
 src/power_control.cpp | 128 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 126 insertions(+), 2 deletions(-)

diff --git a/src/power_control.cpp b/src/power_control.cpp
index 7a47957..586d1e3 100644
--- a/src/power_control.cpp
+++ b/src/power_control.cpp
@@ -27,10 +27,18 @@
 #include <nlohmann/json.hpp>
 #include <phosphor-logging/lg2.hpp>
 #include <sdbusplus/asio/object_server.hpp>
-
 #include <filesystem>
 #include <fstream>
 #include <string_view>
+#include <thread>
+#include <chrono>
+#include <iostream>
+
+extern "C"
+{
+#include <i2c/smbus.h>
+#include <linux/i2c-dev.h>
+}
 
 namespace power_control
 {
@@ -1408,9 +1416,125 @@ static void forcePowerOff()
     });
 }
 
+int i2cWriteRead(std::string& i2cDev, const uint8_t slaveAddr,
+                        std::vector<uint8_t> writeData,
+                        std::vector<uint8_t>& readBuf)
+{
+    int fd = open(i2cDev.c_str(), O_RDWR | O_CLOEXEC);
+    if (fd < 0)
+    {
+        lg2::error("unable to open i2c device");
+        return -1;
+    }
+
+    const size_t writeCount = writeData.size();
+    const size_t readCount = readBuf.size();
+
+    int msgCount = 0;
+    struct i2c_msg i2cmsg[2];
+
+    memset(i2cmsg, 0, sizeof(i2cmsg));
+
+    if (writeCount)
+    {
+        // Data will be writtern to the slave address
+        i2cmsg[msgCount].addr = slaveAddr;
+        i2cmsg[msgCount].flags = 0x00;
+        i2cmsg[msgCount].len = writeCount;
+        i2cmsg[msgCount].buf = writeData.data();
+        msgCount++;
+    }
+
+    if (readCount)
+    {
+        // Data will be read into the buffer from the slave address
+        i2cmsg[msgCount].addr = slaveAddr;
+        i2cmsg[msgCount].flags = I2C_M_RD;
+        i2cmsg[msgCount].len = readCount;
+        i2cmsg[msgCount].buf = readBuf.data();
+        msgCount++;
+    }
+
+    struct i2c_rdwr_ioctl_data msgReadWrite;
+    memset((void*)&msgReadWrite, 0, sizeof(msgReadWrite));
+    msgReadWrite.msgs = i2cmsg;
+    msgReadWrite.nmsgs = msgCount;
+
+    int ret = ioctl(fd, I2C_RDWR, &msgReadWrite);
+    close(fd);
+    if (ret < 0)
+    {
+        lg2::error("I2C Read Write Failed.");
+        return -1;
+    }
+
+    if (readCount)
+    {
+        readBuf.resize(msgReadWrite.msgs[msgCount - 1].len);
+    }
+
+    return 0;
+}
+
+#define BIT2 (1 << 2)
+void luxResetChassis()
+{
+    int ret = 0;
+    std::string i2cDev = "/dev/i2c-0";
+    // Perform the combined write/read
+
+    std::vector<uint8_t> readBuf(1);
+    std::vector<uint8_t> writeData = {0x30, 0x01};
+    const uint8_t slaveAddr = 0x0D;
+    uint8_t regVal, tmp;
+
+    ret = i2cWriteRead(i2cDev, slaveAddr, writeData, readBuf);
+    if (ret < 0)
+    {
+        lg2::error("i2c failed to read regVal.");
+        goto err;
+    }
+
+    regVal = readBuf[0];
+    readBuf.resize(0);
+    tmp = regVal & (~BIT2);
+    writeData.push_back(tmp);
+
+    ret = i2cWriteRead(i2cDev, slaveAddr, writeData, readBuf);
+    if (ret < 0)
+    {
+        lg2::error("i2c WriteRead failed.");
+        goto err;
+    }
+
+    writeData.pop_back();
+    tmp = regVal | BIT2;
+    writeData.push_back(tmp);
+
+    std::this_thread::sleep_for(std::chrono::milliseconds(400));
+
+    ret = i2cWriteRead(i2cDev, slaveAddr, writeData, readBuf);
+    if (ret < 0)
+    {
+        lg2::error("i2c WriteRead failed.");
+        goto err;
+    }
+
+    lg2::error("Success to reset Host.");
+    return;
+err:
+    lg2::error("Fail to reset Host.");
+    return;
+}
+
 static void reset()
 {
-    assertGPIOForMs(resetOutConfig, TimerMap["ResetPulseMs"]);
+    if (!resetOutConfig.lineName.empty())
+        assertGPIOForMs(resetOutConfig, TimerMap["ResetPulseMs"]);
+    else {
+        std::thread myThread(luxResetChassis);
+        myThread.join();
+    }
 }
 
 static void gracefulPowerOffTimerStart()
-- 
2.34.1

