From fd215e3fd7d29c2c8605d8571091dae1c4f133bc Mon Sep 17 00:00:00 2001 From: zilio nicolas Date: Thu, 10 Sep 2015 12:52:27 +0200 Subject: towards better views i hope --- pcilib/register.h | 2 + views.c | 263 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ views.h | 15 ++++ 3 files changed, 280 insertions(+) create mode 100644 views.c create mode 100644 views.h diff --git a/pcilib/register.h b/pcilib/register.h index e7cbae9..9126e9f 100644 --- a/pcilib/register.h +++ b/pcilib/register.h @@ -47,6 +47,8 @@ typedef struct { pcilib_register_bank_t bank; /**< Reference to bank containing the register */ pcilib_register_value_t min, max; /**< Minimum & maximum allowed values */ pcilib_xml_node_t *xml; /**< Additional XML properties */ + pcilib_view_formula_t *formulas; /**< list of views of type formula linked to this register*/ + pcilib_view_enum_t *enums; /**< list of views of type enum linked to this register*/ } pcilib_register_context_t; diff --git a/views.c b/views.c new file mode 100644 index 0000000..db96f4a --- /dev/null +++ b/views.c @@ -0,0 +1,263 @@ +/** + * new type to define an enum view + */ +pcilib_value_enum_s { + const char *name; /**>> import re + >>> m = re.search('(?<=@)\w+', formula) + >>> m.group(0) + */ + + char reg_value_string[66]; /* to register reg_value as a string, need to check the length*/ + sprintf(reg_value_string,"%lu",reg_value); + + /*computation of plain registers in the formula*/ + formula=pcilib_view_formula_compute_plain_registers(formula); + /* computation of @reg with register value*/ + formula=pcilib_view_formula_replace(formula,"@reg",reg_value_string); + + /* evaluation of the formula*/ + *out_value=(pcilib_register_value_t) pcilib_view_eval_formula(formula); + +} + +static int +pcilib_view_apply_write_formula() +{ +} + +int pcilib_read_view(pcilib_t *ctx, const char *bank, const char *regname, const char *view/*, const char *unit*/, size_t value_size, void *value) +{ + int i,j,err; + pcilib_register_value_t temp_value; + + /* we get the index of the register to find the corresponding register context*/ + if((i=pcilib_find_register(ctx,bank,regname))==PCILIB_REGISTER_INVALID){ + pcilib_error("can't get the index of the register %s", regname); + return PCILIB_ERROR_INVALID_REQUEST; + } + + /* we get the value of the register, as we will apply the view on it*/ + if((err==pcilib_read_register_by_id(ctx,i,&temp_value))>0){ + pcilib_error("can't read the register %s value before applying views",regname); + } + /*in the case we don't ask for a view's name, we know it will be for views of type enum. Especially, it's faster to search directly on the values of those views instead of a given name. + we iterate so through the views of type enum to verify if the value we have corresponds to an enum command*/ + if(!(view)){ + for(j=0; ctx->register_ctx[i].enums[j].value;j++){ + if((temp_value >= ctx->register_ctx[i].enums[j].min) && (temp_value <= ctx->register_ctx[i].enums[j].max)){ + value_size=strlen(ctx->register_ctx[i].enums[j].name)*sizeof(char); + value=malloc(sizeof(value_size)); + if(!(value)){ + pcilib_error("can't allocate memory for the returning value of the view %s",view); + return PCILIB_ERROR_MEMORY; + } + /* in the case the value of register is between min and max, then we return the correponding enum command*/ + value=*(char*)ctx->register_ctx[i].enums[j].name; + return 0; + } + } + pcilib_warning("the value of the register asked do not correspond to any enum views"); + return PCILIB_ERROR_NOTAVAILABLE; + } + + /** in the other case we ask for a view of type formula. Indeed, wa can't directly ask for a formula, so we have to provide a name for those views*/ + j=0; + while((ctx->register_ctx[i].formulas[j].name)){ + if(!(strcasecmp(ctx->register_ctx[i].formulas[j].name))){ + /* when we have found the correct view of type formula, we apply the formula, that get the good value for return*/ + pcilib_view_apply_read_formula(ctx->register_ctx[i].formulas[j].read_formula,temp_value, value,....); + return 0; + } + j++; + } + + pcilib_warning("the view asked and the register do not correspond"); + return PCILIB_ERROR_NOTAVAILABLE; +} + + diff --git a/views.h b/views.h new file mode 100644 index 0000000..988e376 --- /dev/null +++ b/views.h @@ -0,0 +1,15 @@ +typedef struct pcilib_view_enum_s pcilib_view_enum_t; + +typedef struct pcilib_view_formula_s pcilib_view_formula_t; + + +/** + * function to read a register using a view + */ +int pcilib_read_view(pcilib_t *ctx, const char *bank, const char *regname, const char *view/*, const char *unit*/, size_t value_size, void *value); + +/** + * function to write to a register using a view + */ +int pcilib_write_view(pcilib_t *ctx, const char *bank, const char *regname, const char *view/*, const char *unit*/, size_t value_size, void *value); + -- cgit v1.2.3 From df677a8fdc70082fe27028ca17c3c643f4d79dd1 Mon Sep 17 00:00:00 2001 From: zilio nicolas Date: Thu, 10 Sep 2015 15:00:17 +0200 Subject: more towards new views, beware, error codes not overhauled now --- views.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 58 insertions(+), 19 deletions(-) diff --git a/views.c b/views.c index db96f4a..159ffa7 100644 --- a/views.c +++ b/views.c @@ -1,3 +1,7 @@ +#include +#include "pci.h" + + /** * new type to define an enum view */ @@ -26,7 +30,8 @@ pcilib_view_formula_s { *@param[in] after - the new value of before substring *@return the modified txt string */ -char *formula_replace (const char *txt, const char *before, const char *after) +static char* +pcilib_view_formula_replace (const char *txt, const char *before, const char *after) { const char *pos; char *return_txt; @@ -84,14 +89,15 @@ char *formula_replace (const char *txt, const char *before, const char *after) return return_txt; } -/* +/** * function used to get the substring of a string s, from the starting and ending indexes * @param[in] s string containing the substring we want to extract. * @param[in] start the start index of the substring. * @param[in] end the ending index of the substring. * @return the extracted substring. */ -char *str_sub (const char *s, unsigned int start, unsigned int end) +static char* +pcilib_view_str_sub (const char *s, unsigned int start, unsigned int end) { char *new_s = NULL; @@ -117,16 +123,52 @@ char *str_sub (const char *s, unsigned int start, unsigned int end) return new_s; } -static int -pcilib_view_compute_plain_registers{ - /* hsould i used regexp.h??? or compile everythin myself? */ +/** + * get the bank name associated with a register name + */ +static char* +pcilib_view_get_bank_from_reg_name(pcilib_t* ctx,char* reg_name){ + int k; + for(k=0;ctx->registers[k].bits;k++){ + if(!(strcasecmp(reg_name,ctx->registers[k].name))){ + return ctx->banks[pcilib_find_register_bank_by_addr(ctx,ctx->registers[k].bank)].name; + } + } } +/** + * replace plain registers name in a formula by their value + */ +static int +pcilib_view_compute_plain_registers(pcilib_t* ctx, char* formula){ + int j,k; + char* substr,substr2; + char temp[66]; + pcilib_register_value_t value; + + /*we get recursively all registers of string , and if they are not equel to '@reg', then we get their value and put it in formula*/ + for(j=0;jregister_ctx[i].formulas[j].name)){ if(!(strcasecmp(ctx->register_ctx[i].formulas[j].name))){ /* when we have found the correct view of type formula, we apply the formula, that get the good value for return*/ - pcilib_view_apply_read_formula(ctx->register_ctx[i].formulas[j].read_formula,temp_value, value,....); + pcilib_view_apply_formula(ctx, ctx->register_ctx[i].formulas[j].read_formula,temp_value,value); + value_size=sizeof(int); return 0; } j++; @@ -260,4 +298,5 @@ int pcilib_read_view(pcilib_t *ctx, const char *bank, const char *regname, const return PCILIB_ERROR_NOTAVAILABLE; } - + int pcilib_write_view(pcilib_t *ctx, const char *bank, const char *regname, const char *view/*, const char *unit*/, size_t value_size, void *value){ + -- cgit v1.2.3 From 9bcd0b7b98dfb10d054913dad34313391f6029f2 Mon Sep 17 00:00:00 2001 From: zilio nicolas Date: Thu, 10 Sep 2015 16:09:02 +0200 Subject: compilation ok --- CMakeLists.txt | 1 + pcilib/CMakeLists.txt | 13 +- pcilib/register.h | 1 + pcilib/views.c | 331 ++++++++++++++++++++++++++++++++++++++++++++++++++ pcilib/views.h | 39 ++++++ views.c | 302 --------------------------------------------- views.h | 15 --- 7 files changed, 381 insertions(+), 321 deletions(-) create mode 100644 pcilib/views.c create mode 100644 pcilib/views.h delete mode 100644 views.c delete mode 100644 views.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 10742fd..d9e637f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,6 +33,7 @@ SET(ENV{PKG_CONFIG_PATH} "${LIB_INSTALL_DIR}/pkgconfig:$ENV{PKG_CONFIG_PATH}") find_package(PkgConfig REQUIRED) find_package(Threads REQUIRED) +find_package(PythonLibs REQUIRED) set(EXTRA_SYSTEM_LIBS -lrt) diff --git a/pcilib/CMakeLists.txt b/pcilib/CMakeLists.txt index 8b11d60..f75d7de 100644 --- a/pcilib/CMakeLists.txt +++ b/pcilib/CMakeLists.txt @@ -4,11 +4,16 @@ include_directories( ${CMAKE_SOURCE_DIR}/pcilib ${CMAKE_BINARY_DIR}/pcilib ${LIBXML2_INCLUDE_DIRS} + ${PYTHON_INCLUDE_DIRS} ) -set(HEADERS pcilib.h pci.h export.h bar.h fifo.h model.h bank.h register.h xml.h kmem.h irq.h locking.h lock.h dma.h event.h plugin.h tools.h error.h debug.h env.h version.h config.h) -add_library(pcilib SHARED pci.c export.c bar.c fifo.c model.c bank.c register.c xml.c kmem.c irq.c locking.c lock.c dma.c event.c plugin.c tools.c error.c debug.c env.c ) -target_link_libraries(pcilib dma protocols ${CMAKE_THREAD_LIBS_INIT} ${UFODECODE_LIBRARIES} ${CMAKE_DL_LIBS} ${EXTRA_SYSTEM_LIBS} ${LIBXML2_LIBRARIES}) +set(HEADERS pcilib.h pci.h export.h bar.h fifo.h model.h bank.h register.h +xml.h kmem.h irq.h locking.h lock.h dma.h event.h plugin.h tools.h error.h +debug.h env.h version.h config.h views.h) +add_library(pcilib SHARED pci.c export.c bar.c fifo.c model.c bank.c register.c xml.c kmem.c irq.c locking.c lock.c dma.c event.c plugin.c tools.c error.c debug.c env.c views.c) +target_link_libraries(pcilib dma protocols ${CMAKE_THREAD_LIBS_INIT} +${UFODECODE_LIBRARIES} ${CMAKE_DL_LIBS} ${EXTRA_SYSTEM_LIBS} +${LIBXML2_LIBRARIES} ${PYTHON_LIBRARIES}) add_dependencies(pcilib dma protocols) install(TARGETS pcilib @@ -19,6 +24,6 @@ install(FILES pcilib.h DESTINATION include ) -install(FILES bar.h kmem.h locking.h lock.h bank.h register.h xml.h dma.h event.h model.h error.h debug.h env.h tools.h export.h version.h +install(FILES bar.h kmem.h locking.h lock.h bank.h register.h views.h xml.h dma.h event.h model.h error.h debug.h env.h tools.h export.h version.h DESTINATION include/pcilib ) diff --git a/pcilib/register.h b/pcilib/register.h index 9126e9f..5669237 100644 --- a/pcilib/register.h +++ b/pcilib/register.h @@ -3,6 +3,7 @@ #include #include +#include #define PCILIB_REGISTER_NO_BITS 0 #define PCILIB_REGISTER_ALL_BITS ((pcilib_register_value_t)-1) diff --git a/pcilib/views.c b/pcilib/views.c new file mode 100644 index 0000000..38ce102 --- /dev/null +++ b/pcilib/views.c @@ -0,0 +1,331 @@ +#include +#include "pci.h" +#include "pcilib.h" +#include +#include "views.h" +#include "error.h" +#include +#include + +/** + * + * replace a substring within a string by another + * @param[in] txt - the string to be modified + *@param[in] before - the substring in the string that will be replaced + *@param[in] after - the new value of before substring + *@return the modified txt string + */ +static char* +pcilib_view_formula_replace (const char *txt, const char *before, const char *after) +{ + const char *pos; + char *return_txt; + size_t pos_return_txt; + size_t len; + size_t allocated_size; + + /*get the first occurence of before. then we need one time to be out of the loop to correctly set the diverses varaibles (malloc instead of realloc notably)*/ + pos = strstr (txt, before); + + if (pos == NULL) + { + pcilib_warning("problem with a formula"); + } + + /* get the position of this occurence*/ + len = (size_t)pos - (size_t)txt; + allocated_size = len + strlen (after) + 1; + return_txt = malloc (allocated_size); + pos_return_txt = 0; + + /* we copy there the in a newly allocated string the start of txt before the "before" occurence, and then we copy after instead*/ + strncpy (return_txt + pos_return_txt, txt, len); + pos_return_txt += len; + txt = pos + strlen (before); + + len = strlen (after); + strncpy (return_txt + pos_return_txt, after, len); + pos_return_txt += len; + + /* we then iterate with the same principle to all occurences of before*/ + pos = strstr (txt, before); + while (pos != NULL) + { + len = (size_t)pos - (size_t)txt; + allocated_size += len + strlen (after); + return_txt = (char *)realloc (return_txt, allocated_size); + + strncpy (return_txt + pos_return_txt, txt, len); + pos_return_txt += len; + + txt = pos + strlen (before); + + len = strlen (after); + strncpy (return_txt + pos_return_txt, after, len); + pos_return_txt += len; + pos = strstr (txt, before); + } + /* put the rest of txt string at the end*/ + len = strlen (txt) + 1; + allocated_size += len; + return_txt = realloc (return_txt, allocated_size); + strncpy (return_txt + pos_return_txt, txt, len); + + return return_txt; +} + +/** + * function used to get the substring of a string s, from the starting and ending indexes + * @param[in] s string containing the substring we want to extract. + * @param[in] start the start index of the substring. + * @param[in] end the ending index of the substring. + * @return the extracted substring. + */ +static char* +pcilib_view_str_sub (const char *s, unsigned int start, unsigned int end) +{ + char *new_s = NULL; + + if (s != NULL && start < end) + { + new_s = malloc (sizeof (*new_s) * (end - start + 2)); + if (new_s != NULL) + { + int i; + + for (i = start; i <= end; i++) + { + new_s[i-start] = s[i]; + } + new_s[i-start] = '\0'; + } + else + { + pcilib_error("insufficient memory for string manipulation\n"); + return NULL; + } + } + return new_s; +} + +/** + * get the bank name associated with a register name + */ +static const char* +pcilib_view_get_bank_from_reg_name(pcilib_t* ctx,char* reg_name){ + int k; + for(k=0;ctx->registers[k].bits;k++){ + if(!(strcasecmp(reg_name,ctx->registers[k].name))){ + return ctx->banks[pcilib_find_register_bank_by_addr(ctx,ctx->registers[k].bank)].name; + } + } + return NULL; +} + +/** + * replace plain registers name in a formula by their value + */ +static char* +pcilib_view_compute_plain_registers(pcilib_t* ctx, char* formula){ + int j,k; + char *substr, *substr2; + char temp[66]; + pcilib_register_value_t value; + + /*we get recursively all registers of string , and if they are not equel to '@reg', then we get their value and put it in formula*/ + for(j=0;j>> import re + >>> m = re.search('(?<=@)\w+', formula) + >>> m.group(0) + */ + + char reg_value_string[66]; /* to register reg_value as a string, need to check the length*/ + sprintf(reg_value_string,"%u",reg_value); + + /*computation of plain registers in the formula*/ + formula=pcilib_view_compute_plain_registers(ctx,formula); + /* computation of @reg with register value*/ + formula=pcilib_view_formula_replace(formula,"@reg",reg_value_string); + + /* evaluation of the formula*/ + *out_value= pcilib_view_eval_formula(formula); + +} + +int pcilib_read_view(pcilib_t *ctx, const char *bank, const char *regname, const char *view/*, const char *unit*/, size_t value_size, void *value) +{ + int i,j,err=0; + pcilib_register_value_t temp_value; + char* formula; + + /* we get the index of the register to find the corresponding register context*/ + if((i=pcilib_find_register(ctx,bank,regname))==PCILIB_REGISTER_INVALID){ + pcilib_error("can't get the index of the register %s", regname); + return PCILIB_ERROR_INVALID_REQUEST; + } + + /* we get the value of the register, as we will apply the view on it*/ + if((err==pcilib_read_register_by_id(ctx,i,&temp_value))>0){ + pcilib_error("can't read the register %s value before applying views",regname); + } + /*in the case we don't ask for a view's name, we know it will be for views of type enum. Especially, it's faster to search directly on the values of those views instead of a given name. + we iterate so through the views of type enum to verify if the value we have corresponds to an enum command*/ + if(!(view)){ + for(j=0; ctx->register_ctx[i].enums[j].value;j++){ + if((temp_value >= ctx->register_ctx[i].enums[j].min) && (temp_value <= ctx->register_ctx[i].enums[j].max)){ + value_size=strlen(ctx->register_ctx[i].enums[j].name)*sizeof(char); + value=malloc(sizeof(value_size)); + if(!(value)){ + pcilib_error("can't allocate memory for the returning value of the view %s",view); + return PCILIB_ERROR_MEMORY; + } + /* in the case the value of register is between min and max, then we return the correponding enum command*/ + strncpy((char*)value,ctx->register_ctx[i].enums[j].name, strlen(ctx->register_ctx[i].enums[j].name)); + return 0; + } + } + pcilib_warning("the value of the register asked do not correspond to any enum views"); + return PCILIB_ERROR_NOTAVAILABLE; + } + + /** in the other case we ask for a view of type formula. Indeed, wa can't directly ask for a formula, so we have to provide a name for those views*/ + j=0; + while((ctx->register_ctx[i].formulas[j].name)){ + if(!(strcasecmp(ctx->register_ctx[i].formulas[j].name,view))){ + /* when we have found the correct view of type formula, we apply the formula, that get the good value for return*/ + formula=malloc(sizeof(char)*strlen(ctx->register_ctx[i].formulas[j].read_formula)); + strncpy(formula,ctx->register_ctx[i].formulas[j].read_formula,strlen(ctx->register_ctx[i].formulas[j].read_formula)); + // pcilib_view_apply_formula(ctx, ctx->register_ctx[i].formulas[j].read_formula,temp_value,value); + pcilib_view_apply_formula(ctx, formula,temp_value,value); + value_size=sizeof(int); + return 0; + } + j++; + } + + pcilib_warning("the view asked and the register do not correspond"); + return PCILIB_ERROR_NOTAVAILABLE; +} + + +/** + * function to write to a register using a view + */ +int pcilib_write_view(pcilib_t *ctx, const char *bank, const char *regname, const char *view, size_t value_size,void* value/*, const char *unit*/){ + int i,j; + pcilib_register_value_t temp_value; + char *formula; + + /* we get the index of the register to find the corresponding register context*/ + if((i=pcilib_find_register(ctx,bank,regname))==PCILIB_REGISTER_INVALID){ + pcilib_error("can't get the index of the register %s", regname); + return PCILIB_ERROR_INVALID_REQUEST; + } + + /*here, in the case of views of type enum, view will correspond to the enum command. + we iterate so through the views of type enum to get the value corresponding to the enum command*/ + for(j=0; ctx->register_ctx[i].enums[j].value;j++){ + if(!(strcasecmp(ctx->register_ctx[i].enums[j].name,view))){ + pcilib_write_register(ctx,bank,regname,ctx->register_ctx[i].enums[j].value); + return 0; + } + } + + /** in the other case we ask for a view of type formula. Indeed, wa can't directly ask for a formula, so we have to provide a name for those views in view, and the value we want to write in value*/ + j=0; + while((ctx->register_ctx[i].formulas[j].name)){ + if(!(strcasecmp(ctx->register_ctx[i].formulas[j].name,view))){ + /* when we have found the correct view of type formula, we apply the formula, that get the good value for return*/ + formula=malloc(sizeof(char)*strlen(ctx->register_ctx[i].formulas[j].write_formula)); + strncpy(formula,ctx->register_ctx[i].formulas[j].write_formula,strlen(ctx->register_ctx[i].formulas[j].write_formula)); + // pcilib_view_apply_formula(ctx, ctx->register_ctx[i].formulas[j].write_formula,(pcilib_register_value_t*)value,temp_value); + pcilib_view_apply_formula(ctx,formula,*(pcilib_register_value_t*)value,&temp_value); + pcilib_write_register(ctx,bank,regname,temp_value); + return 0; + } + j++; + } + pcilib_warning("the view asked and the register do not correspond"); + return PCILIB_ERROR_NOTAVAILABLE; + } diff --git a/pcilib/views.h b/pcilib/views.h new file mode 100644 index 0000000..bdae9f4 --- /dev/null +++ b/pcilib/views.h @@ -0,0 +1,39 @@ +#ifndef _PCILIB_VIEWS_H +#define _PCILIB_VIEWS_H + +#include "pcilib.h" + +typedef struct pcilib_view_enum_s pcilib_view_enum_t; + +typedef struct pcilib_view_formula_s pcilib_view_formula_t; + +/** + * new type to define an enum view + */ +struct pcilib_view_enum_s { + const char *name; /** -#include "pci.h" - - -/** - * new type to define an enum view - */ -pcilib_value_enum_s { - const char *name; /**registers[k].bits;k++){ - if(!(strcasecmp(reg_name,ctx->registers[k].name))){ - return ctx->banks[pcilib_find_register_bank_by_addr(ctx,ctx->registers[k].bank)].name; - } - } -} - -/** - * replace plain registers name in a formula by their value - */ -static int -pcilib_view_compute_plain_registers(pcilib_t* ctx, char* formula){ - int j,k; - char* substr,substr2; - char temp[66]; - pcilib_register_value_t value; - - /*we get recursively all registers of string , and if they are not equel to '@reg', then we get their value and put it in formula*/ - for(j=0;j>> import re - >>> m = re.search('(?<=@)\w+', formula) - >>> m.group(0) - */ - - char reg_value_string[66]; /* to register reg_value as a string, need to check the length*/ - sprintf(reg_value_string,"%lu",reg_value); - - /*computation of plain registers in the formula*/ - formula=pcilib_view_formula_compute_plain_registers(formula,ctx); - /* computation of @reg with register value*/ - formula=pcilib_view_formula_replace(formula,"@reg",reg_value_string); - - /* evaluation of the formula*/ - *out_value=*(pcilib_register_value_t*) pcilib_view_eval_formula(formula); - -} - -int pcilib_read_view(pcilib_t *ctx, const char *bank, const char *regname, const char *view/*, const char *unit*/, size_t value_size, void *value) -{ - int i,j,err; - pcilib_register_value_t temp_value; - - /* we get the index of the register to find the corresponding register context*/ - if((i=pcilib_find_register(ctx,bank,regname))==PCILIB_REGISTER_INVALID){ - pcilib_error("can't get the index of the register %s", regname); - return PCILIB_ERROR_INVALID_REQUEST; - } - - /* we get the value of the register, as we will apply the view on it*/ - if((err==pcilib_read_register_by_id(ctx,i,&temp_value))>0){ - pcilib_error("can't read the register %s value before applying views",regname); - } - /*in the case we don't ask for a view's name, we know it will be for views of type enum. Especially, it's faster to search directly on the values of those views instead of a given name. - we iterate so through the views of type enum to verify if the value we have corresponds to an enum command*/ - if(!(view)){ - for(j=0; ctx->register_ctx[i].enums[j].value;j++){ - if((temp_value >= ctx->register_ctx[i].enums[j].min) && (temp_value <= ctx->register_ctx[i].enums[j].max)){ - value_size=strlen(ctx->register_ctx[i].enums[j].name)*sizeof(char); - value=malloc(sizeof(value_size)); - if(!(value)){ - pcilib_error("can't allocate memory for the returning value of the view %s",view); - return PCILIB_ERROR_MEMORY; - } - /* in the case the value of register is between min and max, then we return the correponding enum command*/ - value=*(char*)ctx->register_ctx[i].enums[j].name; - return 0; - } - } - pcilib_warning("the value of the register asked do not correspond to any enum views"); - return PCILIB_ERROR_NOTAVAILABLE; - } - - /** in the other case we ask for a view of type formula. Indeed, wa can't directly ask for a formula, so we have to provide a name for those views*/ - j=0; - while((ctx->register_ctx[i].formulas[j].name)){ - if(!(strcasecmp(ctx->register_ctx[i].formulas[j].name))){ - /* when we have found the correct view of type formula, we apply the formula, that get the good value for return*/ - pcilib_view_apply_formula(ctx, ctx->register_ctx[i].formulas[j].read_formula,temp_value,value); - value_size=sizeof(int); - return 0; - } - j++; - } - - pcilib_warning("the view asked and the register do not correspond"); - return PCILIB_ERROR_NOTAVAILABLE; -} - - int pcilib_write_view(pcilib_t *ctx, const char *bank, const char *regname, const char *view/*, const char *unit*/, size_t value_size, void *value){ - diff --git a/views.h b/views.h deleted file mode 100644 index 988e376..0000000 --- a/views.h +++ /dev/null @@ -1,15 +0,0 @@ -typedef struct pcilib_view_enum_s pcilib_view_enum_t; - -typedef struct pcilib_view_formula_s pcilib_view_formula_t; - - -/** - * function to read a register using a view - */ -int pcilib_read_view(pcilib_t *ctx, const char *bank, const char *regname, const char *view/*, const char *unit*/, size_t value_size, void *value); - -/** - * function to write to a register using a view - */ -int pcilib_write_view(pcilib_t *ctx, const char *bank, const char *regname, const char *view/*, const char *unit*/, size_t value_size, void *value); - -- cgit v1.2.3 From 2722e76f513ba7be80e63f1f49f2095d39759f09 Mon Sep 17 00:00:00 2001 From: zilio nicolas Date: Thu, 10 Sep 2015 20:40:15 +0200 Subject: more towards views --- pcilib/CMakeLists.txt | 7 +- pcilib/pci.h | 5 ++ pcilib/views.c | 67 +++++++++++++- pcilib/views.h | 16 ++++ pcilib/xml.c | 239 ++++++++++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 324 insertions(+), 10 deletions(-) diff --git a/pcilib/CMakeLists.txt b/pcilib/CMakeLists.txt index f75d7de..48363f6 100644 --- a/pcilib/CMakeLists.txt +++ b/pcilib/CMakeLists.txt @@ -8,9 +8,10 @@ include_directories( ) set(HEADERS pcilib.h pci.h export.h bar.h fifo.h model.h bank.h register.h -xml.h kmem.h irq.h locking.h lock.h dma.h event.h plugin.h tools.h error.h -debug.h env.h version.h config.h views.h) -add_library(pcilib SHARED pci.c export.c bar.c fifo.c model.c bank.c register.c xml.c kmem.c irq.c locking.c lock.c dma.c event.c plugin.c tools.c error.c debug.c env.c views.c) +views.h xml.h kmem.h irq.h locking.h lock.h dma.h event.h plugin.h tools.h error.h +debug.h env.h version.h config.h ) +add_library(pcilib SHARED pci.c export.c bar.c fifo.c model.c bank.c +register.c views.c xml.c kmem.c irq.c locking.c lock.c dma.c event.c plugin.c tools.c error.c debug.c env.c ) target_link_libraries(pcilib dma protocols ${CMAKE_THREAD_LIBS_INIT} ${UFODECODE_LIBRARIES} ${CMAKE_DL_LIBS} ${EXTRA_SYSTEM_LIBS} ${LIBXML2_LIBRARIES} ${PYTHON_LIBRARIES}) diff --git a/pcilib/pci.h b/pcilib/pci.h index 00528e1..657c335 100644 --- a/pcilib/pci.h +++ b/pcilib/pci.h @@ -62,6 +62,8 @@ struct pcilib_s { size_t num_banks, num_protocols, num_ranges; /**< Number of registered banks, protocols, and register ranges */ size_t num_engines; /**< Number of configured DMA engines */ size_t dyn_banks; /**< Number of configured dynamic banks */ + size_t num_enum_views,alloc_enum_views; /**< Number of configured and allocated views of type enum*/ + size_t num_formula_views,alloc_formula_views; /**< Number of configured and allocated views of type formula*/ pcilib_register_description_t *registers; /**< List of currently defined registers (from all sources) */ pcilib_register_bank_description_t banks[PCILIB_MAX_REGISTER_BANKS + 1]; /**< List of currently defined register banks (from all sources) */ @@ -81,6 +83,9 @@ struct pcilib_s { struct pcilib_locking_s locks; /**< Context of locking subsystem */ struct pcilib_xml_s xml; /**< XML context */ + pcilib_view_enum2_t* enum_views; /**< list of currently defined views of type enum*/ + pcilib_view_formula_t* formula_views; /**< list of currently defined views of type formula*/ + #ifdef PCILIB_FILE_IO int file_io_handle; #endif /* PCILIB_FILE_IO */ diff --git a/pcilib/views.c b/pcilib/views.c index 38ce102..44392d9 100644 --- a/pcilib/views.c +++ b/pcilib/views.c @@ -2,7 +2,7 @@ #include "pci.h" #include "pcilib.h" #include -#include "views.h" +//#include "views.h" #include "error.h" #include #include @@ -329,3 +329,68 @@ int pcilib_write_view(pcilib_t *ctx, const char *bank, const char *regname, cons pcilib_warning("the view asked and the register do not correspond"); return PCILIB_ERROR_NOTAVAILABLE; } + +/** + * function to populate ctx enum views, as we could do for registers or banks + */ +int pcilib_add_views_enum(pcilib_t *ctx, size_t n, const pcilib_view_enum2_t* views) { + + pcilib_view_enum2_t *views_enum; + size_t size; + + if (!n) { + for (n = 0; views[n].enums_list[0].value; n++); + } + + if ((ctx->num_enum_views + n + 1) > ctx->alloc_enum_views) { + for (size = ctx->alloc_enum_views; size < 2 * (n + ctx->num_enum_views + 1); size<<=1); + + views_enum = (pcilib_view_enum2_t*)realloc(ctx->enum_views, size * sizeof(pcilib_view_enum2_t)); + if (!views_enum) return PCILIB_ERROR_MEMORY; + + ctx->enum_views = views_enum; + /* context + model part ????*/ + ctx->alloc_enum_views = size; + } + + memcpy(ctx->enum_views + ctx->num_enum_views, views, n * sizeof(pcilib_view_enum2_t)); + memset(ctx->enum_views + ctx->num_enum_views + n, 0, sizeof(pcilib_view_enum2_t)); + + ctx->num_enum_views += n; + + + return 0; +} + + +/** + * function to populate ctx formula views, as we could do for registers or banks + */ +int pcilib_add_views_formula(pcilib_t *ctx, size_t n, const pcilib_view_formula_t* views) { + + pcilib_view_formula_t *views_formula; + size_t size; + + if (!n) { + for (n = 0; views[n].name[0]; n++); + } + + if ((ctx->num_formula_views + n + 1) > ctx->alloc_formula_views) { + for (size = ctx->alloc_formula_views; size < 2 * (n + ctx->num_formula_views + 1); size<<=1); + + views_formula = (pcilib_view_formula_t*)realloc(ctx->formula_views, size * sizeof(pcilib_view_formula_t)); + if (!views_formula) return PCILIB_ERROR_MEMORY; + + ctx->formula_views = views_formula; + /* context + model part?????*/ + ctx->alloc_formula_views = size; + } + + memcpy(ctx->formula_views + ctx->num_formula_views, views, n * sizeof(pcilib_view_formula_t)); + memset(ctx->formula_views + ctx->num_formula_views + n, 0, sizeof(pcilib_view_formula_t)); + + ctx->num_formula_views += n; + + + return 0; +} diff --git a/pcilib/views.h b/pcilib/views.h index bdae9f4..98e3dcd 100644 --- a/pcilib/views.h +++ b/pcilib/views.h @@ -7,6 +7,8 @@ typedef struct pcilib_view_enum_s pcilib_view_enum_t; typedef struct pcilib_view_formula_s pcilib_view_formula_t; +typedef struct pcilib_view_enum2_s pcilib_view_enum2_t; + /** * new type to define an enum view */ @@ -16,6 +18,15 @@ struct pcilib_view_enum_s { }; +/** + * complete type for an enum view : name will be changed after with the previous one + */ +struct pcilib_view_enum2_s { + const char* name; + pcilib_view_enum_t* enums_list; +}; + + /** * new type to define a formula view */ @@ -36,4 +47,9 @@ int pcilib_read_view(pcilib_t *ctx, const char *bank, const char *regname, const */ int pcilib_write_view(pcilib_t *ctx, const char *bank, const char *regname, const char *view/*, const char *unit*/, size_t value_size, void *value); +int pcilib_add_views_enum(pcilib_t* ctx,size_t n, pcilib_view_enum2_t* views); + +int pcilib_add_views_formula(pcilib_t* ctx, size_t n, pcilib_view_formula_t* views); + + #endif diff --git a/pcilib/xml.c b/pcilib/xml.c index 73a3deb..852f319 100644 --- a/pcilib/xml.c +++ b/pcilib/xml.c @@ -39,12 +39,15 @@ #include "register.h" #include "xml.h" #include "error.h" +#include "views.h" #define BANKS_PATH ((xmlChar*)"/model/banks/bank/bank_description") /**< path to complete nodes of banks.*/ //#define REGISTERS_PATH ((xmlChar*)"/model/banks/bank/registers/register") /**< all standard registers nodes.*/ //#define BIT_REGISTERS_PATH ((xmlChar*)"/model/banks/bank/registers/register/registers_bits/register_bits") /**< all bits registers nodes.*/ #define REGISTERS_PATH ((xmlChar*)"../registers/register") /**< all standard registers nodes.*/ #define BIT_REGISTERS_PATH ((xmlChar*)"./registers_bits/register_bits") /**< all bits registers nodes.*/ +#define VIEWS_PATH ((xmlChar*)"/model/views/view") /**< path to complete nodes of views.*/ + static char *pcilib_xml_bank_default_format = "0x%lx"; @@ -67,7 +70,74 @@ static xmlNodePtr pcilib_xml_get_parent_register_node(xmlDocPtr doc, xmlNodePtr } */ -static int pcilib_xml_parse_register(pcilib_t *ctx, pcilib_xml_register_description_t *xml_desc, xmlDocPtr doc, xmlNodePtr node, pcilib_register_bank_description_t *bdesc) { + +/** + * get the associated views of a register, to fill its register context + */ +static int +pcilib_get_associated_views(pcilib_t* ctx, const char* reg_name,xmlXPathContextPtr xpath,pcilib_register_t id){ + char* VIEWS_NAME_PATH="/model/banks/bank/registers/register[@name=\"%s\"]/views/view"; + char* path; + xmlXPathObjectPtr nodes; + xmlNodeSetPtr nodeset; + char* view_name; + + /*we get first the nodes corresponding to the given register*/ + path=malloc(strlen(VIEWS_NAME_PATH)+strlen(reg_name)); + if(!(path)){ + pcilib_error("can't allocate memory for getting path to get associated views of %s",reg_name); + return PCILIB_ERROR_MEMORY; + } + + sprintf(path,VIEWS_NAME_PATH,reg_name); + nodes = xmlXPathEvalExpression((xmlChar*)path, xpath); + nodeset = nodes->nodesetval; + + if (!xmlXPathNodeSetIsEmpty(nodeset)) { + int i,k,l; + /*if we correctly get a nodeset, then we iterate through the nodeset to get all views, using their names*/ + for (i = 0; i < nodeset->nodeNr; i++) { + view_name=(char*)nodeset->nodeTab[i]->children->content; + + /* if the view name obtained is for an enum view, we get all pcilib_view_enum_t corresponding to the register*/ + for(k=0; ctx->enum_views[k].enums_list[0].value;k++){ + if(!(strcasecmp(view_name, ctx->enum_views[k].name))){ + ctx->register_ctx[id].enums=malloc(sizeof(pcilib_view_enum_t)); + + if(!(ctx->register_ctx[id].enums)){ + pcilib_error("error allocating memory for enum views in register context %i",id); + return PCILIB_ERROR_MEMORY; + } + + for(l=0; ctx->enum_views[k].enums_list[l].value;l++){ + ctx->register_ctx[id].enums=realloc(ctx->register_ctx[id].enums,(l+1)*sizeof(pcilib_view_enum_t)); + ctx->register_ctx[id].enums[l]=ctx->enum_views[k].enums_list[l]; + } + } + } + + /*here it is for formula, i assume we have only one formula view per register*/ + for(k=0; ctx->formula_views[k].name[0];k++){ + if(!(strcasecmp(view_name,ctx->formula_views[k].name))){ + ctx->register_ctx[id].formulas=malloc(sizeof(pcilib_view_formula_t)); + if(!(ctx->register_ctx[id].formulas)){ + pcilib_error("error allocating memory for formula views in register context %i",id); + return PCILIB_ERROR_MEMORY; + } + + ctx->register_ctx[id].formulas=&(ctx->formula_views[k]); + } + } + + } + } + + xmlXPathFreeObject(nodes); + return 0; +} + + +static int pcilib_xml_parse_register(pcilib_t *ctx, pcilib_xml_register_description_t *xml_desc, xmlDocPtr doc, xmlNodePtr node, pcilib_register_bank_description_t *bdesc, int* views_ok) { pcilib_register_description_t *desc = (pcilib_register_description_t*)xml_desc; xmlNodePtr cur; @@ -166,6 +236,9 @@ static int pcilib_xml_parse_register(pcilib_t *ctx, pcilib_xml_register_descript } else if (!strcasecmp(name,"description")) { desc->description = value; } + else if (!strcasecmp(name,"views")) { + *views_ok=1; + } } return 0; @@ -173,6 +246,7 @@ static int pcilib_xml_parse_register(pcilib_t *ctx, pcilib_xml_register_descript static int pcilib_xml_create_register(pcilib_t *ctx, pcilib_register_bank_t bank, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node) { int err; + int views_ok=0; xmlXPathObjectPtr nodes; xmlNodeSetPtr nodeset; @@ -187,7 +261,7 @@ static int pcilib_xml_create_register(pcilib_t *ctx, pcilib_register_bank_t bank desc.base.mode = PCILIB_REGISTER_R; desc.base.type = PCILIB_REGISTER_STANDARD; - err = pcilib_xml_parse_register(ctx, &desc, doc, node, &ctx->banks[bank]); + err = pcilib_xml_parse_register(ctx, &desc, doc, node, &ctx->banks[bank],&views_ok); if (err) { pcilib_error("Error (%i) parsing an XML register", err); return err; @@ -202,6 +276,12 @@ static int pcilib_xml_create_register(pcilib_t *ctx, pcilib_register_bank_t bank ctx->register_ctx[reg].xml = node; ctx->register_ctx[reg].min = desc.min; ctx->register_ctx[reg].max = desc.max; + + /* if the register had a node of type views, then we compute its associated registers. I do that here as i need the index for register context*/ + if(views_ok){ + err=pcilib_get_associated_views(ctx,desc.base.name,xpath,reg); + if(err) pcilib_warning("can't get correctly the associated views of the register %s",desc.base.name); + } xpath->node = node; nodes = xmlXPathEvalExpression(BIT_REGISTERS_PATH, xpath); @@ -228,7 +308,7 @@ static int pcilib_xml_create_register(pcilib_t *ctx, pcilib_register_bank_t bank fdesc.base.rwmask = desc.base.rwmask; fdesc.base.type = PCILIB_REGISTER_BITS; - err = pcilib_xml_parse_register(ctx, &fdesc, doc, nodeset->nodeTab[i], &ctx->banks[bank]); + err = pcilib_xml_parse_register(ctx, &fdesc, doc, nodeset->nodeTab[i], &ctx->banks[bank],&views_ok); if (err) { pcilib_error("Error parsing field in the XML register %s", desc.base.name); continue; @@ -243,6 +323,10 @@ static int pcilib_xml_create_register(pcilib_t *ctx, pcilib_register_bank_t bank ctx->register_ctx[reg].xml = nodeset->nodeTab[i]; ctx->register_ctx[reg].min = fdesc.min; ctx->register_ctx[reg].max = fdesc.max; + if(views_ok){ + err=pcilib_get_associated_views(ctx, desc.base.name,xpath,reg); + if(err) pcilib_warning("can't get correctly the associated views of the register %s",fdesc.base.name); + } } } xmlXPathFreeObject(nodes); @@ -397,6 +481,131 @@ static int pcilib_xml_create_bank(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDo } +/** + * function that create a view from a view node, and populate ctx views list + */ +static int pcilib_xml_create_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node) { + int err; + + pcilib_view_enum2_t complete_enum_desc={0}; + pcilib_view_enum_t enum_desc = {0}; + pcilib_view_formula_t formula_desc= {0}; + xmlNodePtr cur; + char *value, *name; + char *endptr; + xmlAttr *attr; + int i=0; + + /*must i initialize? i think it's only needed if we want to include a description property*/ + enum_desc.name="default"; + enum_desc.value=0; + enum_desc.min=0; + enum_desc.max=0; + + complete_enum_desc.name="default enum"; + complete_enum_desc.enums_list=malloc(sizeof(pcilib_view_enum_t)); + if(!(complete_enum_desc.enums_list)){ + pcilib_error("can't allocate memory for the complete enum type"); + return PCILIB_ERROR_MEMORY; + } + complete_enum_desc.enums_list[0]=enum_desc; + + formula_desc.name="formula_default"; + formula_desc.read_formula="@reg"; + formula_desc.write_formula="@reg"; + + /* we get the attribute type of the view node*/ + attr=node->properties; + value=(char*)attr->children->content; + /* regarding the architecture, i decided to follow what has been done for registers and banks. but without the context*/ + /*if the view is of type enum, we get recursively its properties and then populate ctx enum views*/ + if(!(strcasecmp(value,"enum"))){ + for (cur = node->children; cur != NULL; cur = cur->next) { + if (!cur->children) continue; + if (!xmlNodeIsText(cur->children)) continue; + + name = (char*)cur->name; + value = (char*)cur->children->content; + if (!value) continue; + + if (!(strcasecmp((char*)name,"name"))) { + complete_enum_desc.name = value; + }else if (!(strcasecmp((char*)name,"enum"))) { + + complete_enum_desc.enums_list=realloc(complete_enum_desc.enums_list,(i+1)*sizeof(pcilib_view_enum_t)); + complete_enum_desc.enums_list[i].name=value; + + /* we need to iterate through the different attributes of an enum node to get all properties*/ + for(attr=cur->properties; attr!=NULL;attr=attr->next){ + if(!attr->children) continue; + if(!xmlNodeIsText(attr->children)) continue; + + name=(char*)attr->name; + value=(char*)attr->children->content; + + if(!(strcasecmp(name,"value"))){ + pcilib_register_value_t dat_value = strtol(value, &endptr, 0); + if ((strlen(endptr) > 0)) { + pcilib_error("Invalid value (%s) is specified in the XML enum node", value); + return PCILIB_ERROR_INVALID_DATA; + } + complete_enum_desc.enums_list[i].value=dat_value; + }else if(!(strcasecmp(name,"min"))){ + pcilib_register_value_t dat_min = strtol(value, &endptr, 0); + if ((strlen(endptr) > 0)) { + pcilib_error("Invalid min (%s) is specified in the XML enum node", value); + return PCILIB_ERROR_INVALID_DATA; + } + complete_enum_desc.enums_list[i].min=dat_min; + }else if(!(strcasecmp(name,"max"))){ + pcilib_register_value_t dat_max = strtol(value, &endptr, 0); + if ((strlen(endptr) > 0)) { + pcilib_error("Invalid max (%s) is specified in the XML enum node", value); + return PCILIB_ERROR_INVALID_DATA; + } + + complete_enum_desc.enums_list[i].max=dat_max; + } + } + i++; + } + } + err=pcilib_add_views_enum(ctx,1,&complete_enum_desc); + if (err) { + pcilib_error("Error (%i) adding a new enum view (%s) to the pcilib_t", err, complete_enum_desc.name); + return err; + } + + /* we do the same here but for a iew of type formula if the attribute gives formula*/ + }else if(!(strcasecmp(value,"formula"))){ + for (cur = node->children; cur != NULL; cur = cur->next) { + if (!cur->children) continue; + if (!xmlNodeIsText(cur->children)) continue; + + name = (char*)cur->name; + value = (char*)cur->children->content; + if (!value) continue; + + if (!(strcasecmp((char*)name,"name"))) { + formula_desc.name = value; + }else if (!(strcasecmp((char*)name,"read_from_register"))) { + formula_desc.read_formula=value; + }else if (!(strcasecmp((char*)name,"write_to_register"))) { + formula_desc.write_formula=value; + } + } + err=pcilib_add_views_formula(ctx,1,&formula_desc); + if (err) { + pcilib_error("Error (%i) adding a new formula view (%s) to the pcilib_t", err, formula_desc.name); + return err; + } + + } + + return 0; +} + + /** pcilib_xml_initialize_banks * * function to create the structures to store the banks from the AST @@ -405,12 +614,14 @@ static int pcilib_xml_create_bank(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDo * @param[in] pci the pcilib_t running, which will be filled */ static int pcilib_xml_process_document(pcilib_t *ctx, xmlDocPtr doc, xmlXPathContextPtr xpath) { - xmlXPathObjectPtr bank_nodes; + xmlXPathObjectPtr bank_nodes,views_nodes; xmlNodeSetPtr nodeset; + int i; + xmlErrorPtr xmlerr; bank_nodes = xmlXPathEvalExpression(BANKS_PATH, xpath); if (!bank_nodes) { - xmlErrorPtr xmlerr = xmlGetLastError(); + xmlerr = xmlGetLastError(); if (xmlerr) pcilib_error("Failed to parse XPath expression %s, xmlXPathEvalExpression reported error %d - %s", BANKS_PATH, xmlerr->code, xmlerr->message); else pcilib_error("Failed to parse XPath expression %s", BANKS_PATH); return PCILIB_ERROR_FAILED; @@ -419,13 +630,29 @@ static int pcilib_xml_process_document(pcilib_t *ctx, xmlDocPtr doc, xmlXPathCon nodeset = bank_nodes->nodesetval; if (!xmlXPathNodeSetIsEmpty(nodeset)) { - int i; for (i = 0; i < nodeset->nodeNr; i++) { pcilib_xml_create_bank(ctx, xpath, doc, nodeset->nodeTab[i]); } } xmlXPathFreeObject(bank_nodes); + + views_nodes=xmlXPathEvalExpression(VIEWS_PATH,xpath); + if(!views_nodes){ + xmlerr = xmlGetLastError(); + if (xmlerr) pcilib_error("Failed to parse XPath expression %s, xmlXPathEvalExpression reported error %d - %s", BANKS_PATH, xmlerr->code, xmlerr->message); + else pcilib_error("Failed to parse XPath expression %s", BANKS_PATH); + return PCILIB_ERROR_FAILED; + } + + nodeset=views_nodes->nodesetval; + if(!xmlXPathNodeSetIsEmpty(nodeset)){ + for(i=0;i < nodeset->nodeNr; i++){ + pcilib_xml_create_view(ctx,xpath,doc,nodeset->nodeTab[i]); + } + } + xmlXPathFreeObject(views_nodes); + return 0; } -- cgit v1.2.3 From 0d460b28c769fd2a1d2efb85f11edd4189fb5713 Mon Sep 17 00:00:00 2001 From: zilio nicolas Date: Fri, 11 Sep 2015 15:36:17 +0200 Subject: reviewd old tasks comments for doxygen and update --- pcilib/lock.c | 32 +++++++++----------- pcilib/lock.h | 83 ++++++++++++++++++++++++++++++++-------------------- pcilib/locking.c | 28 +++++++++++------- pcilib/locking.h | 54 ++++++++++++++++++++++++++++++++-- protocols/software.c | 42 +++++--------------------- protocols/software.h | 43 +++++++++++++-------------- 6 files changed, 162 insertions(+), 120 deletions(-) diff --git a/pcilib/lock.c b/pcilib/lock.c index 03a2377..25e12a5 100644 --- a/pcilib/lock.c +++ b/pcilib/lock.c @@ -18,22 +18,21 @@ #include "lock.h" #include "pci.h" - +/** + * structure to define a lock + */ struct pcilib_lock_s { - pthread_mutex_t mutex; - pcilib_lock_flags_t flags; + pthread_mutex_t mutex; /**< the pthread robust mutex itself*/ + pcilib_lock_flags_t flags; /**mutex); break; case PCILIB_TIMEOUT_IMMEDIATE: + /* the function returns immediatly if it can't acquire the lock*/ err = pthread_mutex_trylock(&lock->mutex); break; default: + /* the process will be hold till it can acquire the lock and timeout is not reached*/ clock_gettime(CLOCK_REALTIME, &tm); tm.tv_nsec += 1000 * (timeout%1000000); if (tm.tv_nsec < 1000000000) @@ -171,6 +169,7 @@ int pcilib_lock_custom(pcilib_lock_t *lock, pcilib_lock_flags_t flags, pcilib_ti switch (err) { case EOWNERDEAD: + /*in the case an application with a lock acquired crashes, this lock becomes inconsistent. we have so to make it consistent again to use it again.*/ err = pthread_mutex_consistent(&lock->mutex); if (err) { pcilib_error("Failed to mark mutex as consistent, errno %i", err); @@ -195,9 +194,6 @@ int pcilib_try_lock(pcilib_lock_t* lock) { return pcilib_lock_custom(lock, PCILIB_LOCK_FLAGS_DEFAULT, PCILIB_TIMEOUT_IMMEDIATE); } -/** - * this function will unlock the semaphore pointed by lock_ctx. - */ void pcilib_unlock(pcilib_lock_t *lock) { int err; diff --git a/pcilib/lock.h b/pcilib/lock.h index 9ffe4cf..f1a5abf 100644 --- a/pcilib/lock.h +++ b/pcilib/lock.h @@ -1,29 +1,31 @@ /** * @file lock.h - * @skip author zilio nicolas, nicolas.zilio@hotmail.fr * @brief this file is the header file for the functions that implement a semaphore API for the pcitool program, using pthread robust mutexes. - * @details the use of pthread robust mutexes was chosen due to the fact we privilege security over fastness, and that pthread mutexes permits to recover semaphores even with crash ,and that it does not require access to resources that can be easily accessible from extern usage as flock file locking mechanism. A possible other locking mechanism could be the sysv semaphores, but we have a problem of how determine a perfect hash for the init function, and more, benchmarks proves that sysv semaphore aren't that stable and that with more than 10 locks/unlocks, pthread is better in performance, so that should suits more to the final pcitool program. - * We considered that mutex implmentation is enough compared to a reader/writer implementation. If it should change, please go to sysv semaphore. - * Basic explanation on how semaphores here work: a semaphore here is a positive integer, thus that can't go below zero, which is initiated with a value. when a process want access to the critical resource, it asks to decrement the value of the semaphore, and when it has finished, it reincrements it.basically, when the semaphore is equal to zero, any process must have to wait for it to be reincremented before decrementing it again. Here are defined two types of access to the semaphore corresponding to the reader/writer problem : an exclusive lock, which means that no other process than the one who have the resource can access it; a shared lock, which means that other processes who want to access to the resource with a shared lock can have the access, but a concurrent process who want to access the semaphore with an exclusive lock won't be able to. - * explanation on locks here : here locks are registered in kernel memory, where they are defined by a pthread_mutex_t and a name, which corresponds to a register or processus. The iterations like searching a lock are done on names. + * @details the use of pthread robust mutexes was chosen due to the fact we privilege security over fastness, and that pthread mutexes permits to recover semaphores even with crash ,and that it does not require access to resources that can be easily accessible from extern usage as flock file locking mechanism. A possible other locking mechanism could be the sysv semaphores, but we have a problem of how determine a perfect hash for the init function, and more, benchmarks proves that sysv semaphore aren't that stable. For pure locking/unlocking, pthread is better in performance than sysV, but it suffers from big initialization times. In this sense, a kernel memory space is used for saving the locks, and persistence permits to avoid initializations over uses. + * + * We considered that mutex implmentation is enough compared to a reader/writer implementation. If it should change, please go to sysv semaphore. + * + * Basic explanation on how semaphores here work: a semaphore here is a positive integer, thus that can't go below zero, which is initiated with a value. when a process want access to the critical resource, it asks to decrement the value of the semaphore, and when it has finished, it reincrements it.basically, when the semaphore is equal to zero, any process must have to wait for it to be reincremented before decrementing it again. Here are defined two types of access to the semaphore corresponding to the reader/writer problem : an exclusive lock, which means that no other process than the one who have the resource can access it; a shared lock, which means that other processes who want to access to the resource with a shared lock can have the access, but a concurrent process who want to access the semaphore with an exclusive lock won't be able to. + * explanation on locks here : here locks are registered in kernel memory, where they are defined by a pthread_mutex_t and an identifier name, which corresponds most of the time to a mix of the register associated name and processus (but it's up to the user). The iterations like searching a lock are done on this id name. */ #ifndef _PCILIB_LOCK_H #define _PCILIB_LOCK_H -#define PCILIB_LOCK_SIZE 128 /**< size of one lock, determine so the size of the protocol_name in the way locks are registered. 40 bytes are necessary for the mutex structure, so we have a protocol name of length LOCK_SIZE-40*/ +#define PCILIB_LOCK_SIZE 128 /**< size of one lock. indeed, as we can't allocate easily on the fly memory in the kernel, fixed size have been chosen. determines so the size of the identifier name in the way locks are registered. 40 bytes are necessary for the mutex structure, so we have an id name of length LOCK_SIZE-40*/ #include /** - * type that defines possible flags when locking a lock by calling pcilib_lock + * type that defines possible flags for a lock, defining how a lock should be handled by the locking functions */ typedef enum { PCILIB_LOCK_FLAGS_DEFAULT = 0, /**< Default flags */ - PCILIB_LOCK_FLAG_UNLOCKED = 1, /**< Perform operation unlocked (protected by global flock during initialization of locking subsystem) */ + PCILIB_LOCK_FLAG_UNLOCKED = 1, /**< Perform operations unlocked, thus without taking care of the lock (protected by global flock during initialization of locking subsystem) */ PCILIB_LOCK_FLAG_PERSISTENT = 2 /**< Do not create robust mutexes, but preserve the lock across application launches */ } pcilib_lock_flags_t; +/** structure defining a lock*/ typedef struct pcilib_lock_s pcilib_lock_t; @@ -32,70 +34,87 @@ extern "C" { #endif /** - * this function initialize a new semaphore in the kernel given a name that corresponds to a specific processus if the semaphore is not already initialized given the name that permits to differentiate semaphores, and then return the integer that points to the semaphore that have been initialized or to a previously already initialized semaphore. - * @param[in] lock - pointer to lock to initialize - * @param[in] flags - flags + *this function initializes a lock, by setting correctly its property given the flags associated. + * @param[in,out] lock - pointer to lock to initialize + * @param[in] flags - flags: if it's set to two, then not a robust mutex is created * @param[in] lock_id - lock identificator * @return error code or 0 on success */ int pcilib_init_lock(pcilib_lock_t *lock, pcilib_lock_flags_t flags, const char *lock_id); /** - * this function uninitialize a lock in kernel memory and set the corresponding name to 0 - * @param[in] lock_ctx the pointer that points to the lock. + * this function will unref the defined lock. Any subsequent tries to lock it without reinitializaing it will fail. + * @param[in,out] lock_ctx - the pointer that points to the lock. */ void pcilib_free_lock(pcilib_lock_t *lock_ctx); - +/** + * this function gives the identifier name associated to a lock in the kernel space + * @param[in] loc - pointer to the lock we want the name + * @return string corresponding to the name + */ const char *pcilib_lock_get_name(pcilib_lock_t *lock); /** - * Increment reference count. Not thread/process safe unless system supports stdatomic (gcc 4.9+). - * In this case, the access should be synchronized by the caller - * @param[in] lock - pointer to initialized lock + * Increment reference count(number of processes that may access the given lock). + * Not thread/process safe unless system supports stdatomic (gcc 4.9+). In this case, the access should be synchronized by the caller. + * @param[in,out] lock - pointer to initialized lock */ void pcilib_lock_ref(pcilib_lock_t *lock); /** - * Decrement reference count. Not thread/process safe unless system supports stdatomic (gcc 4.9+). - * In this case, the access should be synchronized by the caller - * @param[in] lock - pointer to initialized lock + * Decrement reference count(number of processes that may access the given lock). + * Not thread/process safe unless system supports stdatomic (gcc 4.9+). In this case, the access should be synchronized by the caller + * @param[in,out] lock - pointer to initialized lock */ void pcilib_lock_unref(pcilib_lock_t *lock); /** - * Return _approximate_ number of lock references. The crashed applications will may not unref. - * @param[in] lock - pointer to initialized lock + * Return _approximate_ number of lock references as the crashed applications will may not unref. + * @param[in,out] lock - pointer to initialized lock + * @return the number of lock refs */ size_t pcilib_lock_get_refs(pcilib_lock_t *lock); +/** + * gets the flags associated to the given lock + * @param[in] lock - the lock we want to know the flags + * @return value of the flag associated + */ pcilib_lock_flags_t pcilib_lock_get_flags(pcilib_lock_t *lock); /** - * this function will take a lock for the mutex pointed by lock - * @param[in] lock the pointer to the mutex - * @param[in] flags define the type of lock wanted - * @param[in] timeout defines timeout + * this function will call different locking functions to acquire the given lock. Given the flags, it is thus possible to: + * 1) the process requesting the lock will be held till it can acquire it + * 2)the lock is tried to be acquired, if the lock can be acquired then it is, if not, then the function returns immediatly and the lock is not taken at all + * 3) same than previous, but it's possible to define a waiting time to acquire the lock before returning + * + * @param[in] lock - the pointer to the mutex + * @param[in] flags - define the type of lock wanted + * @param[in] timeout - the waiting time if asked, before the function returns without having obtained the lock, in micro seconds + * @return error code or 0 for correctness */ int pcilib_lock_custom(pcilib_lock_t* lock, pcilib_lock_flags_t flags, pcilib_timeout_t timeout); /** - * this function will take a lock for the mutex pointed by lock - * @param[in] lock the pointer to the mutex + * function to acquire a lock, and wait till the lock can be acquire + * @param[in] lock - the pointer to the mutex + * @return error code or 0 for correctness */ int pcilib_lock(pcilib_lock_t* lock); /** - * this function will try to take a lock for the mutex pointed by lock - * @param[in] lock the pointer to the mutex + * this function will try to take a lock for the mutex pointed by lockfunction to acquire a lock, but that returns immediatly if the lock can't be acquired on first try + * @param[in] lock - the pointer to the mutex + * @return error code or 0 for correctness */ int pcilib_try_lock(pcilib_lock_t* lock); /** - * this function will unlock the lock pointed by lock - * @param[in] lock the integer that points to the semaphore + * this function unlocks the lock pointed by lock + * @param[in] lock - the integer that points to the semaphore */ void pcilib_unlock(pcilib_lock_t* lock); diff --git a/pcilib/locking.c b/pcilib/locking.c index f384ca4..71f204e 100644 --- a/pcilib/locking.c +++ b/pcilib/locking.c @@ -21,10 +21,12 @@ int pcilib_init_locking(pcilib_t* ctx) { pcilib_kmem_reuse_state_t reused; assert(PCILIB_LOCK_PAGES * PCILIB_KMEM_PAGE_SIZE >= PCILIB_MAX_LOCKS * PCILIB_LOCK_SIZE); - + + /*protection against multiple creations of kernel space*/ err = pcilib_lock_global(ctx); if (err) return err; + /* by default, this kernel space is persistent and will be reused, in order to avoid the big initialization times for robust mutexes each time we run pcitool*/ ctx->locks.kmem = pcilib_alloc_kernel_memory(ctx, PCILIB_KMEM_TYPE_PAGE, PCILIB_LOCK_PAGES, PCILIB_KMEM_PAGE_SIZE, 0, PCILIB_KMEM_USE(PCILIB_KMEM_USE_LOCKS,0), PCILIB_KMEM_FLAG_REUSE|PCILIB_KMEM_FLAG_PERSISTENT); if (!ctx->locks.kmem) { pcilib_unlock_global(ctx); @@ -46,6 +48,7 @@ int pcilib_init_locking(pcilib_t* ctx) { } } + /* the lock that has been used for the creation of kernel space is declared unlocked, has we shouldnot use it anymore*/ ctx->locks.locking = pcilib_get_lock(ctx, PCILIB_LOCK_FLAG_UNLOCKED, "locking"); pcilib_unlock_global(ctx); @@ -59,7 +62,7 @@ int pcilib_init_locking(pcilib_t* ctx) { } /* - * this functions destroy all locks and then free the kernel memory allocated for them + * this function free the kernel memory allocated for them and destroys locks by setting memory to 0 */ void pcilib_free_locking(pcilib_t *ctx) { if (ctx->locks.locking) @@ -75,7 +78,7 @@ void pcilib_free_locking(pcilib_t *ctx) { int pcilib_lock_global(pcilib_t *ctx) { int err; - /* we flock() to make sure to not have two initialization in the same time (possible long time to init) */ + /* we flock() on the board's device file to make sure to not have two initialization in the same time (possible long time to init) */ if ((err = flock(ctx->handle, LOCK_EX))==-1) { pcilib_error("Can't get flock on device file"); return PCILIB_ERROR_FAILED; @@ -105,7 +108,7 @@ pcilib_lock_t *pcilib_get_lock(pcilib_t *ctx, pcilib_lock_flags_t flags, const c pcilib_lock_t *lock; char buffer[PCILIB_LOCK_SIZE]; - + /* we construct the complete lock_id given the parameters of the function*/ va_list pa; va_start(pa, lock_id); ret = vsnprintf(buffer, PCILIB_LOCK_SIZE, lock_id, pa); @@ -115,7 +118,9 @@ pcilib_lock_t *pcilib_get_lock(pcilib_t *ctx, pcilib_lock_flags_t flags, const c pcilib_error("Failed to construct the lock id, probably arguments does not match the format string (%s)...", lock_id); return NULL; } - + + + /* we iterate through locks to see if there is one already with the same name*/ // Would be nice to have hash here for (i = 0; i < PCILIB_MAX_LOCKS; i++) { lock = pcilib_get_lock_by_id(ctx, i); @@ -141,6 +146,7 @@ pcilib_lock_t *pcilib_get_lock(pcilib_t *ctx, pcilib_lock_flags_t flags, const c } } #endif /* ! HAVE_STDATOMIC_H */ + /* if yes, we increment its ref variable*/ pcilib_lock_ref(lock); #ifndef HAVE_STDATOMIC_H if ((flags&PCILIB_LOCK_FLAG_UNLOCKED)==0) @@ -192,6 +198,7 @@ pcilib_lock_t *pcilib_get_lock(pcilib_t *ctx, pcilib_lock_flags_t flags, const c return NULL; } + /* if the lock did not exist before, then we create it*/ err = pcilib_init_lock(lock, flags, buffer); if (err) { @@ -229,11 +236,11 @@ void pcilib_return_lock(pcilib_t *ctx, pcilib_lock_flags_t flags, pcilib_lock_t } -/** - * Destroy all existing locks. This is unsafe call as this and other running applications - * will still have all initialized lock pointers. It is user responsibility to issue this - * command when no other application is running. - */ +/* + * Destroy all existing locks. This is unsafe call as this and other running applications + * will still have all initialized lock pointers. It is user responsibility to issue this + * command when no other application is running. + */ int pcilib_destroy_all_locks(pcilib_t *ctx, int force) { int err; pcilib_lock_id_t i; @@ -269,6 +276,7 @@ int pcilib_destroy_all_locks(pcilib_t *ctx, int force) { return 0; } + /* if we run in non-forced case, then if it may be still processes that can have access to the locks, they are not destroyed*/ if (!force) { for (i = 0; i < PCILIB_MAX_LOCKS; i++) { pcilib_lock_t *lock = pcilib_get_lock_by_id(ctx, i); diff --git a/pcilib/locking.h b/pcilib/locking.h index ccacd63..cc45576 100644 --- a/pcilib/locking.h +++ b/pcilib/locking.h @@ -1,5 +1,5 @@ /** - * @file lock_global.h + * @file locking.h * @brief this file is the header file for functions that touch all locks allocated for software registers. * @details for more details about implementation choice, please read the file lock.h */ @@ -14,12 +14,16 @@ #include #include -typedef uint32_t pcilib_lock_id_t; +typedef uint32_t pcilib_lock_id_t; /**< type to represent the index of a lock in the table of locks in the kernel space*/ typedef struct pcilib_locking_s pcilib_locking_t; + +/** + * structure defining the kernel space used for locks + */ struct pcilib_locking_s { pcilib_kmem_handle_t *kmem; /**< kmem used to store mutexes */ - pcilib_lock_t *locking; /**< lock used while intializing other locks */ + pcilib_lock_t *locking; /**< lock used while intializing kernel space */ // pcilib_lock_t *mmap; /**< lock used to protect mmap operation */ }; @@ -27,17 +31,61 @@ struct pcilib_locking_s { extern "C" { #endif +/** + *this function gets the kernel space for the locks : if this space have been already initialized, then the previous space is returned. If not, the space is created. this function has to be protected, in order to avoid the simultaneous creation of 2 kernel spaces. For that, we use pcilib_lock_global. + *@param[in,out] ctx - the pcilib_t structure running, getting filled with a ref to locks' kernel space + */ int pcilib_init_locking(pcilib_t *ctx); + +/** + *this function cleans the memory from all locks : the kernel space is freed, and locks references in pcilib_t are destroyed by setting memory to 0 + *@param[in,out] ctx - the pcilib_t structure running + */ void pcilib_free_locking(pcilib_t *ctx); +/** + * this function use flock locking mechanism on the ALPS platform device file, to make sure to not create two kernel spaces for locks + *@param[in,out] ctx - the pcilib_t structure running + */ int pcilib_lock_global(pcilib_t *ctx); + +/** + *function to remove the lock created by flock on the ALPS platform device file + *@param[in,out] ctx - the pcilib_t structure running + */ void pcilib_unlock_global(pcilib_t *ctx); +/** + * this function returns the lock at the index in the kernel space equal to id + *@param[in] ctx - the pcilib_t structure running + *@param[in] id - the index of the lock + *@return the lock structure corresponding + */ pcilib_lock_t *pcilib_get_lock_by_id(pcilib_t *ctx, pcilib_lock_id_t id); +/** + *this function verify if the lock requested exists in the kernel space. If yes, then nothing is done, else we create the lock in the kernel space. This function also gives the number of processes that may request the lock afterwards, including the one that just created it. + *@param[in] ctx - the pcilib_t structure running + *@param[in] flags - the flag defining the property of the lock + *@param[in@ lock_id - the identifier name for the lock + *@return the corresponding lock, or a new one if it did not exist before + */ pcilib_lock_t *pcilib_get_lock(pcilib_t *ctx, pcilib_lock_flags_t flags, const char *lock_id, ...); + +/** + *this function is to decrement the variable in a lock containing the number of processes that may access to this lock(refs) + *@param[in] ctx - the pcilib_t structure running + *@param[in] flags - the flag defining the property of the lock + *@param[in] lock - pointer to the lock we want to modify + */ void pcilib_return_lock(pcilib_t *ctx, pcilib_lock_flags_t flags, pcilib_lock_t *lock); +/** + * this function destroy all the locks that have been created(unref the locks + set memory to 0), and so is used when we want to clean properly the kernel space. If force is set to 1, then we don't care about other processes that may request locks. If not, if there is locks that may be requested by other processes, then the operation is stopped. Of course, destroying locks that may be requested by other processes results in an undefined behaviour. Thus, it is user responsibility to issue this command with force set to 1 + *@param[in,out] ctx - the pcilib_t structure running + *@param[in] force - should the operation be forced or not + * @return error code : 0 if everything was ok + */ int pcilib_destroy_all_locks(pcilib_t *ctx, int force); diff --git a/protocols/software.c b/protocols/software.c index 55f62e8..0cba819 100644 --- a/protocols/software.c +++ b/protocols/software.c @@ -12,33 +12,21 @@ typedef struct pcilib_software_register_bank_context_s pcilib_software_register_bank_context_t; +/** + * structure defining the context of software registers + */ struct pcilib_software_register_bank_context_s { pcilib_register_bank_context_t bank_ctx; /**< the bank context associated with the software registers */ - pcilib_kmem_handle_t *kmem; /**< the kernel memory for software registers */ void *addr; /**< the virtual adress of the allocated kernel memory*/ }; -/** - * pcilib_software_registers_close - * this function clear the kernel memory space that could have been allocated for software registers - * @param[in] bank_ctx the bank context running that we get from the initialisation function - */ void pcilib_software_registers_close(pcilib_t *ctx, pcilib_register_bank_context_t *bank_ctx) { if (((pcilib_software_register_bank_context_t*)bank_ctx)->kmem) pcilib_free_kernel_memory(ctx, ((pcilib_software_register_bank_context_t*)bank_ctx)->kmem, PCILIB_KMEM_FLAG_REUSE); free(bank_ctx); } -/** - * pcilib_software_registers_open - * this function initializes the kernel space memory and stores in it the default values of the registers of the given bank index, if it was not initialized by a concurrent process, and return a bank context containing the adress of this kernel space. It the kernel space memory was already initialized by a concurrent process, then this function just return the bank context with the adress of this kernel space already used - * @param[in] ctx the pcilib_t structure running - * @param[in] bank the bank index that will permits to get the bank we want registers from - * @param[in] model not used - * @param[in] args not used - * @return a bank context with the adress of the kernel space memory related to it - */ pcilib_register_bank_context_t* pcilib_software_registers_open(pcilib_t *ctx, pcilib_register_bank_t bank, const char* model, const void *args) { int err; pcilib_software_register_bank_context_t *bank_ctx; @@ -59,6 +47,7 @@ pcilib_register_bank_context_t* pcilib_software_registers_open(pcilib_t *ctx, pc return NULL; } + /*we get a lock to protect the creation of the kernel space for software registers against multiple creations*/ lock = pcilib_get_lock(ctx, PCILIB_LOCK_FLAGS_DEFAULT, "softreg/%s", bank_desc->name); if (!lock) { pcilib_software_registers_close(ctx, (pcilib_register_bank_context_t*)bank_ctx); @@ -74,7 +63,7 @@ pcilib_register_bank_context_t* pcilib_software_registers_open(pcilib_t *ctx, pc return NULL; } - + /*creation of the kernel space*/ handle = pcilib_alloc_kernel_memory(ctx, PCILIB_KMEM_TYPE_PAGE, 1, PCILIB_KMEM_PAGE_SIZE, 0, PCILIB_KMEM_USE(PCILIB_KMEM_USE_SOFTWARE_REGISTERS, bank_desc->addr), PCILIB_KMEM_FLAG_REUSE|PCILIB_KMEM_FLAG_PERSISTENT); if (!handle) { pcilib_unlock(lock); @@ -98,7 +87,8 @@ pcilib_register_bank_context_t* pcilib_software_registers_open(pcilib_t *ctx, pc pcilib_error("Inconsistent software registers are found (only part of required buffers is available)"); return NULL; } - + + /* here we fill the software registers with their default value*/ for (i = 0; ctx->model_info.registers[i].name != NULL; i++) { if ((ctx->model_info.registers[i].bank == ctx->banks[bank].addr)&&(ctx->model_info.registers[i].type == PCILIB_REGISTER_STANDARD)) { *(pcilib_register_value_t*)(bank_ctx->addr + ctx->model_info.registers[i].addr) = ctx->model_info.registers[i].defvalue; @@ -112,15 +102,6 @@ pcilib_register_bank_context_t* pcilib_software_registers_open(pcilib_t *ctx, pc return (pcilib_register_bank_context_t*)bank_ctx; } -/** - * pcilib_software_registers_read - * this function read the value of a said register in the kernel space - * @param[in] ctx the pcilib_t structure runnning - * @param[in] bank_ctx the bank context that was returned by the initialisation function - * @param[in] addr the adress of the register we want to read - * @param[out] value the value of the register - * @return 0 in case of success - */ int pcilib_software_registers_read(pcilib_t *ctx, pcilib_register_bank_context_t *bank_ctx, pcilib_register_addr_t addr, pcilib_register_value_t *value){ if ((addr + sizeof(pcilib_register_value_t)) > bank_ctx->bank->size) { pcilib_error("Trying to access space outside of the define register bank (bank: %s, addr: 0x%lx)", bank_ctx->bank->name, addr); @@ -132,15 +113,6 @@ int pcilib_software_registers_read(pcilib_t *ctx, pcilib_register_bank_context_t return 0; } -/** - * pcilib_software_registers_write - * this function write the said value to a said register in the kernel space - * @param[in] ctx the pcilib_t structure runnning - * @param[in] bank_ctx the bank context that was returned by the initialisation function - * @param[in] addr the adress of the register we want to write in - * @param[out] value the value we want to write in the register - * @return 0 in case of success - */ int pcilib_software_registers_write(pcilib_t *ctx, pcilib_register_bank_context_t *bank_ctx, pcilib_register_addr_t addr, pcilib_register_value_t value) { if ((addr + sizeof(pcilib_register_value_t)) > bank_ctx->bank->size) { pcilib_error("Trying to access space outside of the define register bank (bank: %s, addr: 0x%lx)", bank_ctx->bank->name, addr); diff --git a/protocols/software.h b/protocols/software.h index d066cd6..484e344 100644 --- a/protocols/software.h +++ b/protocols/software.h @@ -1,7 +1,6 @@ /** * @file software.h - * @skip author nicolas zilio, nicolas.zilio@hotmail.fr - * @brief header file for implementation of the protocol with software registers allocated in the main memory. + * @brief header file for implementation of the protocol with software registers allocated in the kernel space, for parameters sharing between concurrent pcitool instances */ #ifndef _PCILIB_SOFTWARE_H @@ -13,44 +12,44 @@ /** * this function initialize the kernel space memory for the use of software register. it initializes the kernel space memory and stores in it the default values of the registers of the given bank index, if it was not initialized by a concurrent process, and return a bank context containing the adress of this kernel space. If the kernel space memory was already initialized by a concurrent process, then this function just return the bank context with the adress of this kernel space already used - * @param[in] ctx the pcilib_t structure running - * @param[in] bank the bank index that will permits to get the bank we want registers from - * @param[in] model not used - * @param[in] args not used - * @return a bank context with the adress of the kernel space memory related to it + * @param[in] - ctx the pcilib_t structure running + * @param[in] - bank the bank index that will permits to get the bank we want registers from + * @param[in] - model not used + * @param[in] - args not used + * @return a bank context with the adress of the kernel space memory related to it, as we could have for BAR */ pcilib_register_bank_context_t* pcilib_software_registers_open(pcilib_t *ctx, pcilib_register_bank_t bank, const char* model, const void *args); /** - * this function clear the kernel memory space that could have been allocated for software registers. - * @param[in] ctx the pcilib_t structure runnning - * @param[in] bank_ctx the bank context running that we get from the initialisation function + * this function clear the kernel memory space that could have been allocated for software registers and the bank context that correspond to it too + * @param[in] ctx - the pcilib_t structure runnning + * @param[in] bank_ctx - the bank context running that we get from the initialisation function */ void pcilib_software_registers_close(pcilib_t *ctx, pcilib_register_bank_context_t *bank_ctx); /** * this function read the value of a said register in the kernel space. - * @param[in] ctx the pcilib_t structure runnning - * @param[in] bank_ctx the bank context that was returned by the initialisation function - * @param[in] addr the adress of the register we want to read - * @param[out] value the value of the register - * @return 0 in case of success + * @param[in] - ctx the pcilib_t structure runnning + * @param[in] - bank_ctx the bank context that was returned by the initialisation function + * @param[in] - addr the adress of the register we want to read + * @param[out] - value the value of the register + * @return error code : 0 in case of success */ int pcilib_software_registers_read(pcilib_t *ctx, pcilib_register_bank_context_t* bank_ctx, pcilib_register_addr_t addr, pcilib_register_value_t *value); /** - * this function write the said value to a said register in the kernel space - * @param[in] ctx the pcilib_t structure runnning - * @param[in] bank_ctx the bank context that was returned by the initialisation function - * @param[in] addr the adress of the register we want to write in - * @param[out] value the value we want to write in the register - * @return 0 in case of success + * this function write the given value to a given register in the kernel space + * @param[in] ctx - the pcilib_t structure runnning + * @param[in] bank_ctx - the bank context that was returned by the initialisation function + * @param[in] addr - the adress of the register we want to write in + * @param[in] value - the value we want to write in the register + * @return error code : 0 in case of success */ int pcilib_software_registers_write(pcilib_t *ctx,pcilib_register_bank_context_t* bank_ctx, pcilib_register_addr_t addr, pcilib_register_value_t value); #ifdef _PCILIB_EXPORT_C /** - * new protocol addition to the protocol api. + * software protocol addition to the protocol api. */ const pcilib_register_protocol_api_description_t pcilib_register_software_protocol_api = { PCILIB_VERSION, pcilib_software_registers_open, pcilib_software_registers_close,pcilib_software_registers_read, pcilib_software_registers_write }; /**< we add there the protocol to the list of possible protocols*/ -- cgit v1.2.3 From 60c6bf9f6916b6ae2c05a499675ff54480256ece Mon Sep 17 00:00:00 2001 From: "nicolas.zilio@hotmail.fr" <> Date: Fri, 11 Sep 2015 19:40:33 +0200 Subject: more towards views --- CMakeLists.txt | 2 +- pcilib/pci.c | 12 ++++++++ pcilib/pci.h | 1 + pcilib/views.c | 6 ++-- pcilib/views.h | 6 ++-- pcilib/xml.c | 80 ++++++++++++++++++++++++++++++++--------------------- pcitool/cli.c | 5 ++++ xml/test/camera.xml | 6 ++-- 8 files changed, 77 insertions(+), 41 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d9e637f..c5cc12a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,7 +46,7 @@ if (NOT DISABLE_PCITOOL) pkg_check_modules(FASTWRITER fastwriter REQUIRED) endif (NOT DISABLE_PCITOOL) -add_definitions("-fPIC --std=c99 -Wall -O2 -gdwarf-2 -g3 -fno-omit-frame-pointer") +add_definitions("-fPIC --std=c99 -Wall -O2 -gdwarf-2 -g3 -fno-omit-frame-pointer -g") #add_definitions("-fPIC --std=c99 -Wall -O2") include(cmake/version.cmake) diff --git a/pcilib/pci.c b/pcilib/pci.c index b7dcbcd..8c178f6 100644 --- a/pcilib/pci.c +++ b/pcilib/pci.c @@ -139,8 +139,12 @@ pcilib_t *pcilib_open(const char *device, const char *model) { } ctx->alloc_reg = PCILIB_DEFAULT_REGISTER_SPACE; + ctx->alloc_formula_views=PCILIB_DEFAULT_VIEW_SPACE; + ctx->alloc_enum_views=PCILIB_DEFAULT_VIEW_SPACE; ctx->registers = (pcilib_register_description_t *)malloc(PCILIB_DEFAULT_REGISTER_SPACE * sizeof(pcilib_register_description_t)); ctx->register_ctx = (pcilib_register_context_t *)malloc(PCILIB_DEFAULT_REGISTER_SPACE * sizeof(pcilib_register_context_t)); + ctx->enum_views = (pcilib_view_enum2_t *)malloc(PCILIB_DEFAULT_VIEW_SPACE * sizeof(pcilib_view_enum2_t)); + ctx->formula_views = (pcilib_view_formula_t*)malloc(PCILIB_DEFAULT_VIEW_SPACE * sizeof(pcilib_view_formula_t)); if ((!ctx->registers)||(!ctx->register_ctx)) { pcilib_error("Error allocating memory for register model"); @@ -148,12 +152,20 @@ pcilib_t *pcilib_open(const char *device, const char *model) { return NULL; } + if((!ctx->enum_views)||(!ctx->formula_views)){ + pcilib_error("Error allocating memory for views"); + pcilib_close(ctx); + return NULL; + } + memset(ctx->registers, 0, sizeof(pcilib_register_description_t)); memset(ctx->banks, 0, sizeof(pcilib_register_bank_description_t)); memset(ctx->ranges, 0, sizeof(pcilib_register_range_t)); memset(ctx->register_ctx, 0, PCILIB_DEFAULT_REGISTER_SPACE * sizeof(pcilib_register_context_t)); + memset(ctx->enum_views,0,sizeof(pcilib_view_enum2_t)); + memset(ctx->formula_views,0,sizeof(pcilib_view_formula_t)); for (i = 0; pcilib_protocols[i].api; i++); memcpy(ctx->protocols, pcilib_protocols, i * sizeof(pcilib_register_protocol_description_t)); diff --git a/pcilib/pci.h b/pcilib/pci.h index 657c335..3b1c0e8 100644 --- a/pcilib/pci.h +++ b/pcilib/pci.h @@ -8,6 +8,7 @@ #define PCILIB_DMA_SKIP_TIMEOUT 1000000 /**< us */ #define PCILIB_MAX_BARS 6 /**< this is defined by PCI specification */ #define PCILIB_DEFAULT_REGISTER_SPACE 1024 /**< number of registers to allocate on init */ +#define PCILIB_DEFAULT_VIEW_SPACE 128 /**< number of views to allocate on init */ #define PCILIB_MAX_REGISTER_BANKS 32 /**< maximum number of register banks to allocate space for */ #define PCILIB_MAX_REGISTER_RANGES 32 /**< maximum number of register ranges to allocate space for */ #define PCILIB_MAX_REGISTER_PROTOCOLS 32 /**< maximum number of register protocols to support */ diff --git a/pcilib/views.c b/pcilib/views.c index 44392d9..038b48d 100644 --- a/pcilib/views.c +++ b/pcilib/views.c @@ -2,7 +2,7 @@ #include "pci.h" #include "pcilib.h" #include -//#include "views.h" +#include "views.h" #include "error.h" #include #include @@ -349,7 +349,6 @@ int pcilib_add_views_enum(pcilib_t *ctx, size_t n, const pcilib_view_enum2_t* vi if (!views_enum) return PCILIB_ERROR_MEMORY; ctx->enum_views = views_enum; - /* context + model part ????*/ ctx->alloc_enum_views = size; } @@ -376,13 +375,12 @@ int pcilib_add_views_formula(pcilib_t *ctx, size_t n, const pcilib_view_formula_ } if ((ctx->num_formula_views + n + 1) > ctx->alloc_formula_views) { - for (size = ctx->alloc_formula_views; size < 2 * (n + ctx->num_formula_views + 1); size<<=1); + for (size = ctx->alloc_formula_views; size < 2 * (n + ctx->num_formula_views + 1); size<<=1); views_formula = (pcilib_view_formula_t*)realloc(ctx->formula_views, size * sizeof(pcilib_view_formula_t)); if (!views_formula) return PCILIB_ERROR_MEMORY; ctx->formula_views = views_formula; - /* context + model part?????*/ ctx->alloc_formula_views = size; } diff --git a/pcilib/views.h b/pcilib/views.h index 98e3dcd..dfc9f70 100644 --- a/pcilib/views.h +++ b/pcilib/views.h @@ -24,6 +24,7 @@ struct pcilib_view_enum_s { struct pcilib_view_enum2_s { const char* name; pcilib_view_enum_t* enums_list; + const char* description; }; @@ -35,6 +36,7 @@ struct pcilib_view_formula_s { const char *read_formula; /**< formula to parse to read from a register*/ const char *write_formula; /**nodesetval; - if (!xmlXPathNodeSetIsEmpty(nodeset)) { int i,k,l; /*if we correctly get a nodeset, then we iterate through the nodeset to get all views, using their names*/ for (i = 0; i < nodeset->nodeNr; i++) { view_name=(char*)nodeset->nodeTab[i]->children->content; - + /* if the view name obtained is for an enum view, we get all pcilib_view_enum_t corresponding to the register*/ - for(k=0; ctx->enum_views[k].enums_list[0].value;k++){ + for(k=0; ctx->enum_views[k].enums_list[0].value; k++){ if(!(strcasecmp(view_name, ctx->enum_views[k].name))){ ctx->register_ctx[id].enums=malloc(sizeof(pcilib_view_enum_t)); @@ -109,29 +113,34 @@ pcilib_get_associated_views(pcilib_t* ctx, const char* reg_name,xmlXPathContextP return PCILIB_ERROR_MEMORY; } + /*!!!!!!!!!!this loop here is buggy*/ for(l=0; ctx->enum_views[k].enums_list[l].value;l++){ ctx->register_ctx[id].enums=realloc(ctx->register_ctx[id].enums,(l+1)*sizeof(pcilib_view_enum_t)); ctx->register_ctx[id].enums[l]=ctx->enum_views[k].enums_list[l]; + // printf("names %s %s\n",ctx->register_ctx[id].enums[l].name,ctx->enum_views[k].enums_list[l].name); } + return 0; } } /*here it is for formula, i assume we have only one formula view per register*/ for(k=0; ctx->formula_views[k].name[0];k++){ if(!(strcasecmp(view_name,ctx->formula_views[k].name))){ + ctx->register_ctx[id].formulas=malloc(sizeof(pcilib_view_formula_t)); if(!(ctx->register_ctx[id].formulas)){ pcilib_error("error allocating memory for formula views in register context %i",id); return PCILIB_ERROR_MEMORY; } - ctx->register_ctx[id].formulas=&(ctx->formula_views[k]); + ctx->register_ctx[id].formulas[0]=ctx->formula_views[k]; + break; } } } } - + xmlXPathFreeObject(nodes); return 0; } @@ -247,7 +256,8 @@ static int pcilib_xml_parse_register(pcilib_t *ctx, pcilib_xml_register_descript static int pcilib_xml_create_register(pcilib_t *ctx, pcilib_register_bank_t bank, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node) { int err; int views_ok=0; - + int h; + xmlXPathObjectPtr nodes; xmlNodeSetPtr nodeset; @@ -255,7 +265,7 @@ static int pcilib_xml_create_register(pcilib_t *ctx, pcilib_register_bank_t bank pcilib_xml_register_description_t fdesc; pcilib_register_t reg; - + desc.base.bank = ctx->banks[bank].addr; desc.base.rwmask = PCILIB_REGISTER_ALL_BITS; desc.base.mode = PCILIB_REGISTER_R; @@ -279,7 +289,7 @@ static int pcilib_xml_create_register(pcilib_t *ctx, pcilib_register_bank_t bank /* if the register had a node of type views, then we compute its associated registers. I do that here as i need the index for register context*/ if(views_ok){ - err=pcilib_get_associated_views(ctx,desc.base.name,xpath,reg); + err=pcilib_get_associated_views(ctx,desc.base.name,xpath,reg,1); if(err) pcilib_warning("can't get correctly the associated views of the register %s",desc.base.name); } @@ -324,7 +334,7 @@ static int pcilib_xml_create_register(pcilib_t *ctx, pcilib_register_bank_t bank ctx->register_ctx[reg].min = fdesc.min; ctx->register_ctx[reg].max = fdesc.max; if(views_ok){ - err=pcilib_get_associated_views(ctx, desc.base.name,xpath,reg); + err=pcilib_get_associated_views(ctx, desc.base.name,xpath,reg,0); if(err) pcilib_warning("can't get correctly the associated views of the register %s",fdesc.base.name); } } @@ -503,6 +513,7 @@ static int pcilib_xml_create_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDo enum_desc.max=0; complete_enum_desc.name="default enum"; + complete_enum_desc.description="default description"; complete_enum_desc.enums_list=malloc(sizeof(pcilib_view_enum_t)); if(!(complete_enum_desc.enums_list)){ pcilib_error("can't allocate memory for the complete enum type"); @@ -513,6 +524,7 @@ static int pcilib_xml_create_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDo formula_desc.name="formula_default"; formula_desc.read_formula="@reg"; formula_desc.write_formula="@reg"; + formula_desc.description="default description"; /* we get the attribute type of the view node*/ attr=node->properties; @@ -530,6 +542,10 @@ static int pcilib_xml_create_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDo if (!(strcasecmp((char*)name,"name"))) { complete_enum_desc.name = value; + + }else if (!(strcasecmp((char*)name,"description"))) { + complete_enum_desc.description = value; + }else if (!(strcasecmp((char*)name,"enum"))) { complete_enum_desc.enums_list=realloc(complete_enum_desc.enums_list,(i+1)*sizeof(pcilib_view_enum_t)); @@ -567,7 +583,7 @@ static int pcilib_xml_create_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDo complete_enum_desc.enums_list[i].max=dat_max; } } - i++; + i++; } } err=pcilib_add_views_enum(ctx,1,&complete_enum_desc); @@ -584,6 +600,7 @@ static int pcilib_xml_create_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDo name = (char*)cur->name; value = (char*)cur->children->content; + if (!value) continue; if (!(strcasecmp((char*)name,"name"))) { @@ -592,6 +609,8 @@ static int pcilib_xml_create_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDo formula_desc.read_formula=value; }else if (!(strcasecmp((char*)name,"write_to_register"))) { formula_desc.write_formula=value; + }else if (!(strcasecmp((char*)name,"description"))) { + formula_desc.description=value; } } err=pcilib_add_views_formula(ctx,1,&formula_desc); @@ -619,6 +638,22 @@ static int pcilib_xml_process_document(pcilib_t *ctx, xmlDocPtr doc, xmlXPathCon int i; xmlErrorPtr xmlerr; + views_nodes=xmlXPathEvalExpression(VIEWS_PATH,xpath); + if(!views_nodes){ + xmlerr = xmlGetLastError(); + if (xmlerr) pcilib_error("Failed to parse XPath expression %s, xmlXPathEvalExpression reported error %d - %s", BANKS_PATH, xmlerr->code, xmlerr->message); + else pcilib_error("Failed to parse XPath expression %s", BANKS_PATH); + return PCILIB_ERROR_FAILED; + } + + nodeset=views_nodes->nodesetval; + if(!xmlXPathNodeSetIsEmpty(nodeset)){ + for(i=0;i < nodeset->nodeNr; i++){ + pcilib_xml_create_view(ctx,xpath,doc,nodeset->nodeTab[i]); + } + } + xmlXPathFreeObject(views_nodes); + bank_nodes = xmlXPathEvalExpression(BANKS_PATH, xpath); if (!bank_nodes) { xmlerr = xmlGetLastError(); @@ -636,23 +671,6 @@ static int pcilib_xml_process_document(pcilib_t *ctx, xmlDocPtr doc, xmlXPathCon } xmlXPathFreeObject(bank_nodes); - - views_nodes=xmlXPathEvalExpression(VIEWS_PATH,xpath); - if(!views_nodes){ - xmlerr = xmlGetLastError(); - if (xmlerr) pcilib_error("Failed to parse XPath expression %s, xmlXPathEvalExpression reported error %d - %s", BANKS_PATH, xmlerr->code, xmlerr->message); - else pcilib_error("Failed to parse XPath expression %s", BANKS_PATH); - return PCILIB_ERROR_FAILED; - } - - nodeset=views_nodes->nodesetval; - if(!xmlXPathNodeSetIsEmpty(nodeset)){ - for(i=0;i < nodeset->nodeNr; i++){ - pcilib_xml_create_view(ctx,xpath,doc,nodeset->nodeTab[i]); - } - } - xmlXPathFreeObject(views_nodes); - return 0; } diff --git a/pcitool/cli.c b/pcitool/cli.c index c3663d2..7014190 100644 --- a/pcitool/cli.c +++ b/pcitool/cli.c @@ -2720,6 +2720,11 @@ int main(int argc, char **argv) { mode = MODE_READ; if (optarg) addr = optarg; else if ((optind < argc)&&(argv[optind][0] != '-')) addr = argv[optind++]; + + /* char* s; + if(!(s=strchr(addr,'/'))){ + mode=MODE_READ_VIEW;*/ + break; case OPT_WRITE: if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); diff --git a/xml/test/camera.xml b/xml/test/camera.xml index 5b486ee..815a50e 100644 --- a/xml/test/camera.xml +++ b/xml/test/camera.xml @@ -277,9 +277,9 @@ 16 R sensor_temperature - - formuu1 - formuu2 + + formuu1 + formuu2 enumm2 -- cgit v1.2.3 From 2dfb23016c39a331bf5ed4111b630dffa330edbb Mon Sep 17 00:00:00 2001 From: "nicolas.zilio@hotmail.fr" <> Date: Mon, 14 Sep 2015 11:56:38 +0200 Subject: views working fine, units in progress --- pcilib/CMakeLists.txt | 4 +-- pcilib/pci.c | 14 +++++--- pcilib/pci.h | 5 ++- pcilib/unit.c | 34 ++++++++++++++++++ pcilib/unit.h | 30 ++++++++++++++++ pcilib/views.c | 99 +++++++++++++++++++++++++++++---------------------- pcilib/views.h | 3 ++ pcilib/xml.c | 71 ++++++++++++++++++++++++++++++++++-- pcitool/cli.c | 67 ++++++++++++++++++++++++++++------ xml/test/camera.xml | 4 +-- 10 files changed, 267 insertions(+), 64 deletions(-) create mode 100644 pcilib/unit.c create mode 100644 pcilib/unit.h diff --git a/pcilib/CMakeLists.txt b/pcilib/CMakeLists.txt index 48363f6..1f3e646 100644 --- a/pcilib/CMakeLists.txt +++ b/pcilib/CMakeLists.txt @@ -9,9 +9,9 @@ include_directories( set(HEADERS pcilib.h pci.h export.h bar.h fifo.h model.h bank.h register.h views.h xml.h kmem.h irq.h locking.h lock.h dma.h event.h plugin.h tools.h error.h -debug.h env.h version.h config.h ) +debug.h env.h version.h config.h unit.h) add_library(pcilib SHARED pci.c export.c bar.c fifo.c model.c bank.c -register.c views.c xml.c kmem.c irq.c locking.c lock.c dma.c event.c plugin.c tools.c error.c debug.c env.c ) +register.c views.c xml.c kmem.c irq.c locking.c lock.c dma.c event.c plugin.c tools.c error.c debug.c env.c unit.c) target_link_libraries(pcilib dma protocols ${CMAKE_THREAD_LIBS_INIT} ${UFODECODE_LIBRARIES} ${CMAKE_DL_LIBS} ${EXTRA_SYSTEM_LIBS} ${LIBXML2_LIBRARIES} ${PYTHON_LIBRARIES}) diff --git a/pcilib/pci.c b/pcilib/pci.c index 8c178f6..2742240 100644 --- a/pcilib/pci.c +++ b/pcilib/pci.c @@ -145,19 +145,24 @@ pcilib_t *pcilib_open(const char *device, const char *model) { ctx->register_ctx = (pcilib_register_context_t *)malloc(PCILIB_DEFAULT_REGISTER_SPACE * sizeof(pcilib_register_context_t)); ctx->enum_views = (pcilib_view_enum2_t *)malloc(PCILIB_DEFAULT_VIEW_SPACE * sizeof(pcilib_view_enum2_t)); ctx->formula_views = (pcilib_view_formula_t*)malloc(PCILIB_DEFAULT_VIEW_SPACE * sizeof(pcilib_view_formula_t)); + ctx->alloc_units=PCILIB_DEFAULT_UNIT_SPACE; + ctx->units=(pcilib_unit_t*)malloc(PCILIB_DEFAULT_UNIT_SPACE * sizeof(pcilib_unit_t)); + + if ((!ctx->registers)||(!ctx->register_ctx)) { pcilib_error("Error allocating memory for register model"); pcilib_close(ctx); return NULL; } - if((!ctx->enum_views)||(!ctx->formula_views)){ - pcilib_error("Error allocating memory for views"); - pcilib_close(ctx); - return NULL; + /* i think we need a better error handling here, because, it's not that a problem to not have views working, but how to block the use if the memory here was not good?, and we could have only one type of views that is working*/ + if((!ctx->enum_views)||(!ctx->formula_views) || (!ctx->units)){ + pcilib_warning("Error allocating memory for views"); } + + memset(ctx->registers, 0, sizeof(pcilib_register_description_t)); memset(ctx->banks, 0, sizeof(pcilib_register_bank_description_t)); memset(ctx->ranges, 0, sizeof(pcilib_register_range_t)); @@ -166,6 +171,7 @@ pcilib_t *pcilib_open(const char *device, const char *model) { memset(ctx->enum_views,0,sizeof(pcilib_view_enum2_t)); memset(ctx->formula_views,0,sizeof(pcilib_view_formula_t)); + memset(ctx->units,0,sizeof(pcilib_unit_t)); for (i = 0; pcilib_protocols[i].api; i++); memcpy(ctx->protocols, pcilib_protocols, i * sizeof(pcilib_register_protocol_description_t)); diff --git a/pcilib/pci.h b/pcilib/pci.h index 3b1c0e8..a62e1cc 100644 --- a/pcilib/pci.h +++ b/pcilib/pci.h @@ -9,6 +9,7 @@ #define PCILIB_MAX_BARS 6 /**< this is defined by PCI specification */ #define PCILIB_DEFAULT_REGISTER_SPACE 1024 /**< number of registers to allocate on init */ #define PCILIB_DEFAULT_VIEW_SPACE 128 /**< number of views to allocate on init */ +#define PCILIB_DEFAULT_UNIT_SPACE 128 /** number of units to allocate on init*/ #define PCILIB_MAX_REGISTER_BANKS 32 /**< maximum number of register banks to allocate space for */ #define PCILIB_MAX_REGISTER_RANGES 32 /**< maximum number of register ranges to allocate space for */ #define PCILIB_MAX_REGISTER_PROTOCOLS 32 /**< maximum number of register protocols to support */ @@ -27,6 +28,7 @@ #include "export.h" #include "locking.h" #include "xml.h" +#include "unit.h" typedef struct { uint8_t max_link_speed, link_speed; @@ -65,7 +67,7 @@ struct pcilib_s { size_t dyn_banks; /**< Number of configured dynamic banks */ size_t num_enum_views,alloc_enum_views; /**< Number of configured and allocated views of type enum*/ size_t num_formula_views,alloc_formula_views; /**< Number of configured and allocated views of type formula*/ - + size_t num_units,alloc_units; /**< Number of configured and allocated units*/ pcilib_register_description_t *registers; /**< List of currently defined registers (from all sources) */ pcilib_register_bank_description_t banks[PCILIB_MAX_REGISTER_BANKS + 1]; /**< List of currently defined register banks (from all sources) */ pcilib_register_range_t ranges[PCILIB_MAX_REGISTER_RANGES + 1]; /**< List of currently defined register ranges (from all sources) */ @@ -87,6 +89,7 @@ struct pcilib_s { pcilib_view_enum2_t* enum_views; /**< list of currently defined views of type enum*/ pcilib_view_formula_t* formula_views; /**< list of currently defined views of type formula*/ + pcilib_unit_t* units; /** list of currently defined units*/ #ifdef PCILIB_FILE_IO int file_io_handle; #endif /* PCILIB_FILE_IO */ diff --git a/pcilib/unit.c b/pcilib/unit.c new file mode 100644 index 0000000..a9766ed --- /dev/null +++ b/pcilib/unit.c @@ -0,0 +1,34 @@ +#include "pcilib.h" +#include "pci.h" +#include "stdio.h" +#include +#include "error.h" +#include "unit.h" + +int pcilib_add_units(pcilib_t *ctx, size_t n, const pcilib_unit_t* units) { + + pcilib_unit_t *units2; + size_t size; + + if (!n) { + for (n = 0; units[n].name[0]; n++); + } + + if ((ctx->num_units + n + 1) > ctx->alloc_units) { + for (size = ctx->alloc_units; size < 2 * (n + ctx->num_units + 1); size<<=1); + + units2 = (pcilib_unit_t*)realloc(ctx->units, size * sizeof(pcilib_unit_t)); + if (!units2) return PCILIB_ERROR_MEMORY; + + ctx->units = units2; + ctx->alloc_units = size; + } + + memcpy(ctx->units + ctx->num_units, units, n * sizeof(pcilib_unit_t)); + memset(ctx->units + ctx->num_units + n, 0, sizeof(pcilib_unit_t)); + + ctx->num_units += n; + + return 0; +} + diff --git a/pcilib/unit.h b/pcilib/unit.h new file mode 100644 index 0000000..f9991f1 --- /dev/null +++ b/pcilib/unit.h @@ -0,0 +1,30 @@ +#ifndef _PCILIB_UNITS_H +#define _PCILIB_UNITS_H + +#include "pcilib.h" + +typedef struct pcilib_unit_s pcilib_unit_t; +typedef struct pcilib_transform_unit_s pcilib_transform_unit_t; + +/** + * type to save a transformation unit in the pcitool program + */ +struct pcilib_transform_unit_s{ + char *name; + char *transform_formula; +}; + +/** + * type to save a unit in the pcitool programm + */ +struct pcilib_unit_s{ + char* name; + pcilib_transform_unit_t* other_units; +}; + +/** + * function to populate the ctx with units + */ +int pcilib_add_units(pcilib_t* ctx, size_t n, const pcilib_unit_t* units); + +#endif diff --git a/pcilib/views.c b/pcilib/views.c index 038b48d..c9ad4d3 100644 --- a/pcilib/views.c +++ b/pcilib/views.c @@ -6,6 +6,7 @@ #include "error.h" #include #include +#include "unit.h" /** * @@ -81,7 +82,7 @@ pcilib_view_formula_replace (const char *txt, const char *before, const char *af * @param[in] end the ending index of the substring. * @return the extracted substring. */ -static char* +char* pcilib_view_str_sub (const char *s, unsigned int start, unsigned int end) { char *new_s = NULL; @@ -108,6 +109,39 @@ pcilib_view_str_sub (const char *s, unsigned int start, unsigned int end) return new_s; } +/** + * function to apply a unit for the views of type formula + *@param[in] view - the view we want to get the units supported + *@param[in] base_unit - the base unit of the formulas of the view + *@param[in] unit - the requested unit in which we want to get the value + *@param[in,out] value - the number that needs to get transformed + * +static int +pcilib_view_apply_unit(pcilib_view_formula_t* view, char* base_unit, char* unit,int* value){ + char* formula; + char temp[66]; + int i,j,k; + k=1; + /*we iterate through all the units of the given view to find the corresponding unit, and so the formula to transform it; then we evaluate value with the formula* + for(i=0;view->units[i].name[0];i++){ + if(!(strcasecmp(base_unit,view->units[i].name))){ + for(j=0;view->units[i].other_units[j].name[0];j++){ + if(!(strcasecmp(unit,view->units[i].other_units[j].name))){ + formula=malloc(strlen(units[i].other_units[j].transform_formula)*sizeof(char)); + strcpy(formula,units[i].other_units[j].transform_formula); + sprintf(temp,"%i",*value); + formula=pcilib_view_formula_replace(formula,"@self",temp); + *value=(int)pcilib_view_eval_formula(formula); + return 0; + } + } + } + } + + pcilib_error("no unit corresponds to the base unit asked"); + return PCILIB_ERROR_INVALID_REQUEST; +}*/ + /** * get the bank name associated with a register name */ @@ -162,46 +196,25 @@ pcilib_view_compute_plain_registers(pcilib_t* ctx, char* formula){ */ static pcilib_register_value_t pcilib_view_eval_formula(char* formula){ - setenv("PYTHONPATH",".",1); - PyObject *pName, *pModule, *pDict, *pFunc, *pValue, *presult=NULL; - char* pythonfile; + + // setenv("PYTHONPATH",".",1); - /* path to the python file, we may need a way to set it, maybe with a variable like PCILIB_PYTHON_PATH*/ - pythonfile="pythonscripts.py"; - /* initialization of python interpreter*/ Py_Initialize(); - - pName = PyUnicode_FromString(pythonfile); - pModule = PyImport_Import(pName); /* get the python file*/ - if(!pModule) { - pcilib_error("no python file found for python evaluation of formulas\n"); - PyErr_Print(); - return -1; - } - pDict = PyModule_GetDict(pModule); /*useless but needed*/ - - pFunc = PyDict_GetItemString(pDict, (char*)"evaluate"); /*getting of the function "evaluate" in the script*/ - /* if the function is ok, then call it*/ - if (PyCallable_Check(pFunc)) - { - /* execution of the function*/ - pValue=Py_BuildValue("(z)",formula); - PyErr_Print(); - presult=PyObject_CallObject(pFunc,pValue); - PyErr_Print(); - } else - { - PyErr_Print(); - } - /* remove memory*/ - Py_DECREF(pModule); - Py_DECREF(pName); + /*compilation of the formula as python string*/ + PyCodeObject* code=(PyCodeObject*)Py_CompileString(formula,"test",Py_eval_input); + PyObject* main_module = PyImport_AddModule("__parser__"); + PyObject* global_dict = PyModule_GetDict(main_module); + PyObject* local_dict = PyDict_New(); + /*evaluation of formula*/ + PyObject* obj = PyEval_EvalCode(code, global_dict, local_dict); + double c=PyFloat_AsDouble(obj); + /* close interpreter*/ Py_Finalize(); - - return (pcilib_register_value_t)PyLong_AsUnsignedLong(presult); /*this function is due to python 3.3, as PyLong_AsInt was there in python 2.7 and is no more there, resulting in using cast futhermore*/ + pcilib_register_value_t value=(pcilib_register_value_t)c; + return value; } @@ -227,7 +240,6 @@ pcilib_view_apply_formula(pcilib_t* ctx, char* formula, pcilib_register_value_t formula=pcilib_view_compute_plain_registers(ctx,formula); /* computation of @reg with register value*/ formula=pcilib_view_formula_replace(formula,"@reg",reg_value_string); - /* evaluation of the formula*/ *out_value= pcilib_view_eval_formula(formula); @@ -246,8 +258,10 @@ int pcilib_read_view(pcilib_t *ctx, const char *bank, const char *regname, const } /* we get the value of the register, as we will apply the view on it*/ - if((err==pcilib_read_register_by_id(ctx,i,&temp_value))>0){ - pcilib_error("can't read the register %s value before applying views",regname); + err=pcilib_read_register_by_id(ctx,i,&temp_value); + if(err){ + pcilib_error("can't read the register %s value before applying views : error %i",regname); + return PCILIB_ERROR_INVALID_REQUEST; } /*in the case we don't ask for a view's name, we know it will be for views of type enum. Especially, it's faster to search directly on the values of those views instead of a given name. we iterate so through the views of type enum to verify if the value we have corresponds to an enum command*/ @@ -255,13 +269,15 @@ int pcilib_read_view(pcilib_t *ctx, const char *bank, const char *regname, const for(j=0; ctx->register_ctx[i].enums[j].value;j++){ if((temp_value >= ctx->register_ctx[i].enums[j].min) && (temp_value <= ctx->register_ctx[i].enums[j].max)){ value_size=strlen(ctx->register_ctx[i].enums[j].name)*sizeof(char); - value=malloc(sizeof(value_size)); + value=(char*)realloc(value,sizeof(value_size)); if(!(value)){ pcilib_error("can't allocate memory for the returning value of the view %s",view); return PCILIB_ERROR_MEMORY; } /* in the case the value of register is between min and max, then we return the correponding enum command*/ strncpy((char*)value,ctx->register_ctx[i].enums[j].name, strlen(ctx->register_ctx[i].enums[j].name)); + /* make sure the string is correctly terminated*/ + ((char*)value)[value_size]='\0'; return 0; } } @@ -271,8 +287,7 @@ int pcilib_read_view(pcilib_t *ctx, const char *bank, const char *regname, const /** in the other case we ask for a view of type formula. Indeed, wa can't directly ask for a formula, so we have to provide a name for those views*/ j=0; - while((ctx->register_ctx[i].formulas[j].name)){ - if(!(strcasecmp(ctx->register_ctx[i].formulas[j].name,view))){ + if(!(strcasecmp(ctx->register_ctx[i].formulas[0].name,view))){ /* when we have found the correct view of type formula, we apply the formula, that get the good value for return*/ formula=malloc(sizeof(char)*strlen(ctx->register_ctx[i].formulas[j].read_formula)); strncpy(formula,ctx->register_ctx[i].formulas[j].read_formula,strlen(ctx->register_ctx[i].formulas[j].read_formula)); @@ -281,8 +296,6 @@ int pcilib_read_view(pcilib_t *ctx, const char *bank, const char *regname, const value_size=sizeof(int); return 0; } - j++; - } pcilib_warning("the view asked and the register do not correspond"); return PCILIB_ERROR_NOTAVAILABLE; diff --git a/pcilib/views.h b/pcilib/views.h index dfc9f70..f186336 100644 --- a/pcilib/views.h +++ b/pcilib/views.h @@ -2,6 +2,7 @@ #define _PCILIB_VIEWS_H #include "pcilib.h" +#include "unit.h" typedef struct pcilib_view_enum_s pcilib_view_enum_t; @@ -37,6 +38,7 @@ struct pcilib_view_formula_s { const char *write_formula; /**units[0].other_units.name[0];i++){ + for(j=0;ctx->units[j].name[0];i++){ + if(!(strcasecmp(myview->units[0].other_units.name,ctx->units[i].name))){ + myview.units=realloc(myview.units,k*sizeof(pcilib_unit_t)); + myview.units[k-1]=ctx->units[i]; + k++; + } + } + } + }*/ + /** * get the associated views of a register, to fill its register context */ @@ -490,7 +507,52 @@ static int pcilib_xml_create_bank(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDo return 0; } +/*static int pcilib_xml_create_unit(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node) { + int err; + + int override = 0; + pcilib_unit_t desc = {0}; + xmlNodePtr cur; + char *value, *name, *value2; + char *endptr; + xmlXPathObjectPtr nodes; + xmlNodeSetPtr nodeset; + xmlAttr *attr; + int i=0; + + /* we get the attribute type of the view node* + attr=node->properties; + value=(char*)attr->children->content; + desc.name=value; + desc.other_units=malloc(sizeof(pcilib_transform_unit_t)); + + for (cur = node->children; cur != NULL; cur = cur->next) { + if (!cur->children) continue; + if (!xmlNodeIsText(cur->children)) continue; + + name = (char*)cur->name; + value = (char*)cur->children->content; + attr= cur->properties; + value2=(char*)attr->children->content; + if (!value || !attr) continue; + + if (!strcasecmp(name, "convert_unit")) { + desc.other_units=realloc(des.other_units,sizeof((i+1)*sizeof(pcilib_transform_unit_t))); + desc.other_units[i].name=value2; + desc.other_units[i].transform_formula=value; + } + } + + err = pcilib_add_units(ctx, 1, &desc); + if (err) { + pcilib_error("Error adding unit (%s) specified in the XML", desc.name); + return err; + } + + return 0; +} +*/ /** * function that create a view from a view node, and populate ctx views list */ @@ -505,6 +567,7 @@ static int pcilib_xml_create_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDo char *endptr; xmlAttr *attr; int i=0; + int ok_min=0, ok_max=0; /*must i initialize? i think it's only needed if we want to include a description property*/ enum_desc.name="default"; @@ -573,15 +636,19 @@ static int pcilib_xml_create_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDo return PCILIB_ERROR_INVALID_DATA; } complete_enum_desc.enums_list[i].min=dat_min; + ok_min=1; }else if(!(strcasecmp(name,"max"))){ pcilib_register_value_t dat_max = strtol(value, &endptr, 0); if ((strlen(endptr) > 0)) { pcilib_error("Invalid max (%s) is specified in the XML enum node", value); return PCILIB_ERROR_INVALID_DATA; } - complete_enum_desc.enums_list[i].max=dat_max; + ok_max=1; } + if(ok_min==0) complete_enum_desc.enums_list[i].min=complete_enum_desc.enums_list[i].value; + if(ok_max==0) complete_enum_desc.enums_list[i].max=complete_enum_desc.enums_list[i].value; + } i++; } diff --git a/pcitool/cli.c b/pcitool/cli.c index 7014190..6af70e4 100644 --- a/pcitool/cli.c +++ b/pcitool/cli.c @@ -1024,13 +1024,14 @@ int ReadRegister(pcilib_t *handle, const pcilib_model_description_t *model_info, int i; int err; const char *format; + char *s1,*s2,*s3; + pcilib_register_bank_t bank_id; pcilib_register_bank_addr_t bank_addr = 0; pcilib_register_value_t value; - - if (reg) { + if (reg && !(strchr(reg,'/'))) { pcilib_register_t regid = pcilib_find_register(handle, bank, reg); bank_id = pcilib_find_register_bank_by_addr(handle, model_info->registers[regid].bank); format = model_info->banks[bank_id].format; @@ -1044,7 +1045,36 @@ int ReadRegister(pcilib_t *handle, const pcilib_model_description_t *model_info, printf(format, value); printf("\n"); } + }else if(reg && (s1=strchr(reg,'/'))){ + char* enum_command=malloc(sizeof(char*)); + if(!enum_command){ + printf("Error allocating memory for the result\n"); + return PCILIB_ERROR_MEMORY; + } + s2=pcilib_view_str_sub(reg,0,s1-reg-1); + s3=pcilib_view_str_sub(reg,s1-reg+1,strlen(reg)); + if(!(strcasecmp(s3,"name"))){ + err = pcilib_read_view(handle,bank,s2,NULL,sizeof(char*),enum_command); + if (err) printf("Error reading register %s\n", reg); + else { + printf("%s = %s\n", reg, (char*)enum_command); + } + }else{ + pcilib_register_t regid = pcilib_find_register(handle, bank, s2); + bank_id = pcilib_find_register_bank_by_addr(handle, model_info->registers[regid].bank); + format = model_info->banks[bank_id].format; + if (!format) format = "%lu"; + + err = pcilib_read_view(handle,bank,s2,s3,sizeof(pcilib_register_value_t),&value); + if (err) printf("Error reading register %s\n", reg); + else { + printf("%s = ", reg); + printf(format, value); + printf("\n"); + } + } } else { + printf("da\n"); // Adding DMA registers pcilib_get_dma_description(handle); @@ -1254,6 +1284,7 @@ int WriteRegister(pcilib_t *handle, const pcilib_model_description_t *model_info pcilib_register_value_t value; const char *format = NULL; + char *s1; pcilib_register_t regid = pcilib_find_register(handle, bank, reg); if (regid == PCILIB_REGISTER_INVALID) Error("Can't find register (%s) from bank (%s)", reg, bank?bank:"autodetected"); @@ -1281,14 +1312,27 @@ int WriteRegister(pcilib_t *handle, const pcilib_model_description_t *model_info format = "0x%lx"; } else { - Error("Can't parse data value (%s) is not valid decimal number", *data); + err = pcilib_write_view(handle,bank,reg,*data,0,NULL); + if(err) Error("can't write to the register using an enum view"); + else return 0; } + /* } else { + Error("Can't parse data value (%s) is not valid decimal number", *data); + }*/ value = val; - - err = pcilib_write_register(handle, bank, reg, value); - if (err) Error("Error writting register %s\n", reg); + if((s1=strchr(reg,'/'))){ + char *s3,*s2; + s2=pcilib_view_str_sub(reg,0,s1-reg-1); + s3=pcilib_view_str_sub(reg,s1-reg+1,strlen(reg)); + err = pcilib_write_view(handle,bank,s2,s3,sizeof(pcilib_register_value_t),&value); + if (err) printf("Error writing register %s using view %s\n",s2,s3); + }else{ + err = pcilib_write_register(handle, bank, reg, value); + if (err) Error("Error writting register %s\n", reg); + } + if ((model_info->registers[regid].mode&PCILIB_REGISTER_RW) == PCILIB_REGISTER_RW) { err = pcilib_read_register(handle, bank, reg, &value); if (err) Error("Error reading back register %s for verification\n", reg); @@ -3249,7 +3293,10 @@ int main(int argc, char **argv) { ++mode; } } - } else { + } else if(strchr(addr,'/')) { + reg=addr; + ++mode; + }else { if (pcilib_find_register(handle, bank, addr) == PCILIB_REGISTER_INVALID) { Usage(argc, argv, "Invalid address (%s) is specified", addr); } else { @@ -3349,12 +3396,12 @@ int main(int argc, char **argv) { } else if (addr) { err = ReadData(handle, amode, flags, dma, bar, start, size, access, endianess, (size_t)-1, ofile); } else { - Error("Address to read is not specified"); + Error("Address to read is not specified"); } break; case MODE_READ_REGISTER: - if ((reg)||(!addr)) ReadRegister(handle, model_info, bank, reg); - else ReadRegisterRange(handle, model_info, bank, start, addr_shift, size, ofile); + if ((reg)||(!addr)) ReadRegister(handle, model_info, bank, reg); + else ReadRegisterRange(handle, model_info, bank, start, addr_shift, size, ofile); break; case MODE_WRITE: WriteData(handle, amode, dma, bar, start, size, access, endianess, data, verify); diff --git a/xml/test/camera.xml b/xml/test/camera.xml index 815a50e..bf26d80 100644 --- a/xml/test/camera.xml +++ b/xml/test/camera.xml @@ -466,14 +466,14 @@ formuu2 C - ((1./4)*(@reg - 1200)) if @freq==0 else ((3./10)*(@reg - 1000)) + ((1./4)*(@reg + 1200)) if @freq==0 else ((3./10)*(@reg + 1000)) 4*@value + 1200 if @freq==0 else (10./3)*@value + 1000 formula to get real sensor temperature from the sensor_temperature register in decimal enumm2 high - low + low enum towards sensor_temperature register -- cgit v1.2.3 From a1bf5e300e2345b642d0a13e7e26d22c56156e47 Mon Sep 17 00:00:00 2001 From: "nicolas.zilio@hotmail.fr" <> Date: Mon, 14 Sep 2015 15:49:46 +0200 Subject: views with units functionnal (beware, as formulas are completely crap now, we could get segfault, for example if we want to write a negative value in register) --- pcilib/views.c | 148 +++++++++++++++++++++++++++++----------------------- pcilib/views.h | 6 +-- pcilib/xml.c | 97 ++++++++++++++++++++++------------ pcitool/cli.c | 20 ++++--- xml/model.xsd | 24 ++++++++- xml/test/camera.xml | 34 ++++++++++++ 6 files changed, 221 insertions(+), 108 deletions(-) diff --git a/pcilib/views.c b/pcilib/views.c index c9ad4d3..1f26b52 100644 --- a/pcilib/views.c +++ b/pcilib/views.c @@ -109,38 +109,6 @@ pcilib_view_str_sub (const char *s, unsigned int start, unsigned int end) return new_s; } -/** - * function to apply a unit for the views of type formula - *@param[in] view - the view we want to get the units supported - *@param[in] base_unit - the base unit of the formulas of the view - *@param[in] unit - the requested unit in which we want to get the value - *@param[in,out] value - the number that needs to get transformed - * -static int -pcilib_view_apply_unit(pcilib_view_formula_t* view, char* base_unit, char* unit,int* value){ - char* formula; - char temp[66]; - int i,j,k; - k=1; - /*we iterate through all the units of the given view to find the corresponding unit, and so the formula to transform it; then we evaluate value with the formula* - for(i=0;view->units[i].name[0];i++){ - if(!(strcasecmp(base_unit,view->units[i].name))){ - for(j=0;view->units[i].other_units[j].name[0];j++){ - if(!(strcasecmp(unit,view->units[i].other_units[j].name))){ - formula=malloc(strlen(units[i].other_units[j].transform_formula)*sizeof(char)); - strcpy(formula,units[i].other_units[j].transform_formula); - sprintf(temp,"%i",*value); - formula=pcilib_view_formula_replace(formula,"@self",temp); - *value=(int)pcilib_view_eval_formula(formula); - return 0; - } - } - } - } - - pcilib_error("no unit corresponds to the base unit asked"); - return PCILIB_ERROR_INVALID_REQUEST; -}*/ /** * get the bank name associated with a register name @@ -160,7 +128,7 @@ pcilib_view_get_bank_from_reg_name(pcilib_t* ctx,char* reg_name){ * replace plain registers name in a formula by their value */ static char* -pcilib_view_compute_plain_registers(pcilib_t* ctx, char* formula){ +pcilib_view_compute_plain_registers(pcilib_t* ctx, char* formula, int direction){ int j,k; char *substr, *substr2; char temp[66]; @@ -175,15 +143,24 @@ pcilib_view_compute_plain_registers(pcilib_t* ctx, char* formula){ } substr2=pcilib_view_str_sub((char*)formula,j,k-1); /**< we get the name of the register+@*/ substr=pcilib_view_str_sub(substr2,1,k-j/*length of substr2*/); /**< we get the name of the register*/ - - if((strcasecmp(substr,"reg"))){ + if(direction==0){ + if((strcasecmp(substr,"reg"))){ /* we get the bank name associated to the register, and read its value*/ pcilib_read_register(ctx, pcilib_view_get_bank_from_reg_name(ctx, substr),substr,&value); /* we put the value in formula*/ sprintf(temp,"%i",value); formula = pcilib_view_formula_replace(formula,substr2,temp); + } } - + else if(direction==1){ + if((strcasecmp(substr,"value"))){ + /* we get the bank name associated to the register, and read its value*/ + pcilib_read_register(ctx, pcilib_view_get_bank_from_reg_name(ctx, substr),substr,&value); + /* we put the value in formula*/ + sprintf(temp,"%i",value); + formula = pcilib_view_formula_replace(formula,substr2,temp); + } + } } } return formula; @@ -197,8 +174,6 @@ pcilib_view_compute_plain_registers(pcilib_t* ctx, char* formula){ static pcilib_register_value_t pcilib_view_eval_formula(char* formula){ - // setenv("PYTHONPATH",".",1); - /* initialization of python interpreter*/ Py_Initialize(); @@ -217,9 +192,27 @@ pcilib_view_eval_formula(char* formula){ return value; } +/** + * function to apply a unit for the views of type formula + *@param[in] view - the view we want to get the units supported + *@param[in] unit - the requested unit in which we want to get the value + *@param[in,out] value - the number that needs to get transformed + */ +static void +pcilib_view_apply_unit(pcilib_transform_unit_t unit_desc, const char* unit,pcilib_register_value_t* value){ + char* formula; + char temp[66]; + + formula=malloc(strlen(unit_desc.transform_formula)*sizeof(char)); + strcpy(formula,unit_desc.transform_formula); + sprintf(temp,"%i",*value); + formula=pcilib_view_formula_replace(formula,"@self",temp); + *value=(int)pcilib_view_eval_formula(formula); +} + static void -pcilib_view_apply_formula(pcilib_t* ctx, char* formula, pcilib_register_value_t reg_value, pcilib_register_value_t* out_value) +pcilib_view_apply_formula(pcilib_t* ctx, char* formula, pcilib_register_value_t reg_value, pcilib_register_value_t* out_value, int direction) { /* when applying a formula, we need to: 1) compute the values of all registers present in plain name in the formulas and replace their name with their value : for example, if we have the formula" ((1./4)*(@reg - 1200)) if @freq==0 else ((3./10)*(@reg - 1000)) " we need to get the value of the register "freq" @@ -237,15 +230,15 @@ pcilib_view_apply_formula(pcilib_t* ctx, char* formula, pcilib_register_value_t sprintf(reg_value_string,"%u",reg_value); /*computation of plain registers in the formula*/ - formula=pcilib_view_compute_plain_registers(ctx,formula); + formula=pcilib_view_compute_plain_registers(ctx,formula,direction); /* computation of @reg with register value*/ - formula=pcilib_view_formula_replace(formula,"@reg",reg_value_string); + if(direction==0) formula=pcilib_view_formula_replace(formula,"@reg",reg_value_string); + else if (direction==1) formula=pcilib_view_formula_replace(formula,"@value",reg_value_string); /* evaluation of the formula*/ *out_value= pcilib_view_eval_formula(formula); - } -int pcilib_read_view(pcilib_t *ctx, const char *bank, const char *regname, const char *view/*, const char *unit*/, size_t value_size, void *value) +int pcilib_read_view(pcilib_t *ctx, const char *bank, const char *regname, const char *unit, size_t value_size, void *value) { int i,j,err=0; pcilib_register_value_t temp_value; @@ -265,13 +258,13 @@ int pcilib_read_view(pcilib_t *ctx, const char *bank, const char *regname, const } /*in the case we don't ask for a view's name, we know it will be for views of type enum. Especially, it's faster to search directly on the values of those views instead of a given name. we iterate so through the views of type enum to verify if the value we have corresponds to an enum command*/ - if(!(view)){ + if(!(unit)){ for(j=0; ctx->register_ctx[i].enums[j].value;j++){ if((temp_value >= ctx->register_ctx[i].enums[j].min) && (temp_value <= ctx->register_ctx[i].enums[j].max)){ value_size=strlen(ctx->register_ctx[i].enums[j].name)*sizeof(char); value=(char*)realloc(value,sizeof(value_size)); if(!(value)){ - pcilib_error("can't allocate memory for the returning value of the view %s",view); + pcilib_error("can't allocate memory for the returning value of the view"); return PCILIB_ERROR_MEMORY; } /* in the case the value of register is between min and max, then we return the correponding enum command*/ @@ -287,15 +280,33 @@ int pcilib_read_view(pcilib_t *ctx, const char *bank, const char *regname, const /** in the other case we ask for a view of type formula. Indeed, wa can't directly ask for a formula, so we have to provide a name for those views*/ j=0; - if(!(strcasecmp(ctx->register_ctx[i].formulas[0].name,view))){ + if(!(strcasecmp(unit, ctx->register_ctx[i].formulas[0].base_unit.name))){ + formula=malloc(sizeof(char)*strlen(ctx->register_ctx[i].formulas[0].read_formula)); + if(!(formula)){ + pcilib_error("can't allocate memory for the formula"); + return PCILIB_ERROR_MEMORY; + } + strncpy(formula,ctx->register_ctx[i].formulas[0].read_formula,strlen(ctx->register_ctx[i].formulas[0].read_formula)); + pcilib_view_apply_formula(ctx,formula,temp_value,value,0); + value_size=sizeof(int); + return 0; + } + + for(j=0; ctx->register_ctx[i].formulas[0].base_unit.other_units[j].name;j++){ + if(!(strcasecmp(ctx->register_ctx[i].formulas[0].base_unit.other_units[j].name,unit))){ /* when we have found the correct view of type formula, we apply the formula, that get the good value for return*/ - formula=malloc(sizeof(char)*strlen(ctx->register_ctx[i].formulas[j].read_formula)); - strncpy(formula,ctx->register_ctx[i].formulas[j].read_formula,strlen(ctx->register_ctx[i].formulas[j].read_formula)); - // pcilib_view_apply_formula(ctx, ctx->register_ctx[i].formulas[j].read_formula,temp_value,value); - pcilib_view_apply_formula(ctx, formula,temp_value,value); + formula=malloc(sizeof(char)*strlen(ctx->register_ctx[i].formulas[0].read_formula)); + if(!(formula)){ + pcilib_error("can't allocate memory for the formula"); + return PCILIB_ERROR_MEMORY; + } + strncpy(formula,ctx->register_ctx[i].formulas[0].read_formula,strlen(ctx->register_ctx[i].formulas[0].read_formula)); + pcilib_view_apply_formula(ctx,formula,temp_value,value,0); + pcilib_view_apply_unit(ctx->register_ctx[i].formulas[0].base_unit.other_units[j],unit,value); value_size=sizeof(int); return 0; } + } pcilib_warning("the view asked and the register do not correspond"); return PCILIB_ERROR_NOTAVAILABLE; @@ -305,11 +316,11 @@ int pcilib_read_view(pcilib_t *ctx, const char *bank, const char *regname, const /** * function to write to a register using a view */ -int pcilib_write_view(pcilib_t *ctx, const char *bank, const char *regname, const char *view, size_t value_size,void* value/*, const char *unit*/){ +int pcilib_write_view(pcilib_t *ctx, const char *bank, const char *regname, const char *unit, size_t value_size,void* value){ int i,j; pcilib_register_value_t temp_value; char *formula; - + /* we get the index of the register to find the corresponding register context*/ if((i=pcilib_find_register(ctx,bank,regname))==PCILIB_REGISTER_INVALID){ pcilib_error("can't get the index of the register %s", regname); @@ -318,28 +329,37 @@ int pcilib_write_view(pcilib_t *ctx, const char *bank, const char *regname, cons /*here, in the case of views of type enum, view will correspond to the enum command. we iterate so through the views of type enum to get the value corresponding to the enum command*/ - for(j=0; ctx->register_ctx[i].enums[j].value;j++){ - if(!(strcasecmp(ctx->register_ctx[i].enums[j].name,view))){ + for(j=0; ctx->register_ctx[i].enums[j].name;j++){ + /* we should maybe have another to do it there*/ + if(!(strcasecmp(ctx->register_ctx[i].enums[j].name,unit))){ pcilib_write_register(ctx,bank,regname,ctx->register_ctx[i].enums[j].value); return 0; } } - + /** in the other case we ask for a view of type formula. Indeed, wa can't directly ask for a formula, so we have to provide a name for those views in view, and the value we want to write in value*/ j=0; - while((ctx->register_ctx[i].formulas[j].name)){ - if(!(strcasecmp(ctx->register_ctx[i].formulas[j].name,view))){ + if(!(strcasecmp(unit, ctx->register_ctx[i].formulas[0].base_unit.name))){ + formula=malloc(sizeof(char)*strlen(ctx->register_ctx[i].formulas[0].write_formula)); + strncpy(formula,ctx->register_ctx[i].formulas[0].write_formula,strlen(ctx->register_ctx[i].formulas[0].write_formula)); + pcilib_view_apply_formula(ctx,formula,*(pcilib_register_value_t*)value,&temp_value,1); + pcilib_write_register(ctx,bank,regname,temp_value); + return 0; + } + + for(j=0; ctx->register_ctx[i].formulas[0].base_unit.other_units[j].name;j++){ + if(!(strcasecmp(ctx->register_ctx[i].formulas[0].base_unit.other_units[j].name,unit))){ /* when we have found the correct view of type formula, we apply the formula, that get the good value for return*/ - formula=malloc(sizeof(char)*strlen(ctx->register_ctx[i].formulas[j].write_formula)); - strncpy(formula,ctx->register_ctx[i].formulas[j].write_formula,strlen(ctx->register_ctx[i].formulas[j].write_formula)); - // pcilib_view_apply_formula(ctx, ctx->register_ctx[i].formulas[j].write_formula,(pcilib_register_value_t*)value,temp_value); - pcilib_view_apply_formula(ctx,formula,*(pcilib_register_value_t*)value,&temp_value); + formula=malloc(sizeof(char)*strlen(ctx->register_ctx[i].formulas[0].write_formula)); + strncpy(formula,ctx->register_ctx[i].formulas[0].write_formula,strlen(ctx->register_ctx[i].formulas[0].write_formula)); + pcilib_view_apply_unit(ctx->register_ctx[i].formulas[0].base_unit.other_units[j],unit,value); + pcilib_view_apply_formula(ctx,formula,*(pcilib_register_value_t*)value,&temp_value,1); + /* we maybe need some error checking there , like temp_value >min and num_formula_views + n + 1) > ctx->alloc_formula_views) { diff --git a/pcilib/views.h b/pcilib/views.h index f186336..33bcf4c 100644 --- a/pcilib/views.h +++ b/pcilib/views.h @@ -38,18 +38,18 @@ struct pcilib_view_formula_s { const char *write_formula; /**units[0].other_units.name[0];i++){ - for(j=0;ctx->units[j].name[0];i++){ - if(!(strcasecmp(myview->units[0].other_units.name,ctx->units[i].name))){ - myview.units=realloc(myview.units,k*sizeof(pcilib_unit_t)); - myview.units[k-1]=ctx->units[i]; - k++; - } - } +pcilib_get_unit_of_view(pcilib_t* ctx,pcilib_view_formula_t* myview, char* base_unit){ + int j; + + for(j=0;ctx->units[j].name;j++){ + if(!(strcasecmp(base_unit,ctx->units[j].name))){ + myview->base_unit=ctx->units[j]; + break; + } } - }*/ + +} /** * get the associated views of a register, to fill its register context @@ -141,7 +141,7 @@ pcilib_get_associated_views(pcilib_t* ctx, const char* reg_name,xmlXPathContextP } /*here it is for formula, i assume we have only one formula view per register*/ - for(k=0; ctx->formula_views[k].name[0];k++){ + for(k=0; ctx->formula_views[k].name;k++){ if(!(strcasecmp(view_name,ctx->formula_views[k].name))){ ctx->register_ctx[id].formulas=malloc(sizeof(pcilib_view_formula_t)); @@ -149,7 +149,7 @@ pcilib_get_associated_views(pcilib_t* ctx, const char* reg_name,xmlXPathContextP pcilib_error("error allocating memory for formula views in register context %i",id); return PCILIB_ERROR_MEMORY; } - + pcilib_get_unit_of_view(ctx,&(ctx->formula_views[k]),ctx->formula_views[k].base_unit.name); ctx->register_ctx[id].formulas[0]=ctx->formula_views[k]; break; } @@ -273,8 +273,6 @@ static int pcilib_xml_parse_register(pcilib_t *ctx, pcilib_xml_register_descript static int pcilib_xml_create_register(pcilib_t *ctx, pcilib_register_bank_t bank, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node) { int err; int views_ok=0; - int h; - xmlXPathObjectPtr nodes; xmlNodeSetPtr nodeset; @@ -507,28 +505,33 @@ static int pcilib_xml_create_bank(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDo return 0; } -/*static int pcilib_xml_create_unit(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node) { +/** + * function to create a unit from a unit xml node, then populating ctx with it + *@param[in,out] ctx - the pcilib_t running + *@param[in] xpath - the xpath context of the unis xml file + *@param[in] doc - the AST of the unit xml file + *@param[in] node - the node representing the unit + *@return an error code: 0 if evrythinh is ok + */ +static int +pcilib_xml_create_unit(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node) { int err; - int override = 0; pcilib_unit_t desc = {0}; xmlNodePtr cur; char *value, *name, *value2; - char *endptr; - xmlXPathObjectPtr nodes; - xmlNodeSetPtr nodeset; xmlAttr *attr; int i=0; - /* we get the attribute type of the view node* + /* we get the attribute type of the view node*/ attr=node->properties; value=(char*)attr->children->content; desc.name=value; desc.other_units=malloc(sizeof(pcilib_transform_unit_t)); for (cur = node->children; cur != NULL; cur = cur->next) { - if (!cur->children) continue; + if (!cur->children) continue; if (!xmlNodeIsText(cur->children)) continue; name = (char*)cur->name; @@ -536,11 +539,12 @@ static int pcilib_xml_create_bank(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDo attr= cur->properties; value2=(char*)attr->children->content; if (!value || !attr) continue; - + if (!strcasecmp(name, "convert_unit")) { - desc.other_units=realloc(des.other_units,sizeof((i+1)*sizeof(pcilib_transform_unit_t))); + desc.other_units=realloc(desc.other_units,(i+1)*sizeof(pcilib_transform_unit_t)); desc.other_units[i].name=value2; desc.other_units[i].transform_formula=value; + i++; } } @@ -552,7 +556,7 @@ static int pcilib_xml_create_bank(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDo return 0; } -*/ + /** * function that create a view from a view node, and populate ctx views list */ @@ -678,8 +682,11 @@ static int pcilib_xml_create_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDo formula_desc.write_formula=value; }else if (!(strcasecmp((char*)name,"description"))) { formula_desc.description=value; + }else if (!(strcasecmp((char*)name,"unit"))){ + formula_desc.base_unit.name=value; } } + err=pcilib_add_views_formula(ctx,1,&formula_desc); if (err) { pcilib_error("Error (%i) adding a new formula view (%s) to the pcilib_t", err, formula_desc.name); @@ -700,17 +707,28 @@ static int pcilib_xml_create_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDo * @param[in] pci the pcilib_t running, which will be filled */ static int pcilib_xml_process_document(pcilib_t *ctx, xmlDocPtr doc, xmlXPathContextPtr xpath) { - xmlXPathObjectPtr bank_nodes,views_nodes; + xmlXPathObjectPtr bank_nodes,views_nodes, units_nodes; xmlNodeSetPtr nodeset; int i; xmlErrorPtr xmlerr; + + units_nodes=xmlXPathEvalExpression(UNITS_PATH,xpath); + if(!units_nodes){ + goto views; + } + + nodeset=units_nodes->nodesetval; + if(!xmlXPathNodeSetIsEmpty(nodeset)){ + for(i=0;i < nodeset->nodeNr; i++){ + pcilib_xml_create_unit(ctx,xpath,doc,nodeset->nodeTab[i]); + } + } + xmlXPathFreeObject(units_nodes); + views: views_nodes=xmlXPathEvalExpression(VIEWS_PATH,xpath); if(!views_nodes){ - xmlerr = xmlGetLastError(); - if (xmlerr) pcilib_error("Failed to parse XPath expression %s, xmlXPathEvalExpression reported error %d - %s", BANKS_PATH, xmlerr->code, xmlerr->message); - else pcilib_error("Failed to parse XPath expression %s", BANKS_PATH); - return PCILIB_ERROR_FAILED; + goto banks; } nodeset=views_nodes->nodesetval; @@ -720,7 +738,7 @@ static int pcilib_xml_process_document(pcilib_t *ctx, xmlDocPtr doc, xmlXPathCon } } xmlXPathFreeObject(views_nodes); - + banks: bank_nodes = xmlXPathEvalExpression(BANKS_PATH, xpath); if (!bank_nodes) { xmlerr = xmlGetLastError(); @@ -850,6 +868,8 @@ int pcilib_process_xml(pcilib_t *ctx, const char *location) { struct dirent *file = NULL; char *model_dir, *model_path; + int i; + model_dir = getenv("PCILIB_MODEL_DIR"); if (!model_dir) model_dir = PCILIB_MODEL_DIR; @@ -870,6 +890,17 @@ int pcilib_process_xml(pcilib_t *ctx, const char *location) { if (err) pcilib_error("Error processing XML file %s", file->d_name); } + for(i=0;inum_formula_views;i++){ + pcilib_get_unit_of_view(ctx,&(ctx->formula_views[i]),ctx->formula_views[i].base_unit.name); + } + + for(i=0;inum_reg;i++){ + if(ctx->register_ctx[i].formulas){ + pcilib_get_unit_of_view(ctx,&(ctx->register_ctx[i].formulas[0]),ctx->register_ctx[i].formulas[0].base_unit.name); + } + } + + closedir(rep); return 0; diff --git a/pcitool/cli.c b/pcitool/cli.c index 6af70e4..bd52270 100644 --- a/pcitool/cli.c +++ b/pcitool/cli.c @@ -1054,7 +1054,7 @@ int ReadRegister(pcilib_t *handle, const pcilib_model_description_t *model_info, s2=pcilib_view_str_sub(reg,0,s1-reg-1); s3=pcilib_view_str_sub(reg,s1-reg+1,strlen(reg)); if(!(strcasecmp(s3,"name"))){ - err = pcilib_read_view(handle,bank,s2,NULL,sizeof(char*),enum_command); + err = pcilib_read_view(handle,bank,s2,NULL,sizeof(char*),enum_command); if (err) printf("Error reading register %s\n", reg); else { printf("%s = %s\n", reg, (char*)enum_command); @@ -1282,11 +1282,17 @@ int WriteRegister(pcilib_t *handle, const pcilib_model_description_t *model_info unsigned long val; pcilib_register_value_t value; + pcilib_register_t regid; const char *format = NULL; - char *s1; - - pcilib_register_t regid = pcilib_find_register(handle, bank, reg); + char *s1,*s2=NULL; + + if((s1=strchr(reg,'/'))){ + s2=pcilib_view_str_sub(reg,0,s1-reg-1); + regid=pcilib_find_register(handle,bank,s2); + }else{ + regid = pcilib_find_register(handle, bank, reg); + } if (regid == PCILIB_REGISTER_INVALID) Error("Can't find register (%s) from bank (%s)", reg, bank?bank:"autodetected"); /* @@ -1316,15 +1322,15 @@ int WriteRegister(pcilib_t *handle, const pcilib_model_description_t *model_info if(err) Error("can't write to the register using an enum view"); else return 0; } - /* } else { + /* should i put strchr not null here? + } else { Error("Can't parse data value (%s) is not valid decimal number", *data); }*/ value = val; if((s1=strchr(reg,'/'))){ - char *s3,*s2; - s2=pcilib_view_str_sub(reg,0,s1-reg-1); + char *s3; s3=pcilib_view_str_sub(reg,s1-reg+1,strlen(reg)); err = pcilib_write_view(handle,bank,s2,s3,sizeof(pcilib_register_value_t),&value); if (err) printf("Error writing register %s using view %s\n",s2,s3); diff --git a/xml/model.xsd b/xml/model.xsd index 5febd1a..cd0b4b0 100644 --- a/xml/model.xsd +++ b/xml/model.xsd @@ -4,8 +4,9 @@ - + + @@ -107,8 +108,29 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/test/camera.xml b/xml/test/camera.xml index bf26d80..ed01014 100644 --- a/xml/test/camera.xml +++ b/xml/test/camera.xml @@ -491,4 +491,38 @@ enum towards cmosis_exp_register register + + + @self+273.15 + @self*(9./5)+32 + + + @self-273.15 + (@self-273.15)*(9./5)+32 + + + (@self-32)*5./9 + (@self+273.15-32)*5./9 + + + @self*1000 + @self*1000000 + @self*1000000000 + + + @self/1000 + @self*1000 + @self*1000000 + + + @self/1000000 + @self/1000 + @self*1000 + + + @self/1000000000 + @self/1000000 + @self/1000 + + -- cgit v1.2.3 From de589562bd91cc60ee3e2d739bdd7a03063d38f7 Mon Sep 17 00:00:00 2001 From: "nicolas.zilio@hotmail.fr" <> Date: Mon, 14 Sep 2015 18:18:00 +0200 Subject: first try with pcilib_operation_t --- pcilib/pci.c | 7 ++-- pcilib/pci.h | 7 ++-- pcilib/views.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- pcilib/views.h | 19 +++++++++- 4 files changed, 132 insertions(+), 8 deletions(-) diff --git a/pcilib/pci.c b/pcilib/pci.c index 2742240..946b003 100644 --- a/pcilib/pci.c +++ b/pcilib/pci.c @@ -140,16 +140,16 @@ pcilib_t *pcilib_open(const char *device, const char *model) { ctx->alloc_reg = PCILIB_DEFAULT_REGISTER_SPACE; ctx->alloc_formula_views=PCILIB_DEFAULT_VIEW_SPACE; + ctx->alloc_views=PCILIB_DEFAULT_VIEW_SPACE; ctx->alloc_enum_views=PCILIB_DEFAULT_VIEW_SPACE; ctx->registers = (pcilib_register_description_t *)malloc(PCILIB_DEFAULT_REGISTER_SPACE * sizeof(pcilib_register_description_t)); ctx->register_ctx = (pcilib_register_context_t *)malloc(PCILIB_DEFAULT_REGISTER_SPACE * sizeof(pcilib_register_context_t)); ctx->enum_views = (pcilib_view_enum2_t *)malloc(PCILIB_DEFAULT_VIEW_SPACE * sizeof(pcilib_view_enum2_t)); ctx->formula_views = (pcilib_view_formula_t*)malloc(PCILIB_DEFAULT_VIEW_SPACE * sizeof(pcilib_view_formula_t)); + ctx->views = (pcilib_view_t*)malloc(PCILIB_DEFAULT_VIEW_SPACE * sizeof(pcilib_view_t)); ctx->alloc_units=PCILIB_DEFAULT_UNIT_SPACE; ctx->units=(pcilib_unit_t*)malloc(PCILIB_DEFAULT_UNIT_SPACE * sizeof(pcilib_unit_t)); - - if ((!ctx->registers)||(!ctx->register_ctx)) { pcilib_error("Error allocating memory for register model"); pcilib_close(ctx); @@ -157,7 +157,7 @@ pcilib_t *pcilib_open(const char *device, const char *model) { } /* i think we need a better error handling here, because, it's not that a problem to not have views working, but how to block the use if the memory here was not good?, and we could have only one type of views that is working*/ - if((!ctx->enum_views)||(!ctx->formula_views) || (!ctx->units)){ + if((!ctx->enum_views)||(!ctx->formula_views) || (!ctx->units) || !(ctx->views)){ pcilib_warning("Error allocating memory for views"); } @@ -172,6 +172,7 @@ pcilib_t *pcilib_open(const char *device, const char *model) { memset(ctx->enum_views,0,sizeof(pcilib_view_enum2_t)); memset(ctx->formula_views,0,sizeof(pcilib_view_formula_t)); memset(ctx->units,0,sizeof(pcilib_unit_t)); + memset(ctx->views,0,sizeof(pcilib_view_t)); for (i = 0; pcilib_protocols[i].api; i++); memcpy(ctx->protocols, pcilib_protocols, i * sizeof(pcilib_register_protocol_description_t)); diff --git a/pcilib/pci.h b/pcilib/pci.h index a62e1cc..d5f1811 100644 --- a/pcilib/pci.h +++ b/pcilib/pci.h @@ -67,6 +67,7 @@ struct pcilib_s { size_t dyn_banks; /**< Number of configured dynamic banks */ size_t num_enum_views,alloc_enum_views; /**< Number of configured and allocated views of type enum*/ size_t num_formula_views,alloc_formula_views; /**< Number of configured and allocated views of type formula*/ + size_t num_views,alloc_views; /**< Number of configured and allocated views*/ size_t num_units,alloc_units; /**< Number of configured and allocated units*/ pcilib_register_description_t *registers; /**< List of currently defined registers (from all sources) */ pcilib_register_bank_description_t banks[PCILIB_MAX_REGISTER_BANKS + 1]; /**< List of currently defined register banks (from all sources) */ @@ -86,9 +87,9 @@ struct pcilib_s { struct pcilib_locking_s locks; /**< Context of locking subsystem */ struct pcilib_xml_s xml; /**< XML context */ - pcilib_view_enum2_t* enum_views; /**< list of currently defined views of type enum*/ - pcilib_view_formula_t* formula_views; /**< list of currently defined views of type formula*/ - + pcilib_view_enum2_t* enum_views; /**< list of currently defined views of type enum*/ + pcilib_view_formula_t* formula_views; /**< list of currently defined views of type formula*/ + pcilib_view_t* views; /**< list of currently defined views*/ pcilib_unit_t* units; /** list of currently defined units*/ #ifdef PCILIB_FILE_IO int file_io_handle; diff --git a/pcilib/views.c b/pcilib/views.c index 1f26b52..9dde46b 100644 --- a/pcilib/views.c +++ b/pcilib/views.c @@ -363,6 +363,84 @@ int pcilib_write_view(pcilib_t *ctx, const char *bank, const char *regname, cons return PCILIB_ERROR_NOTAVAILABLE; } +int operation_enum(pcilib_t *ctx, void *params/*name*/, char* name, int read_or_write, pcilib_register_value_t *regval, size_t viewval_size, void* viewval){ + int j,k; + if(read_or_write==1){ + for(j=0; ((pcilib_view_enum_t*)(params))[j].name;j++){ + if(!(strcasecmp(((pcilib_view_enum_t*)(params))[j].name,(char*)viewval))){ + return j; + } + } + }else if (read_or_write==0){ + for(j=0; ((pcilib_view_enum_t*)(params))[j].name;j++){ + if (*regval<((pcilib_view_enum_t*)(params))[j].max && *regval>((pcilib_view_enum_t*)(params))[j].min){ + viewval=(char*)realloc(viewval,strlen(((pcilib_view_enum_t*)(params))[j].name)*sizeof(char)); + strncpy((char*)viewval,((pcilib_view_enum_t*)(params))[j].name, strlen(((pcilib_view_enum_t*)(params))[j].name)); + k=strlen(((pcilib_view_enum_t*)(params))[j].name); + ((char*)regval)[k]='\0'; + return 0; + } + } + } + return -1; +} + +int operation_formula(pcilib_t *ctx, void *params/*name*/, char* unit, int read_or_write, pcilib_register_value_t *regval, size_t viewval_size, void* viewval){ + int j=0; + char* formula; + pcilib_register_value_t value=0; + + if(read_or_write==0){ + if(!(strcasecmp(unit, ((pcilib_view_t*)viewval)->base_unit.name))){ + formula=malloc(sizeof(char)*strlen(((pcilib_formula_t*)params)->read_formula)); + if(!(formula)){ + pcilib_error("can't allocate memory for the formula"); + return PCILIB_ERROR_MEMORY; + } + strncpy(formula,((pcilib_formula_t*)params)->read_formula,strlen(((pcilib_formula_t*)params)->read_formula)); + pcilib_view_apply_formula(ctx,formula,*regval,&value,0); + return value; + } + + for(j=0; ((pcilib_view_t*)viewval)->base_unit.other_units[j].name;j++){ + if(!(strcasecmp(((pcilib_view_t*)viewval)->base_unit.other_units[j].name,unit))){ + /* when we have found the correct view of type formula, we apply the formula, that get the good value for return*/ + formula=malloc(sizeof(char)*strlen(((pcilib_formula_t*)params)->read_formula)); + if(!(formula)){ + pcilib_error("can't allocate memory for the formula"); + return PCILIB_ERROR_MEMORY; + } + strncpy(formula,((pcilib_formula_t*)params)->read_formula,strlen(((pcilib_formula_t*)params)->read_formula)); + pcilib_view_apply_formula(ctx,formula, *regval,&value,0); + pcilib_view_apply_unit(((pcilib_view_t*)viewval)->base_unit.other_units[j],unit,&value); + return value; + } + } + }else if(read_or_write==1){ + j=0; + 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)); + pcilib_view_apply_formula(ctx,formula,*regval,&value,1); + return 0; + } + + for(j=0;((pcilib_view_t*)viewval)->base_unit.other_units[j].name;j++){ + if(!(strcasecmp(((pcilib_view_t*)viewval)->base_unit.other_units[j].name,unit))){ + /* when we have found the correct view of type formula, we apply the formula, that get the good value for return*/ + 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)); + pcilib_view_apply_unit(((pcilib_view_t*)viewval)->base_unit.other_units[j],unit,&value); + pcilib_view_apply_formula(ctx,formula,*regval,&value,1); + /* we maybe need some error checking there , like temp_value >min and formula_views + ctx->num_formula_views + n, 0, sizeof(pcilib_view_formula_t)); ctx->num_formula_views += n; - + return 0; +} + +/** + * function to populate ctx views, as we could do for registers or banks + */ +int pcilib_add_views(pcilib_t *ctx, size_t n, const pcilib_view_t* views) { + + pcilib_view_t *views2; + size_t size; + + if (!n) { + for (n = 0; views[n].name; n++); + } + + if ((ctx->num_views + n + 1) > ctx->alloc_views) { + for (size = ctx->alloc_views; size < 2 * (n + ctx->num_views + 1); size<<=1); + + views2 = (pcilib_view_t*)realloc(ctx->views, size * sizeof(pcilib_view_t)); + if (!views2) return PCILIB_ERROR_MEMORY; + + ctx->views = views2; + ctx->alloc_views = size; + } + + memcpy(ctx->views + ctx->num_views, views, n * sizeof(pcilib_view_t)); + memset(ctx->views + ctx->num_views + n, 0, sizeof(pcilib_view_t)); + ctx->num_views += n; return 0; } diff --git a/pcilib/views.h b/pcilib/views.h index 33bcf4c..c7dee6b 100644 --- a/pcilib/views.h +++ b/pcilib/views.h @@ -10,6 +10,12 @@ typedef struct pcilib_view_formula_s pcilib_view_formula_t; typedef struct pcilib_view_enum2_s pcilib_view_enum2_t; +typedef struct pcilib_view_s pcilib_view_t; + +typedef struct pcilib_formula_s pcilib_formula_t; + +typedef int (*pcilib_view_operation_t)(pcilib_t *ctx, void *params, char* string, int read_or_write, pcilib_register_value_t *regval, size_t viewval_size, void* viewval); + /** * new type to define an enum view */ @@ -18,6 +24,10 @@ struct pcilib_view_enum_s { pcilib_register_value_t value, min, max; }; +struct pcilib_formula_s{ + char* read_formula; + char* write_formula; +}; /** * complete type for an enum view : name will be changed after with the previous one @@ -28,7 +38,14 @@ struct pcilib_view_enum2_s { const char* description; }; - +struct pcilib_view_s{ + const char* name; + const char* description; + pcilib_view_operation_t op; + void* parameters; + pcilib_unit_t base_unit; +}; + /** * new type to define a formula view */ -- cgit v1.2.3 From aaadfff471f02444b2936d824b055e2354b6c725 Mon Sep 17 00:00:00 2001 From: "nicolas.zilio@hotmail.fr" <> Date: Mon, 14 Sep 2015 19:52:48 +0200 Subject: just crap --- pcilib/views.c | 41 +++++++++++++++++++++++++++++++++-------- xml/model.xsd | 2 +- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/pcilib/views.c b/pcilib/views.c index 9dde46b..0e3d26d 100644 --- a/pcilib/views.c +++ b/pcilib/views.c @@ -320,17 +320,40 @@ int pcilib_write_view(pcilib_t *ctx, const char *bank, const char *regname, cons int i,j; pcilib_register_value_t temp_value; char *formula; + int err; /* we get the index of the register to find the corresponding register context*/ if((i=pcilib_find_register(ctx,bank,regname))==PCILIB_REGISTER_INVALID){ pcilib_error("can't get the index of the register %s", regname); return PCILIB_ERROR_INVALID_REQUEST; } - + + for(j=0;ctx>register_ctx[i].views[j].name;j++){ + if(!(strcasecmp(ctx->register_ctx[i].views[j].base_unit,unit))){ + err=ctx->register_ctx[i].views[j].op(ctx,ctx->register_ctx[i].views[j].parameters,unit,1,&temp_value,value); + temp_value=ctx->register_ctx[i].views[value].value; + if(err){ + pcilib_error("can't write to the register with the enum view"); + return PCILIB_ERROR_FAILED; + } + break; + }else if(!(strcasecmp(ctx->register_ctx[i].views[j].name,unit))){ + err=ctx->register_ctx[i].views[j].op(ctx,ctx->register_ctx[i].views[j].parameters, unit, 1, &temp_value,0,&(ctx->register_ctx[i].views[j])); + if(err){ + pcilib_error("can't write to the register with the formula view %s", unit); + return PCILIB_ERROR_FAILED; + } + break; + } + pcilib_write_register(ctx,bank,regname,temp_value); + return 0; + } + + /*here, in the case of views of type enum, view will correspond to the enum command. - we iterate so through the views of type enum to get the value corresponding to the enum command*/ + we iterate so through the views of type enum to get the value corresponding to the enum command* for(j=0; ctx->register_ctx[i].enums[j].name;j++){ - /* we should maybe have another to do it there*/ + /* we should maybe have another to do it there* if(!(strcasecmp(ctx->register_ctx[i].enums[j].name,unit))){ pcilib_write_register(ctx,bank,regname,ctx->register_ctx[i].enums[j].value); return 0; @@ -338,7 +361,7 @@ int pcilib_write_view(pcilib_t *ctx, const char *bank, const char *regname, cons } /** in the other case we ask for a view of type formula. Indeed, wa can't directly ask for a formula, so we have to provide a name for those views in view, and the value we want to write in value*/ - j=0; + /* j=0; if(!(strcasecmp(unit, ctx->register_ctx[i].formulas[0].base_unit.name))){ formula=malloc(sizeof(char)*strlen(ctx->register_ctx[i].formulas[0].write_formula)); strncpy(formula,ctx->register_ctx[i].formulas[0].write_formula,strlen(ctx->register_ctx[i].formulas[0].write_formula)); @@ -349,20 +372,21 @@ int pcilib_write_view(pcilib_t *ctx, const char *bank, const char *regname, cons for(j=0; ctx->register_ctx[i].formulas[0].base_unit.other_units[j].name;j++){ if(!(strcasecmp(ctx->register_ctx[i].formulas[0].base_unit.other_units[j].name,unit))){ - /* when we have found the correct view of type formula, we apply the formula, that get the good value for return*/ + /* when we have found the correct view of type formula, we apply the formula, that get the good value for return* formula=malloc(sizeof(char)*strlen(ctx->register_ctx[i].formulas[0].write_formula)); strncpy(formula,ctx->register_ctx[i].formulas[0].write_formula,strlen(ctx->register_ctx[i].formulas[0].write_formula)); pcilib_view_apply_unit(ctx->register_ctx[i].formulas[0].base_unit.other_units[j],unit,value); pcilib_view_apply_formula(ctx,formula,*(pcilib_register_value_t*)value,&temp_value,1); - /* we maybe need some error checking there , like temp_value >min and min and - + -- cgit v1.2.3 From 6a8b4a516689daa34951ccca841c2a4f57412b0e Mon Sep 17 00:00:00 2001 From: "nicolas.zilio@hotmail.fr" <> Date: Tue, 15 Sep 2015 09:34:52 +0200 Subject: first compil ok with addition of generic views --- pcilib/register.h | 1 + pcilib/views.c | 153 ++++++++++++++++-------------------------------------- pcilib/views.h | 7 ++- pcilib/xml.c | 140 +++++++++++++++++++------------------------------ 4 files changed, 106 insertions(+), 195 deletions(-) diff --git a/pcilib/register.h b/pcilib/register.h index 5669237..2f6334c 100644 --- a/pcilib/register.h +++ b/pcilib/register.h @@ -50,6 +50,7 @@ typedef struct { pcilib_xml_node_t *xml; /**< Additional XML properties */ pcilib_view_formula_t *formulas; /**< list of views of type formula linked to this register*/ pcilib_view_enum_t *enums; /**< list of views of type enum linked to this register*/ + pcilib_view_t *views; /** list of views linked to this register*/ } pcilib_register_context_t; diff --git a/pcilib/views.c b/pcilib/views.c index 0e3d26d..2a0969c 100644 --- a/pcilib/views.c +++ b/pcilib/views.c @@ -242,7 +242,6 @@ int pcilib_read_view(pcilib_t *ctx, const char *bank, const char *regname, const { int i,j,err=0; pcilib_register_value_t temp_value; - char* formula; /* we get the index of the register to find the corresponding register context*/ if((i=pcilib_find_register(ctx,bank,regname))==PCILIB_REGISTER_INVALID){ @@ -256,59 +255,27 @@ int pcilib_read_view(pcilib_t *ctx, const char *bank, const char *regname, const pcilib_error("can't read the register %s value before applying views : error %i",regname); return PCILIB_ERROR_INVALID_REQUEST; } - /*in the case we don't ask for a view's name, we know it will be for views of type enum. Especially, it's faster to search directly on the values of those views instead of a given name. - we iterate so through the views of type enum to verify if the value we have corresponds to an enum command*/ - if(!(unit)){ - for(j=0; ctx->register_ctx[i].enums[j].value;j++){ - if((temp_value >= ctx->register_ctx[i].enums[j].min) && (temp_value <= ctx->register_ctx[i].enums[j].max)){ - value_size=strlen(ctx->register_ctx[i].enums[j].name)*sizeof(char); - value=(char*)realloc(value,sizeof(value_size)); - if(!(value)){ - pcilib_error("can't allocate memory for the returning value of the view"); - return PCILIB_ERROR_MEMORY; + + for(j=0;ctx->register_ctx[i].views[j].name;j++){ + if(!(strcasecmp(ctx->register_ctx[i].views[j].base_unit.name,unit))){/*if we asked for the unit "name"*/ + err=ctx->register_ctx[i].views[j].op(ctx,ctx->register_ctx[i].views[j].parameters,value/*the command name*/,0,&temp_value,0,&(ctx->register_ctx[i].views[j])); + if(err){ + pcilib_error("can't write to the register with the enum view"); + return PCILIB_ERROR_FAILED; } - /* in the case the value of register is between min and max, then we return the correponding enum command*/ - strncpy((char*)value,ctx->register_ctx[i].enums[j].name, strlen(ctx->register_ctx[i].enums[j].name)); - /* make sure the string is correctly terminated*/ - ((char*)value)[value_size]='\0'; - return 0; - } - } - pcilib_warning("the value of the register asked do not correspond to any enum views"); - return PCILIB_ERROR_NOTAVAILABLE; - } - - /** in the other case we ask for a view of type formula. Indeed, wa can't directly ask for a formula, so we have to provide a name for those views*/ - j=0; - if(!(strcasecmp(unit, ctx->register_ctx[i].formulas[0].base_unit.name))){ - formula=malloc(sizeof(char)*strlen(ctx->register_ctx[i].formulas[0].read_formula)); - if(!(formula)){ - pcilib_error("can't allocate memory for the formula"); - return PCILIB_ERROR_MEMORY; + break; + }else if(!(strcasecmp(ctx->register_ctx[i].views[j].name,(char*)unit))){/*in this case we asked for the name of the view in unit*/ + err=ctx->register_ctx[i].views[j].op(ctx,ctx->register_ctx[i].views[j].parameters,(char*)unit, 0, &temp_value,0,&(ctx->register_ctx[i].views[j])); + if(err){ + pcilib_error("can't write to the register with the formula view %s", unit); + return PCILIB_ERROR_FAILED; } - strncpy(formula,ctx->register_ctx[i].formulas[0].read_formula,strlen(ctx->register_ctx[i].formulas[0].read_formula)); - pcilib_view_apply_formula(ctx,formula,temp_value,value,0); - value_size=sizeof(int); - return 0; - } - - for(j=0; ctx->register_ctx[i].formulas[0].base_unit.other_units[j].name;j++){ - if(!(strcasecmp(ctx->register_ctx[i].formulas[0].base_unit.other_units[j].name,unit))){ - /* when we have found the correct view of type formula, we apply the formula, that get the good value for return*/ - formula=malloc(sizeof(char)*strlen(ctx->register_ctx[i].formulas[0].read_formula)); - if(!(formula)){ - pcilib_error("can't allocate memory for the formula"); - return PCILIB_ERROR_MEMORY; + *(pcilib_register_value_t*)value=temp_value; + break; } - strncpy(formula,ctx->register_ctx[i].formulas[0].read_formula,strlen(ctx->register_ctx[i].formulas[0].read_formula)); - pcilib_view_apply_formula(ctx,formula,temp_value,value,0); - pcilib_view_apply_unit(ctx->register_ctx[i].formulas[0].base_unit.other_units[j],unit,value); - value_size=sizeof(int); - return 0; + return 0; } - } - - pcilib_warning("the view asked and the register do not correspond"); + pcilib_error("the view asked and the register do not correspond"); return PCILIB_ERROR_NOTAVAILABLE; } @@ -319,7 +286,6 @@ int pcilib_read_view(pcilib_t *ctx, const char *bank, const char *regname, const int pcilib_write_view(pcilib_t *ctx, const char *bank, const char *regname, const char *unit, size_t value_size,void* value){ int i,j; pcilib_register_value_t temp_value; - char *formula; int err; /* we get the index of the register to find the corresponding register context*/ @@ -328,17 +294,17 @@ int pcilib_write_view(pcilib_t *ctx, const char *bank, const char *regname, cons return PCILIB_ERROR_INVALID_REQUEST; } - for(j=0;ctx>register_ctx[i].views[j].name;j++){ - if(!(strcasecmp(ctx->register_ctx[i].views[j].base_unit,unit))){ - err=ctx->register_ctx[i].views[j].op(ctx,ctx->register_ctx[i].views[j].parameters,unit,1,&temp_value,value); - temp_value=ctx->register_ctx[i].views[value].value; + for(j=0;ctx->register_ctx[i].views[j].name;j++){ + if(!(strcasecmp(ctx->register_ctx[i].views[j].base_unit.name,unit))){/*if we asked for the unit "name"*/ + err=ctx->register_ctx[i].views[j].op(ctx,ctx->register_ctx[i].views[j].parameters,value/*the command name*/,1,&temp_value,0,&(ctx->register_ctx[i].views[j])); if(err){ pcilib_error("can't write to the register with the enum view"); return PCILIB_ERROR_FAILED; } break; - }else if(!(strcasecmp(ctx->register_ctx[i].views[j].name,unit))){ - err=ctx->register_ctx[i].views[j].op(ctx,ctx->register_ctx[i].views[j].parameters, unit, 1, &temp_value,0,&(ctx->register_ctx[i].views[j])); + }else if(!(strcasecmp(ctx->register_ctx[i].views[j].name,(char*)unit))){/*in this case we asked for then name of the view in unit*/ + temp_value=*(pcilib_register_value_t*)value /*the value to put in the register*/; + err=ctx->register_ctx[i].views[j].op(ctx,ctx->register_ctx[i].views[j].parameters, (char*)unit, 1, &temp_value,0,&(ctx->register_ctx[i].views[j])); if(err){ pcilib_error("can't write to the register with the formula view %s", unit); return PCILIB_ERROR_FAILED; @@ -349,73 +315,46 @@ int pcilib_write_view(pcilib_t *ctx, const char *bank, const char *regname, cons return 0; } - - /*here, in the case of views of type enum, view will correspond to the enum command. - we iterate so through the views of type enum to get the value corresponding to the enum command* - for(j=0; ctx->register_ctx[i].enums[j].name;j++){ - /* we should maybe have another to do it there* - if(!(strcasecmp(ctx->register_ctx[i].enums[j].name,unit))){ - pcilib_write_register(ctx,bank,regname,ctx->register_ctx[i].enums[j].value); - return 0; - } - } - - /** in the other case we ask for a view of type formula. Indeed, wa can't directly ask for a formula, so we have to provide a name for those views in view, and the value we want to write in value*/ - /* j=0; - if(!(strcasecmp(unit, ctx->register_ctx[i].formulas[0].base_unit.name))){ - formula=malloc(sizeof(char)*strlen(ctx->register_ctx[i].formulas[0].write_formula)); - strncpy(formula,ctx->register_ctx[i].formulas[0].write_formula,strlen(ctx->register_ctx[i].formulas[0].write_formula)); - pcilib_view_apply_formula(ctx,formula,*(pcilib_register_value_t*)value,&temp_value,1); - pcilib_write_register(ctx,bank,regname,temp_value); - return 0; - } - - for(j=0; ctx->register_ctx[i].formulas[0].base_unit.other_units[j].name;j++){ - if(!(strcasecmp(ctx->register_ctx[i].formulas[0].base_unit.other_units[j].name,unit))){ - /* when we have found the correct view of type formula, we apply the formula, that get the good value for return* - formula=malloc(sizeof(char)*strlen(ctx->register_ctx[i].formulas[0].write_formula)); - strncpy(formula,ctx->register_ctx[i].formulas[0].write_formula,strlen(ctx->register_ctx[i].formulas[0].write_formula)); - pcilib_view_apply_unit(ctx->register_ctx[i].formulas[0].base_unit.other_units[j],unit,value); - pcilib_view_apply_formula(ctx,formula,*(pcilib_register_value_t*)value,&temp_value,1); - /* we maybe need some error checking there , like temp_value >min and ((pcilib_view_enum_t*)(params))[j].min){ - viewval=(char*)realloc(viewval,strlen(((pcilib_view_enum_t*)(params))[j].name)*sizeof(char)); - strncpy((char*)viewval,((pcilib_view_enum_t*)(params))[j].name, strlen(((pcilib_view_enum_t*)(params))[j].name)); + name=(char*)realloc(name,strlen(((pcilib_view_enum_t*)(params))[j].name)*sizeof(char)); + strncpy(name,((pcilib_view_enum_t*)(params))[j].name, strlen(((pcilib_view_enum_t*)(params))[j].name)); k=strlen(((pcilib_view_enum_t*)(params))[j].name); - ((char*)regval)[k]='\0'; + name[k]='\0'; return 0; } } } - return -1; + return PCILIB_ERROR_INVALID_REQUEST; } -/** viewsval=the current view, params=current view parameters*/ -int operation_formula(pcilib_t *ctx, void *params/*name*/, char* unit, int read_or_write, pcilib_register_value_t *regval, size_t viewval_size, void* viewval){ +/** + * pârams: view params unit=unit wanted regval:value before formula/after formula viewval=view + */ +int operation_formula(pcilib_t *ctx, void *params, char* unit, int view2reg, pcilib_register_value_t *regval, size_t viewval_size, void* viewval){ int j=0; - char* formula; pcilib_register_value_t value=0; + char* formula; - if(read_or_write==0){ + if(view2reg==0){ if(!(strcasecmp(unit, ((pcilib_view_t*)viewval)->base_unit.name))){ formula=malloc(sizeof(char)*strlen(((pcilib_formula_t*)params)->read_formula)); if(!(formula)){ @@ -441,8 +380,7 @@ int operation_formula(pcilib_t *ctx, void *params/*name*/, char* unit, int read_ return value; } } - }else if(read_or_write==1){ - j=0; + }else if(view2reg==1){ 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)); @@ -457,12 +395,13 @@ int operation_formula(pcilib_t *ctx, void *params/*name*/, char* unit, int read_ strncpy(formula,((pcilib_formula_t*)params)->write_formula,strlen((( pcilib_formula_t*)params)->write_formula)); pcilib_view_apply_unit(((pcilib_view_t*)viewval)->base_unit.other_units[j],unit,&value); pcilib_view_apply_formula(ctx,formula,*regval,&value,1); + *regval=value; /* we maybe need some error checking there , like temp_value >min and units[j].name;j++){ - if(!(strcasecmp(base_unit,ctx->units[j].name))){ - myview->base_unit=ctx->units[j]; - break; + if((strcasecmp(base_unit,"name"))){ + for(j=0;ctx->units[j].name;j++){ + if(!(strcasecmp(base_unit,ctx->units[j].name))){ + myview->base_unit=ctx->units[j]; + break; + } + } } - } - } /** @@ -114,44 +114,23 @@ pcilib_get_associated_views(pcilib_t* ctx, const char* reg_name,xmlXPathContextP else sprintf(path,VIEWS_NAME_PATH_BITS,reg_name); nodes = xmlXPathEvalExpression((xmlChar*)path, xpath); nodeset = nodes->nodesetval; + ctx->register_ctx[id].views=malloc(sizeof(pcilib_view_t)); + if(!(ctx->register_ctx[id].views)){ + pcilib_error("error allocating memory for enum views in register context %i",id); + return PCILIB_ERROR_MEMORY; + } + if (!xmlXPathNodeSetIsEmpty(nodeset)) { - int i,k,l; + int i,k; /*if we correctly get a nodeset, then we iterate through the nodeset to get all views, using their names*/ for (i = 0; i < nodeset->nodeNr; i++) { view_name=(char*)nodeset->nodeTab[i]->children->content; /* if the view name obtained is for an enum view, we get all pcilib_view_enum_t corresponding to the register*/ - for(k=0; ctx->enum_views[k].enums_list[0].value; k++){ - if(!(strcasecmp(view_name, ctx->enum_views[k].name))){ - ctx->register_ctx[id].enums=malloc(sizeof(pcilib_view_enum_t)); - - if(!(ctx->register_ctx[id].enums)){ - pcilib_error("error allocating memory for enum views in register context %i",id); - return PCILIB_ERROR_MEMORY; - } - - /*!!!!!!!!!!this loop here is buggy*/ - for(l=0; ctx->enum_views[k].enums_list[l].value;l++){ - ctx->register_ctx[id].enums=realloc(ctx->register_ctx[id].enums,(l+1)*sizeof(pcilib_view_enum_t)); - ctx->register_ctx[id].enums[l]=ctx->enum_views[k].enums_list[l]; - // printf("names %s %s\n",ctx->register_ctx[id].enums[l].name,ctx->enum_views[k].enums_list[l].name); - } - return 0; - } - } - - /*here it is for formula, i assume we have only one formula view per register*/ - for(k=0; ctx->formula_views[k].name;k++){ - if(!(strcasecmp(view_name,ctx->formula_views[k].name))){ - - ctx->register_ctx[id].formulas=malloc(sizeof(pcilib_view_formula_t)); - if(!(ctx->register_ctx[id].formulas)){ - pcilib_error("error allocating memory for formula views in register context %i",id); - return PCILIB_ERROR_MEMORY; - } - pcilib_get_unit_of_view(ctx,&(ctx->formula_views[k]),ctx->formula_views[k].base_unit.name); - ctx->register_ctx[id].formulas[0]=ctx->formula_views[k]; - break; + for(k=0; ctx->views[k].name; k++){ + if(!(strcasecmp(view_name, ctx->views[k].name))){ + ctx->register_ctx[id].views=realloc(ctx->register_ctx[id].views,(k+1)*sizeof(pcilib_view_enum_t)); + ctx->register_ctx[id].views[k]=ctx->views[k]; } } @@ -563,9 +542,7 @@ pcilib_xml_create_unit(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, x static int pcilib_xml_create_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node) { int err; - pcilib_view_enum2_t complete_enum_desc={0}; - pcilib_view_enum_t enum_desc = {0}; - pcilib_view_formula_t formula_desc= {0}; + pcilib_view_t desc={0}; xmlNodePtr cur; char *value, *name; char *endptr; @@ -573,32 +550,17 @@ static int pcilib_xml_create_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDo int i=0; int ok_min=0, ok_max=0; - /*must i initialize? i think it's only needed if we want to include a description property*/ - enum_desc.name="default"; - enum_desc.value=0; - enum_desc.min=0; - enum_desc.max=0; - - complete_enum_desc.name="default enum"; - complete_enum_desc.description="default description"; - complete_enum_desc.enums_list=malloc(sizeof(pcilib_view_enum_t)); - if(!(complete_enum_desc.enums_list)){ - pcilib_error("can't allocate memory for the complete enum type"); - return PCILIB_ERROR_MEMORY; - } - complete_enum_desc.enums_list[0]=enum_desc; - - formula_desc.name="formula_default"; - formula_desc.read_formula="@reg"; - formula_desc.write_formula="@reg"; - formula_desc.description="default description"; - + desc.description="default description"; + /* we get the attribute type of the view node*/ attr=node->properties; value=(char*)attr->children->content; /* regarding the architecture, i decided to follow what has been done for registers and banks. but without the context*/ /*if the view is of type enum, we get recursively its properties and then populate ctx enum views*/ if(!(strcasecmp(value,"enum"))){ + desc.op=&operation_enum; + desc.parameters=malloc(sizeof(pcilib_view_enum_t)); + desc.base_unit.name="name"; for (cur = node->children; cur != NULL; cur = cur->next) { if (!cur->children) continue; if (!xmlNodeIsText(cur->children)) continue; @@ -608,15 +570,15 @@ static int pcilib_xml_create_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDo if (!value) continue; if (!(strcasecmp((char*)name,"name"))) { - complete_enum_desc.name = value; + desc.name = value; }else if (!(strcasecmp((char*)name,"description"))) { - complete_enum_desc.description = value; + desc.description = value; }else if (!(strcasecmp((char*)name,"enum"))) { - complete_enum_desc.enums_list=realloc(complete_enum_desc.enums_list,(i+1)*sizeof(pcilib_view_enum_t)); - complete_enum_desc.enums_list[i].name=value; + desc.parameters=realloc(desc.parameters,(i+1)*sizeof(pcilib_view_enum_t)); + ((pcilib_view_enum_t*)(desc.parameters))[i].name=value; /* we need to iterate through the different attributes of an enum node to get all properties*/ for(attr=cur->properties; attr!=NULL;attr=attr->next){ @@ -632,14 +594,14 @@ static int pcilib_xml_create_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDo pcilib_error("Invalid value (%s) is specified in the XML enum node", value); return PCILIB_ERROR_INVALID_DATA; } - complete_enum_desc.enums_list[i].value=dat_value; + ((pcilib_view_enum_t*)(desc.parameters))[i].value=dat_value; }else if(!(strcasecmp(name,"min"))){ pcilib_register_value_t dat_min = strtol(value, &endptr, 0); if ((strlen(endptr) > 0)) { pcilib_error("Invalid min (%s) is specified in the XML enum node", value); return PCILIB_ERROR_INVALID_DATA; } - complete_enum_desc.enums_list[i].min=dat_min; + ((pcilib_view_enum_t*)(desc.parameters))[i].min=dat_min; ok_min=1; }else if(!(strcasecmp(name,"max"))){ pcilib_register_value_t dat_max = strtol(value, &endptr, 0); @@ -647,24 +609,26 @@ static int pcilib_xml_create_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDo pcilib_error("Invalid max (%s) is specified in the XML enum node", value); return PCILIB_ERROR_INVALID_DATA; } - complete_enum_desc.enums_list[i].max=dat_max; + ((pcilib_view_enum_t*)(desc.parameters))[i].max=dat_max; ok_max=1; } - if(ok_min==0) complete_enum_desc.enums_list[i].min=complete_enum_desc.enums_list[i].value; - if(ok_max==0) complete_enum_desc.enums_list[i].max=complete_enum_desc.enums_list[i].value; + if(ok_min==0) ((pcilib_view_enum_t*)(desc.parameters))[i].min=((pcilib_view_enum_t*)(desc.parameters))[i].value; + if(ok_max==0) ((pcilib_view_enum_t*)(desc.parameters))[i].max=((pcilib_view_enum_t*)(desc.parameters))[i].value; } i++; } } - err=pcilib_add_views_enum(ctx,1,&complete_enum_desc); + err=pcilib_add_views(ctx,1,&desc); if (err) { - pcilib_error("Error (%i) adding a new enum view (%s) to the pcilib_t", err, complete_enum_desc.name); + pcilib_error("Error (%i) adding a new enum view (%s) to the pcilib_t", err, desc.name); return err; } /* we do the same here but for a iew of type formula if the attribute gives formula*/ }else if(!(strcasecmp(value,"formula"))){ + desc.op=&operation_formula; + desc.parameters=malloc(sizeof(pcilib_formula_t)); for (cur = node->children; cur != NULL; cur = cur->next) { if (!cur->children) continue; if (!xmlNodeIsText(cur->children)) continue; @@ -675,21 +639,21 @@ static int pcilib_xml_create_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDo if (!value) continue; if (!(strcasecmp((char*)name,"name"))) { - formula_desc.name = value; + desc.name = value; }else if (!(strcasecmp((char*)name,"read_from_register"))) { - formula_desc.read_formula=value; + ((pcilib_formula_t*)(desc.parameters))->read_formula=value; }else if (!(strcasecmp((char*)name,"write_to_register"))) { - formula_desc.write_formula=value; + ((pcilib_formula_t*)(desc.parameters))->write_formula=value; }else if (!(strcasecmp((char*)name,"description"))) { - formula_desc.description=value; + desc.description=value; }else if (!(strcasecmp((char*)name,"unit"))){ - formula_desc.base_unit.name=value; + desc.base_unit.name=value; } } - err=pcilib_add_views_formula(ctx,1,&formula_desc); + err=pcilib_add_views(ctx,1,&desc); if (err) { - pcilib_error("Error (%i) adding a new formula view (%s) to the pcilib_t", err, formula_desc.name); + pcilib_error("Error (%i) adding a new formula view (%s) to the pcilib_t", err, desc.name); return err; } @@ -868,7 +832,7 @@ int pcilib_process_xml(pcilib_t *ctx, const char *location) { struct dirent *file = NULL; char *model_dir, *model_path; - int i; + int i,j; model_dir = getenv("PCILIB_MODEL_DIR"); if (!model_dir) model_dir = PCILIB_MODEL_DIR; @@ -890,16 +854,18 @@ int pcilib_process_xml(pcilib_t *ctx, const char *location) { if (err) pcilib_error("Error processing XML file %s", file->d_name); } - for(i=0;inum_formula_views;i++){ - pcilib_get_unit_of_view(ctx,&(ctx->formula_views[i]),ctx->formula_views[i].base_unit.name); + for(i=0;inum_views;i++){ + pcilib_get_unit_of_view(ctx,&(ctx->views[i]),ctx->views[i].base_unit.name); } for(i=0;inum_reg;i++){ - if(ctx->register_ctx[i].formulas){ - pcilib_get_unit_of_view(ctx,&(ctx->register_ctx[i].formulas[0]),ctx->register_ctx[i].formulas[0].base_unit.name); + for(j=0;jnum_views;j++){ + if(!(ctx->register_ctx[i].views[j].name)) break; + if(ctx->register_ctx[i].views){ + pcilib_get_unit_of_view(ctx,&(ctx->register_ctx[i].views[j]),ctx->register_ctx[i].views[j].base_unit.name); + } } } - closedir(rep); -- cgit v1.2.3 From c71075ca84d896c650dd0b65c7664149ed51dcec Mon Sep 17 00:00:00 2001 From: "nicolas.zilio@hotmail.fr" <> Date: Tue, 15 Sep 2015 11:36:20 +0200 Subject: addition of other remarks, cleaning in progress --- pcilib/unit.h | 4 +- pcilib/views.c | 233 ++++++++++++++++++++------------------------------------- pcilib/xml.c | 3 +- pcitool/cli.c | 52 +++++++------ 4 files changed, 114 insertions(+), 178 deletions(-) diff --git a/pcilib/unit.h b/pcilib/unit.h index f9991f1..4a99f5b 100644 --- a/pcilib/unit.h +++ b/pcilib/unit.h @@ -3,6 +3,8 @@ #include "pcilib.h" +#define PCILIB_MAX_TRANSFORMS_PER_UNIT 16 + typedef struct pcilib_unit_s pcilib_unit_t; typedef struct pcilib_transform_unit_s pcilib_transform_unit_t; @@ -19,7 +21,7 @@ struct pcilib_transform_unit_s{ */ struct pcilib_unit_s{ char* name; - pcilib_transform_unit_t* other_units; + pcilib_transform_unit_t other_units[PCILIB_MAX_TRANSFORMS_PER_UNIT]; }; /** diff --git a/pcilib/views.c b/pcilib/views.c index 2a0969c..86675f5 100644 --- a/pcilib/views.c +++ b/pcilib/views.c @@ -8,73 +8,6 @@ #include #include "unit.h" -/** - * - * replace a substring within a string by another - * @param[in] txt - the string to be modified - *@param[in] before - the substring in the string that will be replaced - *@param[in] after - the new value of before substring - *@return the modified txt string - */ -static char* -pcilib_view_formula_replace (const char *txt, const char *before, const char *after) -{ - const char *pos; - char *return_txt; - size_t pos_return_txt; - size_t len; - size_t allocated_size; - - /*get the first occurence of before. then we need one time to be out of the loop to correctly set the diverses varaibles (malloc instead of realloc notably)*/ - pos = strstr (txt, before); - - if (pos == NULL) - { - pcilib_warning("problem with a formula"); - } - - /* get the position of this occurence*/ - len = (size_t)pos - (size_t)txt; - allocated_size = len + strlen (after) + 1; - return_txt = malloc (allocated_size); - pos_return_txt = 0; - - /* we copy there the in a newly allocated string the start of txt before the "before" occurence, and then we copy after instead*/ - strncpy (return_txt + pos_return_txt, txt, len); - pos_return_txt += len; - txt = pos + strlen (before); - - len = strlen (after); - strncpy (return_txt + pos_return_txt, after, len); - pos_return_txt += len; - - /* we then iterate with the same principle to all occurences of before*/ - pos = strstr (txt, before); - while (pos != NULL) - { - len = (size_t)pos - (size_t)txt; - allocated_size += len + strlen (after); - return_txt = (char *)realloc (return_txt, allocated_size); - - strncpy (return_txt + pos_return_txt, txt, len); - pos_return_txt += len; - - txt = pos + strlen (before); - - len = strlen (after); - strncpy (return_txt + pos_return_txt, after, len); - pos_return_txt += len; - pos = strstr (txt, before); - } - /* put the rest of txt string at the end*/ - len = strlen (txt) + 1; - allocated_size += len; - return_txt = realloc (return_txt, allocated_size); - strncpy (return_txt + pos_return_txt, txt, len); - - return return_txt; -} - /** * function used to get the substring of a string s, from the starting and ending indexes * @param[in] s string containing the substring we want to extract. @@ -110,62 +43,6 @@ pcilib_view_str_sub (const char *s, unsigned int start, unsigned int end) } -/** - * get the bank name associated with a register name - */ -static const char* -pcilib_view_get_bank_from_reg_name(pcilib_t* ctx,char* reg_name){ - int k; - for(k=0;ctx->registers[k].bits;k++){ - if(!(strcasecmp(reg_name,ctx->registers[k].name))){ - return ctx->banks[pcilib_find_register_bank_by_addr(ctx,ctx->registers[k].bank)].name; - } - } - return NULL; -} - -/** - * replace plain registers name in a formula by their value - */ -static char* -pcilib_view_compute_plain_registers(pcilib_t* ctx, char* formula, int direction){ - int j,k; - char *substr, *substr2; - char temp[66]; - pcilib_register_value_t value; - - /*we get recursively all registers of string , and if they are not equel to '@reg', then we get their value and put it in formula*/ - for(j=0;jbase_unit.name))){ @@ -362,8 +291,8 @@ int operation_formula(pcilib_t *ctx, void *params, char* unit, int view2reg, pci return PCILIB_ERROR_MEMORY; } strncpy(formula,((pcilib_formula_t*)params)->read_formula,strlen(((pcilib_formula_t*)params)->read_formula)); - pcilib_view_apply_formula(ctx,formula,*regval,&value,0); - return value; + pcilib_view_apply_formula(ctx,formula,regval); + return 0; } for(j=0; ((pcilib_view_t*)viewval)->base_unit.other_units[j].name;j++){ @@ -375,16 +304,16 @@ int operation_formula(pcilib_t *ctx, void *params, char* unit, int view2reg, pci return PCILIB_ERROR_MEMORY; } strncpy(formula,((pcilib_formula_t*)params)->read_formula,strlen(((pcilib_formula_t*)params)->read_formula)); - pcilib_view_apply_formula(ctx,formula, *regval,&value,0); + pcilib_view_apply_formula(ctx,formula, regval); pcilib_view_apply_unit(((pcilib_view_t*)viewval)->base_unit.other_units[j],unit,&value); - return value; + return 0; } } }else if(view2reg==1){ 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)); - pcilib_view_apply_formula(ctx,formula,*regval,&value,1); + pcilib_view_apply_formula(ctx,formula,regval); return 0; } @@ -394,13 +323,13 @@ int operation_formula(pcilib_t *ctx, void *params, char* unit, int view2reg, pci 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)); pcilib_view_apply_unit(((pcilib_view_t*)viewval)->base_unit.other_units[j],unit,&value); - pcilib_view_apply_formula(ctx,formula,*regval,&value,1); - *regval=value; + pcilib_view_apply_formula(ctx,formula,regval); /* we maybe need some error checking there , like temp_value >min and properties; value=(char*)attr->children->content; desc.name=value; - desc.other_units=malloc(sizeof(pcilib_transform_unit_t)); for (cur = node->children; cur != NULL; cur = cur->next) { if (!cur->children) continue; @@ -520,7 +520,6 @@ pcilib_xml_create_unit(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, x if (!value || !attr) continue; if (!strcasecmp(name, "convert_unit")) { - desc.other_units=realloc(desc.other_units,(i+1)*sizeof(pcilib_transform_unit_t)); desc.other_units[i].name=value2; desc.other_units[i].transform_formula=value; i++; diff --git a/pcitool/cli.c b/pcitool/cli.c index bd52270..378b8ba 100644 --- a/pcitool/cli.c +++ b/pcitool/cli.c @@ -1024,14 +1024,15 @@ int ReadRegister(pcilib_t *handle, const pcilib_model_description_t *model_info, int i; int err; const char *format; - char *s1,*s2,*s3; + char *s1,*regname,*viewname; + char* fullreg=strdup(reg); pcilib_register_bank_t bank_id; pcilib_register_bank_addr_t bank_addr = 0; pcilib_register_value_t value; - if (reg && !(strchr(reg,'/'))) { + if (reg && !(strchr(fullreg,'/'))) { pcilib_register_t regid = pcilib_find_register(handle, bank, reg); bank_id = pcilib_find_register_bank_by_addr(handle, model_info->registers[regid].bank); format = model_info->banks[bank_id].format; @@ -1045,28 +1046,30 @@ int ReadRegister(pcilib_t *handle, const pcilib_model_description_t *model_info, printf(format, value); printf("\n"); } - }else if(reg && (s1=strchr(reg,'/'))){ + }else if(reg && (s1=strchr(fullreg,'/'))){ char* enum_command=malloc(sizeof(char*)); if(!enum_command){ printf("Error allocating memory for the result\n"); return PCILIB_ERROR_MEMORY; } - s2=pcilib_view_str_sub(reg,0,s1-reg-1); - s3=pcilib_view_str_sub(reg,s1-reg+1,strlen(reg)); - if(!(strcasecmp(s3,"name"))){ - err = pcilib_read_view(handle,bank,s2,NULL,sizeof(char*),enum_command); - if (err) printf("Error reading register %s\n", reg); + *s1=0; + regname=fullreg; + viewname=fullreg+1; + if(!strcasecmp(viewname,"name")){ + err = pcilib_read_view(handle,bank,regname,viewname,sizeof(char*),enum_command); + if (err) printf("Error reading register %s with an enum view\n", reg); else { printf("%s = %s\n", reg, (char*)enum_command); } + free(enum_command); }else{ - pcilib_register_t regid = pcilib_find_register(handle, bank, s2); + pcilib_register_t regid = pcilib_find_register(handle, bank, regname); bank_id = pcilib_find_register_bank_by_addr(handle, model_info->registers[regid].bank); format = model_info->banks[bank_id].format; if (!format) format = "%lu"; - err = pcilib_read_view(handle,bank,s2,s3,sizeof(pcilib_register_value_t),&value); - if (err) printf("Error reading register %s\n", reg); + err = pcilib_read_view(handle,bank,regname,viewname,sizeof(pcilib_register_value_t),&value); + if (err) printf("Error reading register %s with a formula view\n", reg); else { printf("%s = ", reg); printf(format, value); @@ -1074,7 +1077,6 @@ int ReadRegister(pcilib_t *handle, const pcilib_model_description_t *model_info, } } } else { - printf("da\n"); // Adding DMA registers pcilib_get_dma_description(handle); @@ -1285,11 +1287,14 @@ int WriteRegister(pcilib_t *handle, const pcilib_model_description_t *model_info pcilib_register_t regid; const char *format = NULL; - char *s1,*s2=NULL; + char *s1,*regname=NULL; - if((s1=strchr(reg,'/'))){ - s2=pcilib_view_str_sub(reg,0,s1-reg-1); - regid=pcilib_find_register(handle,bank,s2); + char *fullregister=strdup(reg); + + if((s1=strchr(fullregister,'/'))){ + *s1=0; + regname=fullregister; + regid=pcilib_find_register(handle,bank,regname); }else{ regid = pcilib_find_register(handle, bank, reg); } @@ -1317,23 +1322,24 @@ int WriteRegister(pcilib_t *handle, const pcilib_model_description_t *model_info } format = "0x%lx"; - } else { + } else if((data) && !(regname)){ err = pcilib_write_view(handle,bank,reg,*data,0,NULL); if(err) Error("can't write to the register using an enum view"); else return 0; } - /* should i put strchr not null here? + /* should i put strchr not null here?* } else { Error("Can't parse data value (%s) is not valid decimal number", *data); }*/ value = val; - if((s1=strchr(reg,'/'))){ - char *s3; - s3=pcilib_view_str_sub(reg,s1-reg+1,strlen(reg)); - err = pcilib_write_view(handle,bank,s2,s3,sizeof(pcilib_register_value_t),&value); - if (err) printf("Error writing register %s using view %s\n",s2,s3); + if((regname)){ + char *view_name; + view_name=fullregister+1;; + err = pcilib_write_view(handle,bank,regname,view_name,sizeof(pcilib_register_value_t),&value); + if (err) printf("Error writing register %s using view %s\n",regname,view_name); + free(fullregister); }else{ err = pcilib_write_register(handle, bank, reg, value); if (err) Error("Error writting register %s\n", reg); -- cgit v1.2.3 From 6c47064466d8484813741f347e41af1d4ac90f85 Mon Sep 17 00:00:00 2001 From: "nicolas.zilio@hotmail.fr" <> Date: Tue, 15 Sep 2015 11:45:37 +0200 Subject: cleaning --- pcilib/pci.c | 8 +--- pcilib/pci.h | 5 +-- pcilib/register.h | 8 ++-- pcilib/views.c | 107 ------------------------------------------------------ pcilib/views.h | 30 --------------- 5 files changed, 5 insertions(+), 153 deletions(-) diff --git a/pcilib/pci.c b/pcilib/pci.c index 946b003..b37e817 100644 --- a/pcilib/pci.c +++ b/pcilib/pci.c @@ -139,13 +139,9 @@ pcilib_t *pcilib_open(const char *device, const char *model) { } ctx->alloc_reg = PCILIB_DEFAULT_REGISTER_SPACE; - ctx->alloc_formula_views=PCILIB_DEFAULT_VIEW_SPACE; ctx->alloc_views=PCILIB_DEFAULT_VIEW_SPACE; - ctx->alloc_enum_views=PCILIB_DEFAULT_VIEW_SPACE; ctx->registers = (pcilib_register_description_t *)malloc(PCILIB_DEFAULT_REGISTER_SPACE * sizeof(pcilib_register_description_t)); ctx->register_ctx = (pcilib_register_context_t *)malloc(PCILIB_DEFAULT_REGISTER_SPACE * sizeof(pcilib_register_context_t)); - ctx->enum_views = (pcilib_view_enum2_t *)malloc(PCILIB_DEFAULT_VIEW_SPACE * sizeof(pcilib_view_enum2_t)); - ctx->formula_views = (pcilib_view_formula_t*)malloc(PCILIB_DEFAULT_VIEW_SPACE * sizeof(pcilib_view_formula_t)); ctx->views = (pcilib_view_t*)malloc(PCILIB_DEFAULT_VIEW_SPACE * sizeof(pcilib_view_t)); ctx->alloc_units=PCILIB_DEFAULT_UNIT_SPACE; ctx->units=(pcilib_unit_t*)malloc(PCILIB_DEFAULT_UNIT_SPACE * sizeof(pcilib_unit_t)); @@ -157,7 +153,7 @@ pcilib_t *pcilib_open(const char *device, const char *model) { } /* i think we need a better error handling here, because, it's not that a problem to not have views working, but how to block the use if the memory here was not good?, and we could have only one type of views that is working*/ - if((!ctx->enum_views)||(!ctx->formula_views) || (!ctx->units) || !(ctx->views)){ + if((!ctx->units) || !(ctx->views)){ pcilib_warning("Error allocating memory for views"); } @@ -169,8 +165,6 @@ pcilib_t *pcilib_open(const char *device, const char *model) { memset(ctx->register_ctx, 0, PCILIB_DEFAULT_REGISTER_SPACE * sizeof(pcilib_register_context_t)); - memset(ctx->enum_views,0,sizeof(pcilib_view_enum2_t)); - memset(ctx->formula_views,0,sizeof(pcilib_view_formula_t)); memset(ctx->units,0,sizeof(pcilib_unit_t)); memset(ctx->views,0,sizeof(pcilib_view_t)); diff --git a/pcilib/pci.h b/pcilib/pci.h index d5f1811..8805fc2 100644 --- a/pcilib/pci.h +++ b/pcilib/pci.h @@ -65,8 +65,6 @@ struct pcilib_s { size_t num_banks, num_protocols, num_ranges; /**< Number of registered banks, protocols, and register ranges */ size_t num_engines; /**< Number of configured DMA engines */ size_t dyn_banks; /**< Number of configured dynamic banks */ - size_t num_enum_views,alloc_enum_views; /**< Number of configured and allocated views of type enum*/ - size_t num_formula_views,alloc_formula_views; /**< Number of configured and allocated views of type formula*/ size_t num_views,alloc_views; /**< Number of configured and allocated views*/ size_t num_units,alloc_units; /**< Number of configured and allocated units*/ pcilib_register_description_t *registers; /**< List of currently defined registers (from all sources) */ @@ -87,10 +85,9 @@ struct pcilib_s { struct pcilib_locking_s locks; /**< Context of locking subsystem */ struct pcilib_xml_s xml; /**< XML context */ - pcilib_view_enum2_t* enum_views; /**< list of currently defined views of type enum*/ - pcilib_view_formula_t* formula_views; /**< list of currently defined views of type formula*/ pcilib_view_t* views; /**< list of currently defined views*/ pcilib_unit_t* units; /** list of currently defined units*/ + #ifdef PCILIB_FILE_IO int file_io_handle; #endif /* PCILIB_FILE_IO */ diff --git a/pcilib/register.h b/pcilib/register.h index 2f6334c..13d4c9b 100644 --- a/pcilib/register.h +++ b/pcilib/register.h @@ -45,11 +45,9 @@ typedef struct { typedef struct { - pcilib_register_bank_t bank; /**< Reference to bank containing the register */ - pcilib_register_value_t min, max; /**< Minimum & maximum allowed values */ - pcilib_xml_node_t *xml; /**< Additional XML properties */ - pcilib_view_formula_t *formulas; /**< list of views of type formula linked to this register*/ - pcilib_view_enum_t *enums; /**< list of views of type enum linked to this register*/ + pcilib_register_bank_t bank; /**< Reference to bank containing the register */ + pcilib_register_value_t min, max; /**< Minimum & maximum allowed values */ + pcilib_xml_node_t *xml; /**< Additional XML properties */ pcilib_view_t *views; /** list of views linked to this register*/ } pcilib_register_context_t; diff --git a/pcilib/views.c b/pcilib/views.c index 86675f5..d0116db 100644 --- a/pcilib/views.c +++ b/pcilib/views.c @@ -8,41 +8,6 @@ #include #include "unit.h" -/** - * function used to get the substring of a string s, from the starting and ending indexes - * @param[in] s string containing the substring we want to extract. - * @param[in] start the start index of the substring. - * @param[in] end the ending index of the substring. - * @return the extracted substring. - */ -char* -pcilib_view_str_sub (const char *s, unsigned int start, unsigned int end) -{ - char *new_s = NULL; - - if (s != NULL && start < end) - { - new_s = malloc (sizeof (*new_s) * (end - start + 2)); - if (new_s != NULL) - { - int i; - - for (i = start; i <= end; i++) - { - new_s[i-start] = s[i]; - } - new_s[i-start] = '\0'; - } - else - { - pcilib_error("insufficient memory for string manipulation\n"); - return NULL; - } - } - return new_s; -} - - /** * this function calls the python script and the function "evaluate" in it to evaluate the given formula *@param[in] the formula to be evaluated @@ -122,17 +87,6 @@ specified one. Add it to the register*/ static int pcilib_view_apply_formula(pcilib_t* ctx, char* formula, pcilib_register_value_t* reg_value) { - /* when applying a formula, we need to: - 1) compute the values of all registers present in plain name in the formulas and replace their name with their value : for example, if we have the formula" ((1./4)*(@reg - 1200)) if @freq==0 else ((3./10)*(@reg - 1000)) " we need to get the value of the register "freq" - 2) compute the "@reg" component, corresponding to the raw value of the register - 3) pass the formula to python interpreter for evaluation - 4) return the final evaluation - - remark: it might be worth to use python regular expression interpreter (the following return all words following @ in formula : - >>> import re - >>> m = re.search('(?<=@)\w+', formula) - >>> m.group(0) - */ char reg_value_string[66]; /* to register reg_value as a string, need to check the length*/ sprintf(reg_value_string,"%u",*reg_value); @@ -334,67 +288,6 @@ int operation_formula(pcilib_t *ctx, void *params, char* unit, int view2reg, pci } -/** - * function to populate ctx enum views, as we could do for registers or banks - */ -int pcilib_add_views_enum(pcilib_t *ctx, size_t n, const pcilib_view_enum2_t* views) { - - pcilib_view_enum2_t *views_enum; - size_t size; - - if (!n) { - for (n = 0; views[n].enums_list[0].value; n++); - } - - if ((ctx->num_enum_views + n + 1) > ctx->alloc_enum_views) { - for (size = ctx->alloc_enum_views; size < 2 * (n + ctx->num_enum_views + 1); size<<=1); - - views_enum = (pcilib_view_enum2_t*)realloc(ctx->enum_views, size * sizeof(pcilib_view_enum2_t)); - if (!views_enum) return PCILIB_ERROR_MEMORY; - - ctx->enum_views = views_enum; - ctx->alloc_enum_views = size; - } - - memcpy(ctx->enum_views + ctx->num_enum_views, views, n * sizeof(pcilib_view_enum2_t)); - memset(ctx->enum_views + ctx->num_enum_views + n, 0, sizeof(pcilib_view_enum2_t)); - - ctx->num_enum_views += n; - - - return 0; -} - - -/** - * function to populate ctx formula views, as we could do for registers or banks - */ -int pcilib_add_views_formula(pcilib_t *ctx, size_t n, const pcilib_view_formula_t* views) { - - pcilib_view_formula_t *views_formula; - size_t size; - - if (!n) { - for (n = 0; views[n].name; n++); - } - - if ((ctx->num_formula_views + n + 1) > ctx->alloc_formula_views) { - for (size = ctx->alloc_formula_views; size < 2 * (n + ctx->num_formula_views + 1); size<<=1); - - views_formula = (pcilib_view_formula_t*)realloc(ctx->formula_views, size * sizeof(pcilib_view_formula_t)); - if (!views_formula) return PCILIB_ERROR_MEMORY; - - ctx->formula_views = views_formula; - ctx->alloc_formula_views = size; - } - - memcpy(ctx->formula_views + ctx->num_formula_views, views, n * sizeof(pcilib_view_formula_t)); - memset(ctx->formula_views + ctx->num_formula_views + n, 0, sizeof(pcilib_view_formula_t)); - - ctx->num_formula_views += n; - return 0; -} - /** * function to populate ctx views, as we could do for registers or banks */ diff --git a/pcilib/views.h b/pcilib/views.h index 5d9100e..ae92d0d 100644 --- a/pcilib/views.h +++ b/pcilib/views.h @@ -6,10 +6,6 @@ typedef struct pcilib_view_enum_s pcilib_view_enum_t; -typedef struct pcilib_view_formula_s pcilib_view_formula_t; - -typedef struct pcilib_view_enum2_s pcilib_view_enum2_t; - typedef struct pcilib_view_s pcilib_view_t; typedef struct pcilib_formula_s pcilib_formula_t; @@ -29,15 +25,6 @@ struct pcilib_formula_s{ char* write_formula; }; -/** - * complete type for an enum view : name will be changed after with the previous one - */ -struct pcilib_view_enum2_s { - const char* name; - pcilib_view_enum_t* enums_list; - const char* description; -}; - struct pcilib_view_s{ const char* name; const char* description; @@ -45,17 +32,6 @@ struct pcilib_view_s{ void* parameters; pcilib_unit_t base_unit; }; -/** - * new type to define a formula view - */ -struct pcilib_view_formula_s { - const char *name; /** Date: Tue, 15 Sep 2015 12:07:04 +0200 Subject: merge views and units, some name homogeneisation --- pcilib/CMakeLists.txt | 4 ++-- pcilib/pci.h | 2 +- pcilib/unit.c | 34 ------------------------------- pcilib/unit.h | 32 ----------------------------- pcilib/views.c | 56 +++++++++++++++++++++++++++++++++++++-------------- pcilib/views.h | 35 +++++++++++++++++++++++++++++--- pcilib/xml.c | 24 +++++++++++----------- 7 files changed, 88 insertions(+), 99 deletions(-) delete mode 100644 pcilib/unit.c delete mode 100644 pcilib/unit.h diff --git a/pcilib/CMakeLists.txt b/pcilib/CMakeLists.txt index 1f3e646..9688065 100644 --- a/pcilib/CMakeLists.txt +++ b/pcilib/CMakeLists.txt @@ -9,9 +9,9 @@ include_directories( set(HEADERS pcilib.h pci.h export.h bar.h fifo.h model.h bank.h register.h views.h xml.h kmem.h irq.h locking.h lock.h dma.h event.h plugin.h tools.h error.h -debug.h env.h version.h config.h unit.h) +debug.h env.h version.h config.h) add_library(pcilib SHARED pci.c export.c bar.c fifo.c model.c bank.c -register.c views.c xml.c kmem.c irq.c locking.c lock.c dma.c event.c plugin.c tools.c error.c debug.c env.c unit.c) +register.c views.c xml.c kmem.c irq.c locking.c lock.c dma.c event.c plugin.c tools.c error.c debug.c env.c) target_link_libraries(pcilib dma protocols ${CMAKE_THREAD_LIBS_INIT} ${UFODECODE_LIBRARIES} ${CMAKE_DL_LIBS} ${EXTRA_SYSTEM_LIBS} ${LIBXML2_LIBRARIES} ${PYTHON_LIBRARIES}) diff --git a/pcilib/pci.h b/pcilib/pci.h index 8805fc2..f364890 100644 --- a/pcilib/pci.h +++ b/pcilib/pci.h @@ -28,7 +28,7 @@ #include "export.h" #include "locking.h" #include "xml.h" -#include "unit.h" +#include "views.h" typedef struct { uint8_t max_link_speed, link_speed; diff --git a/pcilib/unit.c b/pcilib/unit.c deleted file mode 100644 index a9766ed..0000000 --- a/pcilib/unit.c +++ /dev/null @@ -1,34 +0,0 @@ -#include "pcilib.h" -#include "pci.h" -#include "stdio.h" -#include -#include "error.h" -#include "unit.h" - -int pcilib_add_units(pcilib_t *ctx, size_t n, const pcilib_unit_t* units) { - - pcilib_unit_t *units2; - size_t size; - - if (!n) { - for (n = 0; units[n].name[0]; n++); - } - - if ((ctx->num_units + n + 1) > ctx->alloc_units) { - for (size = ctx->alloc_units; size < 2 * (n + ctx->num_units + 1); size<<=1); - - units2 = (pcilib_unit_t*)realloc(ctx->units, size * sizeof(pcilib_unit_t)); - if (!units2) return PCILIB_ERROR_MEMORY; - - ctx->units = units2; - ctx->alloc_units = size; - } - - memcpy(ctx->units + ctx->num_units, units, n * sizeof(pcilib_unit_t)); - memset(ctx->units + ctx->num_units + n, 0, sizeof(pcilib_unit_t)); - - ctx->num_units += n; - - return 0; -} - diff --git a/pcilib/unit.h b/pcilib/unit.h deleted file mode 100644 index 4a99f5b..0000000 --- a/pcilib/unit.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef _PCILIB_UNITS_H -#define _PCILIB_UNITS_H - -#include "pcilib.h" - -#define PCILIB_MAX_TRANSFORMS_PER_UNIT 16 - -typedef struct pcilib_unit_s pcilib_unit_t; -typedef struct pcilib_transform_unit_s pcilib_transform_unit_t; - -/** - * type to save a transformation unit in the pcitool program - */ -struct pcilib_transform_unit_s{ - char *name; - char *transform_formula; -}; - -/** - * type to save a unit in the pcitool programm - */ -struct pcilib_unit_s{ - char* name; - pcilib_transform_unit_t other_units[PCILIB_MAX_TRANSFORMS_PER_UNIT]; -}; - -/** - * function to populate the ctx with units - */ -int pcilib_add_units(pcilib_t* ctx, size_t n, const pcilib_unit_t* units); - -#endif diff --git a/pcilib/views.c b/pcilib/views.c index d0116db..9fe8810 100644 --- a/pcilib/views.c +++ b/pcilib/views.c @@ -6,7 +6,6 @@ #include "error.h" #include #include -#include "unit.h" /** * this function calls the python script and the function "evaluate" in it to evaluate the given formula @@ -209,18 +208,18 @@ int pcilib_write_view(pcilib_t *ctx, const char *bank, const char *regname, cons int operation_enum(pcilib_t *ctx, void *params, char* name, int view2reg, pcilib_register_value_t *regval, size_t viewval_size, void* viewval){ int j,k; if(view2reg==1){ - for(j=0; ((pcilib_view_enum_t*)(params))[j].name;j++){ - if(!(strcasecmp(((pcilib_view_enum_t*)(params))[j].name,name))){ - *regval=((pcilib_view_enum_t*)(params))[j].value; + for(j=0; ((pcilib_enum_t*)(params))[j].name;j++){ + if(!(strcasecmp(((pcilib_enum_t*)(params))[j].name,name))){ + *regval=((pcilib_enum_t*)(params))[j].value; return 0; } } }else if (view2reg==0){ - for(j=0; ((pcilib_view_enum_t*)(params))[j].name;j++){ - if (*regval<((pcilib_view_enum_t*)(params))[j].max && *regval>((pcilib_view_enum_t*)(params))[j].min){ - name=(char*)realloc(name,strlen(((pcilib_view_enum_t*)(params))[j].name)*sizeof(char)); - strncpy(name,((pcilib_view_enum_t*)(params))[j].name, strlen(((pcilib_view_enum_t*)(params))[j].name)); - k=strlen(((pcilib_view_enum_t*)(params))[j].name); + 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){ + name=(char*)realloc(name,strlen(((pcilib_enum_t*)(params))[j].name)*sizeof(char)); + strncpy(name,((pcilib_enum_t*)(params))[j].name, strlen(((pcilib_enum_t*)(params))[j].name)); + k=strlen(((pcilib_enum_t*)(params))[j].name); name[k]='\0'; return 0; } @@ -249,8 +248,8 @@ int operation_formula(pcilib_t *ctx, void *params, char* unit, int view2reg, pci return 0; } - for(j=0; ((pcilib_view_t*)viewval)->base_unit.other_units[j].name;j++){ - if(!(strcasecmp(((pcilib_view_t*)viewval)->base_unit.other_units[j].name,unit))){ + for(j=0; ((pcilib_view_t*)viewval)->base_unit.transforms[j].name;j++){ + if(!(strcasecmp(((pcilib_view_t*)viewval)->base_unit.transforms[j].name,unit))){ /* when we have found the correct view of type formula, we apply the formula, that get the good value for return*/ formula=malloc(sizeof(char)*strlen(((pcilib_formula_t*)params)->read_formula)); if(!(formula)){ @@ -259,7 +258,7 @@ int operation_formula(pcilib_t *ctx, void *params, char* unit, int view2reg, pci } strncpy(formula,((pcilib_formula_t*)params)->read_formula,strlen(((pcilib_formula_t*)params)->read_formula)); pcilib_view_apply_formula(ctx,formula, regval); - pcilib_view_apply_unit(((pcilib_view_t*)viewval)->base_unit.other_units[j],unit,&value); + pcilib_view_apply_unit(((pcilib_view_t*)viewval)->base_unit.transforms[j],unit,&value); return 0; } } @@ -271,12 +270,12 @@ int operation_formula(pcilib_t *ctx, void *params, char* unit, int view2reg, pci return 0; } - for(j=0;((pcilib_view_t*)viewval)->base_unit.other_units[j].name;j++){ - if(!(strcasecmp(((pcilib_view_t*)viewval)->base_unit.other_units[j].name,unit))){ + for(j=0;((pcilib_view_t*)viewval)->base_unit.transforms[j].name;j++){ + if(!(strcasecmp(((pcilib_view_t*)viewval)->base_unit.transforms[j].name,unit))){ /* when we have found the correct view of type formula, we apply the formula, that get the good value for return*/ 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)); - pcilib_view_apply_unit(((pcilib_view_t*)viewval)->base_unit.other_units[j],unit,&value); + pcilib_view_apply_unit(((pcilib_view_t*)viewval)->base_unit.transforms[j],unit,&value); pcilib_view_apply_formula(ctx,formula,regval); /* we maybe need some error checking there , like temp_value >min and num_views += n; return 0; } + +int pcilib_add_units(pcilib_t *ctx, size_t n, const pcilib_unit_t* units) { + + pcilib_unit_t *units2; + size_t size; + + if (!n) { + for (n = 0; units[n].name[0]; n++); + } + + if ((ctx->num_units + n + 1) > ctx->alloc_units) { + for (size = ctx->alloc_units; size < 2 * (n + ctx->num_units + 1); size<<=1); + + units2 = (pcilib_unit_t*)realloc(ctx->units, size * sizeof(pcilib_unit_t)); + if (!units2) return PCILIB_ERROR_MEMORY; + + ctx->units = units2; + ctx->alloc_units = size; + } + + memcpy(ctx->units + ctx->num_units, units, n * sizeof(pcilib_unit_t)); + memset(ctx->units + ctx->num_units + n, 0, sizeof(pcilib_unit_t)); + + ctx->num_units += n; + + return 0; +} diff --git a/pcilib/views.h b/pcilib/views.h index ae92d0d..c44393d 100644 --- a/pcilib/views.h +++ b/pcilib/views.h @@ -2,9 +2,14 @@ #define _PCILIB_VIEWS_H #include "pcilib.h" -#include "unit.h" -typedef struct pcilib_view_enum_s pcilib_view_enum_t; +#define PCILIB_MAX_TRANSFORMS_PER_UNIT 16 + +typedef struct pcilib_transform_unit_s pcilib_transform_unit_t; + +typedef struct pcilib_unit_s pcilib_unit_t; + +typedef struct pcilib_enum_s pcilib_enum_t; typedef struct pcilib_view_s pcilib_view_t; @@ -12,10 +17,26 @@ typedef struct pcilib_formula_s pcilib_formula_t; typedef int (*pcilib_view_operation_t)(pcilib_t *ctx, void *params, char* string, int read_or_write, pcilib_register_value_t *regval, size_t viewval_size, void* viewval); +/** + * type to save a transformation unit in the pcitool program + */ +struct pcilib_transform_unit_s{ + char *name; + char *transform_formula; +}; + +/** + * type to save a unit in the pcitool programm + */ +struct pcilib_unit_s{ + char* name; + pcilib_transform_unit_t transforms[PCILIB_MAX_TRANSFORMS_PER_UNIT]; +}; + /** * new type to define an enum view */ -struct pcilib_view_enum_s { +struct pcilib_enum_s { const char *name; /**nodeNr; i++) { view_name=(char*)nodeset->nodeTab[i]->children->content; - /* if the view name obtained is for an enum view, we get all pcilib_view_enum_t corresponding to the register*/ + /* if the view name obtained is for an enum view, we get all pcilib_enum_t corresponding to the register*/ for(k=0; ctx->views[k].name; k++){ if(!(strcasecmp(view_name, ctx->views[k].name))){ - ctx->register_ctx[id].views=realloc(ctx->register_ctx[id].views,(k+1)*sizeof(pcilib_view_enum_t)); + ctx->register_ctx[id].views=realloc(ctx->register_ctx[id].views,(k+1)*sizeof(pcilib_enum_t)); ctx->register_ctx[id].views[k]=ctx->views[k]; } } @@ -520,8 +520,8 @@ pcilib_xml_create_unit(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, x if (!value || !attr) continue; if (!strcasecmp(name, "convert_unit")) { - desc.other_units[i].name=value2; - desc.other_units[i].transform_formula=value; + desc.transforms[i].name=value2; + desc.transforms[i].transform_formula=value; i++; } } @@ -558,7 +558,7 @@ static int pcilib_xml_create_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDo /*if the view is of type enum, we get recursively its properties and then populate ctx enum views*/ if(!(strcasecmp(value,"enum"))){ desc.op=&operation_enum; - desc.parameters=malloc(sizeof(pcilib_view_enum_t)); + desc.parameters=malloc(sizeof(pcilib_enum_t)); desc.base_unit.name="name"; for (cur = node->children; cur != NULL; cur = cur->next) { if (!cur->children) continue; @@ -576,8 +576,8 @@ static int pcilib_xml_create_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDo }else if (!(strcasecmp((char*)name,"enum"))) { - desc.parameters=realloc(desc.parameters,(i+1)*sizeof(pcilib_view_enum_t)); - ((pcilib_view_enum_t*)(desc.parameters))[i].name=value; + desc.parameters=realloc(desc.parameters,(i+1)*sizeof(pcilib_enum_t)); + ((pcilib_enum_t*)(desc.parameters))[i].name=value; /* we need to iterate through the different attributes of an enum node to get all properties*/ for(attr=cur->properties; attr!=NULL;attr=attr->next){ @@ -593,14 +593,14 @@ static int pcilib_xml_create_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDo pcilib_error("Invalid value (%s) is specified in the XML enum node", value); return PCILIB_ERROR_INVALID_DATA; } - ((pcilib_view_enum_t*)(desc.parameters))[i].value=dat_value; + ((pcilib_enum_t*)(desc.parameters))[i].value=dat_value; }else if(!(strcasecmp(name,"min"))){ pcilib_register_value_t dat_min = strtol(value, &endptr, 0); if ((strlen(endptr) > 0)) { pcilib_error("Invalid min (%s) is specified in the XML enum node", value); return PCILIB_ERROR_INVALID_DATA; } - ((pcilib_view_enum_t*)(desc.parameters))[i].min=dat_min; + ((pcilib_enum_t*)(desc.parameters))[i].min=dat_min; ok_min=1; }else if(!(strcasecmp(name,"max"))){ pcilib_register_value_t dat_max = strtol(value, &endptr, 0); @@ -608,11 +608,11 @@ static int pcilib_xml_create_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDo pcilib_error("Invalid max (%s) is specified in the XML enum node", value); return PCILIB_ERROR_INVALID_DATA; } - ((pcilib_view_enum_t*)(desc.parameters))[i].max=dat_max; + ((pcilib_enum_t*)(desc.parameters))[i].max=dat_max; ok_max=1; } - if(ok_min==0) ((pcilib_view_enum_t*)(desc.parameters))[i].min=((pcilib_view_enum_t*)(desc.parameters))[i].value; - if(ok_max==0) ((pcilib_view_enum_t*)(desc.parameters))[i].max=((pcilib_view_enum_t*)(desc.parameters))[i].value; + if(ok_min==0) ((pcilib_enum_t*)(desc.parameters))[i].min=((pcilib_enum_t*)(desc.parameters))[i].value; + if(ok_max==0) ((pcilib_enum_t*)(desc.parameters))[i].max=((pcilib_enum_t*)(desc.parameters))[i].value; } i++; -- cgit v1.2.3 From 1234f4a7e2410b127120aaa20dfe3c996ad34ef4 Mon Sep 17 00:00:00 2001 From: "nicolas.zilio@hotmail.fr" <> Date: Tue, 15 Sep 2015 14:17:23 +0200 Subject: correction of some fails to load correct --- pcilib/xml.c | 22 ++++++++++++---------- xml/test/camera.xml | 22 ++++++++++++++++------ 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/pcilib/xml.c b/pcilib/xml.c index ebef91e..31b9926 100644 --- a/pcilib/xml.c +++ b/pcilib/xml.c @@ -121,20 +121,22 @@ pcilib_get_associated_views(pcilib_t* ctx, const char* reg_name,xmlXPathContextP } if (!xmlXPathNodeSetIsEmpty(nodeset)) { - int i,k; + int i,k,l=0; /*if we correctly get a nodeset, then we iterate through the nodeset to get all views, using their names*/ for (i = 0; i < nodeset->nodeNr; i++) { view_name=(char*)nodeset->nodeTab[i]->children->content; - /* if the view name obtained is for an enum view, we get all pcilib_enum_t corresponding to the register*/ for(k=0; ctx->views[k].name; k++){ if(!(strcasecmp(view_name, ctx->views[k].name))){ - ctx->register_ctx[id].views=realloc(ctx->register_ctx[id].views,(k+1)*sizeof(pcilib_enum_t)); - ctx->register_ctx[id].views[k]=ctx->views[k]; + ctx->register_ctx[id].views=realloc(ctx->register_ctx[id].views,(l+1)*sizeof(pcilib_view_t)); + ctx->register_ctx[id].views[l]=ctx->views[k]; + l++; } } - } + ctx->register_ctx[id].views=realloc(ctx->register_ctx[id].views,(l+1)*sizeof(pcilib_view_t)); + ctx->register_ctx[id].views[l].name=NULL; + } xmlXPathFreeObject(nodes); @@ -305,6 +307,7 @@ static int pcilib_xml_create_register(pcilib_t *ctx, pcilib_register_bank_t bank int i; for (i = 0; i < nodeset->nodeNr; i++) { + views_ok=0; memset(&fdesc, 0, sizeof(pcilib_xml_register_description_t)); fdesc.base.bank = desc.base.bank; @@ -575,7 +578,6 @@ static int pcilib_xml_create_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDo desc.description = value; }else if (!(strcasecmp((char*)name,"enum"))) { - desc.parameters=realloc(desc.parameters,(i+1)*sizeof(pcilib_enum_t)); ((pcilib_enum_t*)(desc.parameters))[i].name=value; @@ -700,6 +702,7 @@ static int pcilib_xml_process_document(pcilib_t *ctx, xmlDocPtr doc, xmlXPathCon pcilib_xml_create_view(ctx,xpath,doc,nodeset->nodeTab[i]); } } + xmlXPathFreeObject(views_nodes); banks: bank_nodes = xmlXPathEvalExpression(BANKS_PATH, xpath); @@ -718,7 +721,6 @@ static int pcilib_xml_process_document(pcilib_t *ctx, xmlDocPtr doc, xmlXPathCon } } xmlXPathFreeObject(bank_nodes); - return 0; } @@ -852,20 +854,20 @@ int pcilib_process_xml(pcilib_t *ctx, const char *location) { err = pcilib_xml_load_file(ctx, model_path, file->d_name); if (err) pcilib_error("Error processing XML file %s", file->d_name); } - + for(i=0;inum_views;i++){ pcilib_get_unit_of_view(ctx,&(ctx->views[i]),ctx->views[i].base_unit.name); } for(i=0;inum_reg;i++){ + if(!(ctx->register_ctx[i].views)) continue; for(j=0;jnum_views;j++){ if(!(ctx->register_ctx[i].views[j].name)) break; - if(ctx->register_ctx[i].views){ + if(ctx->register_ctx[i].views[j].name){ pcilib_get_unit_of_view(ctx,&(ctx->register_ctx[i].views[j]),ctx->register_ctx[i].views[j].base_unit.name); } } } - closedir(rep); return 0; diff --git a/xml/test/camera.xml b/xml/test/camera.xml index ed01014..021ed61 100644 --- a/xml/test/camera.xml +++ b/xml/test/camera.xml @@ -253,6 +253,10 @@ all RW fr_num_lines_thr + + formuu2 + enumm2 +
0x100
@@ -278,8 +282,8 @@ R sensor_temperature - formuu1 - formuu2 + formuu1 + formuu2 enumm2 @@ -294,10 +298,6 @@ 10 RW fpga_temperature - - formuu1 - enumm1 - 29 @@ -348,6 +348,11 @@ 5 RW motor_phi + + formuu1 + enumm3 + + 5 @@ -392,6 +397,11 @@ 0 RW num_triggers + + formuu1 + formuu3 + enumm3 +
0x180
-- cgit v1.2.3 From c871ef59e748678b11d964e21debab05082948a0 Mon Sep 17 00:00:00 2001 From: "nicolas.zilio@hotmail.fr" <> Date: Tue, 15 Sep 2015 14:56:35 +0200 Subject: soka --- pcilib/views.c | 29 +++++++++++++++++++++-------- pcilib/xml.c | 1 + pcitool/cli.c | 5 ++++- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/pcilib/views.c b/pcilib/views.c index 9fe8810..12c09e5 100644 --- a/pcilib/views.c +++ b/pcilib/views.c @@ -138,25 +138,38 @@ int pcilib_read_view(pcilib_t *ctx, const char *bank, const char *regname, const return PCILIB_ERROR_INVALID_REQUEST; } - for(j=0;ctx->register_ctx[i].views[j].name;j++){ + + for(j=0;ctx->num_views;j++){ + if(!(ctx->register_ctx[i].views[j].name)) break; + if(ctx->register_ctx[i].views[j].name) printf("name %s\n",ctx->register_ctx[i].views[j].name); + } + + for(j=0;ctx->num_views;j++){ + if(!(ctx->register_ctx[i].views[j].name)) break; + if(ctx->register_ctx[i].views[j].name){ + printf("unit %s, view %s\n",unit,ctx->register_ctx[i].views[j].name); if(!(strcasecmp(ctx->register_ctx[i].views[j].base_unit.name,unit))){/*if we asked for the unit "name"*/ + printf("in unit\n"); err=ctx->register_ctx[i].views[j].op(ctx,ctx->register_ctx[i].views[j].parameters,value/*the command name*/,0,&temp_value,0,&(ctx->register_ctx[i].views[j])); if(err){ pcilib_error("can't write to the register with the enum view"); return PCILIB_ERROR_FAILED; } + break; }else if(!(strcasecmp(ctx->register_ctx[i].views[j].name,(char*)unit))){/*in this case we asked for the name of the view in unit*/ + printf("pass here2\n"); err=ctx->register_ctx[i].views[j].op(ctx,ctx->register_ctx[i].views[j].parameters,(char*)unit, 0, &temp_value,0,&(ctx->register_ctx[i].views[j])); - if(err){ - pcilib_error("can't write to the register with the formula view %s", unit); - return PCILIB_ERROR_FAILED; - } - *(pcilib_register_value_t*)value=temp_value; - break; + if(err){ + pcilib_error("can't write to the register with the formula view %s", unit); + return PCILIB_ERROR_FAILED; + } + *(pcilib_register_value_t*)value=temp_value; + break; } - return 0; + return 0; } + } pcilib_error("the view asked and the register do not correspond"); return PCILIB_ERROR_NOTAVAILABLE; } diff --git a/pcilib/xml.c b/pcilib/xml.c index 31b9926..47bcf5c 100644 --- a/pcilib/xml.c +++ b/pcilib/xml.c @@ -864,6 +864,7 @@ int pcilib_process_xml(pcilib_t *ctx, const char *location) { for(j=0;jnum_views;j++){ if(!(ctx->register_ctx[i].views[j].name)) break; if(ctx->register_ctx[i].views[j].name){ + printf("register %s view %s\n",ctx->registers[i].name,ctx->register_ctx[i].views[j].name); pcilib_get_unit_of_view(ctx,&(ctx->register_ctx[i].views[j]),ctx->register_ctx[i].views[j].base_unit.name); } } diff --git a/pcitool/cli.c b/pcitool/cli.c index 378b8ba..69151b6 100644 --- a/pcitool/cli.c +++ b/pcitool/cli.c @@ -1033,6 +1033,7 @@ int ReadRegister(pcilib_t *handle, const pcilib_model_description_t *model_info, pcilib_register_value_t value; if (reg && !(strchr(fullreg,'/'))) { + printf("pass1\n"); pcilib_register_t regid = pcilib_find_register(handle, bank, reg); bank_id = pcilib_find_register_bank_by_addr(handle, model_info->registers[regid].bank); format = model_info->banks[bank_id].format; @@ -1047,6 +1048,7 @@ int ReadRegister(pcilib_t *handle, const pcilib_model_description_t *model_info, printf("\n"); } }else if(reg && (s1=strchr(fullreg,'/'))){ + printf("pass2\n"); char* enum_command=malloc(sizeof(char*)); if(!enum_command){ printf("Error allocating memory for the result\n"); @@ -1054,7 +1056,8 @@ int ReadRegister(pcilib_t *handle, const pcilib_model_description_t *model_info, } *s1=0; regname=fullreg; - viewname=fullreg+1; + viewname=s1+1; + printf("regname %s, viewname %s\n",regname,viewname); if(!strcasecmp(viewname,"name")){ err = pcilib_read_view(handle,bank,regname,viewname,sizeof(char*),enum_command); if (err) printf("Error reading register %s with an enum view\n", reg); -- cgit v1.2.3 From e43b676d8294f37410ea0fa1f9fa39d10df64408 Mon Sep 17 00:00:00 2001 From: "nicolas.zilio@hotmail.fr" <> Date: Tue, 15 Sep 2015 17:27:27 +0200 Subject: not perfect but working --- pcilib/views.c | 93 ++++++++++++++++++++++++++++++++--------------------- pcilib/xml.c | 1 - pcitool/cli.c | 6 ++-- xml/test/camera.xml | 26 +++++++-------- 4 files changed, 71 insertions(+), 55 deletions(-) diff --git a/pcilib/views.c b/pcilib/views.c index 12c09e5..83c5827 100644 --- a/pcilib/views.c +++ b/pcilib/views.c @@ -50,7 +50,7 @@ pcilib_view_compute_formula(pcilib_t* ctx, char* formula,char* reg_value_string) while(1){ reg = strchr(src, '@'); if (!reg) { - strcpy(dst, src); + strcpy(dst+offset, src); break; } regend = strchr(reg + 1, '@'); @@ -64,10 +64,9 @@ pcilib_view_compute_formula(pcilib_t* ctx, char* formula,char* reg_value_string) /* Now (reg + 1) contains the proper register name, you can compare it to reg/value and either get the value of current register or the specified one. Add it to the register*/ - if(!(strcasecmp(reg,"@value")) || !(strcasecmp(reg,"@reg")) || !(strcasecmp(reg,"@self"))){ + if(!(strcasecmp(reg+1,"value")) || !(strcasecmp(reg+1,"reg")) || !(strcasecmp(reg+1,"self"))){ strncpy(dst+offset,reg_value_string,strlen(reg_value_string)); offset+=strlen(reg_value_string); - }else{ pcilib_read_register(ctx, NULL,reg+1,&value); sprintf(temp,"%i",value); @@ -76,7 +75,6 @@ specified one. Add it to the register*/ } src = regend + 1; } - return dst; } @@ -89,8 +87,8 @@ pcilib_view_apply_formula(pcilib_t* ctx, char* formula, pcilib_register_value_t* char reg_value_string[66]; /* to register reg_value as a string, need to check the length*/ sprintf(reg_value_string,"%u",*reg_value); - formula=pcilib_view_compute_formula(ctx,formula,reg_value_string); + if(!(formula)){ pcilib_error("computing of formula failed"); return PCILIB_ERROR_INVALID_DATA; @@ -122,7 +120,7 @@ pcilib_view_apply_unit(pcilib_transform_unit_t unit_desc, const char* unit,pcili int pcilib_read_view(pcilib_t *ctx, const char *bank, const char *regname, const char *unit, size_t value_size, void *value) { - int i,j,err=0; + int i,j,k,err=0; pcilib_register_value_t temp_value; /* we get the index of the register to find the corresponding register context*/ @@ -139,37 +137,37 @@ int pcilib_read_view(pcilib_t *ctx, const char *bank, const char *regname, const } - for(j=0;ctx->num_views;j++){ - if(!(ctx->register_ctx[i].views[j].name)) break; - if(ctx->register_ctx[i].views[j].name) printf("name %s\n",ctx->register_ctx[i].views[j].name); - } - - for(j=0;ctx->num_views;j++){ - if(!(ctx->register_ctx[i].views[j].name)) break; - if(ctx->register_ctx[i].views[j].name){ - printf("unit %s, view %s\n",unit,ctx->register_ctx[i].views[j].name); - if(!(strcasecmp(ctx->register_ctx[i].views[j].base_unit.name,unit))){/*if we asked for the unit "name"*/ - printf("in unit\n"); + for(j=0;ctx->register_ctx[i].views[j].name;j++){ + if(!(strcasecmp("name",ctx->register_ctx[i].views[j].base_unit.name))){/*if we asked for the unit "name"*/ err=ctx->register_ctx[i].views[j].op(ctx,ctx->register_ctx[i].views[j].parameters,value/*the command name*/,0,&temp_value,0,&(ctx->register_ctx[i].views[j])); if(err){ - pcilib_error("can't write to the register with the enum view"); + pcilib_error("can't read from the register with the enum view"); return PCILIB_ERROR_FAILED; } - - break; - }else if(!(strcasecmp(ctx->register_ctx[i].views[j].name,(char*)unit))){/*in this case we asked for the name of the view in unit*/ - printf("pass here2\n"); + return 0; + }else if(!(strcasecmp(ctx->register_ctx[i].views[j].base_unit.name,(char*)unit))){/*in this case we asked for the name of the view in unit*/ err=ctx->register_ctx[i].views[j].op(ctx,ctx->register_ctx[i].views[j].parameters,(char*)unit, 0, &temp_value,0,&(ctx->register_ctx[i].views[j])); if(err){ - pcilib_error("can't write to the register with the formula view %s", unit); + pcilib_error("can't read from the register with the formula view %s", unit); return PCILIB_ERROR_FAILED; } *(pcilib_register_value_t*)value=temp_value; - break; + return 0; + }else{ + for(k=0;ctx->register_ctx[i].views[j].base_unit.transforms[k].name;k++){ + if(!(strcasecmp(ctx->register_ctx[i].views[j].base_unit.transforms[k].name,(char*)unit))){ + err=ctx->register_ctx[i].views[j].op(ctx,ctx->register_ctx[i].views[j].parameters,(char*)unit, 0, &temp_value,0,&(ctx->register_ctx[i].views[j])); + if(err){ + pcilib_error("can't write to the register with the formula view %s", unit); + return PCILIB_ERROR_FAILED; + } + *(pcilib_register_value_t*)value=temp_value; + return 0; + } + } } - return 0; - } } + pcilib_error("the view asked and the register do not correspond"); return PCILIB_ERROR_NOTAVAILABLE; } @@ -179,43 +177,64 @@ int pcilib_read_view(pcilib_t *ctx, const char *bank, const char *regname, const * function to write to a register using a view */ int pcilib_write_view(pcilib_t *ctx, const char *bank, const char *regname, const char *unit, size_t value_size,void* value){ - int i,j; + int i,j,k; pcilib_register_value_t temp_value; int err; + int next=1,ok=0; /* we get the index of the register to find the corresponding register context*/ if((i=pcilib_find_register(ctx,bank,regname))==PCILIB_REGISTER_INVALID){ pcilib_error("can't get the index of the register %s", regname); return PCILIB_ERROR_INVALID_REQUEST; } - + for(j=0;ctx->register_ctx[i].views[j].name;j++){ - if(!(strcasecmp(ctx->register_ctx[i].views[j].base_unit.name,unit))){/*if we asked for the unit "name"*/ - err=ctx->register_ctx[i].views[j].op(ctx,ctx->register_ctx[i].views[j].parameters,value/*the command name*/,1,&temp_value,0,&(ctx->register_ctx[i].views[j])); + if(!(strcasecmp(ctx->register_ctx[i].views[j].base_unit.name,"name"))){/*if we asked for the unit "name"*/ + err=ctx->register_ctx[i].views[j].op(ctx,ctx->register_ctx[i].views[j].parameters,(char*)unit/*the command name*/,1,&temp_value,0,&(ctx->register_ctx[i].views[j])); if(err){ pcilib_error("can't write to the register with the enum view"); return PCILIB_ERROR_FAILED; } + ok=1; break; - }else if(!(strcasecmp(ctx->register_ctx[i].views[j].name,(char*)unit))){/*in this case we asked for then name of the view in unit*/ + }else if(!(strcasecmp(ctx->register_ctx[i].views[j].base_unit.name,(char*)unit))){/*in this case we asked for then name of the view in unit*/ temp_value=*(pcilib_register_value_t*)value /*the value to put in the register*/; err=ctx->register_ctx[i].views[j].op(ctx,ctx->register_ctx[i].views[j].parameters, (char*)unit, 1, &temp_value,0,&(ctx->register_ctx[i].views[j])); if(err){ pcilib_error("can't write to the register with the formula view %s", unit); return PCILIB_ERROR_FAILED; } + ok=1; break; - } + }else{ + for(k=0;ctx->register_ctx[i].views[j].base_unit.transforms[k].name;k++){ + if(!(strcasecmp(ctx->register_ctx[i].views[j].base_unit.transforms[k].name,(char*)unit))){ + err=ctx->register_ctx[i].views[j].op(ctx,ctx->register_ctx[i].views[j].parameters, (char*)unit, 1, &temp_value,0,&(ctx->register_ctx[i].views[j])); + if(err){ + pcilib_error("can't write to the register with the formula view %s", unit); + return PCILIB_ERROR_FAILED; + } + next=0; + ok=1; + break; + } + } + if(next==0)break; + } + } + + if(ok==1) { pcilib_write_register(ctx,bank,regname,temp_value); + printf("value %i written in register\n",temp_value); return 0; } - + pcilib_error("the view asked and the register do not correspond"); return PCILIB_ERROR_NOTAVAILABLE; } /** - * always: viewval=view params=view params + * always : viewval=view params=view params * write: name=enum command regval:the value corresponding to the command */ int operation_enum(pcilib_t *ctx, void *params, char* name, int view2reg, pcilib_register_value_t *regval, size_t viewval_size, void* viewval){ @@ -229,7 +248,7 @@ int operation_enum(pcilib_t *ctx, void *params, char* name, int view2reg, pcilib } }else if (view2reg==0){ 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 (*regval<=((pcilib_enum_t*)(params))[j].max && *regval>=((pcilib_enum_t*)(params))[j].min){ name=(char*)realloc(name,strlen(((pcilib_enum_t*)(params))[j].name)*sizeof(char)); strncpy(name,((pcilib_enum_t*)(params))[j].name, strlen(((pcilib_enum_t*)(params))[j].name)); k=strlen(((pcilib_enum_t*)(params))[j].name); @@ -250,7 +269,7 @@ int operation_formula(pcilib_t *ctx, void *params, char* unit, int view2reg, pci char* formula=NULL; if(view2reg==0){ - if(!(strcasecmp(unit, ((pcilib_view_t*)viewval)->base_unit.name))){ + if(!(strcasecmp(unit,((pcilib_view_t*)viewval)->base_unit.name))){ formula=malloc(sizeof(char)*strlen(((pcilib_formula_t*)params)->read_formula)); if(!(formula)){ pcilib_error("can't allocate memory for the formula"); @@ -271,7 +290,7 @@ int operation_formula(pcilib_t *ctx, void *params, char* unit, int view2reg, pci } strncpy(formula,((pcilib_formula_t*)params)->read_formula,strlen(((pcilib_formula_t*)params)->read_formula)); pcilib_view_apply_formula(ctx,formula, regval); - pcilib_view_apply_unit(((pcilib_view_t*)viewval)->base_unit.transforms[j],unit,&value); + pcilib_view_apply_unit(((pcilib_view_t*)viewval)->base_unit.transforms[j],unit,regval); return 0; } } diff --git a/pcilib/xml.c b/pcilib/xml.c index 47bcf5c..31b9926 100644 --- a/pcilib/xml.c +++ b/pcilib/xml.c @@ -864,7 +864,6 @@ int pcilib_process_xml(pcilib_t *ctx, const char *location) { for(j=0;jnum_views;j++){ if(!(ctx->register_ctx[i].views[j].name)) break; if(ctx->register_ctx[i].views[j].name){ - printf("register %s view %s\n",ctx->registers[i].name,ctx->register_ctx[i].views[j].name); pcilib_get_unit_of_view(ctx,&(ctx->register_ctx[i].views[j]),ctx->register_ctx[i].views[j].base_unit.name); } } diff --git a/pcitool/cli.c b/pcitool/cli.c index 69151b6..aa80b72 100644 --- a/pcitool/cli.c +++ b/pcitool/cli.c @@ -1033,7 +1033,6 @@ int ReadRegister(pcilib_t *handle, const pcilib_model_description_t *model_info, pcilib_register_value_t value; if (reg && !(strchr(fullreg,'/'))) { - printf("pass1\n"); pcilib_register_t regid = pcilib_find_register(handle, bank, reg); bank_id = pcilib_find_register_bank_by_addr(handle, model_info->registers[regid].bank); format = model_info->banks[bank_id].format; @@ -1048,7 +1047,6 @@ int ReadRegister(pcilib_t *handle, const pcilib_model_description_t *model_info, printf("\n"); } }else if(reg && (s1=strchr(fullreg,'/'))){ - printf("pass2\n"); char* enum_command=malloc(sizeof(char*)); if(!enum_command){ printf("Error allocating memory for the result\n"); @@ -1062,7 +1060,7 @@ int ReadRegister(pcilib_t *handle, const pcilib_model_description_t *model_info, err = pcilib_read_view(handle,bank,regname,viewname,sizeof(char*),enum_command); if (err) printf("Error reading register %s with an enum view\n", reg); else { - printf("%s = %s\n", reg, (char*)enum_command); + printf("%s = %s\n", regname, (char*)enum_command); } free(enum_command); }else{ @@ -1339,7 +1337,7 @@ int WriteRegister(pcilib_t *handle, const pcilib_model_description_t *model_info if((regname)){ char *view_name; - view_name=fullregister+1;; + view_name=s1+1;; err = pcilib_write_view(handle,bank,regname,view_name,sizeof(pcilib_register_value_t),&value); if (err) printf("Error writing register %s using view %s\n",regname,view_name); free(fullregister); diff --git a/xml/test/camera.xml b/xml/test/camera.xml index 021ed61..6506467 100644 --- a/xml/test/camera.xml +++ b/xml/test/camera.xml @@ -463,8 +463,8 @@ formuu1 C - (503975./1024000)*@reg - 27315./100 - (@value + 27315./100)*(102400./503975) + (503975./1024000)*@reg@ - 27315./100 + (@value@ + 27315./100)*(102400./503975) formula to get real fpga temperature from the fpga_temperature register in decimal @@ -476,8 +476,8 @@ formuu2 C - ((1./4)*(@reg + 1200)) if @freq==0 else ((3./10)*(@reg + 1000)) - 4*@value + 1200 if @freq==0 else (10./3)*@value + 1000 + ((1./4)*(@reg@ + 1200)) if @freq@==0 else ((3./10)*(@reg@ + 1000)) + 4*@value@ + 1200 if @freq@==0 else (10./3)*@value@ + 1000 formula to get real sensor temperature from the sensor_temperature register in decimal @@ -503,21 +503,21 @@ - @self+273.15 - @self*(9./5)+32 + @self@+273.15 + @self@*(9./5)+32 - @self-273.15 - (@self-273.15)*(9./5)+32 + @self@-273.15 + (@self@-273.15)*(9./5)+32 - (@self-32)*5./9 - (@self+273.15-32)*5./9 + (@self@-32)*5./9 + (@self@+273.15-32)*5./9 - @self*1000 - @self*1000000 - @self*1000000000 + @self@*1000 + @self@*1000000 + @self@*1000000000 @self/1000 -- cgit v1.2.3 From 16556c4b24e37a4d451b7a85a5d260c4ee9828cb Mon Sep 17 00:00:00 2001 From: "nicolas.zilio@hotmail.fr" <> Date: Tue, 15 Sep 2015 19:25:47 +0200 Subject: no more realloc in op enum --- pcilib/views.c | 9 ++++++--- pcitool/cli.c | 14 +++++--------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/pcilib/views.c b/pcilib/views.c index 83c5827..2011d86 100644 --- a/pcilib/views.c +++ b/pcilib/views.c @@ -139,7 +139,7 @@ int pcilib_read_view(pcilib_t *ctx, const char *bank, const char *regname, const for(j=0;ctx->register_ctx[i].views[j].name;j++){ if(!(strcasecmp("name",ctx->register_ctx[i].views[j].base_unit.name))){/*if we asked for the unit "name"*/ - err=ctx->register_ctx[i].views[j].op(ctx,ctx->register_ctx[i].views[j].parameters,value/*the command name*/,0,&temp_value,0,&(ctx->register_ctx[i].views[j])); + err=ctx->register_ctx[i].views[j].op(ctx,ctx->register_ctx[i].views[j].parameters,value/*the command name*/,0,&temp_value,value_size,NULL); if(err){ pcilib_error("can't read from the register with the enum view"); return PCILIB_ERROR_FAILED; @@ -198,7 +198,7 @@ int pcilib_write_view(pcilib_t *ctx, const char *bank, const char *regname, cons ok=1; break; }else if(!(strcasecmp(ctx->register_ctx[i].views[j].base_unit.name,(char*)unit))){/*in this case we asked for then name of the view in unit*/ - temp_value=*(pcilib_register_value_t*)value /*the value to put in the register*/; + //temp_value=*(pcilib_register_value_t*)value /*the value to put in the register*/; err=ctx->register_ctx[i].views[j].op(ctx,ctx->register_ctx[i].views[j].parameters, (char*)unit, 1, &temp_value,0,&(ctx->register_ctx[i].views[j])); if(err){ pcilib_error("can't write to the register with the formula view %s", unit); @@ -249,7 +249,10 @@ int operation_enum(pcilib_t *ctx, void *params, char* name, int view2reg, pcilib }else if (view2reg==0){ 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){ - name=(char*)realloc(name,strlen(((pcilib_enum_t*)(params))[j].name)*sizeof(char)); + if(viewval_sizeregisters[regid].bank); - format = model_info->banks[bank_id].format; - if (!format) format = "%lu"; + format = "%lf"; err = pcilib_read_view(handle,bank,regname,viewname,sizeof(pcilib_register_value_t),&value); if (err) printf("Error reading register %s with a formula view\n", reg); else { printf("%s = ", reg); printf(format, value); - printf("\n"); + printf("%s\n",viewname); } } } else { @@ -1338,7 +1334,7 @@ int WriteRegister(pcilib_t *handle, const pcilib_model_description_t *model_info if((regname)){ char *view_name; view_name=s1+1;; - err = pcilib_write_view(handle,bank,regname,view_name,sizeof(pcilib_register_value_t),&value); + err = pcilib_write_view(handle,bank,regname,view_name,0,&value); if (err) printf("Error writing register %s using view %s\n",regname,view_name); free(fullregister); }else{ -- cgit v1.2.3 From ae7f83a7948d8c3760f8019899a45e6ec90c2c6a Mon Sep 17 00:00:00 2001 From: "nicolas.zilio@hotmail.fr" <> Date: Tue, 15 Sep 2015 20:11:02 +0200 Subject: bof.... --- pcilib/views.c | 23 +++++++++++++---------- pcitool/cli.c | 2 +- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/pcilib/views.c b/pcilib/views.c index 2011d86..f15aeb4 100644 --- a/pcilib/views.c +++ b/pcilib/views.c @@ -138,8 +138,8 @@ int pcilib_read_view(pcilib_t *ctx, const char *bank, const char *regname, const for(j=0;ctx->register_ctx[i].views[j].name;j++){ - if(!(strcasecmp("name",ctx->register_ctx[i].views[j].base_unit.name))){/*if we asked for the unit "name"*/ - err=ctx->register_ctx[i].views[j].op(ctx,ctx->register_ctx[i].views[j].parameters,value/*the command name*/,0,&temp_value,value_size,NULL); + if(!(strcasecmp("name",(char*)unit))){/*if we asked for the unit "name"*/ + err=ctx->register_ctx[i].views[j].op(ctx,ctx->register_ctx[i].views[j].parameters,NULL/*the command name*/,0,&temp_value,value_size,value); if(err){ pcilib_error("can't read from the register with the enum view"); return PCILIB_ERROR_FAILED; @@ -156,7 +156,9 @@ int pcilib_read_view(pcilib_t *ctx, const char *bank, const char *regname, const }else{ for(k=0;ctx->register_ctx[i].views[j].base_unit.transforms[k].name;k++){ if(!(strcasecmp(ctx->register_ctx[i].views[j].base_unit.transforms[k].name,(char*)unit))){ + ctx->register_ctx[i].views[j].base_unit.transforms[k].name err=ctx->register_ctx[i].views[j].op(ctx,ctx->register_ctx[i].views[j].parameters,(char*)unit, 0, &temp_value,0,&(ctx->register_ctx[i].views[j])); + /***wrong***/ pcilib_view_apply_unit(ctx->register_ctx[i].views[j].base_unit.transforms[k].name,unit,(pcilib_register_value_t*)value); if(err){ pcilib_error("can't write to the register with the formula view %s", unit); return PCILIB_ERROR_FAILED; @@ -189,8 +191,8 @@ int pcilib_write_view(pcilib_t *ctx, const char *bank, const char *regname, cons } for(j=0;ctx->register_ctx[i].views[j].name;j++){ - if(!(strcasecmp(ctx->register_ctx[i].views[j].base_unit.name,"name"))){/*if we asked for the unit "name"*/ - err=ctx->register_ctx[i].views[j].op(ctx,ctx->register_ctx[i].views[j].parameters,(char*)unit/*the command name*/,1,&temp_value,0,&(ctx->register_ctx[i].views[j])); + if(!(strcasecmp((char*)unit,"name"))){/*if we asked for the unit "name"*/ + err=ctx->register_ctx[i].views[j].op(ctx,ctx->register_ctx[i].views[j].parameters,NULL,1,&temp_value,0,value); if(err){ pcilib_error("can't write to the register with the enum view"); return PCILIB_ERROR_FAILED; @@ -209,6 +211,7 @@ int pcilib_write_view(pcilib_t *ctx, const char *bank, const char *regname, cons }else{ for(k=0;ctx->register_ctx[i].views[j].base_unit.transforms[k].name;k++){ if(!(strcasecmp(ctx->register_ctx[i].views[j].base_unit.transforms[k].name,(char*)unit))){ + pcilib_view_apply_unit(ctx->register_ctx[i].views[j].base_unit.transforms[k].name,unit,(pcilib_register_value_t*)value); err=ctx->register_ctx[i].views[j].op(ctx,ctx->register_ctx[i].views[j].parameters, (char*)unit, 1, &temp_value,0,&(ctx->register_ctx[i].views[j])); if(err){ pcilib_error("can't write to the register with the formula view %s", unit); @@ -237,11 +240,11 @@ int pcilib_write_view(pcilib_t *ctx, const char *bank, const char *regname, cons * always : viewval=view params=view params * write: name=enum command regval:the value corresponding to the command */ -int operation_enum(pcilib_t *ctx, void *params, char* name, int view2reg, pcilib_register_value_t *regval, size_t viewval_size, void* viewval){ +int operation_enum(pcilib_t *ctx, void *params, char* unit, int view2reg, pcilib_register_value_t *regval, size_t viewval_size, void* viewval){ int j,k; if(view2reg==1){ for(j=0; ((pcilib_enum_t*)(params))[j].name;j++){ - if(!(strcasecmp(((pcilib_enum_t*)(params))[j].name,name))){ + if(!(strcasecmp(((pcilib_enum_t*)(params))[j].name,(char*)viewval))){ *regval=((pcilib_enum_t*)(params))[j].value; return 0; } @@ -253,9 +256,9 @@ int operation_enum(pcilib_t *ctx, void *params, char* name, int view2reg, pcilib pcilib_error("the string to contain the enum command is too tight"); return PCILIB_ERROR_MEMORY; } - strncpy(name,((pcilib_enum_t*)(params))[j].name, strlen(((pcilib_enum_t*)(params))[j].name)); + strncpy((char*)viewval,((pcilib_enum_t*)(params))[j].name, strlen(((pcilib_enum_t*)(params))[j].name)); k=strlen(((pcilib_enum_t*)(params))[j].name); - name[k]='\0'; + ((char*)viewval)[k]='\0'; return 0; } } @@ -293,7 +296,7 @@ int operation_formula(pcilib_t *ctx, void *params, char* unit, int view2reg, pci } strncpy(formula,((pcilib_formula_t*)params)->read_formula,strlen(((pcilib_formula_t*)params)->read_formula)); pcilib_view_apply_formula(ctx,formula, regval); - pcilib_view_apply_unit(((pcilib_view_t*)viewval)->base_unit.transforms[j],unit,regval); + // pcilib_view_apply_unit(((pcilib_view_t*)viewval)->base_unit.transforms[j],unit,regval); return 0; } } @@ -310,7 +313,7 @@ int operation_formula(pcilib_t *ctx, void *params, char* unit, int view2reg, pci /* when we have found the correct view of type formula, we apply the formula, that get the good value for return*/ 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)); - pcilib_view_apply_unit(((pcilib_view_t*)viewval)->base_unit.transforms[j],unit,&value); + //pcilib_view_apply_unit(((pcilib_view_t*)viewval)->base_unit.transforms[j],unit,regval); pcilib_view_apply_formula(ctx,formula,regval); /* we maybe need some error checking there , like temp_value >min and