From 1c52a32779de1569ea41267ac6fc8f51c5a8b7fd Mon Sep 17 00:00:00 2001
From: "Suren A. Chilingaryan" <csa@suren.me>
Date: Sun, 18 Oct 2015 04:28:43 +0200
Subject: Support XML properties

---
 pcilib/property.c   | 11 ++++++-----
 pcilib/py.c         |  2 +-
 pcilib/view.h       |  2 +-
 pcilib/xml.c        | 21 +++++++++++++++++++--
 xml/references.xsd  |  4 ++++
 xml/test/camera.xml |  1 +
 xml/types.xsd       |  3 ++-
 7 files changed, 34 insertions(+), 10 deletions(-)

diff --git a/pcilib/property.c b/pcilib/property.c
index 23c92d1..1db6dd3 100644
--- a/pcilib/property.c
+++ b/pcilib/property.c
@@ -20,7 +20,6 @@ int pcilib_add_register_properties(pcilib_t *ctx, size_t n, const pcilib_registe
 
     pcilib_register_t i;
     pcilib_view_t cur_view = ctx->num_views;
-    pcilib_view_context_t *view_ctx;
 
     if (!n) 
         return PCILIB_ERROR_INVALID_ARGUMENT;
@@ -59,6 +58,7 @@ int pcilib_add_register_properties(pcilib_t *ctx, size_t n, const pcilib_registe
         v.base.name = view_name;
         v.base.description = registers[i].description;
         v.base.mode = registers[i].mode&mode;
+        v.base.flags |= PCILIB_VIEW_FLAG_PROPERTY;
         v.reg = registers[i].name;
         v.bank = b->name;
 
@@ -68,9 +68,10 @@ int pcilib_add_register_properties(pcilib_t *ctx, size_t n, const pcilib_registe
             pcilib_clean_views(ctx, cur_view);
             return err;
         }
-
-        view_ctx = pcilib_find_view_context_by_name(ctx, v.base.name);
+/*
+        pcilib_view_context_t *view_ctx = pcilib_find_view_context_by_name(ctx, v.base.name);
         view_ctx->flags |= PCILIB_VIEW_FLAG_PROPERTY;
+*/
     }
 
     return 0;
@@ -100,7 +101,7 @@ pcilib_property_info_t *pcilib_get_property_list(pcilib_t *ctx, const char *bran
         const char *subname = v->name + name_offset;
         const char *suffix;
 
-        if (!(view_ctx->flags&PCILIB_VIEW_FLAG_PROPERTY)) continue;
+        if (!(v->flags&PCILIB_VIEW_FLAG_PROPERTY)) continue;
         if ((branch)&&(strncasecmp(branch, v->name, strlen(branch)))) continue;
 
         suffix = strchr(subname, '/');
@@ -134,7 +135,7 @@ pcilib_property_info_t *pcilib_get_property_list(pcilib_t *ctx, const char *bran
         const pcilib_view_description_t *v = ctx->views[view_ctx->view];
         const char *subname = v->name + name_offset;
 
-        if (!(view_ctx->flags&PCILIB_VIEW_FLAG_PROPERTY)) continue;
+        if (!(v->flags&PCILIB_VIEW_FLAG_PROPERTY)) continue;
         if ((branch)&&(strncasecmp(branch, v->name, strlen(branch)))) continue;
 
         if (!strchr(subname, '/')) {
diff --git a/pcilib/py.c b/pcilib/py.c
index 3a4fd96..def050e 100644
--- a/pcilib/py.c
+++ b/pcilib/py.c
@@ -108,7 +108,7 @@ static char *pcilib_py_parse_string(pcilib_t *ctx, const char *codestr, pcilib_v
 
             // find the end of the register name
         reg++;
-        for (i = 0; isalnum(reg[i]); i++);
+        for (i = 0; isalnum(reg[i])||(reg[i] == '_'); i++);
         save = reg[i];
         reg[i] = 0;
 
diff --git a/pcilib/view.h b/pcilib/view.h
index 6287942..606a688 100644
--- a/pcilib/view.h
+++ b/pcilib/view.h
@@ -27,6 +27,7 @@ typedef struct {
 
 struct pcilib_view_description_s {
     const pcilib_view_api_description_t *api;
+    pcilib_view_flags_t flags;                                                  /**< Flags specifying type of the view */
     pcilib_value_type_t type;			                                /**< The default data type returned by operation, PCILIB_VIEW_TYPE_STRING is supported by all operations */
     pcilib_access_mode_t mode;                                                  /**< Specifies if the view is read/write-only */
     const char *unit;				                                /**< Returned unit (if any) */
@@ -37,7 +38,6 @@ struct pcilib_view_description_s {
 struct pcilib_view_context_s {
     const char *name;
     pcilib_view_t view;
-    pcilib_view_flags_t flags;                                                  /**< Flags specifying type of the view */
     UT_hash_handle hh;
 };
 
diff --git a/pcilib/xml.c b/pcilib/xml.c
index 4df0d2d..4ecd16d 100644
--- a/pcilib/xml.c
+++ b/pcilib/xml.c
@@ -488,7 +488,12 @@ static int pcilib_xml_parse_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDoc
         if (!value) continue;
 
         if (!strcasecmp(name, "name")) {
-            desc->name = value;
+                // Overriden by path
+            if (!desc->name)
+                desc->name = value;
+	} else if (!strcasecmp(name, "path")) {
+	    desc->name = value;
+	    desc->flags |= PCILIB_VIEW_FLAG_PROPERTY;
         } else if (!strcasecmp((char*)name, "description")) {
     	    desc->description = value;
         } else if (!strcasecmp((char*)name, "unit")) {
@@ -529,10 +534,22 @@ static int pcilib_xml_create_transform_view(pcilib_t *ctx, xmlXPathContextPtr xp
         if (!value) continue;
 
         if (!strcasecmp(name, "read_from_register")) {
+            if (desc.base.flags&PCILIB_VIEW_FLAG_PROPERTY) {
+                if (strstr(value, "$value")) {
+                    pcilib_error("Invalid transform specified in XML property (%s). The properties can't reference $value (%s)", desc.base.name, value);
+                    return PCILIB_ERROR_INVALID_DATA;
+                }
+            }
             desc.read_from_reg = value;
             if ((value)&&(*value)) desc.base.mode |= PCILIB_ACCESS_R;
         } else if (!strcasecmp(name, "write_to_register")) {
-	    desc.write_to_reg = value;
+            if (desc.base.flags&PCILIB_VIEW_FLAG_PROPERTY) {
+                if (strstr(value, "$value")) {
+                    pcilib_error("Invalid transform specified in XML property (%s). The properties can't reference $value (%s)", desc.base.name, value);
+                    return PCILIB_ERROR_INVALID_DATA;
+                }
+            }
+            desc.write_to_reg = value;
             if ((value)&&(*value)) desc.base.mode |= PCILIB_ACCESS_W;
         } 
     }
diff --git a/xml/references.xsd b/xml/references.xsd
index 810913c..f382840 100644
--- a/xml/references.xsd
+++ b/xml/references.xsd
@@ -37,6 +37,10 @@
       <xsd:selector xpath="unit" />
       <xsd:field xpath="@name" />
     </xsd:key>
+    <xsd:key name="pcilib_path_key">
+      <xsd:selector xpath="transform" />
+      <xsd:field xpath="@path" />
+    </xsd:key>
 
     <xsd:keyref name="pcilib_register_view_ref" refer="pcilib_view_key">
       <xsd:selector xpath="bank/register/view|bank/register/field/view" />
diff --git a/xml/test/camera.xml b/xml/test/camera.xml
index a12d26b..9df8de2 100644
--- a/xml/test/camera.xml
+++ b/xml/test/camera.xml
@@ -106,6 +106,7 @@
     <register address="0x1b0" offset="0" size="32" default="0" rwmask="0" mode="R" name="ddr_num_frames"/>
   </bank>
   <bank bar="0" size="0x0200" protocol="software_registers" read_address="0x0" write_address="0x0" word_size="32" endianess="little" format="0x%lx" name="dma" description="DMA Registers"/>
+  <transform path="/test/prop1" unit="C" read_from_register="(503975./1024000)*$sensor_temperature - 27315./100" write_to_register="($sensor_temperature + 27315./100)*(1024000./503975)" description="formula to get real fpga temperature from the fpga_temperature register in decimal"/>
   <transform name="formuu1" unit="C" read_from_register="(503975./1024000)*$value - 27315./100" write_to_register="($value + 27315./100)*(1024000./503975)" description="formula to get real fpga temperature from the fpga_temperature register in decimal"/>
   <transform name="formuu2" unit="C1" read_from_register="((1./4)*($value - 1200)) if $freq==0 else ((3./10)*($value - 1000))" write_to_register="4*$value + 1200 if $freq==0 else (10./3)*$value + 1000" description="formula to get real sensor temperature from the sensor_temperature register in decimal"/>
   <transform name="formuu3" unit="us" read_from_register="($value+(43./100))*129./(40*1000000)if $freq==0 else ($value+(43./100))*129./(48*1000000)" write_to_register="$value/129.*(40*1000000) - 43./100 if $freq==0 else $value/129.*(48*1000000) - 43./100" description="formula to get real exposure time from the cmosis_exp_time register in decimal"/>
diff --git a/xml/types.xsd b/xml/types.xsd
index 6edb35e..f6b5bcd 100644
--- a/xml/types.xsd
+++ b/xml/types.xsd
@@ -52,7 +52,7 @@
   </xsd:complexType>
 
   <xsd:complexType name="pcilib_view_t">
-    <xsd:attribute name="name" type="xsd:ID" use="required" />
+    <xsd:attribute name="name" type="xsd:ID" />
     <xsd:attribute name="unit" type="xsd:string" />
     <xsd:attribute name="type" type="pcilib_data_type_t" />
     <xsd:attribute name="visible" type="bool_t" default="0" />
@@ -62,6 +62,7 @@
   <xsd:complexType name="pcilib_transform_view_t">
     <xsd:complexContent>
         <xsd:extension base="pcilib_view_t">
+          <xsd:attribute name="path" type="xsd:string" />
           <xsd:attribute name="read_from_register" type="xsd:string" />
           <xsd:attribute name="write_to_register" type="xsd:string" />
         </xsd:extension>
-- 
cgit v1.2.3