protocol_pac_stanley.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. #include <furi.h>
  2. #include <math.h>
  3. #include <toolbox/protocols/protocol.h>
  4. #include <toolbox/hex.h>
  5. #include <lfrfid/tools/bit_lib.h>
  6. #include "lfrfid_protocols.h"
  7. #define PAC_STANLEY_ENCODED_BIT_SIZE (128)
  8. #define PAC_STANLEY_ENCODED_BYTE_SIZE (((PAC_STANLEY_ENCODED_BIT_SIZE) / 8))
  9. #define PAC_STANLEY_PREAMBLE_BIT_SIZE (8)
  10. #define PAC_STANLEY_PREAMBLE_BYTE_SIZE (1)
  11. #define PAC_STANLEY_ENCODED_BYTE_FULL_SIZE \
  12. (PAC_STANLEY_ENCODED_BYTE_SIZE + PAC_STANLEY_PREAMBLE_BYTE_SIZE)
  13. #define PAC_STANLEY_BYTE_LENGTH (10) // start bit, 7 data bits, parity bit, stop bit
  14. #define PAC_STANLEY_DATA_START_INDEX 8 + (3 * PAC_STANLEY_BYTE_LENGTH) + 1
  15. #define PAC_STANLEY_DECODED_DATA_SIZE (4)
  16. #define PAC_STANLEY_ENCODED_DATA_SIZE (sizeof(ProtocolPACStanley))
  17. #define PAC_STANLEY_CLOCKS_IN_US (32)
  18. #define PAC_STANLEY_CYCLE_LENGTH (256)
  19. #define PAC_STANLEY_MIN_TIME (60)
  20. #define PAC_STANLEY_MAX_TIME (4000)
  21. typedef struct {
  22. bool inverted;
  23. bool got_preamble;
  24. size_t encoded_index;
  25. uint8_t encoded_data[PAC_STANLEY_ENCODED_BYTE_FULL_SIZE];
  26. uint8_t data[PAC_STANLEY_DECODED_DATA_SIZE];
  27. } ProtocolPACStanley;
  28. ProtocolPACStanley* protocol_pac_stanley_alloc(void) {
  29. ProtocolPACStanley* protocol = malloc(sizeof(ProtocolPACStanley));
  30. return (void*)protocol;
  31. }
  32. void protocol_pac_stanley_free(ProtocolPACStanley* protocol) {
  33. free(protocol);
  34. }
  35. uint8_t* protocol_pac_stanley_get_data(ProtocolPACStanley* protocol) {
  36. return protocol->data;
  37. }
  38. static void protocol_pac_stanley_decode(ProtocolPACStanley* protocol) {
  39. uint8_t asciiCardId[8];
  40. for(size_t idx = 0; idx < 8; idx++) {
  41. uint8_t byte = bit_lib_reverse_8_fast(bit_lib_get_bits(
  42. protocol->encoded_data,
  43. PAC_STANLEY_DATA_START_INDEX + (PAC_STANLEY_BYTE_LENGTH * idx),
  44. 8));
  45. asciiCardId[idx] = byte & 0x7F; // discard the parity bit
  46. }
  47. hex_chars_to_uint8((char*)asciiCardId, protocol->data);
  48. }
  49. static bool protocol_pac_stanley_can_be_decoded(ProtocolPACStanley* protocol) {
  50. // Check preamble
  51. if(bit_lib_get_bits(protocol->encoded_data, 0, 8) != 0b11111111) return false;
  52. if(bit_lib_get_bit(protocol->encoded_data, 8) != 0) return false;
  53. if(bit_lib_get_bit(protocol->encoded_data, 9) != 0) return false;
  54. if(bit_lib_get_bit(protocol->encoded_data, 10) != 1) return false;
  55. if(bit_lib_get_bits(protocol->encoded_data, 11, 8) != 0b00000010) return false;
  56. // Check next preamble
  57. if(bit_lib_get_bits(protocol->encoded_data, 128, 8) != 0b11111111) return false;
  58. // Checksum
  59. uint8_t checksum = 0;
  60. uint8_t stripped_byte;
  61. for(size_t idx = 0; idx < 9; idx++) {
  62. uint8_t byte = bit_lib_reverse_8_fast(bit_lib_get_bits(
  63. protocol->encoded_data,
  64. PAC_STANLEY_DATA_START_INDEX + (PAC_STANLEY_BYTE_LENGTH * idx),
  65. 8));
  66. stripped_byte = byte & 0x7F; // discard the parity bit
  67. if(bit_lib_test_parity_32(stripped_byte, BitLibParityOdd) != (byte & 0x80) >> 7) {
  68. return false;
  69. }
  70. if(idx < 8) checksum ^= stripped_byte;
  71. }
  72. if(stripped_byte != checksum) return false;
  73. return true;
  74. }
  75. void protocol_pac_stanley_decoder_start(ProtocolPACStanley* protocol) {
  76. memset(protocol->data, 0, PAC_STANLEY_DECODED_DATA_SIZE);
  77. protocol->inverted = false;
  78. protocol->got_preamble = false;
  79. }
  80. bool protocol_pac_stanley_decoder_feed(ProtocolPACStanley* protocol, bool level, uint32_t duration) {
  81. bool pushed = false;
  82. if(duration > PAC_STANLEY_MAX_TIME) return false;
  83. uint8_t pulses = (uint8_t)round((float)duration / PAC_STANLEY_CYCLE_LENGTH);
  84. // Handle last stopbit & preamble (1 sb, 8 bit preamble)
  85. if(pulses >= 9 && !protocol->got_preamble) {
  86. pulses = 8;
  87. protocol->got_preamble = true;
  88. protocol->inverted = !level;
  89. } else if(pulses >= 9 && protocol->got_preamble) {
  90. protocol->got_preamble = false;
  91. } else if(pulses == 0 && duration > PAC_STANLEY_MIN_TIME) {
  92. pulses = 1;
  93. }
  94. if(pulses) {
  95. for(uint8_t i = 0; i < pulses; i++) {
  96. bit_lib_push_bit(
  97. protocol->encoded_data,
  98. PAC_STANLEY_ENCODED_BYTE_FULL_SIZE,
  99. level ^ protocol->inverted);
  100. }
  101. pushed = true;
  102. }
  103. if(pushed && protocol_pac_stanley_can_be_decoded(protocol)) {
  104. protocol_pac_stanley_decode(protocol);
  105. return true;
  106. }
  107. return false;
  108. }
  109. bool protocol_pac_stanley_encoder_start(ProtocolPACStanley* protocol) {
  110. memset(protocol->encoded_data, 0, PAC_STANLEY_ENCODED_BYTE_SIZE);
  111. uint8_t idbytes[10];
  112. idbytes[0] = '2';
  113. idbytes[1] = '0';
  114. uint8_to_hex_chars(protocol->data, &idbytes[2], 8);
  115. // insert start and stop bits
  116. for(size_t i = 0; i < 16; i++) protocol->encoded_data[i] = 0x40 >> (i + 3) % 5 * 2;
  117. protocol->encoded_data[0] = 0xFF; // mark + stop
  118. protocol->encoded_data[1] = 0x20; // start + reflect8(STX)
  119. uint8_t checksum = 0;
  120. for(size_t i = 2; i < 13; i++) {
  121. uint8_t shift = 7 - (i + 3) % 4 * 2;
  122. uint8_t index = i + (i - 1) / 4;
  123. uint16_t pattern;
  124. if(i < 12) {
  125. pattern = bit_lib_reverse_8_fast(idbytes[i - 2]);
  126. pattern |= bit_lib_test_parity_32(pattern, BitLibParityOdd);
  127. if(i > 3) checksum ^= idbytes[i - 2];
  128. } else {
  129. pattern = (bit_lib_reverse_8_fast(checksum) & 0xFE) |
  130. (bit_lib_test_parity_32(checksum, BitLibParityOdd));
  131. }
  132. pattern <<= shift;
  133. protocol->encoded_data[index] |= pattern >> 8 & 0xFF;
  134. protocol->encoded_data[index + 1] |= pattern & 0xFF;
  135. }
  136. protocol->encoded_index = 0;
  137. return true;
  138. }
  139. LevelDuration protocol_pac_stanley_encoder_yield(ProtocolPACStanley* protocol) {
  140. uint16_t length = PAC_STANLEY_CLOCKS_IN_US;
  141. bool bit = bit_lib_get_bit(protocol->encoded_data, protocol->encoded_index);
  142. bit_lib_increment_index(protocol->encoded_index, PAC_STANLEY_ENCODED_BIT_SIZE);
  143. while(bit_lib_get_bit(protocol->encoded_data, protocol->encoded_index) == bit) {
  144. length += PAC_STANLEY_CLOCKS_IN_US;
  145. bit_lib_increment_index(protocol->encoded_index, PAC_STANLEY_ENCODED_BIT_SIZE);
  146. }
  147. return level_duration_make(bit, length);
  148. }
  149. bool protocol_pac_stanley_write_data(ProtocolPACStanley* protocol, void* data) {
  150. LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data;
  151. bool result = false;
  152. protocol_pac_stanley_encoder_start(protocol);
  153. if(request->write_type == LFRFIDWriteTypeT5577) {
  154. request->t5577.block[0] = LFRFID_T5577_MODULATION_DIRECT | LFRFID_T5577_BITRATE_RF_32 |
  155. (4 << LFRFID_T5577_MAXBLOCK_SHIFT);
  156. request->t5577.block[1] = bit_lib_get_bits_32(protocol->encoded_data, 0, 32);
  157. request->t5577.block[2] = bit_lib_get_bits_32(protocol->encoded_data, 32, 32);
  158. request->t5577.block[3] = bit_lib_get_bits_32(protocol->encoded_data, 64, 32);
  159. request->t5577.block[4] = bit_lib_get_bits_32(protocol->encoded_data, 96, 32);
  160. request->t5577.blocks_to_write = 5;
  161. result = true;
  162. }
  163. return result;
  164. }
  165. void protocol_pac_stanley_render_data(ProtocolPACStanley* protocol, string_t result) {
  166. uint8_t* data = protocol->data;
  167. string_printf(result, "CIN: %02X%02X%02X%02X", data[0], data[1], data[2], data[3]);
  168. }
  169. const ProtocolBase protocol_pac_stanley = {
  170. .name = "PAC/Stanley",
  171. .manufacturer = "N/A",
  172. .data_size = PAC_STANLEY_DECODED_DATA_SIZE,
  173. .features = LFRFIDFeatureASK,
  174. .validate_count = 3,
  175. .alloc = (ProtocolAlloc)protocol_pac_stanley_alloc,
  176. .free = (ProtocolFree)protocol_pac_stanley_free,
  177. .get_data = (ProtocolGetData)protocol_pac_stanley_get_data,
  178. .decoder =
  179. {
  180. .start = (ProtocolDecoderStart)protocol_pac_stanley_decoder_start,
  181. .feed = (ProtocolDecoderFeed)protocol_pac_stanley_decoder_feed,
  182. },
  183. .encoder =
  184. {
  185. .start = (ProtocolEncoderStart)protocol_pac_stanley_encoder_start,
  186. .yield = (ProtocolEncoderYield)protocol_pac_stanley_encoder_yield,
  187. },
  188. .render_data = (ProtocolRenderData)protocol_pac_stanley_render_data,
  189. .render_brief_data = (ProtocolRenderData)protocol_pac_stanley_render_data,
  190. .write_data = (ProtocolWriteData)protocol_pac_stanley_write_data,
  191. };