mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-08-29 07:38:21 +00:00
Added support for parsing and printing value tickets
This commit is contained in:
@@ -145,6 +145,10 @@ static time_t hrt_apply_local_offset(time_t time) {
|
||||
if (gmtime_r(&time, &utc_time) == NULL) return time;
|
||||
#endif
|
||||
|
||||
// EN1545 stores local wall-clock date/time. Match Java TimeZone.getOffset()
|
||||
// by using the DST state that applies at the represented timestamp.
|
||||
utc_time.tm_isdst = local_time.tm_isdst;
|
||||
|
||||
time_t local_as_time = mktime(&local_time);
|
||||
time_t utc_as_local = mktime(&utc_time);
|
||||
|
||||
@@ -170,6 +174,125 @@ time_t en5145_datetime_to_time(int days, int minutes) {
|
||||
return hrt_apply_local_offset(time);
|
||||
}
|
||||
|
||||
static void hrt_eticket_parse_v1(hrt_eticket_t *ticket, const uint8_t *data, size_t data_len, bool encrypted) {
|
||||
if (!ticket || !data || data_len < (encrypted ? HRT_ETICKET_LEN + 6 : HRT_ETICKET_LEN)) return;
|
||||
|
||||
ticket->product_code = ((uint16_t)data[0] << 6) | ((data[1] & 0xFC) >> 2);
|
||||
ticket->child = (data[1] & 0x02) >> 1;
|
||||
ticket->language_code = ((data[1] & 0x01) << 1) | ((data[2] & 0x80) >> 7);
|
||||
ticket->validity_length_type = (data[2] & 0x60) >> 5;
|
||||
ticket->validity_length = ((data[2] & 0x1F) << 3) | ((data[3] & 0xE0) >> 5);
|
||||
ticket->validity_area_type = (data[3] & 0x10) >> 4;
|
||||
ticket->validity_area = data[3] & 0x0F;
|
||||
ticket->sale_date = en5145_date_to_time(((uint16_t)data[4] << 6) | ((data[5] & 0xFC) >> 2));
|
||||
ticket->sale_time = ((data[5] & 0x03) << 3) | ((data[6] & 0xE0) >> 5);
|
||||
ticket->ticket_fare = convert_get_short_value(data, data_len, 68, 14);
|
||||
ticket->group_size = (data[10] & 0x3E) >> 1;
|
||||
ticket->sale_status = data[10] & 0x01;
|
||||
|
||||
size_t offset = encrypted ? 6 : 0;
|
||||
|
||||
ticket->validity_start_date = en5145_datetime_to_time(
|
||||
((uint16_t)data[offset + 11] << 6) | ((data[offset + 12] & 0xFC) >> 2),
|
||||
((data[offset + 12] & 0x03) << 9) |
|
||||
((uint16_t)data[offset + 13] << 1) |
|
||||
((data[offset + 14] & 0x80) >> 7)
|
||||
);
|
||||
|
||||
ticket->validity_end_date = en5145_datetime_to_time(
|
||||
((data[offset + 14] & 0x7F) << 7) | ((data[offset + 15] & 0xFF) >> 1),
|
||||
((data[offset + 15] & 0x01) << 10) |
|
||||
((uint16_t)data[offset + 16] << 2) |
|
||||
((data[offset + 17] & 0xC0) >> 6)
|
||||
);
|
||||
|
||||
ticket->validity_status = data[offset + 17] & 0x01;
|
||||
|
||||
ticket->boarding_date = en5145_datetime_to_time(
|
||||
((uint16_t)data[offset + 18] << 6) | ((data[offset + 19] & 0xFC) >> 2),
|
||||
((data[offset + 19] & 0x03) << 9) |
|
||||
((uint16_t)data[offset + 20] << 1) |
|
||||
((data[offset + 21] & 0x80) >> 7)
|
||||
);
|
||||
|
||||
ticket->boarding_vehicle = ((data[offset + 21] & 0x7F) << 7) | ((data[offset + 22] & 0xFE) >> 1);
|
||||
ticket->boarding_location_num_type = ((data[offset + 22] & 0x01) << 1) | ((data[offset + 23] & 0x80) >> 7);
|
||||
ticket->boarding_location_num = ((data[offset + 23] & 0x7F) << 7) | ((data[offset + 24] & 0xFE) >> 1);
|
||||
ticket->boarding_direction = data[offset + 24] & 0x01;
|
||||
ticket->boarding_area = (data[offset + 25] & 0xF0) >> 4;
|
||||
}
|
||||
|
||||
static void hrt_eticket_parse_v2(hrt_eticket_t *ticket, const uint8_t *data, size_t data_len) {
|
||||
if (!ticket || !data || data_len < HRT_ETICKET_V2_LEN) return;
|
||||
|
||||
ticket->product_code = convert_get_short_value(data, data_len, 1, 14);
|
||||
ticket->product_code_group = convert_get_short_value(data, data_len, 15, 14);
|
||||
ticket->language_code = convert_get_byte_value(data, data_len, 39, 2);
|
||||
ticket->validity_length_type = convert_get_byte_value(data, data_len, 41, 2);
|
||||
ticket->validity_length = convert_get_short_value(data, data_len, 43, 8);
|
||||
ticket->validity_length_type_group = convert_get_byte_value(data, data_len, 51, 2);
|
||||
ticket->validity_length_group = convert_get_short_value(data, data_len, 53, 8);
|
||||
ticket->validity_area_type = convert_get_byte_value(data, data_len, 61, 2);
|
||||
ticket->validity_area = convert_get_byte_value(data, data_len, 63, 6);
|
||||
ticket->sale_date = en5145_date_to_time(convert_get_short_value(data, data_len, 69, 14));
|
||||
ticket->sale_time = convert_get_byte_value(data, data_len, 83, 5);
|
||||
ticket->ticket_fare = convert_get_short_value(data, data_len, 105, 14);
|
||||
ticket->ticket_fare_group = convert_get_short_value(data, data_len, 119, 14);
|
||||
ticket->group_size = convert_get_byte_value(data, data_len, 133, 6);
|
||||
ticket->extra_zone = convert_get_byte_value(data, data_len, 139, 1);
|
||||
ticket->ext_period_pass_validity_area = convert_get_byte_value(data, data_len, 140, 6);
|
||||
ticket->ext_product_code = convert_get_short_value(data, data_len, 146, 14);
|
||||
ticket->ext1_validity_area = convert_get_byte_value(data, data_len, 160, 6);
|
||||
ticket->ext1_fare = convert_get_short_value(data, data_len, 166, 14);
|
||||
ticket->ext2_validity_area = convert_get_byte_value(data, data_len, 180, 6);
|
||||
ticket->ext2_fare = convert_get_short_value(data, data_len, 186, 14);
|
||||
ticket->sale_status = convert_get_byte_value(data, data_len, 200, 1);
|
||||
ticket->validity_start_date = en5145_datetime_to_time(
|
||||
convert_get_short_value(data, data_len, 205, 14),
|
||||
convert_get_short_value(data, data_len, 219, 11)
|
||||
);
|
||||
ticket->validity_end_date = en5145_datetime_to_time(
|
||||
convert_get_short_value(data, data_len, 230, 14),
|
||||
convert_get_short_value(data, data_len, 244, 11)
|
||||
);
|
||||
|
||||
int group_end_days = convert_get_short_value(data, data_len, 255, 14);
|
||||
int group_end_minutes = convert_get_short_value(data, data_len, 269, 11);
|
||||
if (group_end_days > 0 && group_end_minutes > 0) {
|
||||
ticket->validity_end_date_group = en5145_datetime_to_time(group_end_days, group_end_minutes);
|
||||
ticket->has_validity_end_date_group = true;
|
||||
}
|
||||
|
||||
ticket->validity_status = convert_get_byte_value(data, data_len, 285, 1);
|
||||
ticket->boarding_date = en5145_datetime_to_time(
|
||||
convert_get_short_value(data, data_len, 286, 14),
|
||||
convert_get_short_value(data, data_len, 300, 11)
|
||||
);
|
||||
ticket->boarding_vehicle = convert_get_short_value(data, data_len, 311, 14);
|
||||
ticket->boarding_location_num_type = convert_get_byte_value(data, data_len, 325, 2);
|
||||
ticket->boarding_location_num = convert_get_short_value(data, data_len, 327, 14);
|
||||
ticket->boarding_direction = convert_get_byte_value(data, data_len, 341, 1);
|
||||
ticket->boarding_area = convert_get_byte_value(data, data_len, 344, 6);
|
||||
}
|
||||
|
||||
static hrt_eticket_t *hrt_eticket_create(const uint8_t *data, size_t data_len, bool encrypted, int version) {
|
||||
if (!data) return NULL;
|
||||
|
||||
hrt_eticket_t *ticket = calloc(1, sizeof(hrt_eticket_t));
|
||||
if (!ticket) {
|
||||
PrintAndLogEx(WARNING, "Failed to allocate memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (version == 2) {
|
||||
hrt_eticket_parse_v2(ticket, data, data_len);
|
||||
} else {
|
||||
hrt_eticket_parse_v1(ticket, data, data_len, encrypted);
|
||||
}
|
||||
|
||||
return ticket;
|
||||
}
|
||||
|
||||
void hrt_travelcard_free(hrt_travel_card_t *card) {
|
||||
if (!card) return;
|
||||
|
||||
@@ -190,12 +313,7 @@ void hrt_travelcard_free(hrt_travel_card_t *card) {
|
||||
free(card->application_instance_id);
|
||||
free(card->history_fields);
|
||||
|
||||
// TODO: Implement value tickets
|
||||
// if (card->value_ticket) {
|
||||
// eticket_free(card->value_ticket);
|
||||
// card->value_ticket = NULL;
|
||||
// }
|
||||
|
||||
free(card->value_ticket);
|
||||
memset(card, 0, sizeof(*card));
|
||||
}
|
||||
|
||||
@@ -557,8 +675,143 @@ void hrt_history_set_transfer_end_date(hrt_history_t *history, time_t datetime)
|
||||
if (history) history->transfer_end_date = datetime;
|
||||
}
|
||||
|
||||
// TODO: Implement value tickets
|
||||
// HRT_eTicket *eticket_create(const uint8_t *data, size_t data_len, int is_encrypted, int version);
|
||||
bool hrt_eticket_is_defined(const hrt_eticket_t *ticket) {
|
||||
return ticket &&
|
||||
(ticket->product_code > 0 ||
|
||||
ticket->product_code_group > 0 ||
|
||||
ticket->ticket_fare > 0 ||
|
||||
ticket->ticket_fare_group > 0 ||
|
||||
ticket->group_size > 0 ||
|
||||
ticket->boarding_vehicle > 0);
|
||||
}
|
||||
|
||||
int hrt_eticket_get_product_code(const hrt_eticket_t *ticket) {
|
||||
if (!ticket) return 0;
|
||||
return ticket->product_code_group > 0 ? ticket->product_code_group : ticket->product_code;
|
||||
}
|
||||
|
||||
int hrt_eticket_get_validity_length_type(const hrt_eticket_t *ticket) {
|
||||
if (!ticket) return 0;
|
||||
return ticket->validity_length_type_group > 0 ? ticket->validity_length_type_group : ticket->validity_length_type;
|
||||
}
|
||||
|
||||
int hrt_eticket_get_validity_length(const hrt_eticket_t *ticket) {
|
||||
if (!ticket) return 0;
|
||||
return ticket->validity_length_group > 0 ? ticket->validity_length_group : ticket->validity_length;
|
||||
}
|
||||
|
||||
int hrt_eticket_get_validity_area_type(const hrt_eticket_t *ticket) {
|
||||
return ticket ? ticket->validity_area_type : 0;
|
||||
}
|
||||
|
||||
int hrt_eticket_get_validity_area(const hrt_eticket_t *ticket) {
|
||||
return ticket ? ticket->validity_area : 0;
|
||||
}
|
||||
|
||||
time_t hrt_eticket_get_sale_date(const hrt_eticket_t *ticket) {
|
||||
return ticket ? ticket->sale_date : (time_t)0;
|
||||
}
|
||||
|
||||
int hrt_eticket_get_sale_time(const hrt_eticket_t *ticket) {
|
||||
return ticket ? ticket->sale_time : 0;
|
||||
}
|
||||
|
||||
int hrt_eticket_get_ticket_fare(const hrt_eticket_t *ticket) {
|
||||
if (!ticket) return 0;
|
||||
if (ticket->ticket_fare > 0) return ticket->ticket_fare;
|
||||
return ticket->ticket_fare_group > 0 ? ticket->ticket_fare_group : 0;
|
||||
}
|
||||
|
||||
int hrt_eticket_get_right_fare(const hrt_eticket_t *ticket) {
|
||||
if (!ticket) return 0;
|
||||
|
||||
int fare = ticket->ticket_fare;
|
||||
int group_size = ticket->group_size;
|
||||
if ((ticket->extra_zone == 1 || fare > 0) && group_size > 1) {
|
||||
group_size--;
|
||||
}
|
||||
return fare + (ticket->ticket_fare_group * group_size);
|
||||
}
|
||||
|
||||
int hrt_eticket_get_total_fare(const hrt_eticket_t *ticket) {
|
||||
if (!ticket) return 0;
|
||||
|
||||
int fare = hrt_eticket_get_right_fare(ticket);
|
||||
return ticket->extra_zone == 1 ? fare + ticket->ext1_fare + ticket->ext2_fare : fare;
|
||||
}
|
||||
|
||||
int hrt_eticket_get_group_size(const hrt_eticket_t *ticket) {
|
||||
return ticket ? ticket->group_size : 0;
|
||||
}
|
||||
|
||||
int hrt_eticket_get_sale_status(const hrt_eticket_t *ticket) {
|
||||
return ticket ? ticket->sale_status : 0;
|
||||
}
|
||||
|
||||
time_t hrt_eticket_get_validity_start_date(const hrt_eticket_t *ticket) {
|
||||
return ticket ? ticket->validity_start_date : (time_t)0;
|
||||
}
|
||||
|
||||
time_t hrt_eticket_get_validity_end_date(const hrt_eticket_t *ticket) {
|
||||
if (!ticket) return (time_t)0;
|
||||
return ticket->has_validity_end_date_group ? ticket->validity_end_date_group : ticket->validity_end_date;
|
||||
}
|
||||
|
||||
int hrt_eticket_get_validity_status(const hrt_eticket_t *ticket) {
|
||||
return ticket ? ticket->validity_status : 0;
|
||||
}
|
||||
|
||||
time_t hrt_eticket_get_boarding_date(const hrt_eticket_t *ticket) {
|
||||
return ticket ? ticket->boarding_date : (time_t)0;
|
||||
}
|
||||
|
||||
int hrt_eticket_get_boarding_vehicle(const hrt_eticket_t *ticket) {
|
||||
return ticket ? ticket->boarding_vehicle : 0;
|
||||
}
|
||||
|
||||
int hrt_eticket_get_boarding_location_num_type(const hrt_eticket_t *ticket) {
|
||||
return ticket ? ticket->boarding_location_num_type : 0;
|
||||
}
|
||||
|
||||
int hrt_eticket_get_boarding_location_num(const hrt_eticket_t *ticket) {
|
||||
return ticket ? ticket->boarding_location_num : 0;
|
||||
}
|
||||
|
||||
int hrt_eticket_get_boarding_direction(const hrt_eticket_t *ticket) {
|
||||
return ticket ? ticket->boarding_direction : 0;
|
||||
}
|
||||
|
||||
int hrt_eticket_get_boarding_area(const hrt_eticket_t *ticket) {
|
||||
return ticket ? ticket->boarding_area : 0;
|
||||
}
|
||||
|
||||
int hrt_eticket_get_extra_zone(const hrt_eticket_t *ticket) {
|
||||
return ticket ? ticket->extra_zone : 0;
|
||||
}
|
||||
|
||||
int hrt_eticket_get_ext_period_pass_validity_area(const hrt_eticket_t *ticket) {
|
||||
return ticket ? ticket->ext_period_pass_validity_area : 0;
|
||||
}
|
||||
|
||||
int hrt_eticket_get_ext_product_code(const hrt_eticket_t *ticket) {
|
||||
return ticket ? ticket->ext_product_code : 0;
|
||||
}
|
||||
|
||||
int hrt_eticket_get_ext1_validity_area(const hrt_eticket_t *ticket) {
|
||||
return ticket ? ticket->ext1_validity_area : 0;
|
||||
}
|
||||
|
||||
int hrt_eticket_get_ext1_fare(const hrt_eticket_t *ticket) {
|
||||
return ticket ? ticket->ext1_fare : 0;
|
||||
}
|
||||
|
||||
int hrt_eticket_get_ext2_validity_area(const hrt_eticket_t *ticket) {
|
||||
return ticket ? ticket->ext2_validity_area : 0;
|
||||
}
|
||||
|
||||
int hrt_eticket_get_ext2_fare(const hrt_eticket_t *ticket) {
|
||||
return ticket ? ticket->ext2_fare : 0;
|
||||
}
|
||||
|
||||
// Getter methods for API simplicity
|
||||
int hrt_travelcard_get_application_version(const hrt_travel_card_t *card) {
|
||||
@@ -768,12 +1021,18 @@ bool hrt_travelcard_set_eticket(hrt_travel_card_t *card, const uint8_t *buf, siz
|
||||
if (card->version == 2) {
|
||||
if (!card->eticket_data_v2 || len < HRT_ETICKET_V2_LEN) return false;
|
||||
memcpy(card->eticket_data_v2, buf, HRT_ETICKET_V2_LEN);
|
||||
return true;
|
||||
|
||||
free(card->value_ticket);
|
||||
card->value_ticket = hrt_eticket_create(card->eticket_data_v2, HRT_ETICKET_V2_LEN, false, 2);
|
||||
return card->value_ticket != NULL;
|
||||
}
|
||||
|
||||
if (!card->eticket_data || len < HRT_ETICKET_LEN) return false;
|
||||
memcpy(card->eticket_data, buf, HRT_ETICKET_LEN);
|
||||
return true;
|
||||
|
||||
free(card->value_ticket);
|
||||
card->value_ticket = hrt_eticket_create(card->eticket_data, HRT_ETICKET_LEN, false, 1);
|
||||
return card->value_ticket != NULL;
|
||||
}
|
||||
|
||||
bool hrt_travelcard_set_history(hrt_travel_card_t *card, const uint8_t *buf, size_t len) {
|
||||
|
||||
@@ -33,8 +33,42 @@
|
||||
#define MSB(b) ((b) & 0x80)
|
||||
#define LSB7(b) ((b) & 0x7F)
|
||||
|
||||
// TODO: Implement
|
||||
typedef struct hrt_eticket_t hrt_eticket_t;
|
||||
typedef struct {
|
||||
int boarding_area;
|
||||
time_t boarding_date;
|
||||
int boarding_direction;
|
||||
int boarding_location_num;
|
||||
int boarding_location_num_type;
|
||||
int boarding_vehicle;
|
||||
int child;
|
||||
int ext1_fare;
|
||||
int ext1_validity_area;
|
||||
int ext2_fare;
|
||||
int ext2_validity_area;
|
||||
int ext_period_pass_validity_area;
|
||||
int ext_product_code;
|
||||
int extra_zone;
|
||||
int group_size;
|
||||
int language_code;
|
||||
int product_code;
|
||||
int product_code_group;
|
||||
time_t sale_date;
|
||||
int sale_status;
|
||||
int sale_time;
|
||||
int ticket_fare;
|
||||
int ticket_fare_group;
|
||||
int validity_area;
|
||||
int validity_area_type;
|
||||
time_t validity_end_date;
|
||||
time_t validity_end_date_group;
|
||||
bool has_validity_end_date_group;
|
||||
int validity_length;
|
||||
int validity_length_group;
|
||||
int validity_length_type;
|
||||
int validity_length_type_group;
|
||||
time_t validity_start_date;
|
||||
int validity_status;
|
||||
} hrt_eticket_t;
|
||||
|
||||
typedef struct {
|
||||
int group_size;
|
||||
@@ -163,6 +197,37 @@ void hrt_history_set_group_size(hrt_history_t *history, int group_size);
|
||||
void hrt_history_set_price(hrt_history_t *history, int price);
|
||||
void hrt_history_set_transfer_end_date(hrt_history_t *history, time_t datetime);
|
||||
|
||||
// E-ticket Functions
|
||||
bool hrt_eticket_is_defined(const hrt_eticket_t *ticket);
|
||||
int hrt_eticket_get_product_code(const hrt_eticket_t *ticket);
|
||||
int hrt_eticket_get_validity_length_type(const hrt_eticket_t *ticket);
|
||||
int hrt_eticket_get_validity_length(const hrt_eticket_t *ticket);
|
||||
int hrt_eticket_get_validity_area_type(const hrt_eticket_t *ticket);
|
||||
int hrt_eticket_get_validity_area(const hrt_eticket_t *ticket);
|
||||
time_t hrt_eticket_get_sale_date(const hrt_eticket_t *ticket);
|
||||
int hrt_eticket_get_sale_time(const hrt_eticket_t *ticket);
|
||||
int hrt_eticket_get_ticket_fare(const hrt_eticket_t *ticket);
|
||||
int hrt_eticket_get_right_fare(const hrt_eticket_t *ticket);
|
||||
int hrt_eticket_get_total_fare(const hrt_eticket_t *ticket);
|
||||
int hrt_eticket_get_group_size(const hrt_eticket_t *ticket);
|
||||
int hrt_eticket_get_sale_status(const hrt_eticket_t *ticket);
|
||||
time_t hrt_eticket_get_validity_start_date(const hrt_eticket_t *ticket);
|
||||
time_t hrt_eticket_get_validity_end_date(const hrt_eticket_t *ticket);
|
||||
int hrt_eticket_get_validity_status(const hrt_eticket_t *ticket);
|
||||
time_t hrt_eticket_get_boarding_date(const hrt_eticket_t *ticket);
|
||||
int hrt_eticket_get_boarding_vehicle(const hrt_eticket_t *ticket);
|
||||
int hrt_eticket_get_boarding_location_num_type(const hrt_eticket_t *ticket);
|
||||
int hrt_eticket_get_boarding_location_num(const hrt_eticket_t *ticket);
|
||||
int hrt_eticket_get_boarding_direction(const hrt_eticket_t *ticket);
|
||||
int hrt_eticket_get_boarding_area(const hrt_eticket_t *ticket);
|
||||
int hrt_eticket_get_extra_zone(const hrt_eticket_t *ticket);
|
||||
int hrt_eticket_get_ext_period_pass_validity_area(const hrt_eticket_t *ticket);
|
||||
int hrt_eticket_get_ext_product_code(const hrt_eticket_t *ticket);
|
||||
int hrt_eticket_get_ext1_validity_area(const hrt_eticket_t *ticket);
|
||||
int hrt_eticket_get_ext1_fare(const hrt_eticket_t *ticket);
|
||||
int hrt_eticket_get_ext2_validity_area(const hrt_eticket_t *ticket);
|
||||
int hrt_eticket_get_ext2_fare(const hrt_eticket_t *ticket);
|
||||
|
||||
// Parsing Functions
|
||||
void hrt_read_application_info(hrt_travel_card_t *card, const uint8_t *data, size_t data_len);
|
||||
void hrt_read_control_info(hrt_travel_card_t *card, const uint8_t *data, size_t data_len);
|
||||
|
||||
@@ -180,6 +180,7 @@ static void hrt_print_card(const hrt_travel_card_t *card) {
|
||||
const char *product_name = hrt_lookup_product_name(product_code);
|
||||
int area_type = hrt_travelcard_get_validity_area_type1(card);
|
||||
int area = hrt_travelcard_get_validity_area1(card);
|
||||
const hrt_eticket_t *value_ticket = hrt_travelcard_get_value_ticket(card);
|
||||
|
||||
hrt_price_to_string(
|
||||
hrt_travelcard_get_stored_value_counter(card),
|
||||
@@ -218,7 +219,38 @@ static void hrt_print_card(const hrt_travel_card_t *card) {
|
||||
hrt_print_time(" End date...............", hrt_travelcard_get_period_end_date1(card));
|
||||
PrintAndLogEx(SUCCESS, " Season ticket length... " _GREEN_("%d days"), hrt_travelcard_get_period_length1(card));
|
||||
|
||||
// TODO: Print value ticket information
|
||||
if (hrt_eticket_is_defined(value_ticket)) {
|
||||
char fare_buf[32] = {0};
|
||||
char value_area_buf[64] = {0};
|
||||
int value_product_code = hrt_eticket_get_product_code(value_ticket);
|
||||
const char *value_product_name = hrt_lookup_product_name(value_product_code);
|
||||
int value_area_type = hrt_eticket_get_validity_area_type(value_ticket);
|
||||
int value_area = hrt_eticket_get_validity_area(value_ticket);
|
||||
|
||||
hrt_price_to_string(hrt_eticket_get_total_fare(value_ticket), fare_buf, sizeof(fare_buf));
|
||||
|
||||
PrintAndLogEx(SUCCESS, "");
|
||||
PrintAndLogEx(SUCCESS, "Value ticket information");
|
||||
|
||||
if (value_product_name != NULL) {
|
||||
PrintAndLogEx(SUCCESS, " Product code........... " _GREEN_("%d (%s)"), value_product_code, value_product_name);
|
||||
} else {
|
||||
PrintAndLogEx(SUCCESS, " Product code........... " _GREEN_("%d (unknown)"), value_product_code);
|
||||
}
|
||||
|
||||
if (hrt_format_area(value_area_type, value_area, value_area_buf, sizeof(value_area_buf))) {
|
||||
PrintAndLogEx(SUCCESS, " Area................... " _GREEN_("%s"), value_area_buf);
|
||||
} else {
|
||||
PrintAndLogEx(SUCCESS, " Area................... " _GREEN_("%d (type %d)"), value_area, value_area_type);
|
||||
}
|
||||
|
||||
PrintAndLogEx(SUCCESS, " Fare................... " _GREEN_("%s"), fare_buf);
|
||||
PrintAndLogEx(SUCCESS, " Group size............. " _GREEN_("%d"), hrt_eticket_get_group_size(value_ticket));
|
||||
hrt_print_time(" Valid from.............", hrt_eticket_get_validity_start_date(value_ticket));
|
||||
hrt_print_time(" Valid until............", hrt_eticket_get_validity_end_date(value_ticket));
|
||||
hrt_print_time(" Boarding time..........", hrt_eticket_get_boarding_date(value_ticket));
|
||||
PrintAndLogEx(SUCCESS, " Boarding vehicle....... " _GREEN_("%d"), hrt_eticket_get_boarding_vehicle(value_ticket));
|
||||
}
|
||||
}
|
||||
|
||||
bool is_valid_hrt_card(DesfireContext_t *dctx, const uint8_t *aidbuf, size_t aidbuflen) {
|
||||
|
||||
Reference in New Issue
Block a user