|
@@ -26,16 +26,39 @@ static inline uint8_t evenparity32(uint32_t x) {
|
|
|
return bit_lib_test_parity_32(x, BitLibParityEven);
|
|
return bit_lib_test_parity_32(x, BitLibParityEven);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-static int wiegand_C1k35s_parse(uint8_t bit_length, uint64_t bits, FuriString* description) {
|
|
|
|
|
- if(bit_length != 35) {
|
|
|
|
|
- return 0;
|
|
|
|
|
|
|
+uint8_t get_bit_by_position(wiegand_message_t* data, uint8_t pos) {
|
|
|
|
|
+ if(pos >= data->Length) return false;
|
|
|
|
|
+ pos = (data->Length - pos) -
|
|
|
|
|
+ 1; // invert ordering; Indexing goes from 0 to 1. Subtract 1 for weight of bit.
|
|
|
|
|
+ uint8_t result = 0;
|
|
|
|
|
+ if(pos > 95)
|
|
|
|
|
+ result = 0;
|
|
|
|
|
+ else if(pos > 63)
|
|
|
|
|
+ result = (data->Top >> (pos - 64)) & 1;
|
|
|
|
|
+ else if(pos > 31)
|
|
|
|
|
+ result = (data->Mid >> (pos - 32)) & 1;
|
|
|
|
|
+ else
|
|
|
|
|
+ result = (data->Bot >> pos) & 1;
|
|
|
|
|
+ return result;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+uint64_t get_linear_field(wiegand_message_t* data, uint8_t firstBit, uint8_t length) {
|
|
|
|
|
+ uint64_t result = 0;
|
|
|
|
|
+ for(uint8_t i = 0; i < length; i++) {
|
|
|
|
|
+ result = (result << 1) | get_bit_by_position(data, firstBit + i);
|
|
|
}
|
|
}
|
|
|
|
|
+ return result;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
|
|
+static int wiegand_C1k35s_parse(uint8_t bit_length, uint64_t bits, FuriString* description) {
|
|
|
wiegand_message_t value;
|
|
wiegand_message_t value;
|
|
|
|
|
+ value.Length = bit_length;
|
|
|
value.Mid = bits >> 32;
|
|
value.Mid = bits >> 32;
|
|
|
value.Bot = bits;
|
|
value.Bot = bits;
|
|
|
wiegand_message_t* packed = &value;
|
|
wiegand_message_t* packed = &value;
|
|
|
|
|
|
|
|
|
|
+ if(packed->Length != 35) return false; // Wrong length? Stop here.
|
|
|
|
|
+
|
|
|
uint32_t cn = (packed->Bot >> 1) & 0x000FFFFF;
|
|
uint32_t cn = (packed->Bot >> 1) & 0x000FFFFF;
|
|
|
uint32_t fc = ((packed->Mid & 1) << 11) | ((packed->Bot >> 21));
|
|
uint32_t fc = ((packed->Mid & 1) << 11) | ((packed->Bot >> 21));
|
|
|
bool valid = (evenparity32((packed->Mid & 0x1) ^ (packed->Bot & 0xB6DB6DB6)) ==
|
|
bool valid = (evenparity32((packed->Mid & 0x1) ^ (packed->Bot & 0xB6DB6DB6)) ==
|
|
@@ -48,6 +71,8 @@ static int wiegand_C1k35s_parse(uint8_t bit_length, uint64_t bits, FuriString* d
|
|
|
if(valid) {
|
|
if(valid) {
|
|
|
furi_string_cat_printf(description, "C1k35s\nFC: %ld CN: %ld\n", fc, cn);
|
|
furi_string_cat_printf(description, "C1k35s\nFC: %ld CN: %ld\n", fc, cn);
|
|
|
return 1;
|
|
return 1;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ FURI_LOG_D(PLUGIN_APP_ID, "C1k35s invalid");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
@@ -89,6 +114,57 @@ static int wiegand_h10301_parse(uint8_t bit_length, uint64_t bits, FuriString* d
|
|
|
|
|
|
|
|
furi_string_cat_printf(description, "H10301\nFC: %d CN: %d\n", fc, cn);
|
|
furi_string_cat_printf(description, "H10301\nFC: %d CN: %d\n", fc, cn);
|
|
|
return 1;
|
|
return 1;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ FURI_LOG_D(PLUGIN_APP_ID, "H10301 invalid");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int wiegand_H10304_parse(uint8_t bit_length, uint64_t bits, FuriString* description) {
|
|
|
|
|
+ wiegand_message_t value;
|
|
|
|
|
+ value.Length = bit_length;
|
|
|
|
|
+ value.Mid = bits >> 32;
|
|
|
|
|
+ value.Bot = bits;
|
|
|
|
|
+ wiegand_message_t* packed = &value;
|
|
|
|
|
+
|
|
|
|
|
+ if(packed->Length != 37) return false; // Wrong length? Stop here.
|
|
|
|
|
+
|
|
|
|
|
+ uint32_t fc = get_linear_field(packed, 1, 16);
|
|
|
|
|
+ uint32_t cn = get_linear_field(packed, 17, 19);
|
|
|
|
|
+ bool valid =
|
|
|
|
|
+ (get_bit_by_position(packed, 0) == evenparity32(get_linear_field(packed, 1, 18))) &&
|
|
|
|
|
+ (get_bit_by_position(packed, 36) == oddparity32(get_linear_field(packed, 18, 18)));
|
|
|
|
|
+
|
|
|
|
|
+ if(valid) {
|
|
|
|
|
+ furi_string_cat_printf(description, "H10304\nFC: %ld CN: %ld\n", fc, cn);
|
|
|
|
|
+ return 1;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ FURI_LOG_D(PLUGIN_APP_ID, "H10304 invalid");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int wiegand_H10302_parse(uint8_t bit_length, uint64_t bits, FuriString* description) {
|
|
|
|
|
+ wiegand_message_t value;
|
|
|
|
|
+ value.Length = bit_length;
|
|
|
|
|
+ value.Mid = bits >> 32;
|
|
|
|
|
+ value.Bot = bits;
|
|
|
|
|
+ wiegand_message_t* packed = &value;
|
|
|
|
|
+
|
|
|
|
|
+ if(packed->Length != 37) return false; // Wrong length? Stop here.
|
|
|
|
|
+
|
|
|
|
|
+ uint64_t cn = get_linear_field(packed, 1, 35);
|
|
|
|
|
+ bool valid =
|
|
|
|
|
+ (get_bit_by_position(packed, 0) == evenparity32(get_linear_field(packed, 1, 18))) &&
|
|
|
|
|
+ (get_bit_by_position(packed, 36) == oddparity32(get_linear_field(packed, 18, 18)));
|
|
|
|
|
+
|
|
|
|
|
+ if(valid) {
|
|
|
|
|
+ furi_string_cat_printf(description, "H10302\nCN: %lld\n", cn);
|
|
|
|
|
+ return 1;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ FURI_LOG_D(PLUGIN_APP_ID, "H10302 invalid");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
@@ -100,12 +176,17 @@ static int wiegand_format_count(uint8_t bit_length, uint64_t bits) {
|
|
|
int count = 0;
|
|
int count = 0;
|
|
|
FuriString* ignore = furi_string_alloc();
|
|
FuriString* ignore = furi_string_alloc();
|
|
|
|
|
|
|
|
|
|
+ // NOTE: Always update the `total` and add to the wiegand_format_description function
|
|
|
|
|
+ // TODO: Make this into a function pointer array
|
|
|
count += wiegand_h10301_parse(bit_length, bits, ignore);
|
|
count += wiegand_h10301_parse(bit_length, bits, ignore);
|
|
|
count += wiegand_C1k35s_parse(bit_length, bits, ignore);
|
|
count += wiegand_C1k35s_parse(bit_length, bits, ignore);
|
|
|
|
|
+ count += wiegand_H10302_parse(bit_length, bits, ignore);
|
|
|
|
|
+ count += wiegand_H10304_parse(bit_length, bits, ignore);
|
|
|
|
|
+ int total = 4;
|
|
|
|
|
|
|
|
furi_string_free(ignore);
|
|
furi_string_free(ignore);
|
|
|
|
|
|
|
|
- FURI_LOG_I(PLUGIN_APP_ID, "count: %i", count);
|
|
|
|
|
|
|
+ FURI_LOG_I(PLUGIN_APP_ID, "count: %i/%i", count, total);
|
|
|
return count;
|
|
return count;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -115,21 +196,16 @@ static void wiegand_format_description(
|
|
|
size_t index,
|
|
size_t index,
|
|
|
FuriString* description) {
|
|
FuriString* description) {
|
|
|
FURI_LOG_I(PLUGIN_APP_ID, "description %d", index);
|
|
FURI_LOG_I(PLUGIN_APP_ID, "description %d", index);
|
|
|
- UNUSED(bit_length);
|
|
|
|
|
- UNUSED(bits);
|
|
|
|
|
-
|
|
|
|
|
- size_t i = 0;
|
|
|
|
|
|
|
|
|
|
- i += wiegand_h10301_parse(bit_length, bits, description);
|
|
|
|
|
- if(i - 1 == index) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- i += wiegand_C1k35s_parse(bit_length, bits, description);
|
|
|
|
|
- if(i - 1 == index) {
|
|
|
|
|
|
|
+ // Turns out I did this wrong and trying to use the index means the results get repeated. Instead, just return the results for index == 0
|
|
|
|
|
+ if(index != 0) {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- furi_string_cat_printf(description, "[%i] <name> FC: CN:", index);
|
|
|
|
|
|
|
+ wiegand_h10301_parse(bit_length, bits, description);
|
|
|
|
|
+ wiegand_C1k35s_parse(bit_length, bits, description);
|
|
|
|
|
+ wiegand_H10302_parse(bit_length, bits, description);
|
|
|
|
|
+ wiegand_H10304_parse(bit_length, bits, description);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* Actual implementation of app<>plugin interface */
|
|
/* Actual implementation of app<>plugin interface */
|