Used by synce_dev to acquire current state of its DPLL.

Co-developed-by: Anatolii Gerasymenko <anatolii.gerasyme...@intel.com>
Signed-off-by: Anatolii Gerasymenko <anatolii.gerasyme...@intel.com>
Co-developed-by: Piotr Kwapulinski <piotr.kwapulin...@intel.com>
Signed-off-by: Piotr Kwapulinski <piotr.kwapulin...@intel.com>
Co-developed-by: Michal Michalik <michal.micha...@intel.com>
Signed-off-by: Michal Michalik <michal.micha...@intel.com>
Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalew...@intel.com>

---
v2: updated license headers

 synce_dev_ctrl.c | 153 +++++++++++++++++++++++++++++++++++++++++++++++
 synce_dev_ctrl.h |  64 ++++++++++++++++++++
 2 files changed, 217 insertions(+)
 create mode 100644 synce_dev_ctrl.c
 create mode 100644 synce_dev_ctrl.h

diff --git a/synce_dev_ctrl.c b/synce_dev_ctrl.c
new file mode 100644
index 000000000000..5e75e7119ef4
--- /dev/null
+++ b/synce_dev_ctrl.c
@@ -0,0 +1,153 @@
+/**
+ * @file synce_dev_ctrl.c
+ * @brief Interface for acquiring Sync-E capable device DPLL state changes
+ * @note SPDX-FileCopyrightText: Copyright 2022 Intel Corporation
+ * @note SPDX-License-Identifier: GPL-2.0+
+ */
+#include <errno.h>
+#include <stdlib.h>
+#include "print.h"
+#include "synce_dev_ctrl.h"
+
+#define DPLL_STATE_STR_RETURN_SIZE     0xff
+struct synce_dev_ctrl {
+       const char *dpll_get_state_cmd;
+       struct dpll_state_str dss;
+};
+
+static int dpll_str_state_to_enum(struct synce_dev_ctrl *dc, char *str_state,
+                                 enum dpll_state *enum_state)
+{
+       if (!strncmp(str_state, dc->dss.holdover, DPLL_STATE_STR_RETURN_SIZE)) {
+               *enum_state = DPLL_HOLDOVER;
+       } else if (!strncmp(str_state, dc->dss.locked_ho,
+                           DPLL_STATE_STR_RETURN_SIZE)) {
+               *enum_state = DPLL_LOCKED_HO_ACQ;
+       } else if (!strncmp(str_state, dc->dss.locked,
+                           DPLL_STATE_STR_RETURN_SIZE)) {
+               *enum_state = DPLL_LOCKED;
+       } else if (!strncmp(str_state, dc->dss.freerun,
+                           DPLL_STATE_STR_RETURN_SIZE)) {
+               *enum_state = DPLL_FREERUN;
+       } else if (!strncmp(str_state, dc->dss.invalid,
+                           DPLL_STATE_STR_RETURN_SIZE)) {
+               *enum_state = DPLL_INVALID;
+       } else {
+               *enum_state = DPLL_UNKNOWN;
+       }
+
+       if (*enum_state == DPLL_UNKNOWN) {
+               pr_err("dpll state missing for str_state: '%s'", str_state);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int get_dpll_state_from_cmd(struct synce_dev_ctrl *dc,
+                                  enum dpll_state *state)
+{
+       char buf[DPLL_STATE_STR_RETURN_SIZE] = {0}, *c;
+       FILE *fp;
+       int ret;
+
+       fp = popen(dc->dpll_get_state_cmd, "r");
+       if (!fp) {
+               pr_err("failed open process: '%s'", dc->dpll_get_state_cmd);
+               return DPLL_UNKNOWN;
+       }
+
+       if (!fgets(buf, sizeof(buf), fp)) {
+               pr_err("failed read process output: '%s'", 
dc->dpll_get_state_cmd);
+               goto out;
+       }
+
+       c = buf;
+       while (*c != '\0') {
+               if (*(++c) == '\n') {
+                       *c = '\0';
+               }
+       }
+
+out:
+       ret = pclose(fp);
+       if (ret) {
+               pr_err("process '%s' exit status: %d",
+                      dc->dpll_get_state_cmd, ret);
+       }
+
+       return ret ? DPLL_UNKNOWN : dpll_str_state_to_enum(dc, buf, state);
+}
+
+int synce_dev_ctrl_get_state(struct synce_dev_ctrl *dc,
+                            enum dpll_state *state)
+{
+       int ret = -EINVAL;
+
+       if (!dc) {
+               pr_err("%s: dc is NULL", __func__);
+               return ret;
+       }
+
+       if (!state) {
+               pr_err("%s: state is NULL", __func__);
+               return ret;
+       }
+
+       if (!dc->dpll_get_state_cmd) {
+               pr_err("%s: dc->dpll_get_state_cmd is NULL", __func__);
+               return ret;
+       }
+
+       ret = get_dpll_state_from_cmd(dc, state);
+       if (ret || *state < DPLL_INVALID || *state > DPLL_HOLDOVER) {
+               return ret;
+       }
+
+       return 0;
+}
+
+struct synce_dev_ctrl *synce_dev_ctrl_create(void)
+{
+       struct synce_dev_ctrl *dc = malloc(sizeof(struct synce_dev_ctrl));
+       return dc;
+}
+
+int synce_dev_ctrl_init(struct synce_dev_ctrl *dc, const char *dev_name,
+                       const char *dpll_get_state_cmd,
+                       struct dpll_state_str *dss)
+{
+       if (!dc || !dev_name) {
+               return -ENODEV;
+       }
+
+       if (!dpll_get_state_cmd) {
+               pr_err("failure: dpll_get_state_cmd is NULL on %s", dev_name);
+               return -ENXIO;
+       }
+       if (!dss->holdover) {
+               pr_err("failure: dss.holdover is NULL on %s", dev_name);
+               return -ENXIO;
+       }
+       if (!dss->locked_ho) {
+               pr_err("failure: dss.locked_ho is NULL on %s", dev_name);
+               return -ENXIO;
+       }
+       if (!dss->locked) {
+               pr_err("failure: dss.locked is NULL on %s", dev_name);
+               return -ENXIO;
+       }
+       if (!dss->freerun) {
+               pr_err("failure: dss.freerun is NULL on %s", dev_name);
+               return -ENXIO;
+       }
+       if (!dss->invalid) {
+               pr_err("failure: dss.invalid is NULL on %s", dev_name);
+               return -ENXIO;
+       }
+
+       dc->dpll_get_state_cmd = dpll_get_state_cmd;
+       dc->dss = *dss;
+
+       return 0;
+}
diff --git a/synce_dev_ctrl.h b/synce_dev_ctrl.h
new file mode 100644
index 000000000000..69355dbf61a1
--- /dev/null
+++ b/synce_dev_ctrl.h
@@ -0,0 +1,64 @@
+/**
+ * @file synce_dev_ctrl.h
+ * @brief Interface for acquiring Sync-E capable device DPLL state changes
+ * @note SPDX-FileCopyrightText: Copyright 2022 Intel Corporation
+ * @note SPDX-License-Identifier: GPL-2.0+
+ */
+#ifndef HAVE_SYNCE_DEV_CTRL_H
+#define HAVE_SYNCE_DEV_CTRL_H
+
+/* possible DPLL states */
+enum dpll_state {
+       DPLL_UNKNOWN = -1,
+       DPLL_INVALID,
+       DPLL_FREERUN,
+       DPLL_LOCKED,
+       DPLL_LOCKED_HO_ACQ,
+       DPLL_HOLDOVER,
+};
+
+/* possibe DPLL state strings */
+struct dpll_state_str {
+       const char *holdover;
+       const char *locked_ho;
+       const char *locked;
+       const char *freerun;
+       const char *invalid;
+};
+
+/* Opaque type */
+struct synce_dev_ctrl;
+
+/**
+ * Acquire current state of DPLL of Sync-E capable device.
+ *
+ * @param dc           Instance of DPLL device controller
+ * @param state                State acquired from the device
+ * @return             Zero on success, non-zero if failure
+ */
+int synce_dev_ctrl_get_state(struct synce_dev_ctrl *dc,
+                            enum dpll_state *state);
+
+/**
+ * Initialize DPLL device controller instance.
+ *
+ * @param dc                   Instance of DPLL device controller to be
+ *                             initialized
+ * @param dev_name             Name of device
+ * @param dpll_get_state_cmd   A command to obtain current dpll state
+ * @param dss                  Pointer to a struct holding valid dpll state
+                               strings
+ * @return                     Zero on success, non-zero if failure
+ */
+int synce_dev_ctrl_init(struct synce_dev_ctrl *dc, const char *dev_name,
+                       const char *dpll_get_state_cmd,
+                       struct dpll_state_str *dss);
+
+/**
+ * Allocate memory for a single DPLL device controller instance.
+ *
+ * @return     Pointer to allocated instance or NULL if allocation failed
+ */
+struct synce_dev_ctrl *synce_dev_ctrl_create(void);
+
+#endif /* HAVE_SYNCE_DEV_CTRL_H */
-- 
2.34.1



_______________________________________________
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel

Reply via email to