Merge remote-tracking branch 'ul/dev' into mntm-dev

This commit is contained in:
Willy-JL
2024-10-29 02:11:16 +00:00
3 changed files with 79 additions and 10 deletions

View File

@@ -62,7 +62,7 @@
- UL: Add GangQi protocol (static 34 bit) with button parsing and add manually (by @xMasterX & @Skorpionm) - UL: Add GangQi protocol (static 34 bit) with button parsing and add manually (by @xMasterX & @Skorpionm)
- UL: Add Hollarm protocol (static 42 bit) with button parsing and add manually (by @xMasterX & @Skorpionm) - UL: Add Hollarm protocol (static 42 bit) with button parsing and add manually (by @xMasterX & @Skorpionm)
- UL: Add Hay21 protocol (dynamic 21 bit) with button parsing (by @xMasterX) - UL: Add Hay21 protocol (dynamic 21 bit) with button parsing (by @xMasterX)
- UL: Add Keeloq Monarch full support, with add manually (by anonymous UL contributor) - UL: Add Keeloq Monarch full support, with add manually (by @ashphx)
- UL: Princeton custom buttons support (by @xMasterX) - UL: Princeton custom buttons support (by @xMasterX)
- NFC: - NFC:
- OFW: MIFARE Classic Key Recovery Improvements (PR 3822 by @noproto) - OFW: MIFARE Classic Key Recovery Improvements (PR 3822 by @noproto)
@@ -124,7 +124,7 @@
- Added 6 new Mifare Classic keys from Bulgaria Hotel (#216 by @z3r0l1nk) - Added 6 new Mifare Classic keys from Bulgaria Hotel (#216 by @z3r0l1nk)
- UL: Add iq aparts hotel key (by @xMasterX) - UL: Add iq aparts hotel key (by @xMasterX)
- OFW/UL: Rename 'Detect Reader' to 'Extract MFC Keys' (by @bettse & @xMasterX) - OFW/UL: Rename 'Detect Reader' to 'Extract MFC Keys' (by @bettse & @xMasterX)
- OFW: Plantain parser improvements (by @assasinfil) - OFW: Plantain parser improvements (by @assasinfil) and fixes (by @mxcdoam)
- OFW: Moscow social card parser (by @assasinfil) - OFW: Moscow social card parser (by @assasinfil)
- OFW: Fixes and improvements to iso14443_4a listener and poller (by @RebornedBrain) - OFW: Fixes and improvements to iso14443_4a listener and poller (by @RebornedBrain)
- OFW: Update BART station codes in Clipper plugin (by @ted-logan) - OFW: Update BART station codes in Clipper plugin (by @ted-logan)

View File

@@ -201,8 +201,9 @@ static bool plantain_read(Nfc* nfc, NfcDevice* device) {
static bool plantain_parse(const NfcDevice* device, FuriString* parsed_data) { static bool plantain_parse(const NfcDevice* device, FuriString* parsed_data) {
furi_assert(device); furi_assert(device);
size_t uid_len = 0;
const MfClassicData* data = nfc_device_get_data(device, NfcProtocolMfClassic); const MfClassicData* data = nfc_device_get_data(device, NfcProtocolMfClassic);
const uint8_t* uid = mf_classic_get_uid(data, &uid_len);
bool parsed = false; bool parsed = false;
@@ -220,12 +221,30 @@ static bool plantain_parse(const NfcDevice* device, FuriString* parsed_data) {
if(key != cfg.keys[cfg.data_sector].a) break; if(key != cfg.keys[cfg.data_sector].a) break;
furi_string_printf(parsed_data, "\e#Plantain card\n"); furi_string_printf(parsed_data, "\e#Plantain card\n");
const uint8_t* temp_ptr = &uid[0];
// UID is read from last to first byte
uint8_t card_number_tmp[uid_len];
if(uid_len == 4) {
for(size_t i = 0; i < 4; i++) {
card_number_tmp[i] = temp_ptr[3 - i];
}
} else if(uid_len == 7) {
for(size_t i = 0; i < 7; i++) {
card_number_tmp[i] = temp_ptr[6 - i];
}
} else {
break;
}
//UID is converted to a card number
uint64_t card_number = 0; uint64_t card_number = 0;
for(size_t i = 0; i < 7; i++) { for(size_t i = 0; i < uid_len; i++) {
card_number = (card_number << 8) | data->block[0].data[6 - i]; card_number = (card_number << 8) | card_number_tmp[i];
} }
// Print card number with 4-digit groups // Print card number with 4-digit groups. "3" in "3078" denotes a ticket type "3 - full ticket", will differ on discounted cards.
furi_string_cat_printf(parsed_data, "Number: "); furi_string_cat_printf(parsed_data, "Number: ");
FuriString* card_number_s = furi_string_alloc(); FuriString* card_number_s = furi_string_alloc();
furi_string_cat_printf(card_number_s, "%lld", card_number); furi_string_cat_printf(card_number_s, "%lld", card_number);
@@ -237,6 +256,7 @@ static bool plantain_parse(const NfcDevice* device, FuriString* parsed_data) {
furi_string_push_back(tmp_s, ' '); furi_string_push_back(tmp_s, ' ');
} }
furi_string_cat_printf(parsed_data, "%s\n", furi_string_get_cstr(tmp_s)); furi_string_cat_printf(parsed_data, "%s\n", furi_string_get_cstr(tmp_s));
// this works for 2K Plantain
if(data->type == MfClassicType1k) { if(data->type == MfClassicType1k) {
//balance //balance
uint32_t balance = 0; uint32_t balance = 0;
@@ -290,20 +310,70 @@ static bool plantain_parse(const NfcDevice* device, FuriString* parsed_data) {
last_payment_date.year, last_payment_date.year,
last_payment_date.hour, last_payment_date.hour,
last_payment_date.minute); last_payment_date.minute);
//payment summ //payment amount. This needs to be investigated more, currently it shows incorrect amount on some cards.
uint16_t last_payment = (data->block[18].data[9] << 8) | data->block[18].data[8]; uint16_t last_payment = (data->block[18].data[9] << 8) | data->block[18].data[8];
furi_string_cat_printf(parsed_data, "Amount: %d rub", last_payment / 100); furi_string_cat_printf(parsed_data, "Amount: %d rub", last_payment / 100);
furi_string_free(card_number_s); furi_string_free(card_number_s);
furi_string_free(tmp_s); furi_string_free(tmp_s);
//This is for 4K Plantains.
} else if(data->type == MfClassicType4k) { } else if(data->type == MfClassicType4k) {
//balance
uint32_t balance = 0;
for(uint8_t i = 0; i < 4; i++) {
balance = (balance << 8) | data->block[16].data[3 - i];
}
furi_string_cat_printf(parsed_data, "Balance: %ld rub\n", balance / 100);
//trips //trips
uint8_t trips_metro = data->block[36].data[0]; uint8_t trips_metro = data->block[21].data[0];
uint8_t trips_ground = data->block[36].data[1]; uint8_t trips_ground = data->block[21].data[1];
furi_string_cat_printf(parsed_data, "Trips: %d\n", trips_metro + trips_ground); furi_string_cat_printf(parsed_data, "Trips: %d\n", trips_metro + trips_ground);
//trip time
uint32_t last_trip_timestamp = 0;
for(uint8_t i = 0; i < 3; i++) {
last_trip_timestamp = (last_trip_timestamp << 8) | data->block[21].data[4 - i];
}
DateTime last_trip = {0};
from_minutes_to_datetime(last_trip_timestamp + 24 * 60, &last_trip, 2010);
furi_string_cat_printf(
parsed_data,
"Trip start: %02d.%02d.%04d %02d:%02d\n",
last_trip.day,
last_trip.month,
last_trip.year,
last_trip.hour,
last_trip.minute);
//validator
uint16_t validator = (data->block[20].data[5] << 8) | data->block[20].data[4];
furi_string_cat_printf(parsed_data, "Validator: %d\n", validator);
//tariff
uint16_t fare = (data->block[20].data[7] << 8) | data->block[20].data[6];
furi_string_cat_printf(parsed_data, "Tariff: %d rub\n", fare / 100);
//trips in metro //trips in metro
furi_string_cat_printf(parsed_data, "Trips (Metro): %d\n", trips_metro); furi_string_cat_printf(parsed_data, "Trips (Metro): %d\n", trips_metro);
//trips on ground //trips on ground
furi_string_cat_printf(parsed_data, "Trips (Ground): %d\n", trips_ground); furi_string_cat_printf(parsed_data, "Trips (Ground): %d\n", trips_ground);
//last payment
uint32_t last_payment_timestamp = 0;
for(uint8_t i = 0; i < 3; i++) {
last_payment_timestamp = (last_payment_timestamp << 8) |
data->block[18].data[4 - i];
}
DateTime last_payment_date = {0};
from_minutes_to_datetime(last_payment_timestamp + 24 * 60, &last_payment_date, 2010);
furi_string_cat_printf(
parsed_data,
"Last pay: %02d.%02d.%04d %02d:%02d\n",
last_payment_date.day,
last_payment_date.month,
last_payment_date.year,
last_payment_date.hour,
last_payment_date.minute);
//payment amount
uint16_t last_payment = (data->block[18].data[9] << 8) | data->block[18].data[8];
furi_string_cat_printf(parsed_data, "Amount: %d rub", last_payment / 100);
furi_string_free(card_number_s);
furi_string_free(tmp_s);
} }
parsed = true; parsed = true;
} while(false); } while(false);

View File

@@ -269,7 +269,6 @@ static void js_gpio_get(struct mjs* mjs) {
manager_data->interrupt_semaphore = furi_semaphore_alloc(UINT32_MAX, 0); manager_data->interrupt_semaphore = furi_semaphore_alloc(UINT32_MAX, 0);
manager_data->adc_handle = module->adc_handle; manager_data->adc_handle = module->adc_handle;
manager_data->adc_channel = pin_record->channel; manager_data->adc_channel = pin_record->channel;
mjs_own(mjs, &manager);
mjs_set(mjs, manager, INST_PROP_NAME, ~0, mjs_mk_foreign(mjs, manager_data)); mjs_set(mjs, manager, INST_PROP_NAME, ~0, mjs_mk_foreign(mjs, manager_data));
mjs_set(mjs, manager, "init", ~0, MJS_MK_FN(js_gpio_init)); mjs_set(mjs, manager, "init", ~0, MJS_MK_FN(js_gpio_init));
mjs_set(mjs, manager, "write", ~0, MJS_MK_FN(js_gpio_write)); mjs_set(mjs, manager, "write", ~0, MJS_MK_FN(js_gpio_write));