Add to read model number from VPD

1. Read model number from VPD and set to DBus property

2. Since the original I2C read fucntion (Smbus block read)
   can't read from VPD, change the read function to I2C
   Master write/read for all read actions

Signed-off-by: George Hung <george.hung@quantatw.com>
Change-Id: I13a52469ec6db68a4209d4a8092113c44173aaac
diff --git a/i2c.h b/i2c.h
index 2b2984d..7c5e678 100644
--- a/i2c.h
+++ b/i2c.h
@@ -18,7 +18,7 @@
     msg[0].len = tx_len;
 
     msg[1].addr = slave_addr & 0xFF;
-    msg[1].flags = I2C_M_RD | I2C_M_RECV_LEN;
+    msg[1].flags = I2C_M_RD;
     msg[1].buf = (__u8*)rx_buf;
     msg[1].len = rx_len;
 
diff --git a/nvme_manager.cpp b/nvme_manager.cpp
index 7e0fefd..6f9ca58 100644
--- a/nvme_manager.cpp
+++ b/nvme_manager.cpp
@@ -15,6 +15,7 @@
 #include "i2c.h"
 #define MONITOR_INTERVAL_SECONDS 1
 #define NVME_SSD_SLAVE_ADDRESS 0x6a
+#define NVME_SSD_VPD_SLAVE_ADDRESS 0x53
 #define GPIO_BASE_PATH "/sys/class/gpio/gpio"
 #define IS_PRESENT "0"
 #define POWERGD "1"
@@ -26,6 +27,8 @@
 
 static constexpr const uint8_t COMMAND_CODE_0 = 0;
 static constexpr const uint8_t COMMAND_CODE_8 = 8;
+static constexpr const uint8_t CODE_0_LENGTH = 8;
+static constexpr const uint8_t CODE_8_LENGTH = 23;
 
 static constexpr int CapacityFaultMask = 1;
 static constexpr int temperatureFaultMask = 1 << 1;
@@ -36,6 +39,8 @@
 
 static constexpr int SERIALNUMBER_START_INDEX = 3;
 static constexpr int SERIALNUMBER_END_INDEX = 23;
+static constexpr int MODELNUMBER_START_INDEX = 46;
+static constexpr int MODELNUMBER_END_INDEX = 85;
 
 static constexpr const int TEMPERATURE_SENSOR_FAILURE = 0x81;
 
@@ -64,6 +69,8 @@
                                  ASSET_IFACE, "SerialNumber",
                                  nvmeData.serialNumber);
     util::SDBusPlus::setProperty(bus, INVENTORY_BUSNAME, inventoryPath,
+                                 ASSET_IFACE, "Model", nvmeData.modelNumber);
+    util::SDBusPlus::setProperty(bus, INVENTORY_BUSNAME, inventoryPath,
                                  NVME_STATUS_IFACE, "SmartWarnings",
                                  nvmeData.smartWarnings);
     util::SDBusPlus::setProperty(bus, INVENTORY_BUSNAME, inventoryPath,
@@ -232,9 +239,9 @@
         return nvmeData.present;
     }
 
-    auto res_int =
-        smbus.SendSmbusRWBlockCmdRAW(busID, NVME_SSD_SLAVE_ADDRESS, &tx_data,
-                                     sizeof(tx_data), rsp_data_command_0);
+    auto res_int = smbus.SendSmbusRWCmdRAW(busID, NVME_SSD_SLAVE_ADDRESS,
+                                           &tx_data, sizeof(tx_data),
+                                           rsp_data_command_0, CODE_0_LENGTH);
 
     if (res_int < 0)
     {
@@ -249,11 +256,16 @@
         return nvmeData.present;
     }
 
+    nvmeData.statusFlags = intToHex(rsp_data_command_0[1]);
+    nvmeData.smartWarnings = intToHex(rsp_data_command_0[2]);
+    nvmeData.driveLifeUsed = intToHex(rsp_data_command_0[4]);
+    nvmeData.sensorValue = (int8_t)rsp_data_command_0[3];
+
     tx_data = COMMAND_CODE_8;
 
-    res_int =
-        smbus.SendSmbusRWBlockCmdRAW(busID, NVME_SSD_SLAVE_ADDRESS, &tx_data,
-                                     sizeof(tx_data), rsp_data_command_8);
+    res_int = smbus.SendSmbusRWCmdRAW(busID, NVME_SSD_SLAVE_ADDRESS, &tx_data,
+                                      sizeof(tx_data), rsp_data_command_8,
+                                      CODE_8_LENGTH);
 
     if (res_int < 0)
     {
@@ -288,10 +300,38 @@
                 static_cast<char>(rsp_data_command_8[offset]);
     }
 
-    nvmeData.statusFlags = intToHex(rsp_data_command_0[1]);
-    nvmeData.smartWarnings = intToHex(rsp_data_command_0[2]);
-    nvmeData.driveLifeUsed = intToHex(rsp_data_command_0[4]);
-    nvmeData.sensorValue = (int8_t)rsp_data_command_0[3];
+    if (nvmeData.vendor == "Samsung")
+    {
+        unsigned char rsp_data_vpd[I2C_DATA_MAX] = {0};
+        const int rx_len = (MODELNUMBER_END_INDEX - MODELNUMBER_START_INDEX);
+        tx_data = MODELNUMBER_START_INDEX;
+
+        auto res_int =
+            smbus.SendSmbusRWCmdRAW(busID, NVME_SSD_VPD_SLAVE_ADDRESS, &tx_data,
+                                    sizeof(tx_data), rsp_data_vpd, rx_len);
+
+        if (res_int < 0)
+        {
+            if (isErrorSmbus[busID] != true)
+            {
+                log<level::ERR>("Send command read VPD fail!");
+                isErrorSmbus[busID] = true;
+            }
+
+            smbus.smbusClose(busID);
+            nvmeData.present = false;
+            return nvmeData.present;
+        }
+
+        for (int i = 0; i < rx_len; i++)
+        {
+            if (rsp_data_vpd[i] != ' ')
+                nvmeData.modelNumber += static_cast<char>(rsp_data_vpd[i]);
+        }
+
+        if (nvmeData.modelNumber.substr(0, nvmeData.vendor.size()) == "SAMSUNG")
+            nvmeData.modelNumber.erase(0, nvmeData.vendor.size());
+    }
 
     smbus.smbusClose(busID);
 
diff --git a/nvme_manager.hpp b/nvme_manager.hpp
index b454ed3..7017475 100644
--- a/nvme_manager.hpp
+++ b/nvme_manager.hpp
@@ -72,6 +72,7 @@
         bool present;              /* Whether or not the nvme is present  */
         std::string vendor;        /* The nvme manufacturer  */
         std::string serialNumber;  /* The nvme serial number  */
+        std::string modelNumber;   /* The nvme model number   */
         std::string smartWarnings; /* Indicates smart warnings for the state  */
         std::string statusFlags;   /* Indicates the status of the drives  */
         std::string
diff --git a/smbus.cpp b/smbus.cpp
index 7e8d968..a015714 100644
--- a/smbus.cpp
+++ b/smbus.cpp
@@ -94,26 +94,22 @@
     close(fd[smbus_num]);
 }
 
-int phosphor::smbus::Smbus::SendSmbusRWBlockCmdRAW(int smbus_num,
-                                                   int8_t device_addr,
-                                                   uint8_t* tx_data,
-                                                   uint8_t tx_len,
-                                                   uint8_t* rsp_data)
+int phosphor::smbus::Smbus::SendSmbusRWCmdRAW(int smbus_num, int8_t device_addr,
+                                              uint8_t* tx_data, uint8_t tx_len,
+                                              uint8_t* rsp_data, uint8_t rx_len)
 {
     int res, res_len;
     unsigned char Rx_buf[I2C_DATA_MAX] = {0};
 
-    Rx_buf[0] = 1;
-
     gMutex.lock();
 
     res = i2c_read_after_write(fd[smbus_num], device_addr, tx_len,
-                               (unsigned char*)tx_data, I2C_DATA_MAX,
+                               (unsigned char*)tx_data, rx_len,
                                (unsigned char*)Rx_buf);
 
     if (res < 0)
     {
-        fprintf(stderr, "Error: SendSmbusRWBlockCmdRAW failed\n");
+        fprintf(stderr, "Error: SendSmbusRWCmdRAW failed\n");
     }
 
     res_len = Rx_buf[0] + 1;
diff --git a/smbus.hpp b/smbus.hpp
index c270d01..4dc44f0 100644
--- a/smbus.hpp
+++ b/smbus.hpp
@@ -25,9 +25,8 @@
 
     void smbusClose(int smbus_num);
 
-    int SendSmbusRWBlockCmdRAW(int smbus_num, int8_t device_addr,
-                               uint8_t* tx_data, uint8_t tx_len,
-                               uint8_t* rsp_data);
+    int SendSmbusRWCmdRAW(int smbus_num, int8_t device_addr, uint8_t* tx_data,
+                          uint8_t tx_len, uint8_t* rsp_data, uint8_t rx_len);
 };
 
 } // namespace smbus