#include #include "pci.h" #include "pcilib.h" #include #include "views.h" #include "error.h" #include #include /** * this function calls the python script and the function "evaluate" in it to evaluate the given formula *@param[in] the formula to be evaluated *@return the integer value of the evaluated formula (maybe go to float instead) */ static pcilib_register_value_t pcilib_view_eval_formula(char* formula){ /* initialization of python interpreter*/ Py_Initialize(); /*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(); pcilib_register_value_t value=(pcilib_register_value_t)c; return value; } /** * */ static char* pcilib_view_compute_formula(pcilib_t* ctx, char* formula,char* reg_value_string){ char *src=(char*)formula; char *reg,*regend; char *dst=malloc(6*strlen(src)*sizeof(char)); char temp[66]; pcilib_register_value_t value; int offset=0; /*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*/ while(1){ reg = strchr(src, '@'); if (!reg) { strcpy(dst, src); break; } regend = strchr(reg + 1, '@'); if (!regend){ pcilib_error("formula corresponding is malformed"); return NULL; } strncpy(dst+offset, src, reg - src); offset+=reg-src; *regend = 0; /* 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"))){ 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); strncpy(dst+offset,temp,strlen(temp)); offset+=strlen(temp); } src = regend + 1; } return dst; } static int pcilib_view_apply_formula(pcilib_t* ctx, char* formula, pcilib_register_value_t* reg_value) { 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; } /* evaluation of the formula*/ *reg_value= pcilib_view_eval_formula(formula); return 0; } /** * 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; formula=malloc(strlen(unit_desc.transform_formula)*sizeof(char)); strcpy(formula,unit_desc.transform_formula); pcilib_view_apply_formula(NULL,formula, value); free(formula); } 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; /* 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*/ 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; } 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; } 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; } *(pcilib_register_value_t*)value=temp_value; break; } return 0; } pcilib_error("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 *unit, size_t value_size,void* value){ int i,j; pcilib_register_value_t temp_value; 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.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,(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; } break; } pcilib_write_register(ctx,bank,regname,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 * 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 j,k; if(view2reg==1){ 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_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; } } } return PCILIB_ERROR_INVALID_REQUEST; } /** * 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; pcilib_register_value_t value=0; char* formula=NULL; 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)){ 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); return 0; } 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)){ 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); pcilib_view_apply_unit(((pcilib_view_t*)viewval)->base_unit.transforms[j],unit,&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); return 0; } 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.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 + 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; } 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; }