Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
git-subtree-dir: metroflip
git-subtree-mainline: 9dc3723
git-subtree-split: 1e834b2
  • Loading branch information
Willy-JL committed Nov 27, 2024
2 parents 9dc3723 + 1e834b2 commit 3c9293a
Show file tree
Hide file tree
Showing 26 changed files with 2,790 additions and 0 deletions.
1 change: 1 addition & 0 deletions metroflip/.gitsubtree
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
https://github.com/luu176/Metroflip main /
3 changes: 3 additions & 0 deletions metroflip/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## v1.0

- Initial release by [@luu176](https://github.com/luu176)
21 changes: 21 additions & 0 deletions metroflip/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2024 Luu

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
43 changes: 43 additions & 0 deletions metroflip/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Metroflip
Metroflip is a multi-protocol metro card reader app for the Flipper Zero, inspired by the Metrodroid project. It enables the parsing and analysis of metro cards from transit systems around the world, providing a proof-of-concept for exploring transit card data in a portable format.

# Author
[@luu176](https://github.com/luu176)

# Metroflip - Card Support TODO List

This is a list of metro cards and transit systems that need support or have partial support.

## ✅ Supported Cards
- [x] **Rav-Kav**
- Status: Needs more functionality (currently only able to read balance).
- [x] **Charliecard**
- Status: Fully supported.
- [x] **Metromoney**
- Status: Fully supported.
- [x] **Bip!**
- Status: Fully supported.

## 🚧 In Progress / Needs More Functionality
- [ ] **Rav-Kav**
- Current functionality: Reads balance only.
- To Do: Parse more data from the card (e.g., transaction history, expiration date, etc.).

## 📝 To Do (Unimplemented)
- [ ] **Tianjin Railway Transit (TRT)**
- To Do: Add support for reading and analyzing Tianjin Railway Transit cards.
- [ ] **Clipper**
- To Do: Add support for reading and analyzing Clipper cards.


---

### Credits:
- **App Author**: [@luu176](https://github.com/luu176)
- **Charliecard Parser**: [@zacharyweiss](https://github.com/zacharyweiss)
- **Rav-Kav Parser**: [@luu176](https://github.com/luu176)
- **Metromoney Parser**: [@Leptopt1los](https://github.com/Leptopt1los)
- **Bip! Parser**: [@rbasoalto](https://github.com/rbasoalto) [@gornekich](https://github.com/gornekich)
- **Info Slave**: [@equipter](https://github.com/equipter)


13 changes: 13 additions & 0 deletions metroflip/application.fam
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
App(
appid="metroflip",
name="Metroflip",
apptype=FlipperAppType.EXTERNAL,
entry_point="metroflip",
stack_size=2 * 1024,
fap_category="NFC",
fap_version="0.1",
fap_icon="icon.png",
fap_description="An implementation of metrodroid on the flipper",
fap_author="luu176",
fap_icon_assets="images", # Image assets to compile for this application
)
Binary file added metroflip/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added metroflip/images/RFIDDolphinReceive_97x61.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions metroflip/manifest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
author: 'luu176'
category: 'NFC'
changelog: 'CHANGELOG.md'
description: 'README.md'
icon: 'icon.png'
id: 'metroflip'
name: 'Metroflip'
screenshots:
- 'Menu-Top.png'
- 'Menu-Middle.png'
- 'Rav-Kav.png'
- 'App.png'
short_description: 'An implementation of metrodroid on the flipper'
sourcecode:
location:
commit_sha: 500144a8e9576797c085d8d9506700964a34dd73
origin: https://github.com/luu176/Metroflip
subdir:
type: git
version: 1.0
137 changes: 137 additions & 0 deletions metroflip/metroflip.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@

#include "metroflip_i.h"

static bool metroflip_custom_event_callback(void* context, uint32_t event) {
furi_assert(context);
Metroflip* app = context;
return scene_manager_handle_custom_event(app->scene_manager, event);
}

static bool metroflip_back_event_callback(void* context) {
furi_assert(context);
Metroflip* app = context;

return scene_manager_handle_back_event(app->scene_manager);
}

Metroflip* metroflip_alloc() {
Metroflip* app = malloc(sizeof(Metroflip));
app->gui = furi_record_open(RECORD_GUI);
//nfc device
app->nfc = nfc_alloc();
app->nfc_device = nfc_device_alloc();

// notifs
app->notifications = furi_record_open(RECORD_NOTIFICATION);
// View Dispatcher and Scene Manager
app->view_dispatcher = view_dispatcher_alloc();
app->scene_manager = scene_manager_alloc(&metroflip_scene_handlers, app);

view_dispatcher_set_event_callback_context(app->view_dispatcher, app);

view_dispatcher_set_custom_event_callback(
app->view_dispatcher, metroflip_custom_event_callback);
view_dispatcher_set_navigation_event_callback(
app->view_dispatcher, metroflip_back_event_callback);

view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);

// Custom Widget
app->widget = widget_alloc();
view_dispatcher_add_view(
app->view_dispatcher, MetroflipViewWidget, widget_get_view(app->widget));

// Gui Modules
app->submenu = submenu_alloc();
view_dispatcher_add_view(
app->view_dispatcher, MetroflipViewSubmenu, submenu_get_view(app->submenu));

app->text_input = text_input_alloc();
view_dispatcher_add_view(
app->view_dispatcher, MetroflipViewTextInput, text_input_get_view(app->text_input));

app->byte_input = byte_input_alloc();
view_dispatcher_add_view(
app->view_dispatcher, MetroflipViewByteInput, byte_input_get_view(app->byte_input));

app->popup = popup_alloc();
view_dispatcher_add_view(app->view_dispatcher, MetroflipViewPopup, popup_get_view(app->popup));
app->nfc_device = nfc_device_alloc();

// TextBox
app->text_box = text_box_alloc();
view_dispatcher_add_view(
app->view_dispatcher, MetroflipViewTextBox, text_box_get_view(app->text_box));
app->text_box_store = furi_string_alloc();

return app;
}

void metroflip_free(Metroflip* app) {
furi_assert(app);

//nfc device
nfc_free(app->nfc);
nfc_device_free(app->nfc_device);

//notifs
furi_record_close(RECORD_NOTIFICATION);
app->notifications = NULL;

// Gui modules
view_dispatcher_remove_view(app->view_dispatcher, MetroflipViewSubmenu);
submenu_free(app->submenu);
view_dispatcher_remove_view(app->view_dispatcher, MetroflipViewTextInput);
text_input_free(app->text_input);
view_dispatcher_remove_view(app->view_dispatcher, MetroflipViewByteInput);
byte_input_free(app->byte_input);
view_dispatcher_remove_view(app->view_dispatcher, MetroflipViewPopup);
popup_free(app->popup);

// Custom Widget
view_dispatcher_remove_view(app->view_dispatcher, MetroflipViewWidget);
widget_free(app->widget);

// TextBox
view_dispatcher_remove_view(app->view_dispatcher, MetroflipViewTextBox);
text_box_free(app->text_box);
furi_string_free(app->text_box_store);

// View Dispatcher and Scene Manager
view_dispatcher_free(app->view_dispatcher);
scene_manager_free(app->scene_manager);

// Records
furi_record_close(RECORD_GUI);
free(app);
}

static const NotificationSequence metroflip_app_sequence_blink_start_blue = {
&message_blink_start_10,
&message_blink_set_color_blue,
&message_do_not_reset,
NULL,
};

static const NotificationSequence metroflip_app_sequence_blink_stop = {
&message_blink_stop,
NULL,
};

void metroflip_app_blink_start(Metroflip* metroflip) {
notification_message(metroflip->notifications, &metroflip_app_sequence_blink_start_blue);
}

void metroflip_app_blink_stop(Metroflip* metroflip) {
notification_message(metroflip->notifications, &metroflip_app_sequence_blink_stop);
}

extern int32_t metroflip(void* p) {
UNUSED(p);
Metroflip* app = metroflip_alloc();
scene_manager_set_scene_state(app->scene_manager, MetroflipSceneStart, MetroflipSceneRavKav);
scene_manager_next_scene(app->scene_manager, MetroflipSceneStart);
view_dispatcher_run(app->view_dispatcher);
metroflip_free(app);
return 0;
}
3 changes: 3 additions & 0 deletions metroflip/metroflip.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#pragma once

typedef struct Metroflip Metroflip;
117 changes: 117 additions & 0 deletions metroflip/metroflip_i.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#pragma once

#include <furi.h>
#include <gui/gui.h>
#include <gui/view.h>
#include <gui/modules/validators.h>
#include <gui/view_dispatcher.h>
#include <gui/scene_manager.h>
#if __has_include(<assets_icons.h>)
#include <assets_icons.h>
#else
extern const Icon I_RFIDDolphinReceive_97x61;
#endif

#include <gui/modules/submenu.h>
#include <gui/modules/popup.h>
#include <gui/modules/loading.h>
#include <gui/modules/text_input.h>
#include <gui/modules/text_box.h>
#include <gui/modules/widget.h>
#include <gui/modules/byte_input.h>
#include <gui/modules/popup.h>
#include "scenes/metroflip_scene.h"
#include <lib/flipper_format/flipper_format.h>
#include <toolbox/name_generator.h>
#include <lib/nfc/protocols/mf_ultralight/mf_ultralight.h>
#include <lib/nfc/helpers/nfc_data_generator.h>
#include <furi_hal_bt.h>
#include <notification/notification_messages.h>

#include <lib/nfc/nfc.h>
#include <nfc/nfc_poller.h>
#include <nfc/nfc_scanner.h>

#include <flipper_application/flipper_application.h>
#include <loader/firmware_api/firmware_api.h>

#include "scenes/metroflip_scene.h"

typedef struct {
Gui* gui;
SceneManager* scene_manager;
ViewDispatcher* view_dispatcher;
NotificationApp* notifications;
Submenu* submenu;
TextInput* text_input;
TextBox* text_box;
ByteInput* byte_input;
Popup* popup;
uint8_t mac_buf[GAP_MAC_ADDR_SIZE];
FuriString* text_box_store;
Widget* widget;

Nfc* nfc;
NfcPoller* poller;
NfcScanner* scanner;
NfcDevice* nfc_device;

// card details:
uint32_t balance_lari;
uint8_t balance_tetri;
uint32_t card_number;
size_t sec_num;
float value;
char currency[4];
char card_type[32];

} Metroflip;

enum MetroflipCustomEvent {
// Reserve first 100 events for button types and indexes, starting from 0
MetroflipCustomEventReserved = 100,

MetroflipCustomEventViewExit,
MetroflipCustomEventByteInputDone,
MetroflipCustomEventTextInputDone,
MetroflipCustomEventWorkerExit,

MetroflipCustomEventPollerDetect,
MetroflipCustomEventPollerSuccess,
MetroflipCustomEventPollerFail,
MetroflipCustomEventPollerSelectFailed,
MetroflipCustomEventPollerFileNotFound,

MetroflipCustomEventCardLost,
MetroflipCustomEventCardDetected,
MetroflipCustomEventWrongCard
};

typedef enum {
MetroflipPollerEventTypeStart,
MetroflipPollerEventTypeCardDetect,

MetroflipPollerEventTypeSuccess,
MetroflipPollerEventTypeFail,
} MetroflipPollerEventType;

typedef enum {
MetroflipViewSubmenu,
MetroflipViewTextInput,
MetroflipViewByteInput,
MetroflipViewPopup,
MetroflipViewMenu,
MetroflipViewLoading,
MetroflipViewTextBox,
MetroflipViewWidget,
MetroflipViewUart,
} MetroflipView;

void metroflip_app_blink_start(Metroflip* metroflip);
void metroflip_app_blink_stop(Metroflip* metroflip);

#ifdef FW_ORIGIN_Official
#define submenu_add_lockable_item( \
submenu, label, index, callback, callback_context, locked, locked_message) \
if(!(locked)) submenu_add_item(submenu, label, index, callback, callback_context)
#endif
30 changes: 30 additions & 0 deletions metroflip/scenes/metroflip_scene.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include "metroflip_scene.h"

// Generate scene on_enter handlers array
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter,
void (*const metroflip_on_enter_handlers[])(void*) = {
#include "metroflip_scene_config.h"
};
#undef ADD_SCENE

// Generate scene on_event handlers array
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event,
bool (*const metroflip_on_event_handlers[])(void* context, SceneManagerEvent event) = {
#include "metroflip_scene_config.h"
};
#undef ADD_SCENE

// Generate scene on_exit handlers array
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit,
void (*const metroflip_on_exit_handlers[])(void* context) = {
#include "metroflip_scene_config.h"
};
#undef ADD_SCENE

// Initialize scene handlers configuration structure
const SceneManagerHandlers metroflip_scene_handlers = {
.on_enter_handlers = metroflip_on_enter_handlers,
.on_event_handlers = metroflip_on_event_handlers,
.on_exit_handlers = metroflip_on_exit_handlers,
.scene_num = MetroflipSceneNum,
};
Loading

0 comments on commit 3c9293a

Please sign in to comment.