ibutton_worker.c 6.5 KB

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