PEL: devcallouts: Determine access type

Add a function to determine if the device path represents an I2C, FSI,
FSI-I2C, or FSI-SPI attached device.

Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Change-Id: Ie58452e7988938e9b701357bbb96252be971902f
diff --git a/extensions/openpower-pels/device_callouts.cpp b/extensions/openpower-pels/device_callouts.cpp
index 44226c9..c0a4749 100644
--- a/extensions/openpower-pels/device_callouts.cpp
+++ b/extensions/openpower-pels/device_callouts.cpp
@@ -101,12 +101,71 @@
                                                    const nlohmann::json& json)
 {
     std::vector<Callout> callouts;
+    fs::path path;
 
-    // TODO
+    // Gives the /sys/devices/platform/ path
+    try
+    {
+        path = fs::canonical(devPath);
+    }
+    catch (const fs::filesystem_error& e)
+    {
+        // Path not there, still try to do the callout
+        path = devPath;
+    }
+
+    switch (util::getCalloutType(path))
+    {
+        case util::CalloutType::i2c:
+            // callouts = calloutI2CUsingPath(errnoValue, path, json);
+            break;
+        case util::CalloutType::fsi:
+            // callouts = calloutFSI(errnoValue, path, json);
+            break;
+        case util::CalloutType::fsii2c:
+            // callouts = calloutFSII2C(errnoValue, path, json);
+            break;
+        case util::CalloutType::fsispi:
+            // callouts = calloutFSISPI(errnoValue, path, json);
+            break;
+        default:
+            std::string msg =
+                "Could not get callout type from device path: " + path.string();
+            throw std::invalid_argument{msg.c_str()};
+            break;
+    }
 
     return callouts;
 }
 
+CalloutType getCalloutType(const std::string& devPath)
+{
+    if ((devPath.find("fsi-master") != std::string::npos) &&
+        (devPath.find("i2c-") != std::string::npos))
+    {
+        return CalloutType::fsii2c;
+    }
+
+    if ((devPath.find("fsi-master") != std::string::npos) &&
+        (devPath.find("spi") != std::string::npos))
+    {
+        return CalloutType::fsispi;
+    }
+
+    // Treat anything else FSI related as plain FSI
+    if (devPath.find("fsi-master") != std::string::npos)
+    {
+        return CalloutType::fsi;
+    }
+
+    if (devPath.find("i2c-bus/i2c-") != std::string::npos)
+    {
+        return CalloutType::i2c;
+    }
+
+    return CalloutType::unknown;
+}
+
 } // namespace util
 
 std::vector<Callout> getCallouts(const std::string& devPath,
diff --git a/extensions/openpower-pels/device_callouts.hpp b/extensions/openpower-pels/device_callouts.hpp
index 2945f25..1f559c2 100644
--- a/extensions/openpower-pels/device_callouts.hpp
+++ b/extensions/openpower-pels/device_callouts.hpp
@@ -1,7 +1,5 @@
 #pragma once
 
-#include "pel_types.hpp"
-
 #include <filesystem>
 #include <nlohmann/json.hpp>
 #include <string>
@@ -123,6 +121,18 @@
 {
 
 /**
+ * @brief The different callout path types
+ */
+enum class CalloutType
+{
+    i2c,
+    fsi,
+    fsii2c,
+    fsispi,
+    unknown
+};
+
+/**
  * @brief Returns the path to the JSON file to look up callouts in.
  *
  * @param[in] compatibleList - The list of compatible names for this
@@ -145,5 +155,16 @@
 std::vector<device_callouts::Callout>
     calloutI2C(size_t i2CBus, uint8_t i2cAddress,
                const nlohmann::json& calloutJSON);
+
+/**
+ * @brief Determines the type of the path (FSI, I2C, etc) based
+ *        on tokens in the device path.
+ *
+ * @param[in] devPath - The device path
+ *
+ * @return CalloutType - The callout type
+ */
+CalloutType getCalloutType(const std::string& devPath);
+
 } // namespace util
 } // namespace openpower::pels::device_callouts
diff --git a/test/openpower-pels/device_callouts_test.cpp b/test/openpower-pels/device_callouts_test.cpp
index d2947a1..fd5213d 100644
--- a/test/openpower-pels/device_callouts_test.cpp
+++ b/test/openpower-pels/device_callouts_test.cpp
@@ -240,3 +240,51 @@
         EXPECT_THROW(util::getJSONFilename(compatibles), std::invalid_argument);
     }
 }
+
+// Test determining the callout type from the device path
+TEST_F(DeviceCalloutsTest, getCalloutTypeTest)
+{
+
+    // Invalid
+    {
+        EXPECT_EQ(util::getCalloutType("/some/bad/device/path"),
+                  util::CalloutType::unknown);
+    }
+
+    // I2C
+    {
+        EXPECT_EQ(util::getCalloutType(
+                      "/sys/devices/platform/ahb/ahb:apb/ahb:apb:bus@1e78a000/"
+                      "1e78a340.i2c-bus/i2c-10/10-0022"),
+                  util::CalloutType::i2c);
+    }
+
+    // FSI
+    {
+        EXPECT_EQ(util::getCalloutType(
+                      "/sys/devices/platform/ahb/ahb:apb/1e79b000.fsi/"
+                      "fsi-master/fsi0/slave@00:00/00:00:00:0a/fsi-master/fsi1/"
+                      "slave@01:00/01:01:00:06/sbefifo2-dev0/occ-hwmon.2"),
+                  util::CalloutType::fsi);
+    }
+
+    // FSI-I2C
+    {
+        EXPECT_EQ(util::getCalloutType(
+                      "/sys/devices/platform/ahb/ahb:apb/1e79b000.fsi/"
+                      "fsi-master/fsi0/slave@00:00/00:00:00:0a/fsi-master/fsi1/"
+                      "slave@01:00/01:01:00:03/i2c-211/211-0055"),
+                  util::CalloutType::fsii2c);
+    }
+
+    // FSI-SPI
+    {
+
+        EXPECT_EQ(
+            util::getCalloutType(
+                "/sys/devices/platform/ahb/ahb:apb/1e79b000.fsi/fsi-master/"
+                "fsi0/slave@00:00/00:00:00:0a/fsi-master/fsi1/slave@08:00/"
+                "01:03:00:04/spi_master/spi9/spi9.0/spi9.00/nvmem"),
+            util::CalloutType::fsispi);
+    }
+}