1
mirror of https://github.com/DarkFlippers/unleashed-firmware.git synced 2025-12-12 12:42:30 +04:00

Merge remote-tracking branch 'OFW/dev' into dev

This commit is contained in:
MX
2025-09-24 17:58:32 +03:00
11 changed files with 237 additions and 23 deletions

View File

@@ -17,7 +17,7 @@
#define NICE_FLOR_S_DIR_NAME EXT_PATH("subghz/assets/nice_flor_s")
#define ALUTECH_AT_4N_DIR_NAME EXT_PATH("subghz/assets/alutech_at_4n")
#define TEST_RANDOM_DIR_NAME EXT_PATH("unit_tests/subghz/test_random_raw.sub")
#define TEST_RANDOM_COUNT_PARSE 329
#define TEST_RANDOM_COUNT_PARSE 331
#define TEST_TIMEOUT 10000
static SubGhzEnvironment* environment_handler;

View File

@@ -19,6 +19,7 @@ typedef struct {
bool connected;
bool running;
int rate;
enum HidMouseButtons btn;
} HidMouseClickerModel;
static void hid_mouse_clicker_start_or_restart_timer(void* context) {
@@ -61,6 +62,26 @@ static void hid_mouse_clicker_draw_callback(Canvas* canvas, void* context) {
// Ok
canvas_draw_icon(canvas, 58, 25, &I_Space_65x18);
canvas_draw_icon(canvas, 61, 50, &I_ButtonLeft_4x7);
canvas_draw_icon(canvas, 117, 50, &I_ButtonRight_4x7);
const char* btn_label;
switch(model->btn) {
case HID_MOUSE_BTN_LEFT:
btn_label = "Left";
break;
case HID_MOUSE_BTN_WHEEL:
btn_label = "Middle";
break;
case HID_MOUSE_BTN_RIGHT:
btn_label = "Right";
break;
default:
furi_crash();
}
elements_multiline_text_aligned(canvas, 89, 57, AlignCenter, AlignBottom, btn_label);
if(model->running) {
elements_slightly_rounded_box(canvas, 61, 27, 60, 13);
canvas_set_color(canvas, ColorWhite);
@@ -100,8 +121,8 @@ static void hid_mouse_clicker_timer_callback(void* context) {
HidMouseClickerModel * model,
{
if(model->running) {
hid_hal_mouse_press(hid_mouse_clicker->hid, HID_MOUSE_BTN_LEFT);
hid_hal_mouse_release(hid_mouse_clicker->hid, HID_MOUSE_BTN_LEFT);
hid_hal_mouse_press(hid_mouse_clicker->hid, model->btn);
hid_hal_mouse_release(hid_mouse_clicker->hid, model->btn);
}
},
false);
@@ -154,6 +175,34 @@ static bool hid_mouse_clicker_input_callback(InputEvent* event, void* context) {
case InputKeyBack:
model->running = false;
break;
case InputKeyLeft:
switch(model->btn) {
case HID_MOUSE_BTN_LEFT:
model->btn = HID_MOUSE_BTN_RIGHT;
break;
case HID_MOUSE_BTN_WHEEL:
model->btn = HID_MOUSE_BTN_LEFT;
break;
case HID_MOUSE_BTN_RIGHT:
model->btn = HID_MOUSE_BTN_WHEEL;
break;
}
consumed = true;
break;
case InputKeyRight:
switch(model->btn) {
case HID_MOUSE_BTN_LEFT:
model->btn = HID_MOUSE_BTN_WHEEL;
break;
case HID_MOUSE_BTN_WHEEL:
model->btn = HID_MOUSE_BTN_RIGHT;
break;
case HID_MOUSE_BTN_RIGHT:
model->btn = HID_MOUSE_BTN_LEFT;
break;
}
consumed = true;
break;
default:
consumed = true;
break;
@@ -188,7 +237,10 @@ HidMouseClicker* hid_mouse_clicker_alloc(Hid* hid) {
with_view_model(
hid_mouse_clicker->view,
HidMouseClickerModel * model,
{ model->rate = DEFAULT_CLICK_RATE; },
{
model->rate = DEFAULT_CLICK_RATE;
model->btn = HID_MOUSE_BTN_LEFT;
},
true);
return hid_mouse_clicker;

View File

@@ -9,6 +9,9 @@
#define NFC_MAX_BUFFER_SIZE (256)
#define NFC_FELICA_LISTENER_RESPONSE_TIME_A_FC (512 * 64)
#define NFC_FELICA_LISTENER_RESPONSE_TIME_B_FC (256 * 64)
typedef enum {
NfcStateIdle,
NfcStateRunning,
@@ -661,4 +664,20 @@ NfcError nfc_felica_listener_set_sensf_res_data(
return nfc_process_hal_error(error);
}
void nfc_felica_listener_timer_anticol_start(Nfc* instance, uint8_t target_time_slot) {
furi_check(instance);
furi_hal_nfc_timer_block_tx_start(
NFC_FELICA_LISTENER_RESPONSE_TIME_A_FC +
target_time_slot * NFC_FELICA_LISTENER_RESPONSE_TIME_B_FC);
}
void nfc_felica_listener_timer_anticol_stop(Nfc* instance) {
furi_check(instance);
if(furi_hal_nfc_timer_block_tx_is_running()) {
furi_hal_nfc_timer_block_tx_stop();
}
}
#endif // FW_CFG_unit_tests

View File

@@ -380,6 +380,24 @@ NfcError nfc_felica_listener_set_sensf_res_data(
*/
NfcError nfc_iso15693_listener_tx_sof(Nfc* instance);
/**
* @brief Start the timer used for manual FeliCa collision resolution in listener mode.
*
* This blocks TX until the desired Time Slot, and should be called as soon as the listener
* determines that a collision resolution needs to be handled manually.
*
* @param[in, out] instance instance pointer to the instance to be configured.
* @param[in] target_time_slot Target Time Slot number. Should be a value within the range of 0-15 (double-inclusive).
*/
void nfc_felica_listener_timer_anticol_start(Nfc* instance, uint8_t target_time_slot);
/**
* @brief Cancel the timer used for manual FeliCa collision resolution in listener mode.
*
* @param[in, out] instance instance pointer to the instance to be configured.
*/
void nfc_felica_listener_timer_anticol_stop(Nfc* instance);
#ifdef __cplusplus
}
#endif

View File

@@ -518,4 +518,14 @@ NfcError nfc_felica_listener_set_sensf_res_data(
return NfcErrorNone;
}
void nfc_felica_listener_timer_anticol_start(Nfc* instance, uint8_t target_time_slot) {
furi_check(instance);
UNUSED(target_time_slot);
}
void nfc_felica_listener_timer_anticol_stop(Nfc* instance) {
furi_check(instance);
}
#endif

View File

@@ -38,7 +38,7 @@ extern "C" {
#define FELICA_FDT_POLL_FC (10000U)
#define FELICA_POLL_POLL_MIN_US (1280U)
#define FELICA_FDT_LISTEN_FC (1172)
#define FELICA_FDT_LISTEN_FC (0)
#define FELICA_SYSTEM_CODE_CODE (0xFFFFU)
#define FELICA_TIME_SLOT_1 (0x00U)
@@ -58,6 +58,7 @@ typedef enum {
FelicaErrorWrongCrc,
FelicaErrorProtocol,
FelicaErrorTimeout,
FelicaErrorFeatureUnsupported,
} FelicaError;
typedef struct {

View File

@@ -5,9 +5,20 @@
#include <furi_hal_nfc.h>
#define FELICA_LISTENER_MAX_BUFFER_SIZE (128)
#define FELICA_LISTENER_CMD_POLLING (0x00U)
#define FELICA_LISTENER_RESPONSE_POLLING (0x01U)
#define FELICA_LISTENER_RESPONSE_CODE_READ (0x07)
#define FELICA_LISTENER_RESPONSE_CODE_WRITE (0x09)
#define FELICA_LISTENER_REQUEST_NONE (0x00U)
#define FELICA_LISTENER_REQUEST_SYSTEM_CODE (0x01U)
#define FELICA_LISTENER_REQUEST_PERFORMANCE (0x02U)
#define FELICA_LISTENER_SYSTEM_CODE_NDEF (__builtin_bswap16(0x12FCU))
#define FELICA_LISTENER_SYSTEM_CODE_LITES (__builtin_bswap16(0x88B4U))
#define FELICA_LISTENER_PERFORMANCE_VALUE (__builtin_bswap16(0x0083U))
#define TAG "FelicaListener"
FelicaListener* felica_listener_alloc(Nfc* nfc, FelicaData* data) {
@@ -151,6 +162,70 @@ static FelicaError felica_listener_process_request(
}
}
static void felica_listener_populate_polling_response_header(
FelicaListener* instance,
FelicaListenerPollingResponseHeader* resp) {
resp->idm = instance->data->idm;
resp->pmm = instance->data->pmm;
resp->response_code = FELICA_LISTENER_RESPONSE_POLLING;
}
static bool felica_listener_check_system_code(
const FelicaListenerGenericRequest* const generic_request,
uint16_t code) {
return (
generic_request->polling.system_code == code ||
generic_request->polling.system_code == (code | 0x00FFU) ||
generic_request->polling.system_code == (code | 0xFF00U));
}
static uint16_t felica_listener_get_response_system_code(
FelicaListener* instance,
const FelicaListenerGenericRequest* const generic_request) {
uint16_t resp_system_code = FELICA_SYSTEM_CODE_CODE;
if(felica_listener_check_system_code(generic_request, FELICA_LISTENER_SYSTEM_CODE_NDEF) &&
instance->data->data.fs.mc.data[FELICA_MC_SYS_OP] == 1) {
// NDEF
resp_system_code = FELICA_LISTENER_SYSTEM_CODE_NDEF;
} else if(felica_listener_check_system_code(
generic_request, FELICA_LISTENER_SYSTEM_CODE_LITES)) {
// Lite-S
resp_system_code = FELICA_LISTENER_SYSTEM_CODE_LITES;
}
return resp_system_code;
}
static FelicaError felica_listener_process_system_code(
FelicaListener* instance,
const FelicaListenerGenericRequest* const generic_request) {
FelicaError result = FelicaErrorFeatureUnsupported;
do {
uint16_t resp_system_code =
felica_listener_get_response_system_code(instance, generic_request);
if(resp_system_code == FELICA_SYSTEM_CODE_CODE) break;
FelicaListenerPollingResponse* resp = malloc(sizeof(FelicaListenerPollingResponse));
felica_listener_populate_polling_response_header(instance, &resp->header);
resp->header.length = sizeof(FelicaListenerPollingResponse);
if(generic_request->polling.request_code == FELICA_LISTENER_REQUEST_SYSTEM_CODE) {
resp->optional_request_data = resp_system_code;
} else if(generic_request->polling.request_code == FELICA_LISTENER_REQUEST_PERFORMANCE) {
resp->optional_request_data = FELICA_LISTENER_PERFORMANCE_VALUE;
} else {
resp->header.length = sizeof(FelicaListenerPollingResponseHeader);
}
bit_buffer_reset(instance->tx_buffer);
bit_buffer_append_bytes(instance->tx_buffer, (uint8_t*)resp, resp->header.length);
free(resp);
result = felica_listener_frame_exchange(instance, instance->tx_buffer);
} while(false);
return result;
}
NfcCommand felica_listener_run(NfcGenericEvent event, void* context) {
furi_assert(context);
furi_assert(event.protocol == NfcProtocolInvalid);
@@ -187,7 +262,23 @@ NfcCommand felica_listener_run(NfcGenericEvent event, void* context) {
break;
}
if(!felica_listener_check_idm(instance, &request->header.idm)) {
if(request->header.code == FELICA_LISTENER_CMD_POLLING) {
// Will always respond at Time Slot 0 for now.
nfc_felica_listener_timer_anticol_start(instance->nfc, 0);
if(request->polling.system_code != FELICA_SYSTEM_CODE_CODE) {
FelicaError error = felica_listener_process_system_code(instance, request);
if(error == FelicaErrorFeatureUnsupported) {
command = NfcCommandReset;
} else if(error != FelicaErrorNone) {
FURI_LOG_E(
TAG, "Error when handling Polling with System Code: %2X", error);
}
break;
} else {
FURI_LOG_E(TAG, "Hardware Polling command leaking through");
break;
}
} else if(!felica_listener_check_idm(instance, &request->header.idm)) {
FURI_LOG_E(TAG, "Wrong IDm");
break;
}

View File

@@ -7,19 +7,6 @@
#define FELICA_WCNT_MC2_00_WARNING_BEGIN_VALUE (0x00001027U)
#define FELICA_WCNT_MC2_00_WARNING_END_VALUE (0x00FFFDFFU)
#define FELICA_MC_SP_REG_ALL_RW_BYTES_0_1 (0U)
#define FELICA_MC_ALL_BYTE (2U)
#define FELICA_MC_SYS_OP (3U)
#define FELICA_MC_RF_PRM (4U)
#define FELICA_MC_CKCKV_W_MAC_A (5U)
#define FELICA_MC_SP_REG_R_RESTR_BYTES_6_7 (6U)
#define FELICA_MC_SP_REG_W_RESTR_BYTES_8_9 (8U)
#define FELICA_MC_SP_REG_W_MAC_A_BYTES_10_11 (10U)
#define FELICA_MC_STATE_W_MAC_A (12U)
#define FELICA_MC_RESERVED_13 (13U)
#define FELICA_MC_RESERVED_14 (14U)
#define FELICA_MC_RESERVED_15 (15U)
#define FELICA_MC_BYTE_GET(data, byte) (data->data.fs.mc.data[byte])
#define FELICA_SYSTEM_BLOCK_RO_ACCESS(data) (FELICA_MC_BYTE_GET(data, FELICA_MC_ALL_BYTE) == 0x00)
#define FELICA_SYSTEM_BLOCK_RW_ACCESS(data) (FELICA_MC_BYTE_GET(data, FELICA_MC_ALL_BYTE) == 0xFF)

View File

@@ -7,15 +7,50 @@
#define FELICA_LISTENER_WRITE_BLOCK_COUNT_MAX (2U)
#define FELICA_LISTENER_WRITE_BLOCK_COUNT_MIN (1U)
#define FELICA_MC_SP_REG_ALL_RW_BYTES_0_1 (0U)
#define FELICA_MC_ALL_BYTE (2U)
#define FELICA_MC_SYS_OP (3U)
#define FELICA_MC_RF_PRM (4U)
#define FELICA_MC_CKCKV_W_MAC_A (5U)
#define FELICA_MC_SP_REG_R_RESTR_BYTES_6_7 (6U)
#define FELICA_MC_SP_REG_W_RESTR_BYTES_8_9 (8U)
#define FELICA_MC_SP_REG_W_MAC_A_BYTES_10_11 (10U)
#define FELICA_MC_STATE_W_MAC_A (12U)
#define FELICA_MC_RESERVED_13 (13U)
#define FELICA_MC_RESERVED_14 (14U)
#define FELICA_MC_RESERVED_15 (15U)
typedef enum {
Felica_ListenerStateIdle,
Felica_ListenerStateActivated,
} FelicaListenerState;
typedef struct FURI_PACKED {
uint8_t code;
uint16_t system_code;
uint8_t request_code;
uint8_t time_slot;
} FelicaListenerPollingHeader;
typedef struct {
uint8_t length;
uint8_t response_code;
FelicaIDm idm;
FelicaPMm pmm;
} FelicaListenerPollingResponseHeader;
typedef struct FURI_PACKED {
FelicaListenerPollingResponseHeader header;
uint16_t optional_request_data;
} FelicaListenerPollingResponse;
/** Generic Felica request same for both read and write operations. */
typedef struct {
uint8_t length;
union {
FelicaCommandHeader header;
FelicaListenerPollingHeader polling;
};
} FelicaListenerGenericRequest;
/** Generic request but with list of requested elements. */

View File

@@ -1,5 +1,5 @@
entry,status,name,type,params
Version,+,86.0,,
Version,+,86.1,,
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/bt/bt_service/bt_keys_storage.h,,
@@ -2931,6 +2931,8 @@ Function,+,nfc_device_set_data,void,"NfcDevice*, NfcProtocol, const NfcDeviceDat
Function,+,nfc_device_set_loading_callback,void,"NfcDevice*, NfcLoadingCallback, void*"
Function,+,nfc_device_set_uid,_Bool,"NfcDevice*, const uint8_t*, size_t"
Function,+,nfc_felica_listener_set_sensf_res_data,NfcError,"Nfc*, const uint8_t*, const uint8_t, const uint8_t*, const uint8_t, const uint16_t"
Function,+,nfc_felica_listener_timer_anticol_start,void,"Nfc*, uint8_t"
Function,+,nfc_felica_listener_timer_anticol_stop,void,Nfc*
Function,+,nfc_free,void,Nfc*
Function,+,nfc_iso14443a_listener_set_col_res_data,NfcError,"Nfc*, uint8_t*, uint8_t, uint8_t*, uint8_t"
Function,+,nfc_iso14443a_listener_tx_custom_parity,NfcError,"Nfc*, const BitBuffer*"
1 entry status name type params
2 Version + 86.0 86.1
3 Header + applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h
4 Header + applications/services/bt/bt_service/bt.h
5 Header + applications/services/bt/bt_service/bt_keys_storage.h
2931 Function + nfc_device_set_loading_callback void NfcDevice*, NfcLoadingCallback, void*
2932 Function + nfc_device_set_uid _Bool NfcDevice*, const uint8_t*, size_t
2933 Function + nfc_felica_listener_set_sensf_res_data NfcError Nfc*, const uint8_t*, const uint8_t, const uint8_t*, const uint8_t, const uint16_t
2934 Function + nfc_felica_listener_timer_anticol_start void Nfc*, uint8_t
2935 Function + nfc_felica_listener_timer_anticol_stop void Nfc*
2936 Function + nfc_free void Nfc*
2937 Function + nfc_iso14443a_listener_set_col_res_data NfcError Nfc*, uint8_t*, uint8_t, uint8_t*, uint8_t
2938 Function + nfc_iso14443a_listener_tx_custom_parity NfcError Nfc*, const BitBuffer*

View File

@@ -1,8 +1,7 @@
#include "furi_hal_nfc_i.h"
#include "furi_hal_nfc_tech_i.h"
// Prevent FDT timer from starting
#define FURI_HAL_NFC_FELICA_LISTENER_FDT_COMP_FC (INT32_MAX)
#define FURI_HAL_NFC_FELICA_LISTENER_FDT_COMP_FC (0)
#define FURI_HAL_FELICA_COMMUNICATION_PERFORMANCE (0x0083U)
#define FURI_HAL_FELICA_RESPONSE_CODE (0x01)