debugd: Add EC Type C tool EnterMode command

Add a debugd D-Bus method which will be used by the Type C daemon to
enter an operating mode on a Type C port.

BUG=b:171725237
TEST=- Run debugd unit tests and ensure they pass.
     - Call the D-Bus command using dbus-send from command line and
       verify the mode is entered. The command is:
       dbus-send --system --dest=org.chromium.debugd
       --print-reply /org/chromium/debugd
       org.chromium.debugd.EcTypeCEnterMode uint32:1 uint32:1

Cq-Depend: chromium:2600331
Change-Id: Iab0eb7fc1503867a391dc443f515f12181051929
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2601785
Commit-Queue: Prashant Malani <pmalani@chromium.org>
Reviewed-by: Mike Frysinger <vapier@chromium.org>
Reviewed-by: Jorge Lucangeli Obes <jorgelo@chromium.org>
Tested-by: Prashant Malani <pmalani@chromium.org>
diff --git a/debugd/dbus_bindings/org.chromium.debugd.xml b/debugd/dbus_bindings/org.chromium.debugd.xml
index ed4f034..9b0da15 100644
--- a/debugd/dbus_bindings/org.chromium.debugd.xml
+++ b/debugd/dbus_bindings/org.chromium.debugd.xml
@@ -1231,5 +1231,29 @@
       </arg>
       <annotation name="org.chromium.DBus.Method.Kind" value="normal"/>
     </method>
+    <method name="EcTypeCEnterMode">
+      <tp:docstring>
+        Runs the 'ectool typeccontrol' command with pre-defined
+        sandbox options in rootfs to enter a USB Type-C mode on the
+        specified port.
+      </tp:docstring>
+      <arg name="port_num" type="u" direction="in">
+        <tp:docstring>
+          The index number of the port for which the enter mode
+          command will be run. This wil be used in the ectool command
+          without changes.
+        </tp:docstring>
+      </arg>
+      <arg name="mode" type="u" direction="in">
+        <tp:docstring>
+          The mode number argument specifying the mode to be entered.
+          This will be used in the ectool command directly without changes.
+        </tp:docstring>
+      </arg>
+      <arg name="output" type="s" direction="out">
+        Returns the output of the 'ectool typeccontrol' command.
+      </arg>
+      <annotation name="org.chromium.DBus.Method.Kind" value="normal"/>
+    </method>
   </interface>
 </node>
diff --git a/debugd/src/debugd_dbus_adaptor.cc b/debugd/src/debugd_dbus_adaptor.cc
index c80986a..58f76e4 100644
--- a/debugd/src/debugd_dbus_adaptor.cc
+++ b/debugd/src/debugd_dbus_adaptor.cc
@@ -617,4 +617,11 @@
   return dmesg_tool_->CallDmesg(options, error, output);
 }
 
+bool DebugdDBusAdaptor::EcTypeCEnterMode(brillo::ErrorPtr* error,
+                                         uint32_t port_num,
+                                         uint32_t mode,
+                                         std::string* output) {
+  return ec_typec_tool_->EnterMode(error, port_num, mode, output);
+}
+
 }  // namespace debugd
diff --git a/debugd/src/debugd_dbus_adaptor.h b/debugd/src/debugd_dbus_adaptor.h
index 2456da0..c4a496f 100644
--- a/debugd/src/debugd_dbus_adaptor.h
+++ b/debugd/src/debugd_dbus_adaptor.h
@@ -221,6 +221,10 @@
   bool CallDmesg(brillo::ErrorPtr* error,
                  const brillo::VariantDictionary& options,
                  std::string* output) override;
+  bool EcTypeCEnterMode(brillo::ErrorPtr* error,
+                        uint32_t port_num,
+                        uint32_t mode,
+                        std::string* output) override;
 
  private:
   brillo::dbus_utils::DBusObject dbus_object_;
diff --git a/debugd/src/ec_typec_tool.cc b/debugd/src/ec_typec_tool.cc
index 3c3a292..bc6095c 100644
--- a/debugd/src/ec_typec_tool.cc
+++ b/debugd/src/ec_typec_tool.cc
@@ -8,7 +8,6 @@
 
 #include <base/files/file_path.h>
 #include <base/strings/stringprintf.h>
-#include <brillo/errors/error.h>
 
 #include "debugd/src/ectool_util.h"
 
@@ -41,4 +40,24 @@
   return output;
 }
 
+bool EcTypeCTool::EnterMode(brillo::ErrorPtr* error,
+                            uint32_t port_num,
+                            uint32_t mode,
+                            std::string* output) {
+  const auto seccomp_policy_path =
+      base::FilePath(kSandboxDirPath).Append(GetEctoolPolicyFile("typec"));
+
+  std::vector<std::string> ectool_args = {"typeccontrol"};
+  ectool_args.push_back(base::StringPrintf("%u", port_num));
+  // 2nd argument is '2' for enter mode.
+  ectool_args.push_back("2");
+  ectool_args.push_back(base::StringPrintf("%u", mode));
+
+  if (!RunEctoolWithArgs(error, seccomp_policy_path, ectool_args, kRunAs,
+                         output))
+    return false;
+
+  return true;
+}
+
 }  // namespace debugd
diff --git a/debugd/src/ec_typec_tool.h b/debugd/src/ec_typec_tool.h
index add151f..fe0e462 100644
--- a/debugd/src/ec_typec_tool.h
+++ b/debugd/src/ec_typec_tool.h
@@ -8,6 +8,7 @@
 #include <string>
 
 #include <base/macros.h>
+#include <brillo/errors/error.h>
 
 namespace debugd {
 
@@ -20,6 +21,10 @@
   ~EcTypeCTool() = default;
 
   std::string GetInventory();
+  bool EnterMode(brillo::ErrorPtr* error,
+                 uint32_t port_num,
+                 uint32_t mode,
+                 std::string* output);
 };
 
 }  // namespace debugd