furi-deprecated.c 7.1 KB

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