mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2024-11-22 17:33:13 +03:00
Merge remote-tracking branch 'RebornedBrain/reborned/some_api_adjustments' into dev [ci skip]
This commit is contained in:
commit
0d8d71ff1c
@ -525,6 +525,19 @@ void canvas_draw_xbm(
|
||||
canvas_draw_u8g2_bitmap(&canvas->fb, x, y, width, height, bitmap, IconRotation0);
|
||||
}
|
||||
|
||||
void canvas_draw_xbm_mirrored(
|
||||
Canvas* canvas,
|
||||
int32_t x,
|
||||
int32_t y,
|
||||
size_t width,
|
||||
size_t height,
|
||||
const uint8_t* bitmap_data) {
|
||||
furi_check(canvas);
|
||||
x += canvas->offset_x;
|
||||
y += canvas->offset_y;
|
||||
canvas_draw_u8g2_bitmap(&canvas->fb, x, y, width, height, bitmap_data, IconRotation180);
|
||||
}
|
||||
|
||||
void canvas_draw_glyph(Canvas* canvas, int32_t x, int32_t y, uint16_t ch) {
|
||||
furi_check(canvas);
|
||||
x += canvas->offset_x;
|
||||
|
@ -296,6 +296,23 @@ void canvas_draw_xbm(
|
||||
size_t height,
|
||||
const uint8_t* bitmap);
|
||||
|
||||
/** Draw mirrored XBM bitmap
|
||||
*
|
||||
* @param canvas Canvas instance
|
||||
* @param x x coordinate
|
||||
* @param y y coordinate
|
||||
* @param[in] width bitmap width
|
||||
* @param[in] height bitmap height
|
||||
* @param bitmap pointer to XBM bitmap data
|
||||
*/
|
||||
void canvas_draw_xbm_mirrored(
|
||||
Canvas* canvas,
|
||||
int32_t x,
|
||||
int32_t y,
|
||||
size_t width,
|
||||
size_t height,
|
||||
const uint8_t* bitmap_data);
|
||||
|
||||
/** Draw dot at x,y
|
||||
*
|
||||
* @param canvas Canvas instance
|
||||
|
@ -2,22 +2,50 @@
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
#define ISO14443_4_BLOCK_PCB (1U << 1)
|
||||
#define ISO14443_4_BLOCK_PCB_I (0U)
|
||||
#define ISO14443_4_BLOCK_PCB_R (5U << 5)
|
||||
#define ISO14443_4_BLOCK_PCB_S (3U << 6)
|
||||
|
||||
// EMV Specific masks
|
||||
#define ISO14443_4_BLOCK_PCB_I_ (0U << 6)
|
||||
#define ISO14443_4_BLOCK_PCB_R_ (2U << 6)
|
||||
#define ISO14443_4_BLOCK_PCB_TYPE_MASK (3U << 6)
|
||||
#define ISO14443_4_BLOCK_PCB_S_WTX (3U << 4)
|
||||
#define ISO14443_4_BLOCK_PCB_S (3U << 6)
|
||||
//
|
||||
|
||||
#define ISO14443_4_BLOCK_PCB_S_DESELECT (0U << 4)
|
||||
#define ISO14443_4_BLOCK_PCB_S_WTX (3U << 4)
|
||||
#define ISO14443_4_BLOCK_PCB_BLOCK_NUMBER (1U << 0)
|
||||
#define ISO14443_4_BLOCK_PCB (1U << 1)
|
||||
#define ISO14443_4_BLOCK_PCB_MASK (0x03)
|
||||
|
||||
#define ISO14443_4_BLOCK_PCB_NAD (1U << 2)
|
||||
#define ISO14443_4_BLOCK_PCB_CID (1U << 3)
|
||||
#define ISO14443_4_BLOCK_PCB_CHAINING (1U << 4)
|
||||
#define ISO14443_4_BLOCK_PCB_I (0U)
|
||||
#define ISO14443_4_BLOCK_PCB_I_NAD_OFFSET (2)
|
||||
#define ISO14443_4_BLOCK_PCB_I_CID_OFFSET (3)
|
||||
#define ISO14443_4_BLOCK_PCB_I_CHAIN_OFFSET (4)
|
||||
#define ISO14443_4_BLOCK_PCB_I_NAD_MASK (1U << ISO14443_4_BLOCK_PCB_I_NAD_OFFSET)
|
||||
#define ISO14443_4_BLOCK_PCB_I_CID_MASK (1U << ISO14443_4_BLOCK_PCB_I_CID_OFFSET)
|
||||
#define ISO14443_4_BLOCK_PCB_I_CHAIN_MASK (1U << ISO14443_4_BLOCK_PCB_I_CHAIN_OFFSET)
|
||||
|
||||
#define ISO14443_4_BLOCK_PCB_R_MASK (5U << 5)
|
||||
#define ISO14443_4_BLOCK_PCB_R_NACK_OFFSET (4)
|
||||
#define ISO14443_4_BLOCK_PCB_R_CID_OFFSET (3)
|
||||
#define ISO14443_4_BLOCK_PCB_R_CID_MASK (1U << ISO14443_4_BLOCK_PCB_R_CID_OFFSET)
|
||||
#define ISO14443_4_BLOCK_PCB_R_NACK_MASK (1U << ISO14443_4_BLOCK_PCB_R_NACK_OFFSET)
|
||||
|
||||
#define ISO14443_4_BLOCK_PCB_S_MASK (3U << 6)
|
||||
#define ISO14443_4_BLOCK_PCB_S_CID_OFFSET (3)
|
||||
#define ISO14443_4_BLOCK_PCB_S_WTX_DESELECT_OFFSET (4)
|
||||
#define ISO14443_4_BLOCK_PCB_S_CID_MASK (1U << ISO14443_4_BLOCK_PCB_R_CID_OFFSET)
|
||||
#define ISO14443_4_BLOCK_PCB_S_WTX_DESELECT_MASK (3U << ISO14443_4_BLOCK_PCB_S_WTX_DESELECT_OFFSET)
|
||||
|
||||
#define ISO14443_4_BLOCK_PCB_BITS_ACTIVE(pcb, mask) (((pcb) & mask) == mask)
|
||||
|
||||
#define ISO14443_4_BLOCK_PCB_IS_R_BLOCK(pcb) \
|
||||
ISO14443_4_BLOCK_PCB_BITS_ACTIVE(pcb, ISO14443_4_BLOCK_PCB_R_MASK)
|
||||
|
||||
#define ISO14443_4_BLOCK_PCB_IS_S_BLOCK(pcb) \
|
||||
ISO14443_4_BLOCK_PCB_BITS_ACTIVE(pcb, ISO14443_4_BLOCK_PCB_S_MASK)
|
||||
|
||||
#define ISO14443_4_BLOCK_PCB_IS_CHAIN_ACTIVE(pcb) \
|
||||
ISO14443_4_BLOCK_PCB_BITS_ACTIVE(pcb, ISO14443_4_BLOCK_PCB_I_CHAIN_MASK)
|
||||
|
||||
#define ISO14443_4_BLOCK_PCB_R_NACK_ACTIVE(pcb) \
|
||||
ISO14443_4_BLOCK_PCB_BITS_ACTIVE(pcb, ISO14443_4_BLOCK_PCB_R_NACK_MASK)
|
||||
|
||||
struct Iso14443_4Layer {
|
||||
uint8_t pcb;
|
||||
@ -43,9 +71,31 @@ void iso14443_4_layer_free(Iso14443_4Layer* instance) {
|
||||
|
||||
void iso14443_4_layer_reset(Iso14443_4Layer* instance) {
|
||||
furi_assert(instance);
|
||||
instance->pcb_prev = 0;
|
||||
instance->pcb = ISO14443_4_BLOCK_PCB_I | ISO14443_4_BLOCK_PCB;
|
||||
}
|
||||
|
||||
void iso14443_4_layer_set_i_block(Iso14443_4Layer* instance, bool chaining, bool CID_present) {
|
||||
uint8_t block_pcb = instance->pcb & ISO14443_4_BLOCK_PCB_MASK;
|
||||
instance->pcb = ISO14443_4_BLOCK_PCB_I | (chaining << ISO14443_4_BLOCK_PCB_I_CHAIN_OFFSET) |
|
||||
(CID_present << ISO14443_4_BLOCK_PCB_I_CID_OFFSET) | block_pcb;
|
||||
}
|
||||
|
||||
void iso14443_4_layer_set_r_block(Iso14443_4Layer* instance, bool acknowledged, bool CID_present) {
|
||||
furi_assert(instance);
|
||||
uint8_t block_pcb = instance->pcb & ISO14443_4_BLOCK_PCB_MASK;
|
||||
instance->pcb = ISO14443_4_BLOCK_PCB_R_MASK |
|
||||
(!acknowledged << ISO14443_4_BLOCK_PCB_R_NACK_OFFSET) |
|
||||
(CID_present << ISO14443_4_BLOCK_PCB_R_CID_OFFSET) | block_pcb;
|
||||
}
|
||||
|
||||
void iso14443_4_layer_set_s_block(Iso14443_4Layer* instance, bool deselect, bool CID_present) {
|
||||
furi_assert(instance);
|
||||
uint8_t des_wtx = !deselect ? (ISO14443_4_BLOCK_PCB_S_WTX_DESELECT_MASK) : 0;
|
||||
instance->pcb = ISO14443_4_BLOCK_PCB_S_MASK | des_wtx |
|
||||
(CID_present << ISO14443_4_BLOCK_PCB_S_CID_OFFSET) | ISO14443_4_BLOCK_PCB;
|
||||
}
|
||||
|
||||
void iso14443_4_layer_encode_block(
|
||||
Iso14443_4Layer* instance,
|
||||
const BitBuffer* input_data,
|
||||
@ -58,6 +108,11 @@ void iso14443_4_layer_encode_block(
|
||||
iso14443_4_layer_update_pcb(instance);
|
||||
}
|
||||
|
||||
static inline uint8_t iso14443_4_layer_get_response_pcb(const BitBuffer* block_data) {
|
||||
const uint8_t* data = bit_buffer_get_data(block_data);
|
||||
return data[0];
|
||||
}
|
||||
|
||||
bool iso14443_4_layer_decode_block(
|
||||
Iso14443_4Layer* instance,
|
||||
BitBuffer* output_data,
|
||||
@ -67,10 +122,26 @@ bool iso14443_4_layer_decode_block(
|
||||
bool ret = false;
|
||||
|
||||
do {
|
||||
if(!bit_buffer_starts_with_byte(block_data, instance->pcb_prev)) break;
|
||||
// TODO: Fix crash
|
||||
bit_buffer_copy_right(output_data, block_data, 1);
|
||||
ret = true;
|
||||
if(ISO14443_4_BLOCK_PCB_IS_R_BLOCK(instance->pcb_prev)) {
|
||||
const uint8_t response_pcb = iso14443_4_layer_get_response_pcb(block_data);
|
||||
ret = (ISO14443_4_BLOCK_PCB_IS_R_BLOCK(response_pcb)) &&
|
||||
(!ISO14443_4_BLOCK_PCB_R_NACK_ACTIVE(response_pcb));
|
||||
instance->pcb &= ISO14443_4_BLOCK_PCB_MASK;
|
||||
iso14443_4_layer_update_pcb(instance);
|
||||
} else if(ISO14443_4_BLOCK_PCB_IS_CHAIN_ACTIVE(instance->pcb_prev)) {
|
||||
const uint8_t response_pcb = iso14443_4_layer_get_response_pcb(block_data);
|
||||
ret = (ISO14443_4_BLOCK_PCB_IS_R_BLOCK(response_pcb)) &&
|
||||
(!ISO14443_4_BLOCK_PCB_R_NACK_ACTIVE(response_pcb));
|
||||
instance->pcb &= ~(ISO14443_4_BLOCK_PCB_I_CHAIN_MASK);
|
||||
} else if(ISO14443_4_BLOCK_PCB_IS_S_BLOCK(instance->pcb_prev)) {
|
||||
ret = bit_buffer_starts_with_byte(block_data, instance->pcb_prev);
|
||||
if(bit_buffer_get_size_bytes(block_data) > 1)
|
||||
bit_buffer_copy_right(output_data, block_data, 1);
|
||||
} else {
|
||||
if(!bit_buffer_starts_with_byte(block_data, instance->pcb_prev)) break;
|
||||
bit_buffer_copy_right(output_data, block_data, 1);
|
||||
ret = true;
|
||||
}
|
||||
} while(false);
|
||||
|
||||
return ret;
|
||||
|
@ -15,6 +15,10 @@ void iso14443_4_layer_free(Iso14443_4Layer* instance);
|
||||
|
||||
void iso14443_4_layer_reset(Iso14443_4Layer* instance);
|
||||
|
||||
void iso14443_4_layer_set_i_block(Iso14443_4Layer* instance, bool chaining, bool CID_present);
|
||||
void iso14443_4_layer_set_r_block(Iso14443_4Layer* instance, bool acknowledged, bool CID_present);
|
||||
void iso14443_4_layer_set_s_block(Iso14443_4Layer* instance, bool deselect, bool CID_present);
|
||||
|
||||
void iso14443_4_layer_encode_block(
|
||||
Iso14443_4Layer* instance,
|
||||
const BitBuffer* input_data,
|
||||
|
@ -84,6 +84,15 @@ static NfcCommand iso14443_4a_listener_run(NfcGenericEvent event, void* context)
|
||||
iso14443_3a_event->type == Iso14443_3aListenerEventTypeHalted ||
|
||||
iso14443_3a_event->type == Iso14443_3aListenerEventTypeFieldOff) {
|
||||
instance->state = Iso14443_4aListenerStateIdle;
|
||||
|
||||
instance->iso14443_4a_event.type = iso14443_3a_event->type ==
|
||||
Iso14443_3aListenerEventTypeHalted ?
|
||||
Iso14443_4aListenerEventTypeHalted :
|
||||
Iso14443_4aListenerEventTypeFieldOff;
|
||||
|
||||
if(instance->callback) {
|
||||
command = instance->callback(instance->generic_event, instance->context);
|
||||
}
|
||||
command = NfcCommandContinue;
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@ typedef struct Iso14443_4aListener Iso14443_4aListener;
|
||||
|
||||
typedef enum {
|
||||
Iso14443_4aListenerEventTypeHalted,
|
||||
Iso14443_4aListenerEventTypeFieldOff,
|
||||
Iso14443_4aListenerEventTypeReceivedData,
|
||||
} Iso14443_4aListenerEventType;
|
||||
|
||||
|
@ -61,6 +61,69 @@ Iso14443_4aError iso14443_4a_poller_send_block_pwt_ext(
|
||||
const BitBuffer* tx_buffer,
|
||||
BitBuffer* rx_buffer);
|
||||
|
||||
/**
|
||||
* @brief Transmit and receive Iso14443_4a chained block in poller mode. Also it
|
||||
* automatically modifies PCB packet byte with appropriate bits then resets them back
|
||||
*
|
||||
* Must ONLY be used inside the callback function.
|
||||
*
|
||||
* The rx_buffer will be filled with any data received as a response to data
|
||||
* sent from tx_buffer. The fwt parameter is calculated during activation procedure.
|
||||
*
|
||||
* @param[in, out] instance pointer to the instance to be used in the transaction.
|
||||
* @param[in] tx_buffer pointer to the buffer containing the data to be transmitted.
|
||||
* @param[out] rx_buffer pointer to the buffer to be filled with received data.
|
||||
* @return Iso14443_4aErrorNone on success, an error code on failure.
|
||||
*/
|
||||
Iso14443_4aError iso14443_4a_poller_send_chain_block(
|
||||
Iso14443_4aPoller* instance,
|
||||
const BitBuffer* tx_buffer,
|
||||
BitBuffer* rx_buffer);
|
||||
|
||||
/**
|
||||
* @brief Transmit Iso14443_4a R-block in poller mode. This block never contains
|
||||
* data, but can contain CID and NAD, therefore in tx_buffer only two bytes can be added.
|
||||
* The first one will represent CID, the second one will represent NAD.
|
||||
*
|
||||
* Must ONLY be used inside the callback function.
|
||||
*
|
||||
* The rx_buffer will be filled with R-block repsonse
|
||||
*
|
||||
* @param[in, out] instance pointer to the instance to be used in the transaction.
|
||||
* @param[in] acknowledged Sets appropriate bit in PCB byte. True - ACK, false - NAK
|
||||
* @param[in] tx_buffer pointer to the buffer containing the data to be transmitted.
|
||||
* @param[out] rx_buffer pointer to the buffer to be filled with received data.
|
||||
* @return Iso14443_4aErrorNone on success, an error code on failure.
|
||||
*/
|
||||
Iso14443_4aError iso14443_4a_poller_send_receive_ready_block(
|
||||
Iso14443_4aPoller* instance,
|
||||
bool acknowledged,
|
||||
const BitBuffer* tx_buffer,
|
||||
BitBuffer* rx_buffer);
|
||||
|
||||
/**
|
||||
* @brief Transmit Iso14443_4a S-block in poller mode. S-block used to exchange control
|
||||
* information between the card and the reader. Two different types of S-blocks
|
||||
* are defined:
|
||||
* - Waiting time extension containing a 1 byte long INF field and (deselect = false)
|
||||
* - DESELECT containing no INF field (deselect = true)
|
||||
*
|
||||
* Must ONLY be used inside the callback function.
|
||||
*
|
||||
* The rx_buffer will be filled with R-block repsonse
|
||||
*
|
||||
* @param[in, out] instance pointer to the instance to be used in the transaction.
|
||||
* @param[in] deselect Sets appropriate bit in PCB byte.
|
||||
* @param[in] tx_buffer pointer to the buffer containing the data to be transmitted.
|
||||
* @param[out] rx_buffer pointer to the buffer to be filled with received data.
|
||||
* @return Iso14443_4aErrorNone on success, an error code on failure.
|
||||
*/
|
||||
Iso14443_4aError iso14443_4a_poller_send_supervisory_block(
|
||||
Iso14443_4aPoller* instance,
|
||||
bool deselect,
|
||||
const BitBuffer* tx_buffer,
|
||||
BitBuffer* rx_buffer);
|
||||
|
||||
/**
|
||||
* @brief Send HALT command to the card.
|
||||
*
|
||||
|
@ -164,3 +164,34 @@ Iso14443_4aError iso14443_4a_poller_send_block_pwt_ext(
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
Iso14443_4aError iso14443_4a_poller_send_chain_block(
|
||||
Iso14443_4aPoller* instance,
|
||||
const BitBuffer* tx_buffer,
|
||||
BitBuffer* rx_buffer) {
|
||||
iso14443_4_layer_set_i_block(instance->iso14443_4_layer, true, false);
|
||||
Iso14443_4aError error = iso14443_4a_poller_send_block(instance, tx_buffer, rx_buffer);
|
||||
return error;
|
||||
}
|
||||
|
||||
Iso14443_4aError iso14443_4a_poller_send_receive_ready_block(
|
||||
Iso14443_4aPoller* instance,
|
||||
bool acknowledged,
|
||||
const BitBuffer* tx_buffer,
|
||||
BitBuffer* rx_buffer) {
|
||||
bool CID_present = bit_buffer_get_size_bytes(tx_buffer) != 0;
|
||||
iso14443_4_layer_set_r_block(instance->iso14443_4_layer, acknowledged, CID_present);
|
||||
Iso14443_4aError error = iso14443_4a_poller_send_block(instance, tx_buffer, rx_buffer);
|
||||
return error;
|
||||
}
|
||||
|
||||
Iso14443_4aError iso14443_4a_poller_send_supervisory_block(
|
||||
Iso14443_4aPoller* instance,
|
||||
bool deselect,
|
||||
const BitBuffer* tx_buffer,
|
||||
BitBuffer* rx_buffer) {
|
||||
bool CID_present = bit_buffer_get_size_bytes(tx_buffer) != 0;
|
||||
iso14443_4_layer_set_s_block(instance->iso14443_4_layer, deselect, CID_present);
|
||||
Iso14443_4aError error = iso14443_4a_poller_send_block(instance, tx_buffer, rx_buffer);
|
||||
return error;
|
||||
}
|
||||
|
@ -832,6 +832,7 @@ Function,+,canvas_draw_str,void,"Canvas*, int32_t, int32_t, const char*"
|
||||
Function,+,canvas_draw_str_aligned,void,"Canvas*, int32_t, int32_t, Align, Align, const char*"
|
||||
Function,+,canvas_draw_triangle,void,"Canvas*, int32_t, int32_t, size_t, size_t, CanvasDirection"
|
||||
Function,+,canvas_draw_xbm,void,"Canvas*, int32_t, int32_t, size_t, size_t, const uint8_t*"
|
||||
Function,+,canvas_draw_xbm_mirrored,void,"Canvas*, int32_t, int32_t, size_t, size_t, const uint8_t*"
|
||||
Function,+,canvas_get_font_params,const CanvasFontParameters*,"const Canvas*, Font"
|
||||
Function,+,canvas_glyph_width,size_t,"Canvas*, uint16_t"
|
||||
Function,+,canvas_height,size_t,const Canvas*
|
||||
@ -2174,6 +2175,9 @@ Function,+,iso14443_4a_poller_halt,Iso14443_4aError,Iso14443_4aPoller*
|
||||
Function,+,iso14443_4a_poller_read_ats,Iso14443_4aError,"Iso14443_4aPoller*, Iso14443_4aAtsData*"
|
||||
Function,+,iso14443_4a_poller_send_block,Iso14443_4aError,"Iso14443_4aPoller*, const BitBuffer*, BitBuffer*"
|
||||
Function,+,iso14443_4a_poller_send_block_pwt_ext,Iso14443_4aError,"Iso14443_4aPoller*, const BitBuffer*, BitBuffer*"
|
||||
Function,+,iso14443_4a_poller_send_chain_block,Iso14443_4aError,"Iso14443_4aPoller*, const BitBuffer*, BitBuffer*"
|
||||
Function,+,iso14443_4a_poller_send_receive_ready_block,Iso14443_4aError,"Iso14443_4aPoller*, _Bool, const BitBuffer*, BitBuffer*"
|
||||
Function,+,iso14443_4a_poller_send_supervisory_block,Iso14443_4aError,"Iso14443_4aPoller*, _Bool, const BitBuffer*, BitBuffer*"
|
||||
Function,+,iso14443_4a_reset,void,Iso14443_4aData*
|
||||
Function,+,iso14443_4a_save,_Bool,"const Iso14443_4aData*, FlipperFormat*"
|
||||
Function,+,iso14443_4a_set_uid,_Bool,"Iso14443_4aData*, const uint8_t*, size_t"
|
||||
|
|
Loading…
Reference in New Issue
Block a user