From f13867f64fcba24ef2cb9d726b5ee1082ac1a8b9 Mon Sep 17 00:00:00 2001
From: "Suren A. Chilingaryan" <csa@suren.me>
Date: Fri, 9 Oct 2015 04:42:53 +0200
Subject: Implement enum view

---
 pcilib/pci.h      | 11 ----------
 pcilib/pcilib.h   |  3 ++-
 pcilib/unit.h     |  8 +++++++
 pcilib/value.c    | 16 +++++++++++---
 pcilib/view.c     |  6 ++---
 pcilib/view.h     | 10 ++++++++-
 pcilib/xml.c      |  3 ++-
 pcitool/cli.c     | 18 ++++++++++++---
 views/enum.c      | 66 +++++++++++++++++++++++++++++++++++--------------------
 views/transform.c |  6 +++--
 10 files changed, 98 insertions(+), 49 deletions(-)

diff --git a/pcilib/pci.h b/pcilib/pci.h
index ff18e52..caefe44 100644
--- a/pcilib/pci.h
+++ b/pcilib/pci.h
@@ -39,17 +39,6 @@ typedef struct {
     uint8_t max_payload, payload;
 } pcilib_pcie_link_info_t;
 
-struct pcilib_view_context_s {
-    const char *name;
-    pcilib_view_t view;
-    UT_hash_handle hh;
-};
-
-struct pcilib_unit_context_s {
-    const char *name;
-    pcilib_unit_t unit;
-    UT_hash_handle hh;
-};
 
 typedef struct {
     const char *name;                                                                   /**< Register name */
diff --git a/pcilib/pcilib.h b/pcilib/pcilib.h
index 3909ab4..6acceb6 100644
--- a/pcilib/pcilib.h
+++ b/pcilib/pcilib.h
@@ -112,7 +112,7 @@ typedef struct {
     union {
 	long ival;
 	double fval;
-	char *sval;
+	const char *sval;
     };
 
         // This is a private part
@@ -223,6 +223,7 @@ void pcilib_clean_value(pcilib_t *ctx, pcilib_value_t *val);
 int pcilib_copy_value(pcilib_t *ctx, pcilib_value_t *dst, const pcilib_value_t *src);
 int pcilib_set_value_from_float(pcilib_t *ctx, pcilib_value_t *val, double fval);
 int pcilib_set_value_from_int(pcilib_t *ctx, pcilib_value_t *val, long ival);
+int pcilib_set_value_from_static_string(pcilib_t *ctx, pcilib_value_t *value, const char *str);
 int pcilib_convert_value_unit(pcilib_t *ctx, pcilib_value_t *val, const char *unit_name);
 int pcilib_convert_value_type(pcilib_t *ctx, pcilib_value_t *val, pcilib_value_type_t type);
 
diff --git a/pcilib/unit.h b/pcilib/unit.h
index dad7962..3e49174 100644
--- a/pcilib/unit.h
+++ b/pcilib/unit.h
@@ -1,6 +1,8 @@
 #ifndef _PCILIB_UNIT_H
 #define _PCILIB_UNIT_H
 
+#include <uthash.h>
+
 #include <pcilib.h>
 
 #define PCILIB_UNIT_INVALID ((pcilib_unit_t)-1)
@@ -23,6 +25,12 @@ typedef struct {
     pcilib_unit_transform_t transforms[PCILIB_MAX_TRANSFORMS_PER_UNIT + 1];		/**< Transforms to other units */
 } pcilib_unit_description_t;
 
+struct pcilib_unit_context_s {
+    const char *name;
+    pcilib_unit_t unit;
+    UT_hash_handle hh;
+};
+
 #ifdef __cplusplus
 extern "C" {
 #endif
diff --git a/pcilib/value.c b/pcilib/value.c
index cbf347b..b039e5f 100644
--- a/pcilib/value.c
+++ b/pcilib/value.c
@@ -57,6 +57,16 @@ int pcilib_set_value_from_int(pcilib_t *ctx, pcilib_value_t *value, long ival) {
     return 0;
 }
 
+int pcilib_set_value_from_static_string(pcilib_t *ctx, pcilib_value_t *value, const char *str) {
+    pcilib_clean_value(ctx, value);
+
+    value->type = PCILIB_TYPE_STRING;
+    value->sval = str;
+
+    return 0;
+}
+
+
 /*
 double pcilib_value_get_float(pcilib_value_t *val) {
     pcilib_value_t copy;
@@ -108,7 +118,7 @@ int pcilib_convert_value_type(pcilib_t *ctx, pcilib_value_t *val, pcilib_value_t
      case PCILIB_TYPE_STRING:
         switch (val->type) {
          case PCILIB_TYPE_STRING:
-            break;
+            return 0;
          case PCILIB_TYPE_DOUBLE:
             sprintf(val->str, (val->format?val->format:"%lf"), val->fval);
             val->format = NULL;
@@ -132,7 +142,7 @@ int pcilib_convert_value_type(pcilib_t *ctx, pcilib_value_t *val, pcilib_value_t
             val->format = NULL;
             break;
          case PCILIB_TYPE_DOUBLE:
-            break;
+            return 0;
          case PCILIB_TYPE_LONG:
             val->fval = val->ival;
             val->format = NULL;
@@ -155,7 +165,7 @@ int pcilib_convert_value_type(pcilib_t *ctx, pcilib_value_t *val, pcilib_value_t
             val->format = NULL;
             break;
          case PCILIB_TYPE_LONG:
-            break;
+            return 0;
          default:
             return PCILIB_ERROR_NOTSUPPORTED;
         }
diff --git a/pcilib/view.c b/pcilib/view.c
index bf312e4..e9fdab5 100644
--- a/pcilib/view.c
+++ b/pcilib/view.c
@@ -126,7 +126,7 @@ pcilib_view_context_t *pcilib_find_register_view_context_by_name(pcilib_t *ctx,
     if (!regctx->views) return NULL;
 
     for (i = 0; regctx->views[i].name; i++) {
-	if (strcasecmp(name, regctx->views[i].name)) {
+	if (!strcasecmp(name, regctx->views[i].name)) {
 	    return pcilib_find_view_context_by_name(ctx, regctx->views[i].view);
 	}
     }
@@ -261,7 +261,7 @@ int pcilib_read_register_view(pcilib_t *ctx, const char *bank, const char *regna
 
     pcilib_clean_value(ctx, val);
 
-    err = v->api->read_from_reg(ctx, cfg.view, &regvalue, val);
+    err = v->api->read_from_reg(ctx, cfg.view, regvalue, val);
     if (err) {
         if (regname) 
             pcilib_error("Error (%i) computing view (%s) of register %s", err, view, regname);
@@ -281,7 +281,7 @@ int pcilib_read_register_view(pcilib_t *ctx, const char *bank, const char *regna
 
 int pcilib_write_register_view(pcilib_t *ctx, const char *bank, const char *regname, const char *view, const pcilib_value_t *valarg) {
     int err;
-    pcilib_value_t val;
+    pcilib_value_t val = {0};
 
     pcilib_view_description_t *v;
     pcilib_view_configuration_t cfg;
diff --git a/pcilib/view.h b/pcilib/view.h
index 4af4c00..9d3d32d 100644
--- a/pcilib/view.h
+++ b/pcilib/view.h
@@ -1,6 +1,8 @@
 #ifndef _PCILIB_VIEW_H
 #define _PCILIB_VIEW_H
 
+#include <uthash.h>
+
 #include <pcilib.h>
 #include <pcilib/unit.h>
 
@@ -19,7 +21,7 @@ typedef struct {
     pcilib_view_context_t *(*init)(pcilib_t *ctx);
     void (*free)(pcilib_t *ctx, pcilib_view_context_t *view);
     void (*free_description)(pcilib_t *ctx, pcilib_view_description_t *view);
-    int (*read_from_reg)(pcilib_t *ctx, pcilib_view_context_t *view, const pcilib_register_value_t *regval, pcilib_value_t *val);
+    int (*read_from_reg)(pcilib_t *ctx, pcilib_view_context_t *view, pcilib_register_value_t regval, pcilib_value_t *val);
     int (*write_to_reg)(pcilib_t *ctx, pcilib_view_context_t *view, pcilib_register_value_t *regval, const pcilib_value_t *val);
 } pcilib_view_api_description_t;
 
@@ -32,6 +34,12 @@ struct pcilib_view_description_s {
     const char *description;			                                /**< Short description */
 };
 
+struct pcilib_view_context_s {
+    const char *name;
+    pcilib_view_t view;
+    UT_hash_handle hh;
+};
+
 #ifdef __cplusplus
 extern "C" {
 #endif
diff --git a/pcilib/xml.c b/pcilib/xml.c
index c431b73..25ffbfe 100644
--- a/pcilib/xml.c
+++ b/pcilib/xml.c
@@ -516,7 +516,7 @@ static int pcilib_xml_create_transform_view(pcilib_t *ctx, xmlXPathContextPtr xp
 
     pcilib_transform_view_description_t desc = {0};
 
-    desc.base.api = &pcilib_enum_view_xml_api;
+    desc.base.api = &pcilib_transform_view_api;
 
     err = pcilib_xml_parse_view(ctx, xpath, doc, node, (pcilib_view_description_t*)&desc);
     if (err) return err;
@@ -1037,6 +1037,7 @@ void pcilib_free_xml(pcilib_t *ctx) {
         xmlFreeParserCtxt(ctx->xml.parser);
         ctx->xml.parser = NULL;
     }
+
     /*
         xmlSchemaCleanupTypes();
         xmlCleanupParser();
diff --git a/pcitool/cli.c b/pcitool/cli.c
index d140b98..71a8ea2 100644
--- a/pcitool/cli.c
+++ b/pcitool/cli.c
@@ -574,20 +574,21 @@ void List(pcilib_t *handle, const pcilib_model_description_t *model_info, const
 
 void RegisterInfo(pcilib_t *handle, pcilib_register_t reg) {
     int err;
-    pcilib_register_value_t val;
+    pcilib_value_t val = {0};
+    pcilib_register_value_t regval;
 
     const pcilib_model_description_t *model_info = pcilib_get_model_description(handle);
     const pcilib_register_description_t *r = &model_info->registers[reg];
     pcilib_register_bank_t bank = pcilib_find_register_bank_by_addr(handle, r->bank);
     const pcilib_register_bank_description_t *b = &model_info->banks[bank];
 
-    err = pcilib_read_register_by_id(handle, reg, &val);
+    err = pcilib_read_register_by_id(handle, reg, &regval);
     
 
     printf("%s/%s\n", b->name, r->name);
     printf("  Current value: ");
     if (err) printf("error %i", err);
-    else printf(b->format, val);
+    else printf(b->format, regval);
 
     if (r->mode&PCILIB_REGISTER_W) {
 	printf(" (default: ");
@@ -631,6 +632,17 @@ void RegisterInfo(pcilib_t *handle, pcilib_register_t reg) {
 	    }
 	    printf(")\n");
 
+            err = pcilib_read_register_view(handle, b->name, r->name, r->views[i].name, &val);
+            if (!err) err = pcilib_convert_value_type(handle, &val, PCILIB_TYPE_STRING);
+
+            if (err)
+                printf("    Current value  : error %i\n", err);
+            else {
+                printf("    Current value  : %s", val.sval);
+                if (v->unit) printf(" (units: %s)", v->unit);
+                printf("\n");
+            }
+
 	    if (v->unit) {
 	        pcilib_unit_t unit = pcilib_find_unit_by_name(handle, v->unit);
 
diff --git a/views/enum.c b/views/enum.c
index 5d3a726..d712c71 100644
--- a/views/enum.c
+++ b/views/enum.c
@@ -4,41 +4,59 @@
 #include <unistd.h>
 #include <stdlib.h>
 #include <string.h>
+#include <strings.h>
 
+#include <uthash.h>
+
+#include "error.h"
 #include "version.h"
 #include "model.h"
 #include "enum.h"
+#include "view.h"
+#include "value.h"
+
 
-static void pcilib_enum_view_free(pcilib_t *ctx, pcilib_view_context_t *view) {
+static void pcilib_enum_view_free(pcilib_t *ctx, pcilib_view_description_t *view) {
+    pcilib_enum_view_description_t *v = (pcilib_enum_view_description_t*)view;
+    if (v->names) 
+        free(v->names);
+    free(v);
 }
 
-static int pcilib_enum_view_read(pcilib_t *ctx, pcilib_view_context_t *view, const pcilib_register_value_t *regval, pcilib_value_t *val) {
-/*        for(j=0; ((pcilib_enum_t*)(params))[j].name; j++) {
-            if (*regval<=((pcilib_enum_t*)(params))[j].max && *regval>=((pcilib_enum_t*)(params))[j].min) {
-                if(viewval_size<strlen(((pcilib_enum_t*)(params))[j].name)) {
-                    pcilib_error("the string to contain the enum command is too tight");
-                    return PCILIB_ERROR_MEMORY;
-                }
-                strncpy((char*)viewval,((pcilib_enum_t*)(params))[j].name, strlen(((pcilib_enum_t*)(params))[j].name));
-                k=strlen(((pcilib_enum_t*)(params))[j].name);
-                ((char*)viewval)[k]='\0';
-                return 0;
-            }
-        }
+static int pcilib_enum_view_read(pcilib_t *ctx, pcilib_view_context_t *view_ctx, pcilib_register_value_t regval, pcilib_value_t *val) {
+    int i;
+
+    const pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
+    pcilib_enum_view_description_t *v = (pcilib_enum_view_description_t*)(model_info->views[view_ctx->view]);
+
+    for (i = 0; v->names[i].name; i++) {
+        if ((regval >= v->names[i].min)&&(regval <= v->names[i].max))
+            return pcilib_set_value_from_static_string(ctx, val, v->names[i].name);
     }
-    return PCILIB_ERROR_INVALID_REQUEST;*/
+
+    return pcilib_set_value_from_int(ctx, val, regval);
 }
 
-static int pcilib_enum_view_write(pcilib_t *ctx, pcilib_view_context_t *view, pcilib_register_value_t *regval, pcilib_value_t *val) {
-/*    int j,k;
+static int pcilib_enum_view_write(pcilib_t *ctx, pcilib_view_context_t *view_ctx, pcilib_register_value_t *regval, const pcilib_value_t *val) {
+    int i;
+
+    const pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
+    pcilib_enum_view_description_t *v = (pcilib_enum_view_description_t*)(model_info->views[view_ctx->view]);
+
+    if (val->type != PCILIB_TYPE_STRING) {
+        pcilib_warning("Value of unsupported type (%s) is passed to enum_view", pcilib_get_type_name(val->type));
+        return PCILIB_ERROR_INVALID_ARGUMENT;
+    }
+
+    for (i = 0; v->names[i].name; i++) {
+        if (!strcasecmp(v->names[i].name, val->sval)) {
+            *regval = v->names[i].value;
+            return 0;
+        }
+    }
 
-    if(view2reg==1) {
-        for(j=0; ((pcilib_enum_t*)(params))[j].name; j++) {
-            if(!(strcasecmp(((pcilib_enum_t*)(params))[j].name,(char*)viewval))) {
-                *regval=((pcilib_enum_t*)(params))[j].value;
-                return 0;
-            }
-        }*/
+    pcilib_warning("Error setting register value, the value corresponding to name (%s) is not defined", val->sval);
+    return PCILIB_ERROR_NOTFOUND;
 }
 
 const pcilib_view_api_description_t pcilib_enum_view_static_api =
diff --git a/views/transform.c b/views/transform.c
index 8885e17..818c1d6 100644
--- a/views/transform.c
+++ b/views/transform.c
@@ -10,7 +10,9 @@
 #include "transform.h"
 
 
-static int pcilib_transform_view_read(pcilib_t *ctx, pcilib_view_context_t *view, const pcilib_register_value_t *regval, pcilib_value_t *val) {
+static int pcilib_transform_view_read(pcilib_t *ctx, pcilib_view_context_t *view, pcilib_register_value_t regval, pcilib_value_t *val) {
+    pcilib_set_value_from_int(ctx, val, 0);
+    return 0;
 /*    int j=0;
     pcilib_register_value_t value=0;
     char* formula=NULL;
@@ -43,7 +45,7 @@ static int pcilib_transform_view_read(pcilib_t *ctx, pcilib_view_context_t *view
         }*/
 }
 
-static int pcilib_transform_view_write(pcilib_t *ctx, pcilib_view_context_t *view, pcilib_register_value_t *regval, pcilib_value_t *val) {
+static int pcilib_transform_view_write(pcilib_t *ctx, pcilib_view_context_t *view, pcilib_register_value_t *regval, const pcilib_value_t *val) {
 /*        if(!(strcasecmp(unit, ((pcilib_view_t*)viewval)->base_unit.name))) {
             formula=malloc(sizeof(char)*strlen(((pcilib_formula_t*)params)->write_formula));
             strncpy(formula,((pcilib_formula_t*)params)->write_formula,strlen(((pcilib_formula_t*)params)->write_formula));
-- 
cgit v1.2.3