protocol_em4100.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. #include <furi.h>
  2. #include <toolbox/protocols/protocol.h>
  3. #include <toolbox/manchester_decoder.h>
  4. #include "lfrfid_protocols.h"
  5. typedef uint64_t EM4100DecodedData;
  6. #define EM_HEADER_POS (55)
  7. #define EM_HEADER_MASK (0x1FFLLU << EM_HEADER_POS)
  8. #define EM_FIRST_ROW_POS (50)
  9. #define EM_ROW_COUNT (10)
  10. #define EM_COLUMN_COUNT (4)
  11. #define EM_BITS_PER_ROW_COUNT (EM_COLUMN_COUNT + 1)
  12. #define EM_COLUMN_POS (4)
  13. #define EM_STOP_POS (0)
  14. #define EM_STOP_MASK (0x1LLU << EM_STOP_POS)
  15. #define EM_HEADER_AND_STOP_MASK (EM_HEADER_MASK | EM_STOP_MASK)
  16. #define EM_HEADER_AND_STOP_DATA (EM_HEADER_MASK)
  17. #define EM4100_DECODED_DATA_SIZE (5)
  18. #define EM4100_ENCODED_DATA_SIZE (sizeof(EM4100DecodedData))
  19. #define EM4100_CLOCK_PER_BIT (64)
  20. #define EM_READ_SHORT_TIME (256)
  21. #define EM_READ_LONG_TIME (512)
  22. #define EM_READ_JITTER_TIME (100)
  23. #define EM_READ_SHORT_TIME_LOW (EM_READ_SHORT_TIME - EM_READ_JITTER_TIME)
  24. #define EM_READ_SHORT_TIME_HIGH (EM_READ_SHORT_TIME + EM_READ_JITTER_TIME)
  25. #define EM_READ_LONG_TIME_LOW (EM_READ_LONG_TIME - EM_READ_JITTER_TIME)
  26. #define EM_READ_LONG_TIME_HIGH (EM_READ_LONG_TIME + EM_READ_JITTER_TIME)
  27. typedef struct {
  28. uint8_t data[EM4100_DECODED_DATA_SIZE];
  29. EM4100DecodedData encoded_data;
  30. uint8_t encoded_data_index;
  31. bool encoded_polarity;
  32. ManchesterState decoder_manchester_state;
  33. } ProtocolEM4100;
  34. ProtocolEM4100* protocol_em4100_alloc(void) {
  35. ProtocolEM4100* proto = malloc(sizeof(ProtocolEM4100));
  36. return (void*)proto;
  37. };
  38. void protocol_em4100_free(ProtocolEM4100* proto) {
  39. free(proto);
  40. };
  41. uint8_t* protocol_em4100_get_data(ProtocolEM4100* proto) {
  42. return proto->data;
  43. };
  44. static void em4100_decode(
  45. const uint8_t* encoded_data,
  46. const uint8_t encoded_data_size,
  47. uint8_t* decoded_data,
  48. const uint8_t decoded_data_size) {
  49. furi_check(decoded_data_size >= EM4100_DECODED_DATA_SIZE);
  50. furi_check(encoded_data_size >= EM4100_ENCODED_DATA_SIZE);
  51. uint8_t decoded_data_index = 0;
  52. EM4100DecodedData card_data = *((EM4100DecodedData*)(encoded_data));
  53. // clean result
  54. memset(decoded_data, 0, decoded_data_size);
  55. // header
  56. for(uint8_t i = 0; i < 9; i++) {
  57. card_data = card_data << 1;
  58. }
  59. // nibbles
  60. uint8_t value = 0;
  61. for(uint8_t r = 0; r < EM_ROW_COUNT; r++) {
  62. uint8_t nibble = 0;
  63. for(uint8_t i = 0; i < 5; i++) {
  64. if(i < 4) nibble = (nibble << 1) | (card_data & (1LLU << 63) ? 1 : 0);
  65. card_data = card_data << 1;
  66. }
  67. value = (value << 4) | nibble;
  68. if(r % 2) {
  69. decoded_data[decoded_data_index] |= value;
  70. decoded_data_index++;
  71. value = 0;
  72. }
  73. }
  74. }
  75. static bool em4100_can_be_decoded(const uint8_t* encoded_data, const uint8_t encoded_data_size) {
  76. furi_check(encoded_data_size >= EM4100_ENCODED_DATA_SIZE);
  77. const EM4100DecodedData* card_data = (EM4100DecodedData*)encoded_data;
  78. // check header and stop bit
  79. if((*card_data & EM_HEADER_AND_STOP_MASK) != EM_HEADER_AND_STOP_DATA) return false;
  80. // check row parity
  81. for(uint8_t i = 0; i < EM_ROW_COUNT; i++) {
  82. uint8_t parity_sum = 0;
  83. for(uint8_t j = 0; j < EM_BITS_PER_ROW_COUNT; j++) {
  84. parity_sum += (*card_data >> (EM_FIRST_ROW_POS - i * EM_BITS_PER_ROW_COUNT + j)) & 1;
  85. }
  86. if((parity_sum % 2)) {
  87. return false;
  88. }
  89. }
  90. // check columns parity
  91. for(uint8_t i = 0; i < EM_COLUMN_COUNT; i++) {
  92. uint8_t parity_sum = 0;
  93. for(uint8_t j = 0; j < EM_ROW_COUNT + 1; j++) {
  94. parity_sum += (*card_data >> (EM_COLUMN_POS - i + j * EM_BITS_PER_ROW_COUNT)) & 1;
  95. }
  96. if((parity_sum % 2)) {
  97. return false;
  98. }
  99. }
  100. return true;
  101. }
  102. void protocol_em4100_decoder_start(ProtocolEM4100* proto) {
  103. memset(proto->data, 0, EM4100_DECODED_DATA_SIZE);
  104. proto->encoded_data = 0;
  105. manchester_advance(
  106. proto->decoder_manchester_state,
  107. ManchesterEventReset,
  108. &proto->decoder_manchester_state,
  109. NULL);
  110. };
  111. bool protocol_em4100_decoder_feed(ProtocolEM4100* proto, bool level, uint32_t duration) {
  112. bool result = false;
  113. ManchesterEvent event = ManchesterEventReset;
  114. if(duration > EM_READ_SHORT_TIME_LOW && duration < EM_READ_SHORT_TIME_HIGH) {
  115. if(!level) {
  116. event = ManchesterEventShortHigh;
  117. } else {
  118. event = ManchesterEventShortLow;
  119. }
  120. } else if(duration > EM_READ_LONG_TIME_LOW && duration < EM_READ_LONG_TIME_HIGH) {
  121. if(!level) {
  122. event = ManchesterEventLongHigh;
  123. } else {
  124. event = ManchesterEventLongLow;
  125. }
  126. }
  127. if(event != ManchesterEventReset) {
  128. bool data;
  129. bool data_ok = manchester_advance(
  130. proto->decoder_manchester_state, event, &proto->decoder_manchester_state, &data);
  131. if(data_ok) {
  132. proto->encoded_data = (proto->encoded_data << 1) | data;
  133. if(em4100_can_be_decoded((uint8_t*)&proto->encoded_data, sizeof(EM4100DecodedData))) {
  134. em4100_decode(
  135. (uint8_t*)&proto->encoded_data,
  136. sizeof(EM4100DecodedData),
  137. proto->data,
  138. EM4100_DECODED_DATA_SIZE);
  139. result = true;
  140. }
  141. }
  142. }
  143. return result;
  144. };
  145. static void em4100_write_nibble(bool low_nibble, uint8_t data, EM4100DecodedData* encoded_data) {
  146. uint8_t parity_sum = 0;
  147. uint8_t start = 0;
  148. if(!low_nibble) start = 4;
  149. for(int8_t i = (start + 3); i >= start; i--) {
  150. parity_sum += (data >> i) & 1;
  151. *encoded_data = (*encoded_data << 1) | ((data >> i) & 1);
  152. }
  153. *encoded_data = (*encoded_data << 1) | ((parity_sum % 2) & 1);
  154. }
  155. bool protocol_em4100_encoder_start(ProtocolEM4100* proto) {
  156. // header
  157. proto->encoded_data = 0b111111111;
  158. // data
  159. for(uint8_t i = 0; i < EM4100_DECODED_DATA_SIZE; i++) {
  160. em4100_write_nibble(false, proto->data[i], &proto->encoded_data);
  161. em4100_write_nibble(true, proto->data[i], &proto->encoded_data);
  162. }
  163. // column parity and stop bit
  164. uint8_t parity_sum;
  165. for(uint8_t c = 0; c < EM_COLUMN_COUNT; c++) {
  166. parity_sum = 0;
  167. for(uint8_t i = 1; i <= EM_ROW_COUNT; i++) {
  168. uint8_t parity_bit = (proto->encoded_data >> (i * EM_BITS_PER_ROW_COUNT - 1)) & 1;
  169. parity_sum += parity_bit;
  170. }
  171. proto->encoded_data = (proto->encoded_data << 1) | ((parity_sum % 2) & 1);
  172. }
  173. // stop bit
  174. proto->encoded_data = (proto->encoded_data << 1) | 0;
  175. proto->encoded_data_index = 0;
  176. proto->encoded_polarity = true;
  177. return true;
  178. };
  179. LevelDuration protocol_em4100_encoder_yield(ProtocolEM4100* proto) {
  180. bool level = (proto->encoded_data >> (63 - proto->encoded_data_index)) & 1;
  181. uint32_t duration = EM4100_CLOCK_PER_BIT / 2;
  182. if(proto->encoded_polarity) {
  183. proto->encoded_polarity = false;
  184. } else {
  185. level = !level;
  186. proto->encoded_polarity = true;
  187. proto->encoded_data_index++;
  188. if(proto->encoded_data_index >= 64) {
  189. proto->encoded_data_index = 0;
  190. }
  191. }
  192. return level_duration_make(level, duration);
  193. };
  194. bool protocol_em4100_write_data(ProtocolEM4100* protocol, void* data) {
  195. LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data;
  196. bool result = false;
  197. // Correct protocol data by redecoding
  198. protocol_em4100_encoder_start(protocol);
  199. em4100_decode(
  200. (uint8_t*)&protocol->encoded_data,
  201. sizeof(EM4100DecodedData),
  202. protocol->data,
  203. EM4100_DECODED_DATA_SIZE);
  204. protocol_em4100_encoder_start(protocol);
  205. if(request->write_type == LFRFIDWriteTypeT5577) {
  206. request->t5577.block[0] =
  207. (LFRFID_T5577_MODULATION_MANCHESTER | LFRFID_T5577_BITRATE_RF_64 |
  208. (2 << LFRFID_T5577_MAXBLOCK_SHIFT));
  209. request->t5577.block[1] = protocol->encoded_data;
  210. request->t5577.block[2] = protocol->encoded_data >> 32;
  211. request->t5577.blocks_to_write = 3;
  212. result = true;
  213. }
  214. return result;
  215. };
  216. void protocol_em4100_render_data(ProtocolEM4100* protocol, FuriString* result) {
  217. uint8_t* data = protocol->data;
  218. furi_string_printf(
  219. result, "FC: %03u, Card: %05u", data[2], (uint16_t)((data[3] << 8) | (data[4])));
  220. };
  221. const ProtocolBase protocol_em4100 = {
  222. .name = "EM4100",
  223. .manufacturer = "EM-Micro",
  224. .data_size = EM4100_DECODED_DATA_SIZE,
  225. .features = LFRFIDFeatureASK | LFRFIDFeaturePSK,
  226. .validate_count = 3,
  227. .alloc = (ProtocolAlloc)protocol_em4100_alloc,
  228. .free = (ProtocolFree)protocol_em4100_free,
  229. .get_data = (ProtocolGetData)protocol_em4100_get_data,
  230. .decoder =
  231. {
  232. .start = (ProtocolDecoderStart)protocol_em4100_decoder_start,
  233. .feed = (ProtocolDecoderFeed)protocol_em4100_decoder_feed,
  234. },
  235. .encoder =
  236. {
  237. .start = (ProtocolEncoderStart)protocol_em4100_encoder_start,
  238. .yield = (ProtocolEncoderYield)protocol_em4100_encoder_yield,
  239. },
  240. .render_data = (ProtocolRenderData)protocol_em4100_render_data,
  241. .render_brief_data = (ProtocolRenderData)protocol_em4100_render_data,
  242. .write_data = (ProtocolWriteData)protocol_em4100_write_data,
  243. };