ibutton_protocols.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. #include "ibutton_protocols.h"
  2. #include <storage/storage.h>
  3. #include "ibutton_key_i.h"
  4. #include "protocols/protocol_group_defs.h"
  5. #define IBUTTON_FILE_TYPE "Flipper iButton key"
  6. #define IBUTTON_PROTOCOL_KEY_V1 "Key type"
  7. #define IBUTTON_PROTOCOL_KEY_V2 "Protocol"
  8. #define IBUTTON_CURRENT_FORMAT_VERSION 2U
  9. #define GET_PROTOCOL_GROUP(id) \
  10. iButtonProtocolGroupInfo info; \
  11. ibutton_protocols_get_group_by_id(protocols, (id), &info);
  12. #define GROUP_BASE (info.base)
  13. #define GROUP_DATA (info.group)
  14. #define PROTOCOL_ID (info.id)
  15. struct iButtonProtocols {
  16. iButtonProtocolGroupData** group_datas;
  17. };
  18. typedef struct {
  19. const iButtonProtocolGroupBase* base;
  20. iButtonProtocolGroupData* group;
  21. iButtonProtocolLocalId id;
  22. } iButtonProtocolGroupInfo;
  23. static void ibutton_protocols_get_group_by_id(
  24. iButtonProtocols* protocols,
  25. iButtonProtocolId id,
  26. iButtonProtocolGroupInfo* info) {
  27. iButtonProtocolLocalId local_id = id;
  28. for(iButtonProtocolGroupId i = 0; i < iButtonProtocolGroupMax; ++i) {
  29. if(local_id < (signed)ibutton_protocol_groups[i]->protocol_count) {
  30. info->base = ibutton_protocol_groups[i];
  31. info->group = protocols->group_datas[i];
  32. info->id = local_id;
  33. return;
  34. } else {
  35. local_id -= ibutton_protocol_groups[i]->protocol_count;
  36. }
  37. }
  38. furi_crash(NULL);
  39. }
  40. iButtonProtocols* ibutton_protocols_alloc() {
  41. iButtonProtocols* protocols = malloc(sizeof(iButtonProtocols*));
  42. protocols->group_datas = malloc(sizeof(iButtonProtocolGroupData*) * iButtonProtocolGroupMax);
  43. for(iButtonProtocolGroupId i = 0; i < iButtonProtocolGroupMax; ++i) {
  44. protocols->group_datas[i] = ibutton_protocol_groups[i]->alloc();
  45. }
  46. return protocols;
  47. }
  48. void ibutton_protocols_free(iButtonProtocols* protocols) {
  49. for(iButtonProtocolGroupId i = 0; i < iButtonProtocolGroupMax; ++i) {
  50. ibutton_protocol_groups[i]->free(protocols->group_datas[i]);
  51. }
  52. free(protocols->group_datas);
  53. free(protocols);
  54. }
  55. uint32_t ibutton_protocols_get_protocol_count() {
  56. uint32_t count = 0;
  57. for(iButtonProtocolGroupId i = 0; i < iButtonProtocolGroupMax; ++i) {
  58. count += ibutton_protocol_groups[i]->protocol_count;
  59. }
  60. return count;
  61. }
  62. iButtonProtocolId ibutton_protocols_get_id_by_name(iButtonProtocols* protocols, const char* name) {
  63. iButtonProtocolLocalId offset = 0;
  64. for(iButtonProtocolGroupId i = 0; i < iButtonProtocolGroupMax; ++i) {
  65. iButtonProtocolLocalId local_id;
  66. if(ibutton_protocol_groups[i]->get_id_by_name(protocols->group_datas[i], &local_id, name)) {
  67. return local_id + offset;
  68. }
  69. offset += ibutton_protocol_groups[i]->protocol_count;
  70. }
  71. return iButtonProtocolIdInvalid;
  72. }
  73. uint32_t ibutton_protocols_get_features(iButtonProtocols* protocols, iButtonProtocolId id) {
  74. GET_PROTOCOL_GROUP(id);
  75. return GROUP_BASE->get_features(GROUP_DATA, PROTOCOL_ID);
  76. }
  77. size_t ibutton_protocols_get_max_data_size(iButtonProtocols* protocols) {
  78. size_t max_size = 0;
  79. for(iButtonProtocolGroupId i = 0; i < iButtonProtocolGroupMax; ++i) {
  80. const size_t current_max_size =
  81. ibutton_protocol_groups[i]->get_max_data_size(protocols->group_datas[i]);
  82. if(current_max_size > max_size) {
  83. max_size = current_max_size;
  84. }
  85. }
  86. return max_size;
  87. }
  88. const char* ibutton_protocols_get_manufacturer(iButtonProtocols* protocols, iButtonProtocolId id) {
  89. GET_PROTOCOL_GROUP(id);
  90. return GROUP_BASE->get_manufacturer(GROUP_DATA, PROTOCOL_ID);
  91. }
  92. const char* ibutton_protocols_get_name(iButtonProtocols* protocols, iButtonProtocolId id) {
  93. GET_PROTOCOL_GROUP(id);
  94. return GROUP_BASE->get_name(GROUP_DATA, PROTOCOL_ID);
  95. }
  96. bool ibutton_protocols_read(iButtonProtocols* protocols, iButtonKey* key) {
  97. iButtonProtocolLocalId id = iButtonProtocolIdInvalid;
  98. iButtonProtocolData* data = ibutton_key_get_protocol_data(key);
  99. iButtonProtocolLocalId offset = 0;
  100. for(iButtonProtocolGroupId i = 0; i < iButtonProtocolGroupMax; ++i) {
  101. if(ibutton_protocol_groups[i]->read(protocols->group_datas[i], data, &id)) {
  102. id += offset;
  103. break;
  104. }
  105. offset += ibutton_protocol_groups[i]->protocol_count;
  106. }
  107. ibutton_key_set_protocol_id(key, id);
  108. return id != iButtonProtocolIdInvalid;
  109. }
  110. bool ibutton_protocols_write_blank(iButtonProtocols* protocols, iButtonKey* key) {
  111. const iButtonProtocolId id = ibutton_key_get_protocol_id(key);
  112. iButtonProtocolData* data = ibutton_key_get_protocol_data(key);
  113. GET_PROTOCOL_GROUP(id);
  114. return GROUP_BASE->write_blank(GROUP_DATA, data, PROTOCOL_ID);
  115. }
  116. bool ibutton_protocols_write_copy(iButtonProtocols* protocols, iButtonKey* key) {
  117. const iButtonProtocolId id = ibutton_key_get_protocol_id(key);
  118. iButtonProtocolData* data = ibutton_key_get_protocol_data(key);
  119. GET_PROTOCOL_GROUP(id);
  120. return GROUP_BASE->write_copy(GROUP_DATA, data, PROTOCOL_ID);
  121. }
  122. void ibutton_protocols_emulate_start(iButtonProtocols* protocols, iButtonKey* key) {
  123. const iButtonProtocolId id = ibutton_key_get_protocol_id(key);
  124. iButtonProtocolData* data = ibutton_key_get_protocol_data(key);
  125. GET_PROTOCOL_GROUP(id);
  126. GROUP_BASE->emulate_start(GROUP_DATA, data, PROTOCOL_ID);
  127. }
  128. void ibutton_protocols_emulate_stop(iButtonProtocols* protocols, iButtonKey* key) {
  129. const iButtonProtocolId id = ibutton_key_get_protocol_id(key);
  130. iButtonProtocolData* data = ibutton_key_get_protocol_data(key);
  131. GET_PROTOCOL_GROUP(id);
  132. GROUP_BASE->emulate_stop(GROUP_DATA, data, PROTOCOL_ID);
  133. }
  134. bool ibutton_protocols_save(
  135. iButtonProtocols* protocols,
  136. const iButtonKey* key,
  137. const char* file_name) {
  138. const iButtonProtocolId id = ibutton_key_get_protocol_id(key);
  139. const iButtonProtocolData* data = ibutton_key_get_protocol_data(key);
  140. bool success = false;
  141. Storage* storage = furi_record_open(RECORD_STORAGE);
  142. FlipperFormat* ff = flipper_format_buffered_file_alloc(storage);
  143. do {
  144. const char* protocol_name = ibutton_protocols_get_name(protocols, id);
  145. if(!flipper_format_buffered_file_open_always(ff, file_name)) break;
  146. if(!flipper_format_write_header_cstr(ff, IBUTTON_FILE_TYPE, IBUTTON_CURRENT_FORMAT_VERSION))
  147. break;
  148. if(!flipper_format_write_string_cstr(ff, IBUTTON_PROTOCOL_KEY_V2, protocol_name)) break;
  149. GET_PROTOCOL_GROUP(id);
  150. if(!GROUP_BASE->save(GROUP_DATA, data, PROTOCOL_ID, ff)) break;
  151. success = true;
  152. } while(false);
  153. flipper_format_free(ff);
  154. furi_record_close(RECORD_STORAGE);
  155. return success;
  156. }
  157. bool ibutton_protocols_load(iButtonProtocols* protocols, iButtonKey* key, const char* file_name) {
  158. iButtonProtocolData* data = ibutton_key_get_protocol_data(key);
  159. bool success = false;
  160. Storage* storage = furi_record_open(RECORD_STORAGE);
  161. FlipperFormat* ff = flipper_format_buffered_file_alloc(storage);
  162. FuriString* tmp = furi_string_alloc();
  163. do {
  164. if(!flipper_format_buffered_file_open_existing(ff, file_name)) break;
  165. uint32_t version;
  166. if(!flipper_format_read_header(ff, tmp, &version)) break;
  167. if(!furi_string_equal(tmp, IBUTTON_FILE_TYPE)) break;
  168. if(version == 1) {
  169. if(!flipper_format_read_string(ff, IBUTTON_PROTOCOL_KEY_V1, tmp)) break;
  170. } else if(version == 2) {
  171. if(!flipper_format_read_string(ff, IBUTTON_PROTOCOL_KEY_V2, tmp)) break;
  172. } else {
  173. break;
  174. }
  175. const iButtonProtocolId id =
  176. ibutton_protocols_get_id_by_name(protocols, furi_string_get_cstr(tmp));
  177. ibutton_key_set_protocol_id(key, id);
  178. GET_PROTOCOL_GROUP(id);
  179. if(!GROUP_BASE->load(GROUP_DATA, data, PROTOCOL_ID, version, ff)) break;
  180. success = true;
  181. } while(false);
  182. flipper_format_free(ff);
  183. furi_string_free(tmp);
  184. furi_record_close(RECORD_STORAGE);
  185. return success;
  186. }
  187. void ibutton_protocols_render_data(
  188. iButtonProtocols* protocols,
  189. const iButtonKey* key,
  190. FuriString* result) {
  191. const iButtonProtocolId id = ibutton_key_get_protocol_id(key);
  192. const iButtonProtocolData* data = ibutton_key_get_protocol_data(key);
  193. GET_PROTOCOL_GROUP(id);
  194. GROUP_BASE->render_data(GROUP_DATA, data, PROTOCOL_ID, result);
  195. }
  196. void ibutton_protocols_render_brief_data(
  197. iButtonProtocols* protocols,
  198. const iButtonKey* key,
  199. FuriString* result) {
  200. const iButtonProtocolId id = ibutton_key_get_protocol_id(key);
  201. const iButtonProtocolData* data = ibutton_key_get_protocol_data(key);
  202. GET_PROTOCOL_GROUP(id);
  203. GROUP_BASE->render_brief_data(GROUP_DATA, data, PROTOCOL_ID, result);
  204. }
  205. void ibutton_protocols_render_error(
  206. iButtonProtocols* protocols,
  207. const iButtonKey* key,
  208. FuriString* result) {
  209. const iButtonProtocolId id = ibutton_key_get_protocol_id(key);
  210. const iButtonProtocolData* data = ibutton_key_get_protocol_data(key);
  211. GET_PROTOCOL_GROUP(id);
  212. GROUP_BASE->render_error(GROUP_DATA, data, PROTOCOL_ID, result);
  213. }
  214. bool ibutton_protocols_is_valid(iButtonProtocols* protocols, const iButtonKey* key) {
  215. const iButtonProtocolId id = ibutton_key_get_protocol_id(key);
  216. const iButtonProtocolData* data = ibutton_key_get_protocol_data(key);
  217. GET_PROTOCOL_GROUP(id);
  218. return GROUP_BASE->is_valid(GROUP_DATA, data, PROTOCOL_ID);
  219. }
  220. void ibutton_protocols_get_editable_data(
  221. iButtonProtocols* protocols,
  222. const iButtonKey* key,
  223. iButtonEditableData* editable) {
  224. const iButtonProtocolId id = ibutton_key_get_protocol_id(key);
  225. iButtonProtocolData* data = ibutton_key_get_protocol_data(key);
  226. GET_PROTOCOL_GROUP(id);
  227. GROUP_BASE->get_editable_data(GROUP_DATA, data, PROTOCOL_ID, editable);
  228. }
  229. void ibutton_protocols_apply_edits(iButtonProtocols* protocols, const iButtonKey* key) {
  230. const iButtonProtocolId id = ibutton_key_get_protocol_id(key);
  231. iButtonProtocolData* data = ibutton_key_get_protocol_data(key);
  232. GET_PROTOCOL_GROUP(id);
  233. GROUP_BASE->apply_edits(GROUP_DATA, data, PROTOCOL_ID);
  234. }