diff --git a/gpio/wiegand/scenes/wiegand_data.c b/gpio/wiegand/scenes/wiegand_data.c index ed4f688..87aeaf5 100644 --- a/gpio/wiegand/scenes/wiegand_data.c +++ b/gpio/wiegand/scenes/wiegand_data.c @@ -1,98 +1,131 @@ #include "../wiegand.h" -void wiegand_add_info_4bit_8bit(FuriString* buffer) { - if(bit_count == 8) { - for(int i = 0; i < 4; i++) { +void wiegand_add_info_4bit_8bit(FuriString *buffer) +{ + if (bit_count == 8) + { + for (int i = 0; i < 4; i++) + { furi_string_cat_printf( buffer, "\nbit %d: %d %d (bit %d)", i, data[i], data[i + 4], i + 4); - if(data[i] == data[i + 4]) { + if (data[i] == data[i + 4]) + { furi_string_cat_printf(buffer, " - ERROR"); - } else { + } + else + { furi_string_cat_printf(buffer, " - OK"); } } } - if(bit_count == 4 || bit_count == 8) { + if (bit_count == 4 || bit_count == 8) + { int code = 0; int offset = bit_count == 4 ? 0 : 4; - for(int i = 0; i < 4; i++) { + for (int i = 0; i < 4; i++) + { code = code << 1; code += data[i + offset] ? 1 : 0; } - if(code <= 9) { + if (code <= 9) + { furi_string_cat_printf(buffer, "\nButton: %d", code); - } else if(code == 10) { + } + else if (code == 10) + { furi_string_cat_printf(buffer, "\nButton: Escape"); - } else if(code == 11) { + } + else if (code == 11) + { furi_string_cat_printf(buffer, "\nButton: Enter"); } } } -void wiegand_add_info_26bit(FuriString* buffer) { +void wiegand_add_info_26bit(FuriString *buffer) +{ // 26 bit wiegand, the first bit is the even parity bit, which is // based on the next 12 bits. The number of bits that are a 1 should // be even. int parity = 0; - if(data[0]) { + if (data[0]) + { parity = 1; } - for(int i = 1; i < 13; i++) { - if(data[i]) { + for (int i = 1; i < 13; i++) + { + if (data[i]) + { parity++; } } - if(parity % 2 == 0) { + if (parity % 2 == 0) + { furi_string_cat_printf(buffer, "\nEven Parity (%d): OK", parity); - } else { + } + else + { furi_string_cat_printf(buffer, "\nEven Parity (%d): ERROR", parity); } // After the parity bit, the next 8 bits are the facility code. // Then the next 16 bits are the card id . - furi_string_cat_printf(buffer, "\nFacility: 0x"); + furi_string_cat_printf(buffer, "\nFacility: "); int code = 0; int count = 0; uint32_t dec = 0; - for(int i = 1; i < 25; i++) { + for (int i = 1; i < 25; i++) + { code = code << 1; dec = dec << 1; code |= data[i] ? 1 : 0; dec |= data[i] ? 1 : 0; - if(++count % 4 == 0) { + if (++count % 4 == 0) + { furi_string_cat_printf(buffer, "%X", code); code = 0; } - if(i == 8) { + if (i == 8) + { furi_string_cat_printf(buffer, " (%ld)", dec); dec = 0; } // Parity, then 8 bit facility code, then id. - if(i == 9) { - furi_string_cat_printf(buffer, "\nId: 0x"); + if (i == 9) + { + furi_string_cat_printf(buffer, "\nCard: "); } } furi_string_cat_printf(buffer, " (%ld)", dec); - if(data[13]) { + if (data[13]) + { parity = 1; - } else { + } + else + { parity = 0; } - for(int i = 14; i < 26; i++) { - if(data[i]) { + for (int i = 14; i < 26; i++) + { + if (data[i]) + { parity++; } } - if(parity % 2 == 0) { + if (parity % 2 == 0) + { furi_string_cat_printf(buffer, "\nOdd Parity (%d): ERROR", parity); - } else { + } + else + { furi_string_cat_printf(buffer, "\nOdd Parity (%d): OK", parity); } } -void wiegand_add_info_24bit(FuriString* buffer) { +void wiegand_add_info_24bit(FuriString *buffer) +{ // 24 bit wiegand (no parity info). // The First 8 bits are the facility code. @@ -101,26 +134,30 @@ void wiegand_add_info_24bit(FuriString* buffer) { int code = 0; int count = 0; uint32_t dec = 0; - for(int i = 0; i < 24; i++) { + for (int i = 0; i < 24; i++) + { code = code << 1; dec = dec << 1; code |= data[i] ? 1 : 0; dec |= data[i] ? 1 : 0; - if(++count % 4 == 0) { + if (++count % 4 == 0) + { furi_string_cat_printf(buffer, "%X", code); code = 0; } // The first 8 bits are facility code, then comes id. - if(i == 8) { + if (i == 8) + { furi_string_cat_printf(buffer, " (%ld)", dec); dec = 0; - furi_string_cat_printf(buffer, "\nId: 0x"); + furi_string_cat_printf(buffer, "\nCard: 0x"); } } furi_string_cat_printf(buffer, " (%ld)", dec); } -void wiegand_add_info_48bit(FuriString* buffer) { +void wiegand_add_info_48bit(FuriString *buffer) +{ // We assume this is HID 48 bit Corporate 1000 - H2004064 format. // The first bit is odd parity 2 (based on bits 2-48). // The next bit is even parity (based on 4-5,7-8,10-11,...,46-47). @@ -130,15 +167,17 @@ void wiegand_add_info_48bit(FuriString* buffer) { // 22 bits company code (bits 3-24; data[2..23]) uint32_t code = 0; - for(int i = 2; i <= 23; i++) { + for (int i = 2; i <= 23; i++) + { code = code << 1; code |= data[i] ? 1 : 0; } - furi_string_cat_printf(buffer, "\nCompany: %lX (%ld)", code, code); + furi_string_cat_printf(buffer, "\nFacility: %lX (%ld)", code, code); // 23 bit card id (bits 25-47; data[24..46]). code = 0; - for(int i = 24; i <= 46; i++) { + for (int i = 24; i <= 46; i++) + { code = code << 1; code |= data[i] ? 1 : 0; } @@ -147,45 +186,121 @@ void wiegand_add_info_48bit(FuriString* buffer) { // TODO: Add the 3 parity checks. } -void wiegand_add_info(FuriString* buffer) { +void wiegand_add_info_35bit(FuriString *buffer) +{ + // We assume this is HID 35 bit Corporate 1000 - C1k35s format. + + // 12 bits company code + uint32_t code = 0; + for (int i = 2; i <= 13; i++) + { + code = code << 1; + code |= data[i] ? 1 : 0; + } + furi_string_cat_printf(buffer, "\nFacility: %lX (%ld)", code, code); + + // 20 bit card id + code = 0; + for (int i = 14; i <= 33; i++) + { + code = code << 1; + code |= data[i] ? 1 : 0; + } + furi_string_cat_printf(buffer, "\nCard: %lX (%ld)", code, code); +} + +void wiegand_add_info_36bit(FuriString *buffer) +{ + // We assume this is HID 36 bit Keyscan - C15001 format. + + // 10 bits OEM + uint32_t oem = 0; + for (int i = 1; i <= 10; i++) + { + oem = (oem << 1) | (data[i] ? 1 : 0); + } + furi_string_cat_printf(buffer, "\nOEM: %lX (%ld)", oem, oem); + + // 8 bits facility code + uint32_t facilityCode = 0; + for (int i = 11; i <= 18; i++) + { + facilityCode = (facilityCode << 1) | (data[i] ? 1 : 0); + } + furi_string_cat_printf(buffer, "\nFacility: %lX (%ld)", facilityCode, facilityCode); + + // 16 bits card ID + uint32_t cardID = 0; + for (int i = 19; i <= 34; i++) + { + cardID = (cardID << 1) | (data[i] ? 1 : 0); + } + furi_string_cat_printf(buffer, "\nCard: %lX (%ld)", cardID, cardID); +} + +void wiegand_add_info(FuriString *buffer) +{ furi_string_push_back(buffer, '\n'); - if(bit_count == 4 || bit_count == 8) { + if (bit_count == 4 || bit_count == 8) + { wiegand_add_info_4bit_8bit(buffer); - } else if(bit_count == 26) { + } + else if (bit_count == 26) + { wiegand_add_info_26bit(buffer); - } else if(bit_count == 24) { + } + else if (bit_count == 24) + { wiegand_add_info_24bit(buffer); - } else if(bit_count == 48) { + } + else if (bit_count == 35) + { + wiegand_add_info_35bit(buffer); + } + else if (bit_count == 36) + { + wiegand_add_info_36bit(buffer); + } + else if (bit_count == 48) + { wiegand_add_info_48bit(buffer); } furi_string_push_back(buffer, '\n'); } -void wiegand_button_callback(GuiButtonType result, InputType type, void* context) { - App* app = context; - if(type == InputTypeShort && result == GuiButtonTypeLeft) { +void wiegand_button_callback(GuiButtonType result, InputType type, void *context) +{ + App *app = context; + if (type == InputTypeShort && result == GuiButtonTypeLeft) + { view_dispatcher_send_custom_event(app->view_dispatcher, WiegandDataSceneSaveButtonEvent); - } else if(type == InputTypeShort && result == GuiButtonTypeCenter) { + } + else if (type == InputTypeShort && result == GuiButtonTypeCenter) + { view_dispatcher_send_custom_event(app->view_dispatcher, WiegandDataScenePlayButtonEvent); } } -void wiegand_data_scene_on_enter(void* context) { - App* app = context; +void wiegand_data_scene_on_enter(void *context) +{ + App *app = context; widget_reset(app->widget); widget_add_string_element(app->widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "Wiegand Data"); - FuriString* buffer = furi_string_alloc(1024); + FuriString *buffer = furi_string_alloc(1024); furi_string_printf(buffer, "Bits: %d\n", bit_count); - for(int i = 0; i < bit_count; i++) { + for (int i = 0; i < bit_count; i++) + { furi_string_push_back(buffer, data[i] ? '1' : '0'); - if((bit_count - i - 1) % 22 == 21) { + if ((bit_count - i - 1) % 22 == 21) + { furi_string_push_back(buffer, '\n'); } } furi_string_cat_printf(buffer, "\nPulse: %ld us", (data_rise[0] - data_fall[0]) / 64); furi_string_cat_printf(buffer, "\nPeriod: %ld us", (data_fall[1] - data_fall[0]) / 64); wiegand_add_info(buffer); - for(int i = 0; i < bit_count;) { + for (int i = 0; i < bit_count;) + { uint32_t pulse = (data_rise[i] - data_fall[i]) / 64; i++; uint32_t period = (i < bit_count) ? (data_fall[i] - data_fall[i - 1]) / 64 : 0; @@ -193,7 +308,8 @@ void wiegand_data_scene_on_enter(void* context) { buffer, "\n%c : %ld us, %ld us", data[i] ? '1' : '0', pulse, period); } widget_add_text_scroll_element(app->widget, 0, 12, 128, 34, furi_string_get_cstr(buffer)); - if(!data_saved) { + if (!data_saved) + { widget_add_button_element( app->widget, GuiButtonTypeLeft, "Save", wiegand_button_callback, app); } @@ -202,12 +318,15 @@ void wiegand_data_scene_on_enter(void* context) { view_dispatcher_switch_to_view(app->view_dispatcher, WiegandWidgetView); } -bool wiegand_data_scene_on_event(void* context, SceneManagerEvent event) { - App* app = context; +bool wiegand_data_scene_on_event(void *context, SceneManagerEvent event) +{ + App *app = context; bool consumed = false; - switch(event.type) { + switch (event.type) + { case SceneManagerEventTypeCustom: - switch(event.event) { + switch (event.event) + { case WiegandDataScenePlayButtonEvent: wiegand_play(); consumed = true; diff --git a/gpio/wiegand/scenes/wiegand_read.c b/gpio/wiegand/scenes/wiegand_read.c index 9ee0622..16863eb 100644 --- a/gpio/wiegand/scenes/wiegand_read.c +++ b/gpio/wiegand/scenes/wiegand_read.c @@ -1,41 +1,52 @@ #include "../wiegand.h" -void wiegand_isr_d0(void* context) { +void wiegand_isr_d0(void *context) +{ UNUSED(context); uint32_t time = DWT->CYCCNT; bool rise = furi_hal_gpio_read(pinD0); data[bit_count] = 0; - if(rise) { + if (rise) + { data_rise[bit_count] = time; - if(bit_count < MAX_BITS) { + if (bit_count < MAX_BITS) + { bit_count++; } - } else { + } + else + { data_fall[bit_count] = time; } } -void wiegand_isr_d1(void* context) { +void wiegand_isr_d1(void *context) +{ UNUSED(context); uint32_t time = DWT->CYCCNT; bool rise = furi_hal_gpio_read(pinD1); data[bit_count] = 1; - if(rise) { + if (rise) + { data_rise[bit_count] = time; - if(bit_count < MAX_BITS) { + if (bit_count < MAX_BITS) + { bit_count++; } - } else { + } + else + { data_fall[bit_count] = time; } } -void wiegand_start_read(void* context) { - App* app = context; +void wiegand_start_read(void *context) +{ + App *app = context; data_saved = false; bit_count = 0; furi_hal_gpio_init_simple(pinD0, GpioModeInterruptRiseFall); @@ -45,8 +56,9 @@ void wiegand_start_read(void* context) { furi_timer_start(app->timer, 100); } -void wiegand_stop_read(void* context) { - App* app = context; +void wiegand_stop_read(void *context) +{ + App *app = context; furi_hal_gpio_remove_int_callback(pinD0); furi_hal_gpio_remove_int_callback(pinD1); furi_hal_gpio_init_simple(pinD0, GpioModeAnalog); @@ -54,25 +66,31 @@ void wiegand_stop_read(void* context) { furi_timer_stop(app->timer); } -void wiegand_timer_callback(void* context) { - App* app = context; +void wiegand_timer_callback(void *context) +{ + App *app = context; uint32_t duration = DWT->CYCCNT; const uint32_t one_millisecond = 64000; - if(bit_count == 0) { + if (bit_count == 0) + { return; } duration -= data_fall[bit_count - 1]; FURI_CRITICAL_ENTER(); - if(duration > 25 * one_millisecond) { - if(bit_count == 4 || bit_count == 8 || bit_count == 24 || bit_count == 26 || - bit_count == 32 || bit_count == 34 || bit_count == 37 || bit_count == 40 || - bit_count == 48) { + if (duration > 25 * one_millisecond) + { + if (bit_count == 4 || bit_count == 8 || bit_count == 24 || bit_count == 26 || + bit_count == 32 || bit_count == 34 || bit_count == 35 || bit_count == 36 || + bit_count == 37 || bit_count == 40 || bit_count == 48) + { wiegand_stop_read(app); scene_manager_next_scene(app->scene_manager, WiegandDataScene); - } else { + } + else + { // No data, clear bit_count = 0; } @@ -80,8 +98,9 @@ void wiegand_timer_callback(void* context) { FURI_CRITICAL_EXIT(); } -void wiegand_read_scene_on_enter(void* context) { - App* app = context; +void wiegand_read_scene_on_enter(void *context) +{ + App *app = context; widget_reset(app->widget); widget_add_string_element(app->widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "Read Wiegand"); widget_add_string_element( @@ -94,7 +113,8 @@ void wiegand_read_scene_on_enter(void* context) { view_dispatcher_switch_to_view(app->view_dispatcher, WiegandWidgetView); } -void wiegand_read_scene_on_exit(void* context) { - App* app = context; +void wiegand_read_scene_on_exit(void *context) +{ + App *app = context; wiegand_stop_read(app); } diff --git a/gpio/wiegand/scenes/wiegand_scan.c b/gpio/wiegand/scenes/wiegand_scan.c index 62eb481..fb3bf7e 100644 --- a/gpio/wiegand/scenes/wiegand_scan.c +++ b/gpio/wiegand/scenes/wiegand_scan.c @@ -1,42 +1,53 @@ #include "../wiegand.h" -FuriTimer* timer = NULL; +FuriTimer *timer = NULL; -static void wiegand_scan_isr_d0(void* context) { +static void wiegand_scan_isr_d0(void *context) +{ UNUSED(context); uint32_t time = DWT->CYCCNT; bool rise = furi_hal_gpio_read(pinD0); data[bit_count] = 0; - if(rise) { + if (rise) + { data_rise[bit_count] = time; - if(bit_count < MAX_BITS) { + if (bit_count < MAX_BITS) + { bit_count++; } - } else { + } + else + { data_fall[bit_count] = time; } } -static void wiegand_scan_isr_d1(void* context) { +static void wiegand_scan_isr_d1(void *context) +{ UNUSED(context); uint32_t time = DWT->CYCCNT; bool rise = furi_hal_gpio_read(pinD1); data[bit_count] = 1; - if(rise) { + if (rise) + { data_rise[bit_count] = time; - if(bit_count < MAX_BITS) { + if (bit_count < MAX_BITS) + { bit_count++; } - } else { + } + else + { data_fall[bit_count] = time; } } -static void wiegand_start_scan(void* context) { +static void wiegand_start_scan(void *context) +{ UNUSED(context); data_saved = false; bit_count = 0; @@ -47,7 +58,8 @@ static void wiegand_start_scan(void* context) { furi_timer_start(timer, 100); } -static void wiegand_stop_scan(void* context) { +static void wiegand_stop_scan(void *context) +{ UNUSED(context); furi_hal_gpio_remove_int_callback(pinD0); furi_hal_gpio_remove_int_callback(pinD1); @@ -56,8 +68,9 @@ static void wiegand_stop_scan(void* context) { furi_timer_stop(timer); } -static void wiegand_scan_found(void* context) { - App* app = context; +static void wiegand_scan_found(void *context) +{ + App *app = context; FuriHalRtcDateTime datetime; furi_hal_rtc_get_datetime(&datetime); @@ -83,12 +96,14 @@ static void wiegand_scan_found(void* context) { wiegand_start_scan(app); } -static void wiegand_scan_timer_callback(void* context) { - App* app = context; +static void wiegand_scan_timer_callback(void *context) +{ + App *app = context; uint32_t duration = DWT->CYCCNT; const uint32_t one_millisecond = 64000; - if(bit_count == 0) { + if (bit_count == 0) + { return; } @@ -96,26 +111,32 @@ static void wiegand_scan_timer_callback(void* context) { bool found = false; FURI_CRITICAL_ENTER(); - if(duration > 25 * one_millisecond) { - if(bit_count == 4 || bit_count == 8 || bit_count == 24 || bit_count == 26 || - bit_count == 32 || bit_count == 34 || bit_count == 37 || bit_count == 40 || - bit_count == 48) { + if (duration > 25 * one_millisecond) + { + if (bit_count == 4 || bit_count == 8 || bit_count == 24 || bit_count == 26 || + bit_count == 32 || bit_count == 34 || bit_count == 35 || bit_count == 36 || + bit_count == 37 || bit_count == 40 || bit_count == 48) + { wiegand_stop_scan(app); found = true; - } else { + } + else + { // No data, clear bit_count = 0; } } FURI_CRITICAL_EXIT(); - if(found) { + if (found) + { wiegand_scan_found(app); } } -void wiegand_scan_scene_on_enter(void* context) { - App* app = context; +void wiegand_scan_scene_on_enter(void *context) +{ + App *app = context; timer = furi_timer_alloc(wiegand_scan_timer_callback, FuriTimerTypePeriodic, app); widget_reset(app->widget); widget_add_string_element(app->widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "Scan Wiegand"); @@ -131,8 +152,9 @@ void wiegand_scan_scene_on_enter(void* context) { view_dispatcher_switch_to_view(app->view_dispatcher, WiegandWidgetView); } -void wiegand_scan_scene_on_exit(void* context) { - App* app = context; +void wiegand_scan_scene_on_exit(void *context) +{ + App *app = context; wiegand_stop_scan(app); furi_timer_free(timer); }