property.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. #define _GNU_SOURCE
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <strings.h>
  5. #include <stdlib.h>
  6. #include <views/register.h>
  7. #include "pci.h"
  8. #include "bank.h"
  9. #include "view.h"
  10. #include "register.h"
  11. #include "property.h"
  12. #include "tools.h"
  13. #include "error.h"
  14. int pcilib_add_register_properties(pcilib_t *ctx, size_t n, const pcilib_register_bank_t *banks, const pcilib_register_description_t *registers) {
  15. int err;
  16. pcilib_register_t i;
  17. pcilib_view_t cur_view = ctx->num_views;
  18. pcilib_view_context_t *view_ctx;
  19. if (!n)
  20. return PCILIB_ERROR_INVALID_ARGUMENT;
  21. for (i = 0; i < n; i++) {
  22. pcilib_access_mode_t mode = 0;
  23. pcilib_register_view_description_t v;
  24. pcilib_register_bank_description_t *b = &ctx->banks[banks[i]];
  25. char *view_name = malloc(strlen(registers[i].name) + strlen(b->name) + 13);
  26. if (!view_name) {
  27. pcilib_clean_views(ctx, cur_view);
  28. return PCILIB_ERROR_MEMORY;
  29. }
  30. sprintf(view_name, "/registers/%s/%s", b->name, registers[i].name);
  31. if ((registers[i].views)&&(registers[i].views[0].view)) {
  32. pcilib_view_t view = pcilib_find_view_by_name(ctx, registers[i].views[0].view);
  33. if (view == PCILIB_VIEW_INVALID) return PCILIB_ERROR_NOTFOUND;
  34. memcpy(&v, ctx->views[view], sizeof(pcilib_view_description_t));
  35. v.view = registers[i].views[0].name;
  36. if (ctx->views[view]->api->read_from_reg) mode |= PCILIB_ACCESS_R;
  37. if (ctx->views[view]->api->write_to_reg) mode |= PCILIB_ACCESS_W;
  38. mode &= ctx->views[view]->mode;
  39. } else {
  40. v.base.type = PCILIB_TYPE_LONG;
  41. mode = PCILIB_ACCESS_RW;
  42. }
  43. v.base.api = &pcilib_register_view_api;
  44. v.base.name = view_name;
  45. v.base.description = registers[i].description;
  46. v.base.mode = registers[i].mode&mode;
  47. v.reg = registers[i].name;
  48. v.bank = b->name;
  49. err = pcilib_add_views(ctx, 1, (pcilib_view_description_t*)&v);
  50. if (err) {
  51. free(view_name);
  52. pcilib_clean_views(ctx, cur_view);
  53. return err;
  54. }
  55. view_ctx = pcilib_find_view_context_by_name(ctx, v.base.name);
  56. view_ctx->flags |= PCILIB_VIEW_FLAG_PROPERTY;
  57. }
  58. return 0;
  59. }
  60. pcilib_property_info_t *pcilib_get_property_list(pcilib_t *ctx, const char *branch, pcilib_list_flags_t flags) {
  61. int err = 0;
  62. size_t pos = 0;
  63. size_t name_offset = 0;
  64. pcilib_view_context_t *view_ctx, *view_tmp;
  65. pcilib_property_info_t *info = (pcilib_property_info_t*)malloc((ctx->num_views + 1) * sizeof(pcilib_property_info_t));
  66. struct dir_hash_s {
  67. char *name;
  68. UT_hash_handle hh;
  69. } *dir_hash = NULL, *dir, *dir_tmp;
  70. if (branch) {
  71. name_offset = strlen(branch);
  72. if (branch[name_offset - 1] != '/') name_offset++;
  73. }
  74. // Find all folders
  75. HASH_ITER(hh, ctx->view_hash, view_ctx, view_tmp) {
  76. const pcilib_view_description_t *v = ctx->views[view_ctx->view];
  77. const char *subname = v->name + name_offset;
  78. const char *suffix;
  79. if (!(view_ctx->flags&PCILIB_VIEW_FLAG_PROPERTY)) continue;
  80. if ((branch)&&(strncasecmp(branch, v->name, strlen(branch)))) continue;
  81. suffix = strchr(subname, '/');
  82. if (suffix) {
  83. char *name = strndup(v->name, suffix - v->name);
  84. if (!name) {
  85. err = PCILIB_ERROR_MEMORY;
  86. break;
  87. }
  88. HASH_FIND_STR(dir_hash, name + name_offset, dir);
  89. if (dir) {
  90. free(name);
  91. continue;
  92. }
  93. dir = (struct dir_hash_s*)malloc(sizeof(struct dir_hash_s));
  94. if (!dir) {
  95. err = PCILIB_ERROR_MEMORY;
  96. break;
  97. }
  98. dir->name = name;
  99. HASH_ADD_KEYPTR(hh, dir_hash, dir->name + name_offset, strlen(dir->name + name_offset), dir);
  100. }
  101. }
  102. HASH_ITER(hh, ctx->view_hash, view_ctx, view_tmp) {
  103. const pcilib_view_description_t *v = ctx->views[view_ctx->view];
  104. const char *subname = v->name + name_offset;
  105. if (!(view_ctx->flags&PCILIB_VIEW_FLAG_PROPERTY)) continue;
  106. if ((branch)&&(strncasecmp(branch, v->name, strlen(branch)))) continue;
  107. if (!strchr(subname, '/')) {
  108. pcilib_view_context_t *found_view;
  109. char *path = strdup(v->name);
  110. if (!path) {
  111. err = PCILIB_ERROR_MEMORY;
  112. break;
  113. }
  114. char *name = strrchr(v->name, '/');
  115. if (name) name++;
  116. else name = path;
  117. HASH_FIND_STR(dir_hash, name, found_view);
  118. info[pos++] = (pcilib_property_info_t) {
  119. .name = name,
  120. .path = path,
  121. .description = v->description,
  122. .type = v->type,
  123. .mode = v->mode,
  124. .unit = v->unit,
  125. .flags = (found_view?PCILIB_LIST_FLAG_CHILDS:0)
  126. };
  127. if (found_view) HASH_DEL(dir_hash, found_view);
  128. }
  129. }
  130. HASH_ITER(hh, dir_hash, dir, dir_tmp) {
  131. char *name = strrchr(dir->name, '/');
  132. if (name) name++;
  133. else name = dir->name;
  134. info[pos++] = (pcilib_property_info_t) {
  135. .name = name,
  136. .path = dir->name,
  137. .type = PCILIB_TYPE_INVALID,
  138. .flags = PCILIB_LIST_FLAG_CHILDS
  139. };
  140. }
  141. HASH_CLEAR(hh, dir_hash);
  142. memset(&info[pos], 0, sizeof(pcilib_property_info_t));
  143. if (err) {
  144. pcilib_free_property_info(ctx, info);
  145. return NULL;
  146. }
  147. return info;
  148. }
  149. void pcilib_free_property_info(pcilib_t *ctx, pcilib_property_info_t *info) {
  150. int i;
  151. for (i = 0; info[i].path; i++)
  152. free((char*)info[i].path);
  153. free(info);
  154. }
  155. int pcilib_get_property(pcilib_t *ctx, const char *prop, pcilib_value_t *val) {
  156. return pcilib_read_register_view(ctx, NULL, NULL, prop, val);
  157. }
  158. int pcilib_set_property(pcilib_t *ctx, const char *prop, const pcilib_value_t *val) {
  159. return pcilib_write_register_view(ctx, NULL, NULL, prop, val);
  160. }