ibutton_worker.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. #include <furi.h>
  2. #include <furi_hal.h>
  3. #include <atomic.h>
  4. #include "ibutton_worker_i.h"
  5. typedef enum {
  6. iButtonMessageEnd,
  7. iButtonMessageStop,
  8. iButtonMessageRead,
  9. iButtonMessageWrite,
  10. iButtonMessageEmulate,
  11. iButtonMessageNotifyEmulate,
  12. } iButtonMessageType;
  13. typedef struct {
  14. iButtonMessageType type;
  15. union {
  16. iButtonKey* key;
  17. } data;
  18. } iButtonMessage;
  19. static int32_t ibutton_worker_thread(void* thread_context);
  20. iButtonWorker* ibutton_worker_alloc() {
  21. iButtonWorker* worker = malloc(sizeof(iButtonWorker));
  22. worker->key_p = NULL;
  23. worker->key_data = malloc(ibutton_key_get_max_size());
  24. worker->host = onewire_host_alloc();
  25. worker->slave = onewire_slave_alloc();
  26. worker->writer = ibutton_writer_alloc(worker->host);
  27. worker->device = onewire_device_alloc(0, 0, 0, 0, 0, 0, 0, 0);
  28. worker->messages = furi_message_queue_alloc(1, sizeof(iButtonMessage));
  29. worker->mode_index = iButtonWorkerIdle;
  30. worker->read_cb = NULL;
  31. worker->write_cb = NULL;
  32. worker->emulate_cb = NULL;
  33. worker->cb_ctx = NULL;
  34. worker->thread = furi_thread_alloc();
  35. furi_thread_set_name(worker->thread, "ibutton_worker");
  36. furi_thread_set_callback(worker->thread, ibutton_worker_thread);
  37. furi_thread_set_context(worker->thread, worker);
  38. furi_thread_set_stack_size(worker->thread, 2048);
  39. worker->protocols = protocol_dict_alloc(ibutton_protocols, iButtonProtocolMax);
  40. return worker;
  41. }
  42. void ibutton_worker_read_set_callback(
  43. iButtonWorker* worker,
  44. iButtonWorkerReadCallback callback,
  45. void* context) {
  46. furi_check(worker->mode_index == iButtonWorkerIdle);
  47. worker->read_cb = callback;
  48. worker->cb_ctx = context;
  49. }
  50. void ibutton_worker_write_set_callback(
  51. iButtonWorker* worker,
  52. iButtonWorkerWriteCallback callback,
  53. void* context) {
  54. furi_check(worker->mode_index == iButtonWorkerIdle);
  55. worker->write_cb = callback;
  56. worker->cb_ctx = context;
  57. }
  58. void ibutton_worker_emulate_set_callback(
  59. iButtonWorker* worker,
  60. iButtonWorkerEmulateCallback callback,
  61. void* context) {
  62. furi_check(worker->mode_index == iButtonWorkerIdle);
  63. worker->emulate_cb = callback;
  64. worker->cb_ctx = context;
  65. }
  66. void ibutton_worker_read_start(iButtonWorker* worker, iButtonKey* key) {
  67. iButtonMessage message = {.type = iButtonMessageRead, .data.key = key};
  68. furi_check(
  69. furi_message_queue_put(worker->messages, &message, FuriWaitForever) == FuriStatusOk);
  70. }
  71. void ibutton_worker_write_start(iButtonWorker* worker, iButtonKey* key) {
  72. iButtonMessage message = {.type = iButtonMessageWrite, .data.key = key};
  73. furi_check(
  74. furi_message_queue_put(worker->messages, &message, FuriWaitForever) == FuriStatusOk);
  75. }
  76. void ibutton_worker_emulate_start(iButtonWorker* worker, iButtonKey* key) {
  77. iButtonMessage message = {.type = iButtonMessageEmulate, .data.key = key};
  78. furi_check(
  79. furi_message_queue_put(worker->messages, &message, FuriWaitForever) == FuriStatusOk);
  80. }
  81. void ibutton_worker_stop(iButtonWorker* worker) {
  82. iButtonMessage message = {.type = iButtonMessageStop};
  83. furi_check(
  84. furi_message_queue_put(worker->messages, &message, FuriWaitForever) == FuriStatusOk);
  85. }
  86. void ibutton_worker_free(iButtonWorker* worker) {
  87. ibutton_writer_free(worker->writer);
  88. onewire_slave_free(worker->slave);
  89. onewire_host_free(worker->host);
  90. onewire_device_free(worker->device);
  91. protocol_dict_free(worker->protocols);
  92. furi_message_queue_free(worker->messages);
  93. furi_thread_free(worker->thread);
  94. free(worker->key_data);
  95. free(worker);
  96. }
  97. void ibutton_worker_start_thread(iButtonWorker* worker) {
  98. furi_thread_start(worker->thread);
  99. }
  100. void ibutton_worker_stop_thread(iButtonWorker* worker) {
  101. iButtonMessage message = {.type = iButtonMessageEnd};
  102. furi_check(
  103. furi_message_queue_put(worker->messages, &message, FuriWaitForever) == FuriStatusOk);
  104. furi_thread_join(worker->thread);
  105. }
  106. void ibutton_worker_switch_mode(iButtonWorker* worker, iButtonWorkerMode mode) {
  107. ibutton_worker_modes[worker->mode_index].stop(worker);
  108. worker->mode_index = mode;
  109. ibutton_worker_modes[worker->mode_index].start(worker);
  110. }
  111. void ibutton_worker_notify_emulate(iButtonWorker* worker) {
  112. iButtonMessage message = {.type = iButtonMessageNotifyEmulate};
  113. furi_check(furi_message_queue_put(worker->messages, &message, 0) == FuriStatusOk);
  114. }
  115. void ibutton_worker_set_key_p(iButtonWorker* worker, iButtonKey* key) {
  116. worker->key_p = key;
  117. }
  118. static int32_t ibutton_worker_thread(void* thread_context) {
  119. iButtonWorker* worker = thread_context;
  120. bool running = true;
  121. iButtonMessage message;
  122. FuriStatus status;
  123. ibutton_worker_modes[worker->mode_index].start(worker);
  124. while(running) {
  125. status = furi_message_queue_get(
  126. worker->messages, &message, ibutton_worker_modes[worker->mode_index].quant);
  127. if(status == FuriStatusOk) {
  128. switch(message.type) {
  129. case iButtonMessageEnd:
  130. ibutton_worker_switch_mode(worker, iButtonWorkerIdle);
  131. ibutton_worker_set_key_p(worker, NULL);
  132. running = false;
  133. break;
  134. case iButtonMessageStop:
  135. ibutton_worker_switch_mode(worker, iButtonWorkerIdle);
  136. ibutton_worker_set_key_p(worker, NULL);
  137. break;
  138. case iButtonMessageRead:
  139. ibutton_worker_set_key_p(worker, message.data.key);
  140. ibutton_worker_switch_mode(worker, iButtonWorkerRead);
  141. break;
  142. case iButtonMessageWrite:
  143. ibutton_worker_set_key_p(worker, message.data.key);
  144. ibutton_worker_switch_mode(worker, iButtonWorkerWrite);
  145. break;
  146. case iButtonMessageEmulate:
  147. ibutton_worker_set_key_p(worker, message.data.key);
  148. ibutton_worker_switch_mode(worker, iButtonWorkerEmulate);
  149. break;
  150. case iButtonMessageNotifyEmulate:
  151. if(worker->emulate_cb) {
  152. worker->emulate_cb(worker->cb_ctx, true);
  153. }
  154. break;
  155. }
  156. } else if(status == FuriStatusErrorTimeout) {
  157. ibutton_worker_modes[worker->mode_index].tick(worker);
  158. } else {
  159. furi_crash("iButton worker error");
  160. }
  161. }
  162. ibutton_worker_modes[worker->mode_index].stop(worker);
  163. return 0;
  164. }