furi.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. #include "furi.h"
  2. #include "cmsis_os.h"
  3. #include <string.h>
  4. // TODO: this file contains printf, that not implemented on uC target
  5. #ifdef FURI_DEBUG
  6. #include <stdio.h>
  7. #endif
  8. #define MAX_RECORD_COUNT 32
  9. static FuriRecord records[MAX_RECORD_COUNT];
  10. static size_t current_buffer_idx = 0;
  11. // find record pointer by name
  12. static FuriRecord* find_record(const char* name) {
  13. if(name == NULL) return NULL;
  14. FuriRecord* res = NULL;
  15. for(size_t i = 0; i < MAX_RECORD_COUNT; i++) {
  16. if(records[i].name != NULL && strcmp(name, records[i].name) == 0) {
  17. res = &records[i];
  18. }
  19. }
  20. return res;
  21. }
  22. // TODO: change open-create to only open
  23. bool furi_create(const char* name, void* value, size_t size) {
  24. #ifdef FURI_DEBUG
  25. printf("[FURI] creating %s record\n", name);
  26. #endif
  27. FuriRecord* record = find_record(name);
  28. if(record != NULL) {
  29. #ifdef FURI_DEBUG
  30. printf("[FURI] record already exist\n");
  31. #endif
  32. record->value = value;
  33. record->size = size;
  34. return true;
  35. }
  36. // record not exist, create new
  37. if(current_buffer_idx >= MAX_RECORD_COUNT) {
  38. // max record count exceed
  39. #ifdef FURI_DEBUG
  40. printf("[FURI] create: max record count exceed\n");
  41. #endif
  42. return NULL;
  43. }
  44. records[current_buffer_idx].mute_counter = 0;
  45. records[current_buffer_idx].mutex =
  46. xSemaphoreCreateMutexStatic(&records[current_buffer_idx].mutex_buffer);
  47. records[current_buffer_idx].value = value;
  48. records[current_buffer_idx].size = size;
  49. records[current_buffer_idx].name = name;
  50. for(size_t i = 0; i < MAX_RECORD_SUBSCRIBERS; i++) {
  51. records[current_buffer_idx].subscribers[i].allocated = false;
  52. records[current_buffer_idx].subscribers[i].ctx = NULL;
  53. }
  54. current_buffer_idx++;
  55. return true;
  56. }
  57. FuriRecordSubscriber* furi_open(
  58. const char* name,
  59. bool solo,
  60. bool no_mute,
  61. FlipperRecordCallback value_callback,
  62. FlipperRecordStateCallback state_callback,
  63. void* ctx) {
  64. #ifdef FURI_DEBUG
  65. printf("[FURI] opening %s record\n", name);
  66. #endif
  67. // get furi record by name
  68. FuriRecord* record = find_record(name);
  69. if(record == NULL) {
  70. // cannot find record
  71. #ifdef FURI_DEBUG
  72. printf("[FURI] cannot find record %s\n", name);
  73. #endif
  74. // create record if not exist
  75. if(!furi_create(name, NULL, 0)) {
  76. return NULL;
  77. }
  78. record = find_record(name);
  79. if(record == NULL) {
  80. return NULL;
  81. }
  82. }
  83. // allocate subscriber
  84. FuriRecordSubscriber* subscriber = NULL;
  85. for(size_t i = 0; i < MAX_RECORD_SUBSCRIBERS; i++) {
  86. if(!record->subscribers[i].allocated) {
  87. subscriber = &record->subscribers[i];
  88. break;
  89. }
  90. }
  91. if(subscriber == NULL) {
  92. // cannot add subscriber (full)
  93. #ifdef FURI_DEBUG
  94. printf("[FURI] open: cannot add subscriber (full)\n");
  95. #endif
  96. return NULL;
  97. }
  98. // increase mute_counter
  99. if(solo) {
  100. record->mute_counter++;
  101. }
  102. // set all parameters
  103. subscriber->allocated = true;
  104. subscriber->mute_counter = record->mute_counter;
  105. subscriber->no_mute = no_mute;
  106. subscriber->cb = value_callback;
  107. subscriber->state_cb = state_callback;
  108. subscriber->record = record;
  109. subscriber->ctx = ctx;
  110. // register record in application
  111. FuriApp* current_task = find_task(xTaskGetCurrentTaskHandle());
  112. if(current_task != NULL) {
  113. current_task->records[current_task->records_count] = record;
  114. current_task->records_count++;
  115. } else {
  116. #ifdef FURI_DEBUG
  117. printf("[FURI] open: no current task\n");
  118. #endif
  119. }
  120. return subscriber;
  121. }
  122. void furi_close(FuriRecordSubscriber* handler) {
  123. #ifdef FURI_DEBUG
  124. printf("[FURI] closing %s record\n", handler->record->name);
  125. #endif
  126. // deallocate subscriber
  127. handler->allocated = false;
  128. // set mute counter to next max value
  129. uint8_t max_mute_counter = 0;
  130. for(size_t i = 0; i < MAX_RECORD_SUBSCRIBERS; i++) {
  131. if(handler->record->subscribers[i].allocated) {
  132. if(handler->record->subscribers[i].mute_counter > max_mute_counter) {
  133. max_mute_counter = handler->record->subscribers[i].mute_counter;
  134. }
  135. }
  136. }
  137. handler->record->mute_counter = max_mute_counter;
  138. }
  139. static void furi_notify(FuriRecordSubscriber* handler, const void* value, size_t size) {
  140. for(size_t i = 0; i < MAX_RECORD_SUBSCRIBERS; i++) {
  141. if(handler->record->subscribers[i].allocated) {
  142. if(handler->record->subscribers[i].cb != NULL) {
  143. handler->record->subscribers[i].cb(
  144. value, size, handler->record->subscribers[i].ctx);
  145. }
  146. }
  147. }
  148. }
  149. void* furi_take(FuriRecordSubscriber* handler) {
  150. if(handler == NULL || handler->record == NULL) return NULL;
  151. if(xSemaphoreTake(handler->record->mutex, portMAX_DELAY) == pdTRUE) {
  152. return handler->record->value;
  153. } else {
  154. return NULL;
  155. }
  156. }
  157. void furi_give(FuriRecordSubscriber* handler) {
  158. if(handler == NULL || handler->record == NULL) return;
  159. xSemaphoreGive(handler->record->mutex);
  160. }
  161. void furi_commit(FuriRecordSubscriber* handler) {
  162. if(handler == NULL || handler->record == NULL) return;
  163. furi_notify(handler, handler->record->value, handler->record->size);
  164. furi_give(handler);
  165. }
  166. bool furi_read(FuriRecordSubscriber* handler, void* value, size_t size) {
  167. #ifdef FURI_DEBUG
  168. printf("[FURI] read from %s\n", handler->record->name);
  169. #endif
  170. if(handler == NULL || handler->record == NULL || value == NULL) return false;
  171. if(size > handler->record->size) return false;
  172. // return false if read from pipe
  173. if(handler->record->value == NULL) return false;
  174. furi_take(handler);
  175. memcpy(value, handler->record->value, size);
  176. furi_notify(handler, value, size);
  177. furi_give(handler);
  178. return true;
  179. }
  180. bool furi_write(FuriRecordSubscriber* handler, const void* value, size_t size) {
  181. #ifdef FURI_DEBUG
  182. printf("[FURI] write to %s\n", handler->record->name);
  183. #endif
  184. if(handler == NULL || handler->record == NULL || value == NULL) {
  185. #ifdef FURI_DEBUG
  186. printf(
  187. "[FURI] write: null param %x %x\n",
  188. (uint32_t)(size_t)handler,
  189. (uint32_t)(size_t)value);
  190. #endif
  191. return false;
  192. }
  193. // check if closed
  194. if(!handler->allocated) {
  195. #ifdef FURI_DEBUG
  196. printf("[FURI] write: handler closed\n");
  197. #endif
  198. return false;
  199. }
  200. if(handler->record->value != NULL && size > handler->record->size) {
  201. #ifdef FURI_DEBUG
  202. printf("[FURI] write: wrong size %d\n", (uint32_t)size);
  203. #endif
  204. return false;
  205. }
  206. // check mute
  207. if(handler->record->mute_counter != handler->mute_counter && !handler->no_mute) {
  208. #ifdef FURI_DEBUG
  209. printf("[FURI] write: muted\n");
  210. #endif
  211. return false;
  212. }
  213. furi_take(handler);
  214. if(handler->record->value != NULL) {
  215. // real write to value
  216. memcpy(handler->record->value, value, size);
  217. // notify subscribers
  218. furi_notify(handler, handler->record->value, handler->record->size);
  219. } else {
  220. furi_notify(handler, value, size);
  221. }
  222. furi_give(handler);
  223. return true;
  224. }