#include #include "pci.h" #include "pcilib.h" #include #include "views.h" #include "error.h" #include #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. * @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; } /** * 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;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,direction); /* computation of @reg with register value*/ 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 *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_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; 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); 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; 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,&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(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); 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); *regval=value; /* we maybe need some error checking there , like temp_value >min and 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 */ 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; }