Merge branch 'ofw_dev' into nfcrefactoring

This commit is contained in:
MX
2023-10-24 14:42:49 +03:00
512 changed files with 41484 additions and 68283 deletions
+95 -14
View File
@@ -1,5 +1,5 @@
entry,status,name,type,params
Version,+,39.2,,
Version,+,40.0,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,,
Header,+,applications/services/cli/cli_vcp.h,,
@@ -81,6 +81,7 @@ Header,+,firmware/targets/furi_hal_include/furi_hal_usb_hid.h,,
Header,+,firmware/targets/furi_hal_include/furi_hal_usb_hid_u2f.h,,
Header,+,firmware/targets/furi_hal_include/furi_hal_version.h,,
Header,+,firmware/targets/furi_hal_include/furi_hal_vibro.h,,
Header,+,lib/digital_signal/digital_sequence.h,,
Header,+,lib/digital_signal/digital_signal.h,,
Header,+,lib/drivers/cc1101_regs.h,,
Header,+,lib/flipper_application/api_hashtable/api_hashtable.h,,
@@ -132,11 +133,15 @@ Header,+,lib/mlib/m-rbtree.h,,
Header,+,lib/mlib/m-tuple.h,,
Header,+,lib/mlib/m-variant.h,,
Header,+,lib/music_worker/music_worker.h,,
Header,+,lib/nanopb/pb.h,,
Header,+,lib/nanopb/pb_decode.h,,
Header,+,lib/nanopb/pb_encode.h,,
Header,+,lib/one_wire/maxim_crc.h,,
Header,+,lib/one_wire/one_wire_host.h,,
Header,+,lib/one_wire/one_wire_slave.h,,
Header,+,lib/print/wrappers.h,,
Header,+,lib/pulse_reader/pulse_reader.h,,
Header,+,lib/signal_reader/signal_reader.h,,
Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_adc.h,,
Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_bus.h,,
Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_comp.h,,
@@ -166,6 +171,7 @@ Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_utils.h,,
Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_wwdg.h,,
Header,+,lib/toolbox/api_lock.h,,
Header,+,lib/toolbox/args.h,,
Header,+,lib/toolbox/bit_buffer.h,,
Header,+,lib/toolbox/compress.h,,
Header,+,lib/toolbox/crc32_calc.h,,
Header,+,lib/toolbox/dir_walk.h,,
@@ -180,6 +186,7 @@ Header,+,lib/toolbox/pretty_format.h,,
Header,+,lib/toolbox/protocols/protocol_dict.h,,
Header,+,lib/toolbox/saved_struct.h,,
Header,+,lib/toolbox/sha256.h,,
Header,+,lib/toolbox/simple_array.h,,
Header,+,lib/toolbox/stream/buffered_file_stream.h,,
Header,+,lib/toolbox/stream/file_stream.h,,
Header,+,lib/toolbox/stream/stream.h,,
@@ -521,6 +528,36 @@ Function,-,atoll,long long,const char*
Function,-,basename,char*,const char*
Function,-,bcmp,int,"const void*, const void*, size_t"
Function,-,bcopy,void,"const void*, void*, size_t"
Function,+,bit_buffer_alloc,BitBuffer*,size_t
Function,+,bit_buffer_append,void,"BitBuffer*, const BitBuffer*"
Function,+,bit_buffer_append_bit,void,"BitBuffer*, _Bool"
Function,+,bit_buffer_append_byte,void,"BitBuffer*, uint8_t"
Function,+,bit_buffer_append_bytes,void,"BitBuffer*, const uint8_t*, size_t"
Function,+,bit_buffer_append_right,void,"BitBuffer*, const BitBuffer*, size_t"
Function,+,bit_buffer_copy,void,"BitBuffer*, const BitBuffer*"
Function,+,bit_buffer_copy_bits,void,"BitBuffer*, const uint8_t*, size_t"
Function,+,bit_buffer_copy_bytes,void,"BitBuffer*, const uint8_t*, size_t"
Function,+,bit_buffer_copy_bytes_with_parity,void,"BitBuffer*, const uint8_t*, size_t"
Function,+,bit_buffer_copy_left,void,"BitBuffer*, const BitBuffer*, size_t"
Function,+,bit_buffer_copy_right,void,"BitBuffer*, const BitBuffer*, size_t"
Function,+,bit_buffer_free,void,BitBuffer*
Function,+,bit_buffer_get_byte,uint8_t,"const BitBuffer*, size_t"
Function,+,bit_buffer_get_byte_from_bit,uint8_t,"const BitBuffer*, size_t"
Function,+,bit_buffer_get_capacity_bytes,size_t,const BitBuffer*
Function,+,bit_buffer_get_data,const uint8_t*,const BitBuffer*
Function,+,bit_buffer_get_parity,const uint8_t*,const BitBuffer*
Function,+,bit_buffer_get_size,size_t,const BitBuffer*
Function,+,bit_buffer_get_size_bytes,size_t,const BitBuffer*
Function,+,bit_buffer_has_partial_byte,_Bool,const BitBuffer*
Function,+,bit_buffer_reset,void,BitBuffer*
Function,+,bit_buffer_set_byte,void,"BitBuffer*, size_t, uint8_t"
Function,+,bit_buffer_set_byte_with_parity,void,"BitBuffer*, size_t, uint8_t, _Bool"
Function,+,bit_buffer_set_size,void,"BitBuffer*, size_t"
Function,+,bit_buffer_set_size_bytes,void,"BitBuffer*, size_t"
Function,+,bit_buffer_starts_with_byte,_Bool,"const BitBuffer*, uint8_t"
Function,+,bit_buffer_write_bytes,void,"const BitBuffer*, void*, size_t"
Function,+,bit_buffer_write_bytes_mid,void,"const BitBuffer*, void*, size_t, size_t"
Function,+,bit_buffer_write_bytes_with_parity,void,"const BitBuffer*, void*, size_t, size_t*"
Function,+,ble_app_get_key_storage_buff,void,"uint8_t**, uint16_t*"
Function,+,ble_app_init,_Bool,
Function,+,ble_app_thread_stop,void,
@@ -678,24 +715,19 @@ Function,+,dialog_message_set_text,void,"DialogMessage*, const char*, uint8_t, u
Function,+,dialog_message_show,DialogMessageButton,"DialogsApp*, const DialogMessage*"
Function,+,dialog_message_show_storage_error,void,"DialogsApp*, const char*"
Function,-,difftime,double,"time_t, time_t"
Function,-,digital_sequence_add,void,"DigitalSequence*, uint8_t"
Function,+,digital_sequence_add_signal,void,"DigitalSequence*, uint8_t"
Function,-,digital_sequence_alloc,DigitalSequence*,"uint32_t, const GpioPin*"
Function,-,digital_sequence_clear,void,DigitalSequence*
Function,-,digital_sequence_free,void,DigitalSequence*
Function,-,digital_sequence_send,_Bool,DigitalSequence*
Function,-,digital_sequence_set_sendtime,void,"DigitalSequence*, uint32_t"
Function,-,digital_sequence_set_signal,void,"DigitalSequence*, uint8_t, DigitalSignal*"
Function,-,digital_sequence_timebase_correction,void,"DigitalSequence*, float"
Function,-,digital_signal_add,void,"DigitalSignal*, uint32_t"
Function,-,digital_signal_add_pulse,void,"DigitalSignal*, uint32_t, _Bool"
Function,+,digital_sequence_register_signal,void,"DigitalSequence*, uint8_t, const DigitalSignal*"
Function,+,digital_sequence_transmit,void,DigitalSequence*
Function,+,digital_signal_add_period,void,"DigitalSignal*, uint32_t"
Function,+,digital_signal_add_period_with_level,void,"DigitalSignal*, uint32_t, _Bool"
Function,-,digital_signal_alloc,DigitalSignal*,uint32_t
Function,-,digital_signal_append,_Bool,"DigitalSignal*, DigitalSignal*"
Function,-,digital_signal_free,void,DigitalSignal*
Function,-,digital_signal_get_edge,uint32_t,"DigitalSignal*, uint32_t"
Function,-,digital_signal_get_edges_cnt,uint32_t,DigitalSignal*
Function,-,digital_signal_get_start_level,_Bool,DigitalSignal*
Function,-,digital_signal_prepare_arr,void,DigitalSignal*
Function,-,digital_signal_send,void,"DigitalSignal*, const GpioPin*"
Function,+,digital_signal_get_size,uint32_t,const DigitalSignal*
Function,+,digital_signal_get_start_level,_Bool,const DigitalSignal*
Function,+,digital_signal_set_start_level,void,"DigitalSignal*, _Bool"
Function,-,diprintf,int,"int, const char*, ..."
Function,+,dir_walk_alloc,DirWalk*,Storage*
Function,+,dir_walk_close,void,DirWalk*
@@ -1776,6 +1808,35 @@ Function,+,path_extract_dirname,void,"const char*, FuriString*"
Function,+,path_extract_extension,void,"FuriString*, char*, size_t"
Function,+,path_extract_filename,void,"FuriString*, FuriString*, _Bool"
Function,+,path_extract_filename_no_ext,void,"const char*, FuriString*"
Function,+,pb_close_string_substream,_Bool,"pb_istream_t*, pb_istream_t*"
Function,+,pb_decode,_Bool,"pb_istream_t*, const pb_msgdesc_t*, void*"
Function,+,pb_decode_bool,_Bool,"pb_istream_t*, _Bool*"
Function,+,pb_decode_ex,_Bool,"pb_istream_t*, const pb_msgdesc_t*, void*, unsigned int"
Function,+,pb_decode_fixed32,_Bool,"pb_istream_t*, void*"
Function,+,pb_decode_fixed64,_Bool,"pb_istream_t*, void*"
Function,+,pb_decode_svarint,_Bool,"pb_istream_t*, int64_t*"
Function,+,pb_decode_tag,_Bool,"pb_istream_t*, pb_wire_type_t*, uint32_t*, _Bool*"
Function,+,pb_decode_varint,_Bool,"pb_istream_t*, uint64_t*"
Function,+,pb_decode_varint32,_Bool,"pb_istream_t*, uint32_t*"
Function,+,pb_default_field_callback,_Bool,"pb_istream_t*, pb_ostream_t*, const pb_field_t*"
Function,+,pb_encode,_Bool,"pb_ostream_t*, const pb_msgdesc_t*, const void*"
Function,+,pb_encode_ex,_Bool,"pb_ostream_t*, const pb_msgdesc_t*, const void*, unsigned int"
Function,+,pb_encode_fixed32,_Bool,"pb_ostream_t*, const void*"
Function,+,pb_encode_fixed64,_Bool,"pb_ostream_t*, const void*"
Function,+,pb_encode_string,_Bool,"pb_ostream_t*, const pb_byte_t*, size_t"
Function,+,pb_encode_submessage,_Bool,"pb_ostream_t*, const pb_msgdesc_t*, const void*"
Function,+,pb_encode_svarint,_Bool,"pb_ostream_t*, int64_t"
Function,+,pb_encode_tag,_Bool,"pb_ostream_t*, pb_wire_type_t, uint32_t"
Function,+,pb_encode_tag_for_field,_Bool,"pb_ostream_t*, const pb_field_iter_t*"
Function,+,pb_encode_varint,_Bool,"pb_ostream_t*, uint64_t"
Function,+,pb_get_encoded_size,_Bool,"size_t*, const pb_msgdesc_t*, const void*"
Function,+,pb_istream_from_buffer,pb_istream_t,"const pb_byte_t*, size_t"
Function,+,pb_make_string_substream,_Bool,"pb_istream_t*, pb_istream_t*"
Function,+,pb_ostream_from_buffer,pb_ostream_t,"pb_byte_t*, size_t"
Function,+,pb_read,_Bool,"pb_istream_t*, pb_byte_t*, size_t"
Function,+,pb_release,void,"const pb_msgdesc_t*, void*"
Function,+,pb_skip_field,_Bool,"pb_istream_t*, pb_wire_type_t"
Function,+,pb_write,_Bool,"pb_ostream_t*, const pb_byte_t*, size_t"
Function,-,pcTaskGetName,char*,TaskHandle_t
Function,-,pcTimerGetName,const char*,TimerHandle_t
Function,-,pclose,int,FILE*
@@ -1954,6 +2015,25 @@ Function,+,sha256_finish,void,"sha256_context*, unsigned char[32]"
Function,+,sha256_process,void,sha256_context*
Function,+,sha256_start,void,sha256_context*
Function,+,sha256_update,void,"sha256_context*, const unsigned char*, unsigned int"
Function,+,signal_reader_alloc,SignalReader*,"const GpioPin*, uint32_t"
Function,+,signal_reader_free,void,SignalReader*
Function,+,signal_reader_set_polarity,void,"SignalReader*, SignalReaderPolarity"
Function,+,signal_reader_set_pull,void,"SignalReader*, GpioPull"
Function,+,signal_reader_set_sample_rate,void,"SignalReader*, SignalReaderTimeUnit, uint32_t"
Function,+,signal_reader_set_trigger,void,"SignalReader*, SignalReaderTrigger"
Function,+,signal_reader_start,void,"SignalReader*, SignalReaderCallback, void*"
Function,+,signal_reader_stop,void,SignalReader*
Function,+,simple_array_alloc,SimpleArray*,const SimpleArrayConfig*
Function,+,simple_array_cget,const SimpleArrayElement*,"const SimpleArray*, uint32_t"
Function,+,simple_array_cget_data,const SimpleArrayData*,const SimpleArray*
Function,+,simple_array_copy,void,"SimpleArray*, const SimpleArray*"
Function,+,simple_array_free,void,SimpleArray*
Function,+,simple_array_get,SimpleArrayElement*,"SimpleArray*, uint32_t"
Function,+,simple_array_get_count,uint32_t,const SimpleArray*
Function,+,simple_array_get_data,SimpleArrayData*,SimpleArray*
Function,+,simple_array_init,void,"SimpleArray*, uint32_t"
Function,+,simple_array_is_equal,_Bool,"const SimpleArray*, const SimpleArray*"
Function,+,simple_array_reset,void,SimpleArray*
Function,-,sin,double,double
Function,-,sincos,void,"double, double*, double*"
Function,-,sincosf,void,"float, float*, float*"
@@ -2695,6 +2775,7 @@ Variable,+,sequence_set_vibro_on,const NotificationSequence,
Variable,+,sequence_single_vibro,const NotificationSequence,
Variable,+,sequence_solid_yellow,const NotificationSequence,
Variable,+,sequence_success,const NotificationSequence,
Variable,+,simple_array_config_uint8_t,const SimpleArrayConfig,
Variable,-,suboptarg,char*,
Variable,+,usb_ccid,FuriHalUsbInterface,
Variable,+,usb_cdc_dual,FuriHalUsbInterface,
1 entry status name type params
2 Version + 39.2 40.0
3 Header + applications/services/bt/bt_service/bt.h
4 Header + applications/services/cli/cli.h
5 Header + applications/services/cli/cli_vcp.h
81 Header + firmware/targets/furi_hal_include/furi_hal_usb_hid_u2f.h
82 Header + firmware/targets/furi_hal_include/furi_hal_version.h
83 Header + firmware/targets/furi_hal_include/furi_hal_vibro.h
84 Header + lib/digital_signal/digital_sequence.h
85 Header + lib/digital_signal/digital_signal.h
86 Header + lib/drivers/cc1101_regs.h
87 Header + lib/flipper_application/api_hashtable/api_hashtable.h
133 Header + lib/mlib/m-tuple.h
134 Header + lib/mlib/m-variant.h
135 Header + lib/music_worker/music_worker.h
136 Header + lib/nanopb/pb.h
137 Header + lib/nanopb/pb_decode.h
138 Header + lib/nanopb/pb_encode.h
139 Header + lib/one_wire/maxim_crc.h
140 Header + lib/one_wire/one_wire_host.h
141 Header + lib/one_wire/one_wire_slave.h
142 Header + lib/print/wrappers.h
143 Header + lib/pulse_reader/pulse_reader.h
144 Header + lib/signal_reader/signal_reader.h
145 Header + lib/stm32wb_hal/Inc/stm32wbxx_ll_adc.h
146 Header + lib/stm32wb_hal/Inc/stm32wbxx_ll_bus.h
147 Header + lib/stm32wb_hal/Inc/stm32wbxx_ll_comp.h
171 Header + lib/stm32wb_hal/Inc/stm32wbxx_ll_wwdg.h
172 Header + lib/toolbox/api_lock.h
173 Header + lib/toolbox/args.h
174 Header + lib/toolbox/bit_buffer.h
175 Header + lib/toolbox/compress.h
176 Header + lib/toolbox/crc32_calc.h
177 Header + lib/toolbox/dir_walk.h
186 Header + lib/toolbox/protocols/protocol_dict.h
187 Header + lib/toolbox/saved_struct.h
188 Header + lib/toolbox/sha256.h
189 Header + lib/toolbox/simple_array.h
190 Header + lib/toolbox/stream/buffered_file_stream.h
191 Header + lib/toolbox/stream/file_stream.h
192 Header + lib/toolbox/stream/stream.h
528 Function - basename char* const char*
529 Function - bcmp int const void*, const void*, size_t
530 Function - bcopy void const void*, void*, size_t
531 Function + bit_buffer_alloc BitBuffer* size_t
532 Function + bit_buffer_append void BitBuffer*, const BitBuffer*
533 Function + bit_buffer_append_bit void BitBuffer*, _Bool
534 Function + bit_buffer_append_byte void BitBuffer*, uint8_t
535 Function + bit_buffer_append_bytes void BitBuffer*, const uint8_t*, size_t
536 Function + bit_buffer_append_right void BitBuffer*, const BitBuffer*, size_t
537 Function + bit_buffer_copy void BitBuffer*, const BitBuffer*
538 Function + bit_buffer_copy_bits void BitBuffer*, const uint8_t*, size_t
539 Function + bit_buffer_copy_bytes void BitBuffer*, const uint8_t*, size_t
540 Function + bit_buffer_copy_bytes_with_parity void BitBuffer*, const uint8_t*, size_t
541 Function + bit_buffer_copy_left void BitBuffer*, const BitBuffer*, size_t
542 Function + bit_buffer_copy_right void BitBuffer*, const BitBuffer*, size_t
543 Function + bit_buffer_free void BitBuffer*
544 Function + bit_buffer_get_byte uint8_t const BitBuffer*, size_t
545 Function + bit_buffer_get_byte_from_bit uint8_t const BitBuffer*, size_t
546 Function + bit_buffer_get_capacity_bytes size_t const BitBuffer*
547 Function + bit_buffer_get_data const uint8_t* const BitBuffer*
548 Function + bit_buffer_get_parity const uint8_t* const BitBuffer*
549 Function + bit_buffer_get_size size_t const BitBuffer*
550 Function + bit_buffer_get_size_bytes size_t const BitBuffer*
551 Function + bit_buffer_has_partial_byte _Bool const BitBuffer*
552 Function + bit_buffer_reset void BitBuffer*
553 Function + bit_buffer_set_byte void BitBuffer*, size_t, uint8_t
554 Function + bit_buffer_set_byte_with_parity void BitBuffer*, size_t, uint8_t, _Bool
555 Function + bit_buffer_set_size void BitBuffer*, size_t
556 Function + bit_buffer_set_size_bytes void BitBuffer*, size_t
557 Function + bit_buffer_starts_with_byte _Bool const BitBuffer*, uint8_t
558 Function + bit_buffer_write_bytes void const BitBuffer*, void*, size_t
559 Function + bit_buffer_write_bytes_mid void const BitBuffer*, void*, size_t, size_t
560 Function + bit_buffer_write_bytes_with_parity void const BitBuffer*, void*, size_t, size_t*
561 Function + ble_app_get_key_storage_buff void uint8_t**, uint16_t*
562 Function + ble_app_init _Bool
563 Function + ble_app_thread_stop void
715 Function + dialog_message_show DialogMessageButton DialogsApp*, const DialogMessage*
716 Function + dialog_message_show_storage_error void DialogsApp*, const char*
717 Function - difftime double time_t, time_t
718 Function - + digital_sequence_add digital_sequence_add_signal void DigitalSequence*, uint8_t
719 Function - digital_sequence_alloc DigitalSequence* uint32_t, const GpioPin*
720 Function - digital_sequence_clear void DigitalSequence*
721 Function - digital_sequence_free void DigitalSequence*
722 Function - + digital_sequence_send digital_sequence_register_signal _Bool void DigitalSequence* DigitalSequence*, uint8_t, const DigitalSignal*
723 Function - + digital_sequence_set_sendtime digital_sequence_transmit void DigitalSequence*, uint32_t DigitalSequence*
724 Function - + digital_sequence_set_signal digital_signal_add_period void DigitalSequence*, uint8_t, DigitalSignal* DigitalSignal*, uint32_t
725 Function - + digital_sequence_timebase_correction digital_signal_add_period_with_level void DigitalSequence*, float DigitalSignal*, uint32_t, _Bool
Function - digital_signal_add void DigitalSignal*, uint32_t
Function - digital_signal_add_pulse void DigitalSignal*, uint32_t, _Bool
726 Function - digital_signal_alloc DigitalSignal* uint32_t
Function - digital_signal_append _Bool DigitalSignal*, DigitalSignal*
727 Function - digital_signal_free void DigitalSignal*
728 Function - + digital_signal_get_edge digital_signal_get_size uint32_t DigitalSignal*, uint32_t const DigitalSignal*
729 Function - + digital_signal_get_edges_cnt digital_signal_get_start_level uint32_t _Bool DigitalSignal* const DigitalSignal*
730 Function - + digital_signal_get_start_level digital_signal_set_start_level _Bool void DigitalSignal* DigitalSignal*, _Bool
Function - digital_signal_prepare_arr void DigitalSignal*
Function - digital_signal_send void DigitalSignal*, const GpioPin*
731 Function - diprintf int int, const char*, ...
732 Function + dir_walk_alloc DirWalk* Storage*
733 Function + dir_walk_close void DirWalk*
1808 Function + path_extract_extension void FuriString*, char*, size_t
1809 Function + path_extract_filename void FuriString*, FuriString*, _Bool
1810 Function + path_extract_filename_no_ext void const char*, FuriString*
1811 Function + pb_close_string_substream _Bool pb_istream_t*, pb_istream_t*
1812 Function + pb_decode _Bool pb_istream_t*, const pb_msgdesc_t*, void*
1813 Function + pb_decode_bool _Bool pb_istream_t*, _Bool*
1814 Function + pb_decode_ex _Bool pb_istream_t*, const pb_msgdesc_t*, void*, unsigned int
1815 Function + pb_decode_fixed32 _Bool pb_istream_t*, void*
1816 Function + pb_decode_fixed64 _Bool pb_istream_t*, void*
1817 Function + pb_decode_svarint _Bool pb_istream_t*, int64_t*
1818 Function + pb_decode_tag _Bool pb_istream_t*, pb_wire_type_t*, uint32_t*, _Bool*
1819 Function + pb_decode_varint _Bool pb_istream_t*, uint64_t*
1820 Function + pb_decode_varint32 _Bool pb_istream_t*, uint32_t*
1821 Function + pb_default_field_callback _Bool pb_istream_t*, pb_ostream_t*, const pb_field_t*
1822 Function + pb_encode _Bool pb_ostream_t*, const pb_msgdesc_t*, const void*
1823 Function + pb_encode_ex _Bool pb_ostream_t*, const pb_msgdesc_t*, const void*, unsigned int
1824 Function + pb_encode_fixed32 _Bool pb_ostream_t*, const void*
1825 Function + pb_encode_fixed64 _Bool pb_ostream_t*, const void*
1826 Function + pb_encode_string _Bool pb_ostream_t*, const pb_byte_t*, size_t
1827 Function + pb_encode_submessage _Bool pb_ostream_t*, const pb_msgdesc_t*, const void*
1828 Function + pb_encode_svarint _Bool pb_ostream_t*, int64_t
1829 Function + pb_encode_tag _Bool pb_ostream_t*, pb_wire_type_t, uint32_t
1830 Function + pb_encode_tag_for_field _Bool pb_ostream_t*, const pb_field_iter_t*
1831 Function + pb_encode_varint _Bool pb_ostream_t*, uint64_t
1832 Function + pb_get_encoded_size _Bool size_t*, const pb_msgdesc_t*, const void*
1833 Function + pb_istream_from_buffer pb_istream_t const pb_byte_t*, size_t
1834 Function + pb_make_string_substream _Bool pb_istream_t*, pb_istream_t*
1835 Function + pb_ostream_from_buffer pb_ostream_t pb_byte_t*, size_t
1836 Function + pb_read _Bool pb_istream_t*, pb_byte_t*, size_t
1837 Function + pb_release void const pb_msgdesc_t*, void*
1838 Function + pb_skip_field _Bool pb_istream_t*, pb_wire_type_t
1839 Function + pb_write _Bool pb_ostream_t*, const pb_byte_t*, size_t
1840 Function - pcTaskGetName char* TaskHandle_t
1841 Function - pcTimerGetName const char* TimerHandle_t
1842 Function - pclose int FILE*
2015 Function + sha256_process void sha256_context*
2016 Function + sha256_start void sha256_context*
2017 Function + sha256_update void sha256_context*, const unsigned char*, unsigned int
2018 Function + signal_reader_alloc SignalReader* const GpioPin*, uint32_t
2019 Function + signal_reader_free void SignalReader*
2020 Function + signal_reader_set_polarity void SignalReader*, SignalReaderPolarity
2021 Function + signal_reader_set_pull void SignalReader*, GpioPull
2022 Function + signal_reader_set_sample_rate void SignalReader*, SignalReaderTimeUnit, uint32_t
2023 Function + signal_reader_set_trigger void SignalReader*, SignalReaderTrigger
2024 Function + signal_reader_start void SignalReader*, SignalReaderCallback, void*
2025 Function + signal_reader_stop void SignalReader*
2026 Function + simple_array_alloc SimpleArray* const SimpleArrayConfig*
2027 Function + simple_array_cget const SimpleArrayElement* const SimpleArray*, uint32_t
2028 Function + simple_array_cget_data const SimpleArrayData* const SimpleArray*
2029 Function + simple_array_copy void SimpleArray*, const SimpleArray*
2030 Function + simple_array_free void SimpleArray*
2031 Function + simple_array_get SimpleArrayElement* SimpleArray*, uint32_t
2032 Function + simple_array_get_count uint32_t const SimpleArray*
2033 Function + simple_array_get_data SimpleArrayData* SimpleArray*
2034 Function + simple_array_init void SimpleArray*, uint32_t
2035 Function + simple_array_is_equal _Bool const SimpleArray*, const SimpleArray*
2036 Function + simple_array_reset void SimpleArray*
2037 Function - sin double double
2038 Function - sincos void double, double*, double*
2039 Function - sincosf void float, float*, float*
2775 Variable + sequence_single_vibro const NotificationSequence
2776 Variable + sequence_solid_yellow const NotificationSequence
2777 Variable + sequence_success const NotificationSequence
2778 Variable + simple_array_config_uint8_t const SimpleArrayConfig
2779 Variable - suboptarg char*
2780 Variable + usb_ccid FuriHalUsbInterface
2781 Variable + usb_cdc_dual FuriHalUsbInterface
+12 -3
View File
@@ -20,6 +20,8 @@
"littlefs",
"flipperformat",
"toolbox",
"digital_signal",
"signal_reader",
"microtar",
"usb_stm32",
"appframe",
@@ -31,10 +33,18 @@
"flipperformat",
"toolbox",
"flipper18"
],
"excluded_sources": [
"furi_hal_infrared.c",
"furi_hal_nfc.c",
"furi_hal_nfc_timer.c",
"furi_hal_nfc_irq.c",
"furi_hal_nfc_event.c",
"furi_hal_nfc_iso15693.c",
"furi_hal_nfc_iso14443a.c",
"furi_hal_nfc_iso14443b.c",
"furi_hal_nfc_felica.c",
"furi_hal_rfid.c",
"furi_hal_subghz.c"
],
@@ -51,7 +61,6 @@
"lfrfid",
"subghz",
"ibutton",
"infrared",
"st25rfal002"
"infrared"
]
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-431
View File
@@ -1,431 +0,0 @@
/**
* @file furi_hal_nfc.h
* NFC HAL API
*/
#pragma once
#include <st_errno.h>
#include <stdbool.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <rfal_nfc.h>
#include <lib/nfc/protocols/nfca.h>
#define FURI_HAL_NFC_UID_MAX_LEN 10
#define FURI_HAL_NFC_DATA_BUFF_SIZE (512)
#define FURI_HAL_NFC_PARITY_BUFF_SIZE (FURI_HAL_NFC_DATA_BUFF_SIZE / 8)
#define FURI_HAL_NFC_TXRX_DEFAULT \
((uint32_t)RFAL_TXRX_FLAGS_CRC_TX_AUTO | (uint32_t)RFAL_TXRX_FLAGS_CRC_RX_REMV | \
(uint32_t)RFAL_TXRX_FLAGS_PAR_RX_REMV | (uint32_t)RFAL_TXRX_FLAGS_PAR_TX_AUTO)
#define FURI_HAL_NFC_TX_DEFAULT_RX_NO_CRC \
((uint32_t)RFAL_TXRX_FLAGS_CRC_TX_AUTO | (uint32_t)RFAL_TXRX_FLAGS_CRC_RX_KEEP | \
(uint32_t)RFAL_TXRX_FLAGS_PAR_RX_REMV | (uint32_t)RFAL_TXRX_FLAGS_PAR_TX_AUTO)
#define FURI_HAL_NFC_TXRX_WITH_PAR \
((uint32_t)RFAL_TXRX_FLAGS_CRC_TX_MANUAL | (uint32_t)RFAL_TXRX_FLAGS_CRC_RX_KEEP | \
(uint32_t)RFAL_TXRX_FLAGS_PAR_RX_KEEP | (uint32_t)RFAL_TXRX_FLAGS_PAR_TX_AUTO)
#define FURI_HAL_NFC_TXRX_RAW \
((uint32_t)RFAL_TXRX_FLAGS_CRC_TX_MANUAL | (uint32_t)RFAL_TXRX_FLAGS_CRC_RX_KEEP | \
(uint32_t)RFAL_TXRX_FLAGS_PAR_RX_KEEP | (uint32_t)RFAL_TXRX_FLAGS_PAR_TX_NONE)
#define FURI_HAL_NFC_TX_RAW_RX_DEFAULT \
((uint32_t)RFAL_TXRX_FLAGS_CRC_TX_MANUAL | (uint32_t)RFAL_TXRX_FLAGS_CRC_RX_REMV | \
(uint32_t)RFAL_TXRX_FLAGS_PAR_RX_REMV | (uint32_t)RFAL_TXRX_FLAGS_PAR_TX_NONE)
typedef enum {
FuriHalNfcTxRxTypeDefault,
FuriHalNfcTxRxTypeRxNoCrc,
FuriHalNfcTxRxTypeRxKeepPar,
FuriHalNfcTxRxTypeRaw,
FuriHalNfcTxRxTypeRxRaw,
FuriHalNfcTxRxTransparent,
} FuriHalNfcTxRxType;
typedef bool (*FuriHalNfcEmulateCallback)(
uint8_t* buff_rx,
uint16_t buff_rx_len,
uint8_t* buff_tx,
uint16_t* buff_tx_len,
uint32_t* flags,
void* context);
typedef enum {
FuriHalNfcTypeA,
FuriHalNfcTypeB,
FuriHalNfcTypeF,
FuriHalNfcTypeV,
} FuriHalNfcType;
typedef enum {
FuriHalNfcInterfaceRf,
FuriHalNfcInterfaceIsoDep,
FuriHalNfcInterfaceNfcDep,
} FuriHalNfcInterface;
typedef struct {
FuriHalNfcType type;
FuriHalNfcInterface interface;
uint8_t uid_len;
uint8_t uid[10];
uint32_t cuid;
uint8_t atqa[2];
uint8_t sak;
} FuriHalNfcDevData;
typedef void (
*FuriHalNfcTxRxSniffCallback)(uint8_t* data, uint16_t bits, bool crc_dropped, void* context);
typedef struct {
uint8_t tx_data[FURI_HAL_NFC_DATA_BUFF_SIZE];
uint8_t tx_parity[FURI_HAL_NFC_PARITY_BUFF_SIZE];
uint16_t tx_bits;
uint8_t rx_data[FURI_HAL_NFC_DATA_BUFF_SIZE];
uint8_t rx_parity[FURI_HAL_NFC_PARITY_BUFF_SIZE];
uint16_t rx_bits;
FuriHalNfcTxRxType tx_rx_type;
NfcaSignal* nfca_signal;
FuriHalNfcTxRxSniffCallback sniff_tx;
FuriHalNfcTxRxSniffCallback sniff_rx;
void* sniff_context;
} FuriHalNfcTxRxContext;
/** Init nfc
*/
void furi_hal_nfc_init();
/** Deinit nfc
*/
void furi_hal_nfc_deinit();
/** Check if nfc worker is busy
*
* @return true if busy
*/
bool furi_hal_nfc_is_busy();
/** Check if nfc is initialized
*
* @return true if initialized
*/
bool furi_hal_nfc_is_init();
/** NFC field on
*/
void furi_hal_nfc_field_on();
/** NFC field off
*/
void furi_hal_nfc_field_off();
/** NFC start sleep
*/
void furi_hal_nfc_start_sleep();
void furi_hal_nfc_stop_cmd();
/** NFC stop sleep
*/
void furi_hal_nfc_exit_sleep();
/** NFC poll
*
* @param dev_list pointer to rfalNfcDevice buffer
* @param dev_cnt pointer device count
* @param timeout timeout in ms
* @param deactivate deactivate flag
*
* @return true on success
*/
bool furi_hal_nfc_detect(FuriHalNfcDevData* nfc_data, uint32_t timeout);
/** Activate NFC-A tag
*
* @param timeout timeout in ms
* @param cuid pointer to 32bit uid
*
* @return true on succeess
*/
bool furi_hal_nfc_activate_nfca(uint32_t timeout, uint32_t* cuid);
/** NFC listen
*
* @param uid pointer to uid buffer
* @param uid_len uid length
* @param atqa pointer to atqa
* @param sak sak
* @param activate_after_sak activate after sak flag
* @param timeout timeout in ms
*
* @return true on success
*/
bool furi_hal_nfc_listen(
uint8_t* uid,
uint8_t uid_len,
uint8_t* atqa,
uint8_t sak,
bool activate_after_sak,
uint32_t timeout);
/** Start Target Listen mode
* @note RFAL free implementation
*
* @param nfc_data FuriHalNfcDevData instance
*/
void furi_hal_nfc_listen_start(FuriHalNfcDevData* nfc_data);
/** Read data in Target Listen mode
* @note Must be called only after furi_hal_nfc_listen_start()
*
* @param tx_rx FuriHalNfcTxRxContext instance
* @param timeout_ms timeout im ms
*
* @return true on not empty receive
*/
bool furi_hal_nfc_listen_rx(FuriHalNfcTxRxContext* tx_rx, uint32_t timeout_ms);
/** Set Target in Sleep state */
void furi_hal_nfc_listen_sleep();
/** Emulate NFC-A Target
* @note RFAL based implementation
*
* @param uid NFC-A UID
* @param uid_len NFC-A UID length
* @param atqa NFC-A ATQA
* @param sak NFC-A SAK
* @param callback FuriHalNfcEmulateCallback instance
* @param context pointer to context for callback
* @param timeout timeout in ms
*
* @return true on success
*/
bool furi_hal_nfc_emulate_nfca(
uint8_t* uid,
uint8_t uid_len,
uint8_t* atqa,
uint8_t sak,
FuriHalNfcEmulateCallback callback,
void* context,
uint32_t timeout);
/** NFC data exchange
*
* @param tx_rx_ctx FuriHalNfcTxRxContext instance
*
* @return true on success
*/
bool furi_hal_nfc_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms);
/** NFC data full exhange
*
* @param tx_rx_ctx FuriHalNfcTxRxContext instance
*
* @return true on success
*/
bool furi_hal_nfc_tx_rx_full(FuriHalNfcTxRxContext* tx_rx);
/** NFC deactivate and start sleep
*/
void furi_hal_nfc_sleep();
void furi_hal_nfc_stop();
/* Low level transport API, use it to implement your own transport layers */
#define furi_hal_nfc_ll_ms2fc rfalConvMsTo1fc
#define FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_TX_MANUAL RFAL_TXRX_FLAGS_CRC_TX_MANUAL
#define FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON RFAL_TXRX_FLAGS_AGC_ON
#define FURI_HAL_NFC_LL_TXRX_FLAGS_PAR_RX_REMV RFAL_TXRX_FLAGS_PAR_RX_REMV
#define FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP RFAL_TXRX_FLAGS_CRC_RX_KEEP
typedef enum {
FuriHalNfcReturnOk = 0, /*!< no error occurred */
FuriHalNfcReturnNomem = 1, /*!< not enough memory to perform the requested operation */
FuriHalNfcReturnBusy = 2, /*!< device or resource busy */
FuriHalNfcReturnIo = 3, /*!< generic IO error */
FuriHalNfcReturnTimeout = 4, /*!< error due to timeout */
FuriHalNfcReturnRequest =
5, /*!< invalid request or requested function can't be executed at the moment */
FuriHalNfcReturnNomsg = 6, /*!< No message of desired type */
FuriHalNfcReturnParam = 7, /*!< Parameter error */
FuriHalNfcReturnSystem = 8, /*!< System error */
FuriHalNfcReturnFraming = 9, /*!< Framing error */
FuriHalNfcReturnOverrun = 10, /*!< lost one or more received bytes */
FuriHalNfcReturnProto = 11, /*!< protocol error */
FuriHalNfcReturnInternal = 12, /*!< Internal Error */
FuriHalNfcReturnAgain = 13, /*!< Call again */
FuriHalNfcReturnMemCorrupt = 14, /*!< memory corruption */
FuriHalNfcReturnNotImplemented = 15, /*!< not implemented */
FuriHalNfcReturnPcCorrupt =
16, /*!< Program Counter has been manipulated or spike/noise trigger illegal operation */
FuriHalNfcReturnSend = 17, /*!< error sending*/
FuriHalNfcReturnIgnore = 18, /*!< indicates error detected but to be ignored */
FuriHalNfcReturnSemantic = 19, /*!< indicates error in state machine (unexpected cmd) */
FuriHalNfcReturnSyntax = 20, /*!< indicates error in state machine (unknown cmd) */
FuriHalNfcReturnCrc = 21, /*!< crc error */
FuriHalNfcReturnNotfound = 22, /*!< transponder not found */
FuriHalNfcReturnNotunique =
23, /*!< transponder not unique - more than one transponder in field */
FuriHalNfcReturnNotsupp = 24, /*!< requested operation not supported */
FuriHalNfcReturnWrite = 25, /*!< write error */
FuriHalNfcReturnFifo = 26, /*!< fifo over or underflow error */
FuriHalNfcReturnPar = 27, /*!< parity error */
FuriHalNfcReturnDone = 28, /*!< transfer has already finished */
FuriHalNfcReturnRfCollision =
29, /*!< collision error (Bit Collision or during RF Collision avoidance ) */
FuriHalNfcReturnHwOverrun = 30, /*!< lost one or more received bytes */
FuriHalNfcReturnReleaseReq = 31, /*!< device requested release */
FuriHalNfcReturnSleepReq = 32, /*!< device requested sleep */
FuriHalNfcReturnWrongState = 33, /*!< incorrent state for requested operation */
FuriHalNfcReturnMaxReruns = 34, /*!< blocking procedure reached maximum runs */
FuriHalNfcReturnDisabled = 35, /*!< operation aborted due to disabled configuration */
FuriHalNfcReturnHwMismatch = 36, /*!< expected hw do not match */
FuriHalNfcReturnLinkLoss =
37, /*!< Other device's field didn't behave as expected: turned off by Initiator in Passive mode, or AP2P did not turn on field */
FuriHalNfcReturnInvalidHandle = 38, /*!< invalid or not initalized device handle */
FuriHalNfcReturnIncompleteByte = 40, /*!< Incomplete byte rcvd */
FuriHalNfcReturnIncompleteByte01 = 41, /*!< Incomplete byte rcvd - 1 bit */
FuriHalNfcReturnIncompleteByte02 = 42, /*!< Incomplete byte rcvd - 2 bit */
FuriHalNfcReturnIncompleteByte03 = 43, /*!< Incomplete byte rcvd - 3 bit */
FuriHalNfcReturnIncompleteByte04 = 44, /*!< Incomplete byte rcvd - 4 bit */
FuriHalNfcReturnIncompleteByte05 = 45, /*!< Incomplete byte rcvd - 5 bit */
FuriHalNfcReturnIncompleteByte06 = 46, /*!< Incomplete byte rcvd - 6 bit */
FuriHalNfcReturnIncompleteByte07 = 47, /*!< Incomplete byte rcvd - 7 bit */
} FuriHalNfcReturn;
typedef enum {
FuriHalNfcModeNone = 0, /*!< No mode selected/defined */
FuriHalNfcModePollNfca = 1, /*!< Mode to perform as NFCA (ISO14443A) Poller (PCD) */
FuriHalNfcModePollNfcaT1t = 2, /*!< Mode to perform as NFCA T1T (Topaz) Poller (PCD) */
FuriHalNfcModePollNfcb = 3, /*!< Mode to perform as NFCB (ISO14443B) Poller (PCD) */
FuriHalNfcModePollBPrime = 4, /*!< Mode to perform as B' Calypso (Innovatron) (PCD) */
FuriHalNfcModePollBCts = 5, /*!< Mode to perform as CTS Poller (PCD) */
FuriHalNfcModePollNfcf = 6, /*!< Mode to perform as NFCF (FeliCa) Poller (PCD) */
FuriHalNfcModePollNfcv = 7, /*!< Mode to perform as NFCV (ISO15963) Poller (PCD) */
FuriHalNfcModePollPicopass = 8, /*!< Mode to perform as PicoPass / iClass Poller (PCD) */
FuriHalNfcModePollActiveP2p = 9, /*!< Mode to perform as Active P2P (ISO18092) Initiator */
FuriHalNfcModeListenNfca = 10, /*!< Mode to perform as NFCA (ISO14443A) Listener (PICC) */
FuriHalNfcModeListenNfcb = 11, /*!< Mode to perform as NFCA (ISO14443B) Listener (PICC) */
FuriHalNfcModeListenNfcf = 12, /*!< Mode to perform as NFCA (ISO15963) Listener (PICC) */
FuriHalNfcModeListenActiveP2p = 13 /*!< Mode to perform as Active P2P (ISO18092) Target */
} FuriHalNfcMode;
typedef enum {
FuriHalNfcBitrate106 = 0, /*!< Bit Rate 106 kbit/s (fc/128) */
FuriHalNfcBitrate212 = 1, /*!< Bit Rate 212 kbit/s (fc/64) */
FuriHalNfcBitrate424 = 2, /*!< Bit Rate 424 kbit/s (fc/32) */
FuriHalNfcBitrate848 = 3, /*!< Bit Rate 848 kbit/s (fc/16) */
FuriHalNfcBitrate1695 = 4, /*!< Bit Rate 1695 kbit/s (fc/8) */
FuriHalNfcBitrate3390 = 5, /*!< Bit Rate 3390 kbit/s (fc/4) */
FuriHalNfcBitrate6780 = 6, /*!< Bit Rate 6780 kbit/s (fc/2) */
FuriHalNfcBitrate13560 = 7, /*!< Bit Rate 13560 kbit/s (fc) */
FuriHalNfcBitrate52p97 = 0xEB, /*!< Bit Rate 52.97 kbit/s (fc/256) Fast Mode VICC->VCD */
FuriHalNfcBitrate26p48 =
0xEC, /*!< Bit Rate 26,48 kbit/s (fc/512) NFCV VICC->VCD & VCD->VICC 1of4 */
FuriHalNfcBitrate1p66 = 0xED, /*!< Bit Rate 1,66 kbit/s (fc/8192) NFCV VCD->VICC 1of256 */
FuriHalNfcBitrateKeep = 0xFF /*!< Value indicating to keep the same previous bit rate */
} FuriHalNfcBitrate;
FuriHalNfcReturn
furi_hal_nfc_ll_set_mode(FuriHalNfcMode mode, FuriHalNfcBitrate txBR, FuriHalNfcBitrate rxBR);
#define FURI_HAL_NFC_LL_GT_NFCA furi_hal_nfc_ll_ms2fc(5U) /*!< GTA Digital 2.0 6.10.4.1 & B.2 */
#define FURI_HAL_NFC_LL_GT_NFCB furi_hal_nfc_ll_ms2fc(5U) /*!< GTB Digital 2.0 7.9.4.1 & B.3 */
#define FURI_HAL_NFC_LL_GT_NFCF furi_hal_nfc_ll_ms2fc(20U) /*!< GTF Digital 2.0 8.7.4.1 & B.4 */
#define FURI_HAL_NFC_LL_GT_NFCV furi_hal_nfc_ll_ms2fc(5U) /*!< GTV Digital 2.0 9.7.5.1 & B.5 */
#define FURI_HAL_NFC_LL_GT_PICOPASS furi_hal_nfc_ll_ms2fc(1U) /*!< GT Picopass */
#define FURI_HAL_NFC_LL_GT_AP2P furi_hal_nfc_ll_ms2fc(5U) /*!< TIRFG Ecma 340 11.1.1 */
#define FURI_HAL_NFC_LL_GT_AP2P_ADJUSTED \
furi_hal_nfc_ll_ms2fc( \
5U + \
25U) /*!< Adjusted GT for greater interoperability (Sony XPERIA P, Nokia N9, Huawei P2) */
void furi_hal_nfc_ll_set_guard_time(uint32_t cycles);
typedef enum {
FuriHalNfcErrorHandlingNone = 0, /*!< No special error handling will be performed */
FuriHalNfcErrorHandlingNfc = 1, /*!< Error handling set to perform as NFC compliant device */
FuriHalNfcErrorHandlingEmvco =
2 /*!< Error handling set to perform as EMVCo compliant device */
} FuriHalNfcErrorHandling;
void furi_hal_nfc_ll_set_error_handling(FuriHalNfcErrorHandling eHandling);
/* RFAL Frame Delay Time (FDT) Listen default values */
#define FURI_HAL_NFC_LL_FDT_LISTEN_NFCA_POLLER \
1172U /*!< FDTA,LISTEN,MIN (n=9) Last bit: Logic "1" - tnn,min/2 Digital 1.1 6.10 ; EMV CCP Spec Book D v2.01 4.8.1.3 */
#define FURI_HAL_NFC_LL_FDT_LISTEN_NFCB_POLLER \
1008U /*!< TR0B,MIN Digital 1.1 7.1.3 & A.3 ; EMV CCP Spec Book D v2.01 4.8.1.3 & Table A.5 */
#define FURI_HAL_NFC_LL_FDT_LISTEN_NFCF_POLLER \
2672U /*!< TR0F,LISTEN,MIN Digital 1.1 8.7.1.1 & A.4 */
#define FURI_HAL_NFC_LL_FDT_LISTEN_NFCV_POLLER \
4310U /*!< FDTV,LISTEN,MIN t1 min Digital 2.1 B.5 ; ISO15693-3 2009 9.1 */
#define FURI_HAL_NFC_LL_FDT_LISTEN_PICOPASS_POLLER \
3400U /*!< ISO15693 t1 min - observed adjustment */
#define FURI_HAL_NFC_LL_FDT_LISTEN_AP2P_POLLER \
64U /*!< FDT AP2P No actual FDTListen is required as fields switch and collision avoidance */
#define FURI_HAL_NFC_LL_FDT_LISTEN_NFCA_LISTENER 1172U /*!< FDTA,LISTEN,MIN Digital 1.1 6.10 */
#define FURI_HAL_NFC_LL_FDT_LISTEN_NFCB_LISTENER \
1024U /*!< TR0B,MIN Digital 1.1 7.1.3 & A.3 ; EMV CCP Spec Book D v2.01 4.8.1.3 & Table A.5 */
#define FURI_HAL_NFC_LL_FDT_LISTEN_NFCF_LISTENER \
2688U /*!< TR0F,LISTEN,MIN Digital 2.1 8.7.1.1 & B.4 */
#define FURI_HAL_NFC_LL_FDT_LISTEN_AP2P_LISTENER \
64U /*!< FDT AP2P No actual FDTListen exists as fields switch and collision avoidance */
void furi_hal_nfc_ll_set_fdt_listen(uint32_t cycles);
/* RFAL Frame Delay Time (FDT) Poll default values */
#define FURI_HAL_NFC_LL_FDT_POLL_NFCA_POLLER \
6780U /*!< FDTA,POLL,MIN Digital 1.1 6.10.3.1 & A.2 */
#define FURI_HAL_NFC_LL_FDT_POLL_NFCA_T1T_POLLER \
384U /*!< RRDDT1T,MIN,B1 Digital 1.1 10.7.1 & A.5 */
#define FURI_HAL_NFC_LL_FDT_POLL_NFCB_POLLER \
6780U /*!< FDTB,POLL,MIN = TR2B,MIN,DEFAULT Digital 1.1 7.9.3 & A.3 ; EMVCo 3.0 FDTB,PCD,MIN Table A.5 */
#define FURI_HAL_NFC_LL_FDT_POLL_NFCF_POLLER 6800U /*!< FDTF,POLL,MIN Digital 2.1 8.7.3 & B.4 */
#define FURI_HAL_NFC_LL_FDT_POLL_NFCV_POLLER 4192U /*!< FDTV,POLL Digital 2.1 9.7.3.1 & B.5 */
#define FURI_HAL_NFC_LL_FDT_POLL_PICOPASS_POLLER 1790U /*!< FDT Max */
#define FURI_HAL_NFC_LL_FDT_POLL_AP2P_POLLER \
0U /*!< FDT AP2P No actual FDTPoll exists as fields switch and collision avoidance */
void furi_hal_nfc_ll_set_fdt_poll(uint32_t FDTPoll);
void furi_hal_nfc_ll_txrx_on();
void furi_hal_nfc_ll_txrx_off();
FuriHalNfcReturn furi_hal_nfc_ll_txrx(
uint8_t* txBuf,
uint16_t txBufLen,
uint8_t* rxBuf,
uint16_t rxBufLen,
uint16_t* actLen,
uint32_t flags,
uint32_t fwt);
FuriHalNfcReturn furi_hal_nfc_ll_txrx_bits(
uint8_t* txBuf,
uint16_t txBufLen,
uint8_t* rxBuf,
uint16_t rxBufLen,
uint16_t* actLen,
uint32_t flags,
uint32_t fwt);
void furi_hal_nfc_ll_poll();
void furi_hal_nfc_field_detect_start();
bool furi_hal_nfc_field_is_present();
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,116 @@
#include <furi_hal_nfc_i.h>
FuriHalNfcEventInternal* furi_hal_nfc_event = NULL;
void furi_hal_nfc_event_init() {
furi_hal_nfc_event = malloc(sizeof(FuriHalNfcEventInternal));
}
FuriHalNfcError furi_hal_nfc_event_start() {
furi_assert(furi_hal_nfc_event);
furi_hal_nfc_event->thread = furi_thread_get_current_id();
furi_thread_flags_clear(FURI_HAL_NFC_EVENT_INTERNAL_ALL);
return FuriHalNfcErrorNone;
}
FuriHalNfcError furi_hal_nfc_event_stop() {
furi_assert(furi_hal_nfc_event);
furi_hal_nfc_event->thread = NULL;
return FuriHalNfcErrorNone;
}
void furi_hal_nfc_event_set(FuriHalNfcEventInternalType event) {
furi_assert(furi_hal_nfc_event);
furi_assert(furi_hal_nfc_event->thread);
furi_thread_flags_set(furi_hal_nfc_event->thread, event);
}
FuriHalNfcError furi_hal_nfc_abort() {
furi_hal_nfc_event_set(FuriHalNfcEventInternalTypeAbort);
return FuriHalNfcErrorNone;
}
FuriHalNfcEvent furi_hal_nfc_wait_event_common(uint32_t timeout_ms) {
furi_assert(furi_hal_nfc_event);
furi_assert(furi_hal_nfc_event->thread);
FuriHalNfcEvent event = 0;
uint32_t event_timeout = timeout_ms == FURI_HAL_NFC_EVENT_WAIT_FOREVER ? FuriWaitForever :
timeout_ms;
uint32_t event_flag =
furi_thread_flags_wait(FURI_HAL_NFC_EVENT_INTERNAL_ALL, FuriFlagWaitAny, event_timeout);
if(event_flag != (unsigned)FuriFlagErrorTimeout) {
if(event_flag & FuriHalNfcEventInternalTypeIrq) {
furi_thread_flags_clear(FuriHalNfcEventInternalTypeIrq);
FuriHalSpiBusHandle* handle = &furi_hal_spi_bus_handle_nfc;
uint32_t irq = furi_hal_nfc_get_irq(handle);
if(irq & ST25R3916_IRQ_MASK_OSC) {
event |= FuriHalNfcEventOscOn;
}
if(irq & ST25R3916_IRQ_MASK_TXE) {
event |= FuriHalNfcEventTxEnd;
}
if(irq & ST25R3916_IRQ_MASK_RXS) {
event |= FuriHalNfcEventRxStart;
}
if(irq & ST25R3916_IRQ_MASK_RXE) {
event |= FuriHalNfcEventRxEnd;
}
if(irq & ST25R3916_IRQ_MASK_COL) {
event |= FuriHalNfcEventCollision;
}
if(irq & ST25R3916_IRQ_MASK_EON) {
event |= FuriHalNfcEventFieldOn;
}
if(irq & ST25R3916_IRQ_MASK_EOF) {
event |= FuriHalNfcEventFieldOff;
}
if(irq & ST25R3916_IRQ_MASK_WU_A) {
event |= FuriHalNfcEventListenerActive;
}
if(irq & ST25R3916_IRQ_MASK_WU_A_X) {
event |= FuriHalNfcEventListenerActive;
}
}
if(event_flag & FuriHalNfcEventInternalTypeTimerFwtExpired) {
event |= FuriHalNfcEventTimerFwtExpired;
furi_thread_flags_clear(FuriHalNfcEventInternalTypeTimerFwtExpired);
}
if(event_flag & FuriHalNfcEventInternalTypeTimerBlockTxExpired) {
event |= FuriHalNfcEventTimerBlockTxExpired;
furi_thread_flags_clear(FuriHalNfcEventInternalTypeTimerBlockTxExpired);
}
if(event_flag & FuriHalNfcEventInternalTypeAbort) {
event |= FuriHalNfcEventAbortRequest;
furi_thread_flags_clear(FuriHalNfcEventInternalTypeAbort);
}
} else {
event = FuriHalNfcEventTimeout;
}
return event;
}
bool furi_hal_nfc_event_wait_for_specific_irq(
FuriHalSpiBusHandle* handle,
uint32_t mask,
uint32_t timeout_ms) {
furi_assert(furi_hal_nfc_event);
furi_assert(furi_hal_nfc_event->thread);
bool irq_received = false;
uint32_t event_flag =
furi_thread_flags_wait(FuriHalNfcEventInternalTypeIrq, FuriFlagWaitAny, timeout_ms);
if(event_flag == FuriHalNfcEventInternalTypeIrq) {
uint32_t irq = furi_hal_nfc_get_irq(handle);
irq_received = ((irq & mask) == mask);
furi_thread_flags_clear(FuriHalNfcEventInternalTypeIrq);
}
return irq_received;
}
@@ -0,0 +1,69 @@
#include "furi_hal_nfc_i.h"
#include "furi_hal_nfc_tech_i.h"
static FuriHalNfcError furi_hal_nfc_felica_poller_init(FuriHalSpiBusHandle* handle) {
// Enable Felica mode, AM modulation
st25r3916_change_reg_bits(
handle,
ST25R3916_REG_MODE,
ST25R3916_REG_MODE_om_mask | ST25R3916_REG_MODE_tr_am,
ST25R3916_REG_MODE_om_felica | ST25R3916_REG_MODE_tr_am_am);
// 10% ASK modulation
st25r3916_change_reg_bits(
handle,
ST25R3916_REG_TX_DRIVER,
ST25R3916_REG_TX_DRIVER_am_mod_mask,
ST25R3916_REG_TX_DRIVER_am_mod_10percent);
// Use regulator AM, resistive AM disabled
st25r3916_clear_reg_bits(
handle,
ST25R3916_REG_AUX_MOD,
ST25R3916_REG_AUX_MOD_dis_reg_am | ST25R3916_REG_AUX_MOD_res_am);
st25r3916_change_reg_bits(
handle,
ST25R3916_REG_BIT_RATE,
ST25R3916_REG_BIT_RATE_txrate_mask | ST25R3916_REG_BIT_RATE_rxrate_mask,
ST25R3916_REG_BIT_RATE_txrate_212 | ST25R3916_REG_BIT_RATE_rxrate_212);
// Receive configuration
st25r3916_write_reg(
handle,
ST25R3916_REG_RX_CONF1,
ST25R3916_REG_RX_CONF1_lp0 | ST25R3916_REG_RX_CONF1_hz_12_80khz);
// Correlator setup
st25r3916_write_reg(
handle,
ST25R3916_REG_CORR_CONF1,
ST25R3916_REG_CORR_CONF1_corr_s6 | ST25R3916_REG_CORR_CONF1_corr_s4 |
ST25R3916_REG_CORR_CONF1_corr_s3);
return FuriHalNfcErrorNone;
}
static FuriHalNfcError furi_hal_nfc_felica_poller_deinit(FuriHalSpiBusHandle* handle) {
UNUSED(handle);
return FuriHalNfcErrorNone;
}
const FuriHalNfcTechBase furi_hal_nfc_felica = {
.poller =
{
.compensation =
{
.fdt = FURI_HAL_NFC_POLLER_FDT_COMP_FC,
.fwt = FURI_HAL_NFC_POLLER_FWT_COMP_FC,
},
.init = furi_hal_nfc_felica_poller_init,
.deinit = furi_hal_nfc_felica_poller_deinit,
.wait_event = furi_hal_nfc_wait_event_common,
.tx = furi_hal_nfc_poller_tx_common,
.rx = furi_hal_nfc_common_fifo_rx,
},
.listener = {},
};
@@ -0,0 +1,191 @@
/**
* @file furi_hal_nfc_i.h
* @brief NFC HAL library (private definitions).
*
* This file is an implementation detail. It must not be included in
* any public API-related headers.
*/
#pragma once
#include <furi.h>
#include <furi_hal_nfc.h>
#include <furi_hal_spi.h>
#include <drivers/st25r3916.h>
#include <drivers/st25r3916_reg.h>
#ifdef __cplusplus
extern "C" {
#endif
/** @brief Common frame delay time compensation for pollers. */
#define FURI_HAL_NFC_POLLER_FDT_COMP_FC (-500)
/** @brief Common frame wait time compensation for pollers. */
#define FURI_HAL_NFC_POLLER_FWT_COMP_FC (FURI_HAL_NFC_POLLER_FDT_COMP_FC)
/**
* @brief Enumeration containing bitmask values for NFC HAL internal events.
*/
typedef enum {
FuriHalNfcEventInternalTypeAbort = (1U << 0), /**< Abort waiting for hardware events. */
FuriHalNfcEventInternalTypeIrq = (1U << 1), /**< NFC hardware interrupt has occurred. */
FuriHalNfcEventInternalTypeTimerFwtExpired =
(1U << 2), /**< Frame wait time timeout has expired. */
FuriHalNfcEventInternalTypeTimerBlockTxExpired =
(1U << 3), /**< Transmission block timeout has expired. */
FuriHalNfcEventInternalTypeTransparentDataReceived =
(1U << 4), /**< Data was received in transparent mode. */
} FuriHalNfcEventInternalType;
/** @brief Special bitmask value of all internal events. */
#define FURI_HAL_NFC_EVENT_INTERNAL_ALL \
((FuriHalNfcEventInternalTypeAbort | FuriHalNfcEventInternalTypeIrq | \
FuriHalNfcEventInternalTypeTimerFwtExpired | \
FuriHalNfcEventInternalTypeTimerBlockTxExpired | \
FuriHalNfcEventInternalTypeTransparentDataReceived))
/**
* @brief NFC HAL internal event structure.
*/
typedef struct {
FuriThreadId thread; /**< Identifier of the thread that will be receiving events. */
void* context; /**< Pointer to the user-provided context (will be passed to the event callback). */
} FuriHalNfcEventInternal;
/**
* @brief NFC HAL global state structure.
*/
typedef struct {
FuriMutex* mutex; /**< Pointer to the mutex serving as global NFC HAL lock. */
FuriHalNfcMode mode; /**< Currently selected operating mode. */
FuriHalNfcTech tech; /**< Currently selected NFC technology. */
} FuriHalNfc;
/**
* @brief NFC HAL global state object declaration.
*/
extern FuriHalNfc furi_hal_nfc;
/**
* @brief Initialise NFC HAL event system.
*/
void furi_hal_nfc_event_init();
/**
* @brief Forcibly emit (a) particular internal event(s).
*
* @param[in] event bitmask of one or more events to be emitted.
*/
void furi_hal_nfc_event_set(FuriHalNfcEventInternalType event);
/**
* @brief Initialise GPIO to generate an interrupt from the NFC hardware.
*/
void furi_hal_nfc_init_gpio_isr();
/**
* @brief Disable interrupts from the NFC hardware.
*/
void furi_hal_nfc_deinit_gpio_isr();
/**
* @brief Initialise all NFC timers.
*/
void furi_hal_nfc_timers_init();
/**
* @brief Disable all NFC timers.
*/
void furi_hal_nfc_timers_deinit();
/**
* @brief Get the interrupt bitmask from the NFC hardware.
*
* @param[in,out] handle pointer to the SPI handle associated with the NFC chip.
* @returns bitmask of zero or more occurred interrupts.
*/
uint32_t furi_hal_nfc_get_irq(FuriHalSpiBusHandle* handle);
/**
* @brief Wait until a specified type of interrupt occurs.
*
* @param[in,out] handle pointer to the SPI handle associated with the NFC chip.
* @param[in] mask bitmask of one or more interrupts to wait for.
* @param[in] timeout_ms maximum time to wait for an interrupt, in milliseconds.
* @returns true if specified interrupt(s) have occured within timeout, false otherwise.
*/
bool furi_hal_nfc_event_wait_for_specific_irq(
FuriHalSpiBusHandle* handle,
uint32_t mask,
uint32_t timeout_ms);
/**
* @brief Wait for any event to occur.
*
* This function is common to all technologies.
*
* @param[in] timeout_ms maximum time to wait for an event, in milliseconds.
* @returns bitmask of zero or more occurred events.
*/
FuriHalNfcEvent furi_hal_nfc_wait_event_common(uint32_t timeout_ms);
/**
* @brief Start reception in listener mode.
*
* This function is common to all technologies.
*
* @param[in,out] handle pointer to the SPI handle associated with the NFC chip.
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
FuriHalNfcError furi_hal_nfc_common_listener_rx_start(FuriHalSpiBusHandle* handle);
/**
* @brief Transmit data using on-chip FIFO.
*
* This function is common to all technologies.
*
* @param[in,out] handle pointer to the SPI handle associated with the NFC chip.
* @param[in] tx_data pointer to a byte array containing the data to be transmitted.
* @param[in] tx_bits transmit data size, in bits.
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
FuriHalNfcError furi_hal_nfc_common_fifo_tx(
FuriHalSpiBusHandle* handle,
const uint8_t* tx_data,
size_t tx_bits);
/**
* @brief Receive data using on-chip FIFO.
*
* This function is common to all technologies.
*
* @param[in,out] handle pointer to the SPI handle associated with the NFC chip.
* @param[out] rx_data pointer to a byte array to be filled with received data.
* @param[in] rx_data_size maximum received data size, in bytes.
* @param[out] rx_bits pointer to the variable to contain the received data size, in bits.
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
FuriHalNfcError furi_hal_nfc_common_fifo_rx(
FuriHalSpiBusHandle* handle,
uint8_t* rx_data,
size_t rx_data_size,
size_t* rx_bits);
/**
* @brief Transmit data in poller mode.
*
* This function is common to all technologies.
*
* @param[in,out] handle pointer to the SPI handle associated with the NFC chip.
* @param[in] tx_data pointer to a byte array containing the data to be transmitted.
* @param[in] tx_bits transmit data size, in bits.
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
FuriHalNfcError furi_hal_nfc_poller_tx_common(
FuriHalSpiBusHandle* handle,
const uint8_t* tx_data,
size_t tx_bits);
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,28 @@
#include "furi_hal_nfc_i.h"
#include <lib/drivers/st25r3916.h>
#include <furi_hal_resources.h>
static void furi_hal_nfc_int_callback() {
furi_hal_nfc_event_set(FuriHalNfcEventInternalTypeIrq);
}
uint32_t furi_hal_nfc_get_irq(FuriHalSpiBusHandle* handle) {
uint32_t irq = 0;
while(furi_hal_gpio_read_port_pin(gpio_nfc_irq_rfid_pull.port, gpio_nfc_irq_rfid_pull.pin)) {
irq |= st25r3916_get_irq(handle);
}
return irq;
}
void furi_hal_nfc_init_gpio_isr() {
furi_hal_gpio_init(
&gpio_nfc_irq_rfid_pull, GpioModeInterruptRise, GpioPullDown, GpioSpeedVeryHigh);
furi_hal_gpio_add_int_callback(&gpio_nfc_irq_rfid_pull, furi_hal_nfc_int_callback, NULL);
furi_hal_gpio_enable_int_callback(&gpio_nfc_irq_rfid_pull);
}
void furi_hal_nfc_deinit_gpio_isr() {
furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedLow);
furi_hal_gpio_remove_int_callback(&gpio_nfc_irq_rfid_pull);
}
@@ -0,0 +1,356 @@
#include "furi_hal_nfc_i.h"
#include "furi_hal_nfc_tech_i.h"
#include <furi.h>
#include <furi_hal_resources.h>
#include <digital_signal/presets/nfc/iso14443_3a_signal.h>
#define TAG "FuriHalIso14443a"
// Prevent FDT timer from starting
#define FURI_HAL_NFC_ISO14443A_LISTENER_FDT_COMP_FC (INT32_MAX)
static Iso14443_3aSignal* iso14443_3a_signal = NULL;
static FuriHalNfcError furi_hal_nfc_iso14443a_common_init(FuriHalSpiBusHandle* handle) {
// Common NFC-A settings, 106 kbps
// 1st stage zero = 600kHz, 3rd stage zero = 200 kHz
st25r3916_write_reg(handle, ST25R3916_REG_RX_CONF1, ST25R3916_REG_RX_CONF1_z600k);
// AGC enabled, ratio 3:1, squelch after TX
st25r3916_write_reg(
handle,
ST25R3916_REG_RX_CONF2,
ST25R3916_REG_RX_CONF2_agc6_3 | ST25R3916_REG_RX_CONF2_agc_m |
ST25R3916_REG_RX_CONF2_agc_en | ST25R3916_REG_RX_CONF2_sqm_dyn);
// HF operation, full gain on AM and PM channels
st25r3916_write_reg(handle, ST25R3916_REG_RX_CONF3, 0x00);
// No gain reduction on AM and PM channels
st25r3916_write_reg(handle, ST25R3916_REG_RX_CONF4, 0x00);
// Correlator config
st25r3916_write_reg(
handle,
ST25R3916_REG_CORR_CONF1,
ST25R3916_REG_CORR_CONF1_corr_s0 | ST25R3916_REG_CORR_CONF1_corr_s4 |
ST25R3916_REG_CORR_CONF1_corr_s6);
// Sleep mode disable, 424kHz mode off
st25r3916_write_reg(handle, ST25R3916_REG_CORR_CONF2, 0x00);
return FuriHalNfcErrorNone;
}
static FuriHalNfcError furi_hal_nfc_iso14443a_poller_init(FuriHalSpiBusHandle* handle) {
// Enable ISO14443A mode, OOK modulation
st25r3916_change_reg_bits(
handle,
ST25R3916_REG_MODE,
ST25R3916_REG_MODE_om_mask | ST25R3916_REG_MODE_tr_am,
ST25R3916_REG_MODE_om_iso14443a | ST25R3916_REG_MODE_tr_am_ook);
// Overshoot protection - is this necessary here?
st25r3916_change_reg_bits(handle, ST25R3916_REG_OVERSHOOT_CONF1, 0xff, 0x40);
st25r3916_change_reg_bits(handle, ST25R3916_REG_OVERSHOOT_CONF2, 0xff, 0x03);
st25r3916_change_reg_bits(handle, ST25R3916_REG_UNDERSHOOT_CONF1, 0xff, 0x40);
st25r3916_change_reg_bits(handle, ST25R3916_REG_UNDERSHOOT_CONF2, 0xff, 0x03);
return furi_hal_nfc_iso14443a_common_init(handle);
}
static FuriHalNfcError furi_hal_nfc_iso14443a_poller_deinit(FuriHalSpiBusHandle* handle) {
st25r3916_change_reg_bits(
handle,
ST25R3916_REG_ISO14443A_NFC,
(ST25R3916_REG_ISO14443A_NFC_no_tx_par | ST25R3916_REG_ISO14443A_NFC_no_rx_par),
(ST25R3916_REG_ISO14443A_NFC_no_tx_par_off | ST25R3916_REG_ISO14443A_NFC_no_rx_par_off));
return FuriHalNfcErrorNone;
}
static FuriHalNfcError furi_hal_nfc_iso14443a_listener_init(FuriHalSpiBusHandle* handle) {
furi_check(iso14443_3a_signal == NULL);
iso14443_3a_signal = iso14443_3a_signal_alloc(&gpio_spi_r_mosi);
st25r3916_write_reg(
handle,
ST25R3916_REG_OP_CONTROL,
ST25R3916_REG_OP_CONTROL_en | ST25R3916_REG_OP_CONTROL_rx_en |
ST25R3916_REG_OP_CONTROL_en_fd_auto_efd);
st25r3916_write_reg(
handle, ST25R3916_REG_MODE, ST25R3916_REG_MODE_targ_targ | ST25R3916_REG_MODE_om0);
st25r3916_write_reg(
handle,
ST25R3916_REG_PASSIVE_TARGET,
ST25R3916_REG_PASSIVE_TARGET_fdel_2 | ST25R3916_REG_PASSIVE_TARGET_fdel_0 |
ST25R3916_REG_PASSIVE_TARGET_d_ac_ap2p | ST25R3916_REG_PASSIVE_TARGET_d_212_424_1r);
st25r3916_write_reg(handle, ST25R3916_REG_MASK_RX_TIMER, 0x02);
st25r3916_direct_cmd(handle, ST25R3916_CMD_STOP);
uint32_t interrupts =
(ST25R3916_IRQ_MASK_FWL | ST25R3916_IRQ_MASK_TXE | ST25R3916_IRQ_MASK_RXS |
ST25R3916_IRQ_MASK_RXE | ST25R3916_IRQ_MASK_PAR | ST25R3916_IRQ_MASK_CRC |
ST25R3916_IRQ_MASK_ERR1 | ST25R3916_IRQ_MASK_ERR2 | ST25R3916_IRQ_MASK_NRE |
ST25R3916_IRQ_MASK_EON | ST25R3916_IRQ_MASK_EOF | ST25R3916_IRQ_MASK_WU_A_X |
ST25R3916_IRQ_MASK_WU_A);
// Clear interrupts
st25r3916_get_irq(handle);
// Enable interrupts
st25r3916_mask_irq(handle, ~interrupts);
// Enable auto collision resolution
st25r3916_clear_reg_bits(
handle, ST25R3916_REG_PASSIVE_TARGET, ST25R3916_REG_PASSIVE_TARGET_d_106_ac_a);
st25r3916_direct_cmd(handle, ST25R3916_CMD_GOTO_SENSE);
return furi_hal_nfc_iso14443a_common_init(handle);
}
static FuriHalNfcError furi_hal_nfc_iso14443a_listener_deinit(FuriHalSpiBusHandle* handle) {
UNUSED(handle);
if(iso14443_3a_signal) {
iso14443_3a_signal_free(iso14443_3a_signal);
iso14443_3a_signal = NULL;
}
return FuriHalNfcErrorNone;
}
static FuriHalNfcEvent furi_hal_nfc_iso14443_3a_listener_wait_event(uint32_t timeout_ms) {
FuriHalNfcEvent event = furi_hal_nfc_wait_event_common(timeout_ms);
FuriHalSpiBusHandle* handle = &furi_hal_spi_bus_handle_nfc;
if(event & FuriHalNfcEventListenerActive) {
st25r3916_set_reg_bits(
handle, ST25R3916_REG_PASSIVE_TARGET, ST25R3916_REG_PASSIVE_TARGET_d_106_ac_a);
}
return event;
}
FuriHalNfcError furi_hal_nfc_iso14443a_poller_trx_short_frame(FuriHalNfcaShortFrame frame) {
FuriHalNfcError error = FuriHalNfcErrorNone;
FuriHalSpiBusHandle* handle = &furi_hal_spi_bus_handle_nfc;
// Disable crc check
st25r3916_set_reg_bits(handle, ST25R3916_REG_AUX, ST25R3916_REG_AUX_no_crc_rx);
st25r3916_change_reg_bits(
handle,
ST25R3916_REG_ISO14443A_NFC,
(ST25R3916_REG_ISO14443A_NFC_no_tx_par | ST25R3916_REG_ISO14443A_NFC_no_rx_par),
(ST25R3916_REG_ISO14443A_NFC_no_tx_par_off | ST25R3916_REG_ISO14443A_NFC_no_rx_par_off));
st25r3916_write_reg(handle, ST25R3916_REG_NUM_TX_BYTES2, 0);
uint32_t interrupts =
(ST25R3916_IRQ_MASK_FWL | ST25R3916_IRQ_MASK_TXE | ST25R3916_IRQ_MASK_RXS |
ST25R3916_IRQ_MASK_RXE | ST25R3916_IRQ_MASK_PAR | ST25R3916_IRQ_MASK_CRC |
ST25R3916_IRQ_MASK_ERR1 | ST25R3916_IRQ_MASK_ERR2 | ST25R3916_IRQ_MASK_NRE);
// Clear interrupts
st25r3916_get_irq(handle);
// Enable interrupts
st25r3916_mask_irq(handle, ~interrupts);
if(frame == FuriHalNfcaShortFrameAllReq) {
st25r3916_direct_cmd(handle, ST25R3916_CMD_TRANSMIT_REQA);
} else {
st25r3916_direct_cmd(handle, ST25R3916_CMD_TRANSMIT_WUPA);
}
return error;
}
FuriHalNfcError furi_hal_nfc_iso14443a_tx_sdd_frame(const uint8_t* tx_data, size_t tx_bits) {
FuriHalNfcError error = FuriHalNfcErrorNone;
// No anticollision is supported in this version of library
error = furi_hal_nfc_poller_tx(tx_data, tx_bits);
return error;
}
FuriHalNfcError
furi_hal_nfc_iso14443a_rx_sdd_frame(uint8_t* rx_data, size_t rx_data_size, size_t* rx_bits) {
FuriHalNfcError error = FuriHalNfcErrorNone;
UNUSED(rx_data);
UNUSED(rx_bits);
UNUSED(rx_data_size);
error = furi_hal_nfc_poller_rx(rx_data, rx_data_size, rx_bits);
// No anticollision is supported in this version of library
return error;
}
FuriHalNfcError
furi_hal_nfc_iso14443a_poller_tx_custom_parity(const uint8_t* tx_data, size_t tx_bits) {
furi_assert(tx_data);
FuriHalNfcError err = FuriHalNfcErrorNone;
FuriHalSpiBusHandle* handle = &furi_hal_spi_bus_handle_nfc;
// Prepare tx
st25r3916_direct_cmd(handle, ST25R3916_CMD_CLEAR_FIFO);
st25r3916_clear_reg_bits(
handle, ST25R3916_REG_TIMER_EMV_CONTROL, ST25R3916_REG_TIMER_EMV_CONTROL_nrt_emv);
st25r3916_change_reg_bits(
handle,
ST25R3916_REG_ISO14443A_NFC,
(ST25R3916_REG_ISO14443A_NFC_no_tx_par | ST25R3916_REG_ISO14443A_NFC_no_rx_par),
(ST25R3916_REG_ISO14443A_NFC_no_tx_par | ST25R3916_REG_ISO14443A_NFC_no_rx_par));
uint32_t interrupts =
(ST25R3916_IRQ_MASK_FWL | ST25R3916_IRQ_MASK_TXE | ST25R3916_IRQ_MASK_RXS |
ST25R3916_IRQ_MASK_RXE | ST25R3916_IRQ_MASK_PAR | ST25R3916_IRQ_MASK_CRC |
ST25R3916_IRQ_MASK_ERR1 | ST25R3916_IRQ_MASK_ERR2 | ST25R3916_IRQ_MASK_NRE);
// Clear interrupts
st25r3916_get_irq(handle);
// Enable interrupts
st25r3916_mask_irq(handle, ~interrupts);
st25r3916_write_fifo(handle, tx_data, tx_bits);
st25r3916_direct_cmd(handle, ST25R3916_CMD_TRANSMIT_WITHOUT_CRC);
return err;
}
FuriHalNfcError furi_hal_nfc_iso14443a_listener_set_col_res_data(
uint8_t* uid,
uint8_t uid_len,
uint8_t* atqa,
uint8_t sak) {
furi_assert(uid);
furi_assert(atqa);
UNUSED(uid_len);
UNUSED(sak);
FuriHalNfcError error = FuriHalNfcErrorNone;
FuriHalSpiBusHandle* handle = &furi_hal_spi_bus_handle_nfc;
// Set 4 or 7 bytes UID
if(uid_len == 4) {
st25r3916_change_reg_bits(
handle,
ST25R3916_REG_AUX,
ST25R3916_REG_AUX_nfc_id_mask,
ST25R3916_REG_AUX_nfc_id_4bytes);
} else {
st25r3916_change_reg_bits(
handle,
ST25R3916_REG_AUX,
ST25R3916_REG_AUX_nfc_id_mask,
ST25R3916_REG_AUX_nfc_id_7bytes);
}
// Write PT Memory
uint8_t pt_memory[15] = {};
memcpy(pt_memory, uid, uid_len);
pt_memory[10] = atqa[0];
pt_memory[11] = atqa[1];
if(uid_len == 4) {
pt_memory[12] = sak & ~0x04;
} else {
pt_memory[12] = 0x04;
}
pt_memory[13] = sak & ~0x04;
pt_memory[14] = sak & ~0x04;
st25r3916_write_pta_mem(handle, pt_memory, sizeof(pt_memory));
return error;
}
FuriHalNfcError furi_hal_nfc_iso4443a_listener_tx(
FuriHalSpiBusHandle* handle,
const uint8_t* tx_data,
size_t tx_bits) {
FuriHalNfcError error = FuriHalNfcErrorNone;
do {
error = furi_hal_nfc_common_fifo_tx(handle, tx_data, tx_bits);
if(error != FuriHalNfcErrorNone) break;
bool tx_end = furi_hal_nfc_event_wait_for_specific_irq(handle, ST25R3916_IRQ_MASK_TXE, 10);
if(!tx_end) {
error = FuriHalNfcErrorCommunicationTimeout;
break;
}
} while(false);
return error;
}
FuriHalNfcError furi_hal_nfc_iso14443a_listener_tx_custom_parity(
const uint8_t* tx_data,
const uint8_t* tx_parity,
size_t tx_bits) {
furi_assert(tx_data);
furi_assert(tx_parity);
furi_assert(iso14443_3a_signal);
FuriHalSpiBusHandle* handle = &furi_hal_spi_bus_handle_nfc;
st25r3916_direct_cmd(handle, ST25R3916_CMD_TRANSPARENT_MODE);
// Reconfigure gpio for Transparent mode
furi_hal_spi_bus_handle_deinit(&furi_hal_spi_bus_handle_nfc);
// Send signal
iso14443_3a_signal_tx(iso14443_3a_signal, tx_data, tx_parity, tx_bits);
// Exit transparent mode
furi_hal_gpio_write(&gpio_spi_r_mosi, false);
// Configure gpio back to SPI and exit transparent
furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_nfc);
st25r3916_direct_cmd(handle, ST25R3916_CMD_UNMASK_RECEIVE_DATA);
return FuriHalNfcErrorNone;
}
FuriHalNfcError furi_hal_nfc_iso14443_3a_listener_sleep(FuriHalSpiBusHandle* handle) {
// Enable auto collision resolution
st25r3916_clear_reg_bits(
handle, ST25R3916_REG_PASSIVE_TARGET, ST25R3916_REG_PASSIVE_TARGET_d_106_ac_a);
st25r3916_direct_cmd(handle, ST25R3916_CMD_STOP);
st25r3916_direct_cmd(handle, ST25R3916_CMD_GOTO_SLEEP);
return FuriHalNfcErrorNone;
}
FuriHalNfcError furi_hal_nfc_iso14443_3a_listener_idle(FuriHalSpiBusHandle* handle) {
// Enable auto collision resolution
st25r3916_clear_reg_bits(
handle, ST25R3916_REG_PASSIVE_TARGET, ST25R3916_REG_PASSIVE_TARGET_d_106_ac_a);
st25r3916_direct_cmd(handle, ST25R3916_CMD_STOP);
st25r3916_direct_cmd(handle, ST25R3916_CMD_GOTO_SENSE);
return FuriHalNfcErrorNone;
}
const FuriHalNfcTechBase furi_hal_nfc_iso14443a = {
.poller =
{
.compensation =
{
.fdt = FURI_HAL_NFC_POLLER_FDT_COMP_FC,
.fwt = FURI_HAL_NFC_POLLER_FWT_COMP_FC,
},
.init = furi_hal_nfc_iso14443a_poller_init,
.deinit = furi_hal_nfc_iso14443a_poller_deinit,
.wait_event = furi_hal_nfc_wait_event_common,
.tx = furi_hal_nfc_poller_tx_common,
.rx = furi_hal_nfc_common_fifo_rx,
},
.listener =
{
.compensation =
{
.fdt = FURI_HAL_NFC_ISO14443A_LISTENER_FDT_COMP_FC,
},
.init = furi_hal_nfc_iso14443a_listener_init,
.deinit = furi_hal_nfc_iso14443a_listener_deinit,
.wait_event = furi_hal_nfc_iso14443_3a_listener_wait_event,
.tx = furi_hal_nfc_iso4443a_listener_tx,
.rx = furi_hal_nfc_common_fifo_rx,
.sleep = furi_hal_nfc_iso14443_3a_listener_sleep,
.idle = furi_hal_nfc_iso14443_3a_listener_idle,
},
};
@@ -0,0 +1,108 @@
#include "furi_hal_nfc_i.h"
#include "furi_hal_nfc_tech_i.h"
static FuriHalNfcError furi_hal_nfc_iso14443b_common_init(FuriHalSpiBusHandle* handle) {
// Common NFC-B settings, 106kbps
// 1st stage zero = 60kHz, 3rd stage zero = 200 kHz
st25r3916_write_reg(handle, ST25R3916_REG_RX_CONF1, ST25R3916_REG_RX_CONF1_h200);
// Enable AGC
// AGC Ratio 6
// AGC algorithm with RESET (recommended for ISO14443-B)
// AGC operation during complete receive period
// Squelch ratio 6/3 (recommended for ISO14443-B)
// Squelch automatic activation on TX end
st25r3916_write_reg(
handle,
ST25R3916_REG_RX_CONF2,
ST25R3916_REG_RX_CONF2_agc6_3 | ST25R3916_REG_RX_CONF2_agc_alg |
ST25R3916_REG_RX_CONF2_agc_m | ST25R3916_REG_RX_CONF2_agc_en |
ST25R3916_REG_RX_CONF2_pulz_61 | ST25R3916_REG_RX_CONF2_sqm_dyn);
// HF operation, full gain on AM and PM channels
st25r3916_write_reg(handle, ST25R3916_REG_RX_CONF3, 0x00);
// No gain reduction on AM and PM channels
st25r3916_write_reg(handle, ST25R3916_REG_RX_CONF4, 0x00);
// Subcarrier end detector enabled
// Subcarrier end detection level = 66%
// BPSK start 33 pilot pulses
// AM & PM summation before digitizing on
st25r3916_write_reg(
handle,
ST25R3916_REG_CORR_CONF1,
ST25R3916_REG_CORR_CONF1_corr_s0 | ST25R3916_REG_CORR_CONF1_corr_s1 |
ST25R3916_REG_CORR_CONF1_corr_s3 | ST25R3916_REG_CORR_CONF1_corr_s4);
// Sleep mode disable, 424kHz mode off
st25r3916_write_reg(handle, ST25R3916_REG_CORR_CONF2, 0x00);
return FuriHalNfcErrorNone;
}
static FuriHalNfcError furi_hal_nfc_iso14443b_poller_init(FuriHalSpiBusHandle* handle) {
// Enable ISO14443B mode, AM modulation
st25r3916_change_reg_bits(
handle,
ST25R3916_REG_MODE,
ST25R3916_REG_MODE_om_mask | ST25R3916_REG_MODE_tr_am,
ST25R3916_REG_MODE_om_iso14443b | ST25R3916_REG_MODE_tr_am_am);
// 10% ASK modulation
st25r3916_change_reg_bits(
handle,
ST25R3916_REG_TX_DRIVER,
ST25R3916_REG_TX_DRIVER_am_mod_mask,
ST25R3916_REG_TX_DRIVER_am_mod_10percent);
// Use regulator AM, resistive AM disabled
st25r3916_clear_reg_bits(
handle,
ST25R3916_REG_AUX_MOD,
ST25R3916_REG_AUX_MOD_dis_reg_am | ST25R3916_REG_AUX_MOD_res_am);
// EGT = 0 etu
// SOF = 10 etu LOW + 2 etu HIGH
// EOF = 10 etu
st25r3916_change_reg_bits(
handle,
ST25R3916_REG_ISO14443B_1,
ST25R3916_REG_ISO14443B_1_egt_mask | ST25R3916_REG_ISO14443B_1_sof_mask |
ST25R3916_REG_ISO14443B_1_eof,
(0U << ST25R3916_REG_ISO14443B_1_egt_shift) | ST25R3916_REG_ISO14443B_1_sof_0_10etu |
ST25R3916_REG_ISO14443B_1_sof_1_2etu | ST25R3916_REG_ISO14443B_1_eof_10etu);
// TR1 = 80 / fs
// B' mode off (no_sof & no_eof = 0)
st25r3916_change_reg_bits(
handle,
ST25R3916_REG_ISO14443B_2,
ST25R3916_REG_ISO14443B_2_tr1_mask | ST25R3916_REG_ISO14443B_2_no_sof |
ST25R3916_REG_ISO14443B_2_no_eof,
ST25R3916_REG_ISO14443B_2_tr1_80fs80fs);
return furi_hal_nfc_iso14443b_common_init(handle);
}
static FuriHalNfcError furi_hal_nfc_iso14443b_poller_deinit(FuriHalSpiBusHandle* handle) {
UNUSED(handle);
return FuriHalNfcErrorNone;
}
const FuriHalNfcTechBase furi_hal_nfc_iso14443b = {
.poller =
{
.compensation =
{
.fdt = FURI_HAL_NFC_POLLER_FDT_COMP_FC,
.fwt = FURI_HAL_NFC_POLLER_FWT_COMP_FC,
},
.init = furi_hal_nfc_iso14443b_poller_init,
.deinit = furi_hal_nfc_iso14443b_poller_deinit,
.wait_event = furi_hal_nfc_wait_event_common,
.tx = furi_hal_nfc_poller_tx_common,
.rx = furi_hal_nfc_common_fifo_rx,
},
.listener = {},
};
@@ -0,0 +1,463 @@
#include "furi_hal_nfc_i.h"
#include "furi_hal_nfc_tech_i.h"
#include <digital_signal/presets/nfc/iso15693_signal.h>
#include <signal_reader/parsers/iso15693/iso15693_parser.h>
#include <furi_hal_resources.h>
#define FURI_HAL_NFC_ISO15693_MAX_FRAME_SIZE (1024U)
#define FURI_HAL_NFC_ISO15693_POLLER_MAX_BUFFER_SIZE (64)
#define FURI_HAL_NFC_ISO15693_RESP_SOF_SIZE (5)
#define FURI_HAL_NFC_ISO15693_RESP_EOF_SIZE (5)
#define FURI_HAL_NFC_ISO15693_RESP_SOF_MASK (0x1FU)
#define FURI_HAL_NFC_ISO15693_RESP_SOF_PATTERN (0x17U)
#define FURI_HAL_NFC_ISO15693_RESP_EOF_PATTERN (0x1DU)
#define FURI_HAL_NFC_ISO15693_RESP_PATTERN_MASK (0x03U)
#define FURI_HAL_NFC_ISO15693_RESP_PATTERN_0 (0x01U)
#define FURI_HAL_NFC_ISO15693_RESP_PATTERN_1 (0x02U)
// Derived experimentally
#define FURI_HAL_NFC_ISO15693_POLLER_FWT_COMP_FC (-1300)
#define FURI_HAL_NFC_ISO15693_LISTENER_FDT_COMP_FC (2850)
#define BITS_IN_BYTE (8U)
#define TAG "FuriHalIso15693"
typedef struct {
Iso15693Signal* signal;
Iso15693Parser* parser;
} FuriHalNfcIso15693Listener;
typedef struct {
// 4 bits per data bit on transmit
uint8_t fifo_buf[FURI_HAL_NFC_ISO15693_POLLER_MAX_BUFFER_SIZE * 4];
size_t fifo_buf_bits;
uint8_t frame_buf[FURI_HAL_NFC_ISO15693_POLLER_MAX_BUFFER_SIZE * 2];
size_t frame_buf_bits;
} FuriHalNfcIso15693Poller;
static FuriHalNfcIso15693Listener* furi_hal_nfc_iso15693_listener = NULL;
static FuriHalNfcIso15693Poller* furi_hal_nfc_iso15693_poller = NULL;
static FuriHalNfcIso15693Listener* furi_hal_nfc_iso15693_listener_alloc() {
FuriHalNfcIso15693Listener* instance = malloc(sizeof(FuriHalNfcIso15693Listener));
instance->signal = iso15693_signal_alloc(&gpio_spi_r_mosi);
instance->parser =
iso15693_parser_alloc(&gpio_spi_r_miso, FURI_HAL_NFC_ISO15693_MAX_FRAME_SIZE);
return instance;
}
static void furi_hal_nfc_iso15693_listener_free(FuriHalNfcIso15693Listener* instance) {
furi_assert(instance);
iso15693_signal_free(instance->signal);
iso15693_parser_free(instance->parser);
free(instance);
}
static FuriHalNfcIso15693Poller* furi_hal_nfc_iso15693_poller_alloc() {
FuriHalNfcIso15693Poller* instance = malloc(sizeof(FuriHalNfcIso15693Poller));
return instance;
}
static void furi_hal_nfc_iso15693_poller_free(FuriHalNfcIso15693Poller* instance) {
furi_assert(instance);
free(instance);
}
static FuriHalNfcError furi_hal_nfc_iso15693_common_init(FuriHalSpiBusHandle* handle) {
// Common NFC-V settings, 26.48 kbps
// 1st stage zero = 12 kHz, 3rd stage zero = 80 kHz, low-pass = 600 kHz
st25r3916_write_reg(
handle,
ST25R3916_REG_RX_CONF1,
ST25R3916_REG_RX_CONF1_z12k | ST25R3916_REG_RX_CONF1_h80 |
ST25R3916_REG_RX_CONF1_lp_600khz);
// Enable AGC
// AGC Ratio 6
// AGC algorithm with RESET (recommended for ISO15693)
// AGC operation during complete receive period
// Squelch automatic activation on TX end
st25r3916_write_reg(
handle,
ST25R3916_REG_RX_CONF2,
ST25R3916_REG_RX_CONF2_agc6_3 | ST25R3916_REG_RX_CONF2_agc_m |
ST25R3916_REG_RX_CONF2_agc_en | ST25R3916_REG_RX_CONF2_sqm_dyn);
// HF operation, full gain on AM and PM channels
st25r3916_write_reg(handle, ST25R3916_REG_RX_CONF3, 0x00);
// No gain reduction on AM and PM channels
st25r3916_write_reg(handle, ST25R3916_REG_RX_CONF4, 0x00);
// Collision detection level 53%
// AM & PM summation before digitizing on
st25r3916_write_reg(
handle,
ST25R3916_REG_CORR_CONF1,
ST25R3916_REG_CORR_CONF1_corr_s0 | ST25R3916_REG_CORR_CONF1_corr_s1 |
ST25R3916_REG_CORR_CONF1_corr_s4);
// 424 kHz subcarrier stream mode on
st25r3916_write_reg(handle, ST25R3916_REG_CORR_CONF2, ST25R3916_REG_CORR_CONF2_corr_s8);
return FuriHalNfcErrorNone;
}
static FuriHalNfcError furi_hal_nfc_iso15693_poller_init(FuriHalSpiBusHandle* handle) {
furi_assert(furi_hal_nfc_iso15693_poller == NULL);
furi_hal_nfc_iso15693_poller = furi_hal_nfc_iso15693_poller_alloc();
// Enable Subcarrier Stream mode, OOK modulation
st25r3916_change_reg_bits(
handle,
ST25R3916_REG_MODE,
ST25R3916_REG_MODE_om_mask | ST25R3916_REG_MODE_tr_am,
ST25R3916_REG_MODE_om_subcarrier_stream | ST25R3916_REG_MODE_tr_am_ook);
// Subcarrier 424 kHz mode
// 8 sub-carrier pulses in report period
st25r3916_write_reg(
handle,
ST25R3916_REG_STREAM_MODE,
ST25R3916_REG_STREAM_MODE_scf_sc424 | ST25R3916_REG_STREAM_MODE_stx_106 |
ST25R3916_REG_STREAM_MODE_scp_8pulses);
// Use regulator AM, resistive AM disabled
st25r3916_clear_reg_bits(
handle,
ST25R3916_REG_AUX_MOD,
ST25R3916_REG_AUX_MOD_dis_reg_am | ST25R3916_REG_AUX_MOD_res_am);
return furi_hal_nfc_iso15693_common_init(handle);
}
static FuriHalNfcError furi_hal_nfc_iso15693_poller_deinit(FuriHalSpiBusHandle* handle) {
UNUSED(handle);
furi_assert(furi_hal_nfc_iso15693_poller);
furi_hal_nfc_iso15693_poller_free(furi_hal_nfc_iso15693_poller);
furi_hal_nfc_iso15693_poller = NULL;
return FuriHalNfcErrorNone;
}
static void iso15693_3_poller_encode_frame(
const uint8_t* tx_data,
size_t tx_bits,
uint8_t* frame_buf,
size_t frame_buf_size,
size_t* frame_buf_bits) {
static const uint8_t bit_patterns_1_out_of_4[] = {0x02, 0x08, 0x20, 0x80};
size_t frame_buf_size_calc = (tx_bits / 2) + 2;
furi_assert(frame_buf_size >= frame_buf_size_calc);
// Add SOF 1 out of 4
frame_buf[0] = 0x21;
size_t byte_pos = 1;
for(size_t i = 0; i < tx_bits / BITS_IN_BYTE; ++i) {
for(size_t j = 0; j < BITS_IN_BYTE; j += (BITS_IN_BYTE) / 4) {
const uint8_t bit_pair = (tx_data[i] >> j) & 0x03;
frame_buf[byte_pos++] = bit_patterns_1_out_of_4[bit_pair];
}
}
// Add EOF
frame_buf[byte_pos++] = 0x04;
*frame_buf_bits = byte_pos * BITS_IN_BYTE;
}
static FuriHalNfcError iso15693_3_poller_decode_frame(
const uint8_t* buf,
size_t buf_bits,
uint8_t* buf_decoded,
size_t buf_decoded_size,
size_t* buf_decoded_bits) {
FuriHalNfcError ret = FuriHalNfcErrorDataFormat;
size_t bit_pos = 0;
memset(buf_decoded, 0, buf_decoded_size);
do {
if(buf_bits == 0) break;
// Check SOF
if((buf[0] & FURI_HAL_NFC_ISO15693_RESP_SOF_MASK) !=
FURI_HAL_NFC_ISO15693_RESP_SOF_PATTERN)
break;
if(buf_bits == BITS_IN_BYTE) {
ret = FuriHalNfcErrorIncompleteFrame;
break;
}
// 2 response bits = 1 data bit
for(uint32_t i = FURI_HAL_NFC_ISO15693_RESP_SOF_SIZE;
i < buf_bits - FURI_HAL_NFC_ISO15693_RESP_SOF_SIZE;
i += BITS_IN_BYTE / 4) {
const size_t byte_index = i / BITS_IN_BYTE;
const size_t bit_offset = i % BITS_IN_BYTE;
const uint8_t resp_byte = (buf[byte_index] >> bit_offset) |
(buf[byte_index + 1] << (BITS_IN_BYTE - bit_offset));
// Check EOF
if(resp_byte == FURI_HAL_NFC_ISO15693_RESP_EOF_PATTERN) {
ret = FuriHalNfcErrorNone;
break;
}
const uint8_t bit_pattern = resp_byte & FURI_HAL_NFC_ISO15693_RESP_PATTERN_MASK;
if(bit_pattern == FURI_HAL_NFC_ISO15693_RESP_PATTERN_0) {
bit_pos++;
} else if(bit_pattern == FURI_HAL_NFC_ISO15693_RESP_PATTERN_1) {
buf_decoded[bit_pos / BITS_IN_BYTE] |= 1 << (bit_pos % BITS_IN_BYTE);
bit_pos++;
} else {
break;
}
if(bit_pos / BITS_IN_BYTE > buf_decoded_size) {
break;
}
}
} while(false);
if(ret == FuriHalNfcErrorNone) {
*buf_decoded_bits = bit_pos;
}
return ret;
}
static FuriHalNfcError furi_hal_nfc_iso15693_poller_tx(
FuriHalSpiBusHandle* handle,
const uint8_t* tx_data,
size_t tx_bits) {
FuriHalNfcIso15693Poller* instance = furi_hal_nfc_iso15693_poller;
iso15693_3_poller_encode_frame(
tx_data,
tx_bits,
instance->frame_buf,
sizeof(instance->frame_buf),
&instance->frame_buf_bits);
return furi_hal_nfc_poller_tx_common(handle, instance->frame_buf, instance->frame_buf_bits);
}
static FuriHalNfcError furi_hal_nfc_iso15693_poller_rx(
FuriHalSpiBusHandle* handle,
uint8_t* rx_data,
size_t rx_data_size,
size_t* rx_bits) {
FuriHalNfcError error = FuriHalNfcErrorNone;
FuriHalNfcIso15693Poller* instance = furi_hal_nfc_iso15693_poller;
do {
error = furi_hal_nfc_common_fifo_rx(
handle, instance->fifo_buf, sizeof(instance->fifo_buf), &instance->fifo_buf_bits);
if(error != FuriHalNfcErrorNone) break;
error = iso15693_3_poller_decode_frame(
instance->fifo_buf,
instance->fifo_buf_bits,
instance->frame_buf,
sizeof(instance->frame_buf),
&instance->frame_buf_bits);
if(error != FuriHalNfcErrorNone) break;
if(rx_data_size < instance->frame_buf_bits / BITS_IN_BYTE) {
error = FuriHalNfcErrorBufferOverflow;
break;
}
memcpy(rx_data, instance->frame_buf, instance->frame_buf_bits / BITS_IN_BYTE);
*rx_bits = instance->frame_buf_bits;
} while(false);
return error;
}
static void furi_hal_nfc_iso15693_listener_transparent_mode_enter(FuriHalSpiBusHandle* handle) {
st25r3916_direct_cmd(handle, ST25R3916_CMD_TRANSPARENT_MODE);
furi_hal_spi_bus_handle_deinit(handle);
furi_hal_nfc_deinit_gpio_isr();
}
static void furi_hal_nfc_iso15693_listener_transparent_mode_exit(FuriHalSpiBusHandle* handle) {
// Configure gpio back to SPI and exit transparent mode
furi_hal_nfc_init_gpio_isr();
furi_hal_spi_bus_handle_init(handle);
st25r3916_direct_cmd(handle, ST25R3916_CMD_UNMASK_RECEIVE_DATA);
}
static FuriHalNfcError furi_hal_nfc_iso15693_listener_init(FuriHalSpiBusHandle* handle) {
furi_assert(furi_hal_nfc_iso15693_listener == NULL);
furi_hal_nfc_iso15693_listener = furi_hal_nfc_iso15693_listener_alloc();
// Set default operation mode
st25r3916_change_reg_bits(
handle,
ST25R3916_REG_MODE,
ST25R3916_REG_MODE_om_mask | ST25R3916_REG_MODE_tr_am,
ST25R3916_REG_MODE_om_targ_nfca | ST25R3916_REG_MODE_tr_am_ook);
st25r3916_change_reg_bits(
handle,
ST25R3916_REG_OP_CONTROL,
ST25R3916_REG_OP_CONTROL_rx_en,
ST25R3916_REG_OP_CONTROL_rx_en);
// Enable passive target mode
st25r3916_change_reg_bits(
handle, ST25R3916_REG_MODE, ST25R3916_REG_MODE_targ, ST25R3916_REG_MODE_targ_targ);
FuriHalNfcError error = furi_hal_nfc_iso15693_common_init(handle);
furi_hal_nfc_iso15693_listener_transparent_mode_enter(handle);
return error;
}
static FuriHalNfcError furi_hal_nfc_iso15693_listener_deinit(FuriHalSpiBusHandle* handle) {
furi_assert(furi_hal_nfc_iso15693_listener);
furi_hal_nfc_iso15693_listener_transparent_mode_exit(handle);
furi_hal_nfc_iso15693_listener_free(furi_hal_nfc_iso15693_listener);
furi_hal_nfc_iso15693_listener = NULL;
return FuriHalNfcErrorNone;
}
static FuriHalNfcError
furi_hal_nfc_iso15693_listener_tx_transparent(const uint8_t* data, size_t data_size) {
iso15693_signal_tx(
furi_hal_nfc_iso15693_listener->signal, Iso15693SignalDataRateHi, data, data_size);
return FuriHalNfcErrorNone;
}
static void furi_hal_nfc_iso15693_parser_callback(Iso15693ParserEvent event, void* context) {
furi_assert(context);
if(event == Iso15693ParserEventDataReceived) {
FuriThreadId thread_id = context;
furi_thread_flags_set(thread_id, FuriHalNfcEventInternalTypeTransparentDataReceived);
}
}
static FuriHalNfcEvent furi_hal_nfc_iso15693_wait_event(uint32_t timeout_ms) {
FuriHalNfcEvent event = 0;
FuriThreadId thread_id = furi_thread_get_current_id();
iso15693_parser_start(
furi_hal_nfc_iso15693_listener->parser, furi_hal_nfc_iso15693_parser_callback, thread_id);
while(true) {
uint32_t flag = furi_thread_flags_wait(
FuriHalNfcEventInternalTypeAbort | FuriHalNfcEventInternalTypeTransparentDataReceived,
FuriFlagWaitAny,
timeout_ms);
furi_thread_flags_clear(flag);
if(flag & FuriHalNfcEventInternalTypeAbort) {
event = FuriHalNfcEventAbortRequest;
break;
}
if(flag & FuriHalNfcEventInternalTypeTransparentDataReceived) {
if(iso15693_parser_run(furi_hal_nfc_iso15693_listener->parser)) {
event = FuriHalNfcEventRxEnd;
break;
}
}
}
iso15693_parser_stop(furi_hal_nfc_iso15693_listener->parser);
return event;
}
static FuriHalNfcError furi_hal_nfc_iso15693_listener_tx(
FuriHalSpiBusHandle* handle,
const uint8_t* tx_data,
size_t tx_bits) {
UNUSED(handle);
furi_assert(furi_hal_nfc_iso15693_listener);
FuriHalNfcError error = FuriHalNfcErrorNone;
error = furi_hal_nfc_iso15693_listener_tx_transparent(tx_data, tx_bits / BITS_IN_BYTE);
return error;
}
FuriHalNfcError furi_hal_nfc_iso15693_listener_tx_sof() {
iso15693_signal_tx_sof(furi_hal_nfc_iso15693_listener->signal, Iso15693SignalDataRateHi);
return FuriHalNfcErrorNone;
}
static FuriHalNfcError furi_hal_nfc_iso15693_listener_rx(
FuriHalSpiBusHandle* handle,
uint8_t* rx_data,
size_t rx_data_size,
size_t* rx_bits) {
furi_assert(furi_hal_nfc_iso15693_listener);
UNUSED(handle);
if(rx_data_size <
iso15693_parser_get_data_size_bytes(furi_hal_nfc_iso15693_listener->parser)) {
return FuriHalNfcErrorBufferOverflow;
}
iso15693_parser_get_data(
furi_hal_nfc_iso15693_listener->parser, rx_data, rx_data_size, rx_bits);
return FuriHalNfcErrorNone;
}
FuriHalNfcError furi_hal_nfc_iso15693_listener_sleep(FuriHalSpiBusHandle* handle) {
UNUSED(handle);
return FuriHalNfcErrorNone;
}
const FuriHalNfcTechBase furi_hal_nfc_iso15693 = {
.poller =
{
.compensation =
{
.fdt = FURI_HAL_NFC_POLLER_FDT_COMP_FC,
.fwt = FURI_HAL_NFC_ISO15693_POLLER_FWT_COMP_FC,
},
.init = furi_hal_nfc_iso15693_poller_init,
.deinit = furi_hal_nfc_iso15693_poller_deinit,
.wait_event = furi_hal_nfc_wait_event_common,
.tx = furi_hal_nfc_iso15693_poller_tx,
.rx = furi_hal_nfc_iso15693_poller_rx,
},
.listener =
{
.compensation =
{
.fdt = FURI_HAL_NFC_ISO15693_LISTENER_FDT_COMP_FC,
},
.init = furi_hal_nfc_iso15693_listener_init,
.deinit = furi_hal_nfc_iso15693_listener_deinit,
.wait_event = furi_hal_nfc_iso15693_wait_event,
.tx = furi_hal_nfc_iso15693_listener_tx,
.rx = furi_hal_nfc_iso15693_listener_rx,
.sleep = furi_hal_nfc_iso15693_listener_sleep,
.idle = furi_hal_nfc_iso15693_listener_sleep,
},
};
@@ -0,0 +1,167 @@
/**
* @file furi_hal_nfc_tech_i.h
* @brief NFC HAL technology-related private definitions.
*
* This file is an implementation detail. It must not be included in
* any public API-related headers.
*
* This file is to be changed in an unlikely event of adding support
* for a new NFC technology.
*/
#pragma once
#include <furi_hal_nfc.h>
#include <furi_hal_spi.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Configure the NFC chip for use with this technology.
*
* Used for init() and deinit() functions.
*
* @param[in,out] handle pointer to the NFC chip SPI handle.
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
typedef FuriHalNfcError (*FuriHalNfcChipConfig)(FuriHalSpiBusHandle* handle);
/**
* @brief Transmit data using technology-specific framing and timings.
*
* @param[in,out] handle pointer to the NFC chip SPI handle.
* @param[in] tx_data pointer to a byte array containing the data to be transmitted.
* @param[in] tx_bits transmit data size, in bits.
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
typedef FuriHalNfcError (
*FuriHalNfcTx)(FuriHalSpiBusHandle* handle, const uint8_t* tx_data, size_t tx_bits);
/**
* @brief Receive data using technology-specific framing and timings.
*
* @param[in,out] handle pointer to the NFC chip SPI handle.
* @param[out] rx_data pointer to a byte array to be filled with received data.
* @param[in] rx_data_size maximum received data length, in bytes.
* @param[out] rx_bits pointer to a variable to contain received data length, in bits.
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
typedef FuriHalNfcError (*FuriHalNfcRx)(
FuriHalSpiBusHandle* handle,
uint8_t* rx_data,
size_t rx_data_size,
size_t* rx_bits);
/**
* @brief Wait for an event using technology-specific method.
*
* @param[in] timeout_ms maximum time to wait, in milliseconds.
* @return bitmask of occurred events.
*/
typedef FuriHalNfcEvent (*FuriHalNfcWaitEvent)(uint32_t timeout_ms);
/**
* @brief Go to sleep in listener mode.
*
* Puts the passive target logic into Sleep (Halt) state.
*
* @param[in,out] handle pointer to the NFC chip SPI handle.
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
typedef FuriHalNfcError (*FuriHalNfcSleep)(FuriHalSpiBusHandle* handle);
/**
* @brief Go to idle in listener mode.
*
* Puts the passive target logic into Sense (Idle) state.
*
* @param[in,out] handle pointer to the NFC chip SPI handle.
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
typedef FuriHalNfcError (*FuriHalNfcIdle)(FuriHalSpiBusHandle* handle);
/**
* @brief Technology-specific compenstaion values for pollers.
*
* Timing compensations are needed due to execution delays not accounted for
* in standards, they are usually found out experimentally.
*
* The compensation value will be subtracted from the respective timer running
* time, so positive values shorten timeouts, and negative ones make them longer.
*/
typedef struct {
int32_t fdt; /**< Frame delay time compensation, in carrier cycles. */
int32_t fwt; /**< Frame wait time compensaton, in carrier cycles. */
} FuriHalNfcPollerCompensation;
/**
* @brief Abstract technology-specific poller structure.
*/
typedef struct {
FuriHalNfcPollerCompensation compensation; /**< Compensation values in poller mode. */
FuriHalNfcChipConfig init; /**< Pointer to the init() function. */
FuriHalNfcChipConfig deinit; /**< Pointer to the deinit() function. */
FuriHalNfcWaitEvent wait_event; /**< Pointer to the wait_event() function. */
FuriHalNfcTx tx; /**< Pointer to the tx() function. */
FuriHalNfcRx rx; /**< Pointer to the rx() function. */
} FuriHalNfcTechPollerBase;
/**
* @brief Technology-specific compenstaion values for listeners.
*
* Same considerations apply as with FuriHalNfcPollerCompensation.
*/
typedef struct {
int32_t fdt; /**< Frame delay time compensation, in carrier cycles. */
} FuriHalNfcListenerCompensation;
/**
* @brief Abstract technology-specific listener structure.
*
* If the listener operating mode is not supported for a particular
* technology, fill this structure with zeroes.
*/
typedef struct {
FuriHalNfcListenerCompensation compensation; /**< Compensation values in listener mode. */
FuriHalNfcChipConfig init; /**< Pointer to the init() function. */
FuriHalNfcChipConfig deinit; /**< Pointer to the deinit() function. */
FuriHalNfcWaitEvent wait_event; /**< Pointer to the wait_event() function. */
FuriHalNfcTx tx; /**< Pointer to the tx() function. */
FuriHalNfcRx rx; /**< Pointer to the rx() function. */
FuriHalNfcSleep sleep; /**< Pointer to the sleep() function. */
FuriHalNfcIdle idle; /**< Pointer to the idle() function. */
} FuriHalNfcTechListenerBase;
/**
* @brief Abstract NFC technology definition structure.
*
* Each concrete technology implementation must fill this structure
* with its proper functions and constants.
*/
typedef struct {
FuriHalNfcTechPollerBase poller; /**< Structure containing the poller definition. */
FuriHalNfcTechListenerBase listener; /**< Structure containing the listener definition. */
} FuriHalNfcTechBase;
/** @brief Technology declaration for ISO14443 (Type A). */
extern const FuriHalNfcTechBase furi_hal_nfc_iso14443a;
/** @brief Technology declaration for ISO14443 (Type B). */
extern const FuriHalNfcTechBase furi_hal_nfc_iso14443b;
/** @brief Technology declaration for ISO15693. */
extern const FuriHalNfcTechBase furi_hal_nfc_iso15693;
/** @brief Technology declaration for FeliCa. */
extern const FuriHalNfcTechBase furi_hal_nfc_felica;
/* Declare new tehcnologies here. */
/**
* @brief Array of pointers to every supported technology.
*
* This variable is defined in furi_hal_nfc.c. It will need to be modified
* in case when a new technology is to be added.
*/
extern const FuriHalNfcTechBase* furi_hal_nfc_tech[];
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,229 @@
#include "furi_hal_nfc_i.h"
#include "furi_hal_nfc_tech_i.h"
#include <stm32wbxx_ll_tim.h>
#include <furi_hal_interrupt.h>
#include <furi_hal_resources.h>
#include <furi_hal_bus.h>
#define TAG "FuriHalNfcTimer"
#define FURI_HAL_NFC_TIMER_US_IN_S (1000000UL)
/**
* To enable timer debug output on GPIO, define the FURI_HAL_NFC_TIMER_DEBUG macro
* Example: ./fbt --extra-define=FURI_HAL_NFC_TIMER_DEBUG
*/
typedef enum {
FuriHalNfcTimerFwt,
FuriHalNfcTimerBlockTx,
FuriHalNfcTimerCount,
} FuriHalNfcTimer;
typedef struct {
TIM_TypeDef* timer;
FuriHalBus bus;
uint32_t prescaler;
uint32_t freq_khz;
FuriHalNfcEventInternalType event;
FuriHalInterruptId irq_id;
IRQn_Type irq_type;
#ifdef FURI_HAL_NFC_TIMER_DEBUG
const GpioPin* pin;
#endif
} FuriHalNfcTimerConfig;
static const FuriHalNfcTimerConfig furi_hal_nfc_timers[FuriHalNfcTimerCount] = {
[FuriHalNfcTimerFwt] =
{
.timer = TIM1,
.bus = FuriHalBusTIM1,
.event = FuriHalNfcEventInternalTypeTimerFwtExpired,
.irq_id = FuriHalInterruptIdTim1UpTim16,
.irq_type = TIM1_UP_TIM16_IRQn,
#ifdef FURI_HAL_NFC_TIMER_DEBUG
.pin = &gpio_ext_pa7,
#endif
},
[FuriHalNfcTimerBlockTx] =
{
.timer = TIM17,
.bus = FuriHalBusTIM17,
.event = FuriHalNfcEventInternalTypeTimerBlockTxExpired,
.irq_id = FuriHalInterruptIdTim1TrgComTim17,
.irq_type = TIM1_TRG_COM_TIM17_IRQn,
#ifdef FURI_HAL_NFC_TIMER_DEBUG
.pin = &gpio_ext_pa6,
#endif
},
};
static void furi_hal_nfc_timer_irq_callback(void* context) {
// Returning removed const-ness
const FuriHalNfcTimerConfig* config = context;
if(LL_TIM_IsActiveFlag_UPDATE(config->timer)) {
LL_TIM_ClearFlag_UPDATE(config->timer);
furi_hal_nfc_event_set(config->event);
#ifdef FURI_HAL_NFC_TIMER_DEBUG
furi_hal_gpio_write(timer_config->pin, false);
#endif
}
}
static void furi_hal_nfc_timer_init(FuriHalNfcTimer timer) {
const FuriHalNfcTimerConfig* config = &furi_hal_nfc_timers[timer];
furi_hal_bus_enable(config->bus);
LL_TIM_SetOnePulseMode(config->timer, LL_TIM_ONEPULSEMODE_SINGLE);
LL_TIM_EnableUpdateEvent(config->timer);
LL_TIM_SetCounterMode(config->timer, LL_TIM_COUNTERMODE_UP);
LL_TIM_SetClockSource(config->timer, LL_TIM_CLOCKSOURCE_INTERNAL);
furi_hal_interrupt_set_isr(
config->irq_id,
furi_hal_nfc_timer_irq_callback,
// Warning: casting const-ness away
(FuriHalNfcTimerConfig*)config);
NVIC_SetPriority(config->irq_type, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
NVIC_EnableIRQ(config->irq_type);
#ifdef FURI_HAL_NFC_TIMER_DEBUG
furi_hal_gpio_init(config->pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
furi_hal_gpio_write(config->pin, false);
#endif
}
static void furi_hal_nfc_timer_deinit(FuriHalNfcTimer timer) {
const FuriHalNfcTimerConfig* config = &furi_hal_nfc_timers[timer];
LL_TIM_ClearFlag_UPDATE(config->timer);
furi_hal_interrupt_set_isr(config->irq_id, NULL, NULL);
NVIC_DisableIRQ(config->irq_type);
if(furi_hal_bus_is_enabled(config->bus)) {
furi_hal_bus_disable(config->bus);
}
#ifdef FURI_HAL_NFC_TIMER_DEBUG
furi_hal_gpio_init_simple(config->pin, GpioModeAnalog);
furi_hal_gpio_write(config->pin, false);
#endif
}
static int32_t furi_hal_nfc_timer_get_compensation(FuriHalNfcTimer timer) {
const FuriHalNfcTechBase* current_tech = furi_hal_nfc_tech[furi_hal_nfc.tech];
if(furi_hal_nfc.mode == FuriHalNfcModePoller) {
const FuriHalNfcPollerCompensation* comp = &current_tech->poller.compensation;
if(timer == FuriHalNfcTimerFwt)
return comp->fwt;
else if(timer == FuriHalNfcTimerBlockTx)
return comp->fdt;
} else if(furi_hal_nfc.mode == FuriHalNfcModeListener) {
const FuriHalNfcListenerCompensation* comp = &current_tech->listener.compensation;
if(timer == FuriHalNfcTimerBlockTx) return comp->fdt;
}
return 0;
}
static inline bool furi_hal_nfc_timer_is_running(FuriHalNfcTimer timer) {
return LL_TIM_IsEnabledCounter(furi_hal_nfc_timers[timer].timer) != 0;
}
static void furi_hal_nfc_timer_start_core_ticks(FuriHalNfcTimer timer, uint64_t core_ticks) {
furi_check(!furi_hal_nfc_timer_is_running(timer));
const FuriHalNfcTimerConfig* config = &furi_hal_nfc_timers[timer];
furi_check(furi_hal_bus_is_enabled(config->bus));
const uint32_t prescaler = (core_ticks - 1) / UINT16_MAX;
furi_check(prescaler <= UINT16_MAX);
const uint32_t arr_reg = core_ticks / (prescaler + 1);
furi_check(arr_reg <= UINT16_MAX);
LL_TIM_DisableIT_UPDATE(config->timer);
LL_TIM_SetPrescaler(config->timer, prescaler);
LL_TIM_SetAutoReload(config->timer, arr_reg);
LL_TIM_GenerateEvent_UPDATE(config->timer);
while(!LL_TIM_IsActiveFlag_UPDATE(config->timer))
;
LL_TIM_ClearFlag_UPDATE(config->timer);
LL_TIM_EnableIT_UPDATE(config->timer);
LL_TIM_EnableCounter(config->timer);
#ifdef FURI_HAL_NFC_TIMER_DEBUG
furi_hal_gpio_write(config->pin, true);
#endif
}
static void furi_hal_nfc_timer_start_us(FuriHalNfcTimer timer, uint32_t time_us) {
furi_hal_nfc_timer_start_core_ticks(
timer, SystemCoreClock / FURI_HAL_NFC_TIMER_US_IN_S * time_us);
}
static void furi_hal_nfc_timer_start_fc(FuriHalNfcTimer timer, uint32_t time_fc) {
const int32_t comp_fc = furi_hal_nfc_timer_get_compensation(timer);
// Not starting the timer if the compensation value is greater than the requested delay
if(comp_fc >= (int32_t)time_fc) return;
furi_hal_nfc_timer_start_core_ticks(
timer, ((uint64_t)SystemCoreClock * (time_fc - comp_fc)) / FURI_HAL_NFC_CARRIER_HZ);
}
static void furi_hal_nfc_timer_stop(FuriHalNfcTimer timer) {
const FuriHalNfcTimerConfig* config = &furi_hal_nfc_timers[timer];
LL_TIM_DisableIT_UPDATE(config->timer);
LL_TIM_DisableCounter(config->timer);
LL_TIM_SetCounter(config->timer, 0);
LL_TIM_SetAutoReload(config->timer, 0);
if(LL_TIM_IsActiveFlag_UPDATE(config->timer)) {
LL_TIM_ClearFlag_UPDATE(config->timer);
}
#ifdef FURI_HAL_NFC_TIMER_DEBUG
furi_hal_gpio_write(config->pin, false);
#endif
}
void furi_hal_nfc_timers_init() {
for(size_t i = 0; i < FuriHalNfcTimerCount; i++) {
furi_hal_nfc_timer_init(i);
}
}
void furi_hal_nfc_timers_deinit() {
for(size_t i = 0; i < FuriHalNfcTimerCount; i++) {
furi_hal_nfc_timer_deinit(i);
}
}
void furi_hal_nfc_timer_fwt_start(uint32_t time_fc) {
furi_hal_nfc_timer_start_fc(FuriHalNfcTimerFwt, time_fc);
}
void furi_hal_nfc_timer_fwt_stop() {
furi_hal_nfc_timer_stop(FuriHalNfcTimerFwt);
}
void furi_hal_nfc_timer_block_tx_start(uint32_t time_fc) {
furi_hal_nfc_timer_start_fc(FuriHalNfcTimerBlockTx, time_fc);
}
void furi_hal_nfc_timer_block_tx_start_us(uint32_t time_us) {
furi_hal_nfc_timer_start_us(FuriHalNfcTimerBlockTx, time_us);
}
void furi_hal_nfc_timer_block_tx_stop() {
furi_hal_nfc_timer_stop(FuriHalNfcTimerBlockTx);
}
bool furi_hal_nfc_timer_block_tx_is_running() {
return furi_hal_nfc_timer_is_running(FuriHalNfcTimerBlockTx);
}
+3 -2
View File
@@ -30,9 +30,9 @@
"nfc",
"digital_signal",
"pulse_reader",
"signal_reader",
"microtar",
"usb_stm32",
"st25rfal002",
"infrared",
"appframe",
"assets",
@@ -44,6 +44,7 @@
"lfrfid",
"flipper_application",
"flipperformat",
"toolbox"
"toolbox",
"flipper7"
]
}
@@ -0,0 +1,457 @@
/**
* @file furi_hal_nfc.h
* @brief NFC HAL library.
*
* This library contains functions and definitions needed for NFC hardware low-level access.
*
* Application developers should first consider using the NFC protocol stack or
* the NFC transport layer and see if the APIs provided there sufficient
* for the applicaton's intended purpose.
*
* @see nfc.h
* @see nfc_protocol.h
*
* If any of the above mentioned options is used, calling any of the functions provided by this
* library is hardly necessary, as it will be taken care of under the hood.
*
*/
#pragma once
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief NFC carrier frequency, in Hz.
*/
#define FURI_HAL_NFC_CARRIER_HZ (13560000UL)
/**
* @brief Special value indicating that waiting for an event shall never time out.
*/
#define FURI_HAL_NFC_EVENT_WAIT_FOREVER (0xFFFFFFFFU)
/**
* @brief Enumeration of possible NFC HAL events.
*/
typedef enum {
FuriHalNfcEventOscOn = (1U << 0), /**< Oscillator has been started. */
FuriHalNfcEventFieldOn = (1U << 1), /**< External field (carrier) has been detected. */
FuriHalNfcEventFieldOff = (1U << 2), /**< External field (carrier) has been lost. */
FuriHalNfcEventListenerActive = (1U << 3), /**< Reader has issued a wake-up command. */
FuriHalNfcEventTxStart = (1U << 4), /**< Transmission has started. */
FuriHalNfcEventTxEnd = (1U << 5), /**< Transmission has ended. */
FuriHalNfcEventRxStart = (1U << 6), /**< Reception has started. */
FuriHalNfcEventRxEnd = (1U << 7), /**< Reception has ended. */
FuriHalNfcEventCollision = (1U << 8), /**< A collision has occurred. */
FuriHalNfcEventTimerFwtExpired = (1U << 9), /**< Frame wait timer has expired. */
FuriHalNfcEventTimerBlockTxExpired = (1U << 10), /**< Transmission block timer has expired. */
FuriHalNfcEventTimeout =
(1U << 11), /**< No events have occurred in a specified time period. */
FuriHalNfcEventAbortRequest =
(1U << 12), /**< User has requested to abort current operation. */
} FuriHalNfcEvent;
/**
* @brief Enumeration of possible NFC HAL errors.
*/
typedef enum {
FuriHalNfcErrorNone, /**< No error has occurred. */
FuriHalNfcErrorBusy, /**< The communication bus is busy. */
FuriHalNfcErrorCommunication, /**< NFC hardware did not respond or responded unexpectedly. */
FuriHalNfcErrorOscillator, /**< Oscillator failed to start. */
FuriHalNfcErrorCommunicationTimeout, /**< NFC hardware did not respond in time. */
FuriHalNfcErrorBufferOverflow, /**< Receive buffer was too small for the received data. */
FuriHalNfcErrorIncompleteFrame, /**< Not enough data was received to parse a valid frame. */
FuriHalNfcErrorDataFormat, /**< Cannot parse a frame due to unexpected/invalid data. */
} FuriHalNfcError;
/**
* @brief Enumeration of possible NFC HAL operating modes.
*/
typedef enum {
FuriHalNfcModePoller, /**< Configure NFC HAL to operate as a poller. */
FuriHalNfcModeListener, /**< Configure NFC HAL to operate as a listener. */
FuriHalNfcModeNum, /**< Special value equal to the operating modes count. Internal use. */
} FuriHalNfcMode;
/**
* @brief Enumeration of supported NFC technologies.
*/
typedef enum {
FuriHalNfcTechIso14443a, /**< Configure NFC HAL to use the ISO14443 (type A) technology. */
FuriHalNfcTechIso14443b, /**< Configure NFC HAL to use the ISO14443 (type B) technology. */
FuriHalNfcTechIso15693, /**< Configure NFC HAL to use the ISO15693 technology. */
FuriHalNfcTechFelica, /**< Configure NFC HAL to use the FeliCa technology. */
FuriHalNfcTechNum, /**< Special value equal to the supported technologies count. Internal use. */
FuriHalNfcTechInvalid, /**< Special value indicating the unconfigured state. Internal use. */
} FuriHalNfcTech;
/**
* @brief Initialise the NFC HAL and associated hardware.
*
* This function is called automatically during the firmware initialisation,
* so there is no need to call it explicitly.
*
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
FuriHalNfcError furi_hal_nfc_init();
/**
* @brief Check whether the NFC HAL was properly initialised and is ready.
*
* @returns FuriHalNfcErrorNone if ready, any other error code if not ready.
*/
FuriHalNfcError furi_hal_nfc_is_hal_ready();
/**
* @brief Exclusively take over the NFC HAL and associated hardware.
*
* This function needs to be called whenever an interaction with the NFC HAL
* is to take place (usually once upon the application start).
*
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
FuriHalNfcError furi_hal_nfc_acquire();
/**
* @brief Release the exclusive lock and make the NFC HAL available for others.
*
* This function needs to be called when the user code is done working
* with the NFC HAL (usually once upon application exit). It must be called
* from the same thread that has called furi_hal_nfc_acquire().
*
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
FuriHalNfcError furi_hal_nfc_release();
/**
* @brief Configure the NFC hardware to enter the low-power mode.
*
* This function must be called each time when the user code is done working
* with the NFC HAL for the time being (e.g. waiting on user input).
*
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
FuriHalNfcError furi_hal_nfc_low_power_mode_start();
/**
* @brief Configure the NFC hardware to exit the low-power mode.
*
* This function must be called each time when the user code begins working
* with the NFC HAL, as the default state is low-power mode.
*
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
FuriHalNfcError furi_hal_nfc_low_power_mode_stop();
/**
* @brief Configure the NFC HAL to work in a particular mode.
*
* Not all technologies implement the listener operating mode.
*
* @param[in] mode required operating mode.
* @param[in] tech required technology configuration.
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
FuriHalNfcError furi_hal_nfc_set_mode(FuriHalNfcMode mode, FuriHalNfcTech tech);
/**
* @brief Reset the NFC HAL to its default (unconfigured) state.
*
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
FuriHalNfcError furi_hal_nfc_reset_mode();
/**
* @brief Enable field (carrier) detection by the NFC hardware.
*
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
FuriHalNfcError furi_hal_nfc_field_detect_start();
/**
* @brief Disable field (carrier) detection by the NFC hardware.
*
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
FuriHalNfcError furi_hal_nfc_field_detect_stop();
/**
* @brief Check if the reader field (carrier) was detected by the NFC hardware.
*
* @returns true if the field was detected, false otherwise.
*/
bool furi_hal_nfc_field_is_present();
/**
* @brief Enable field (carrier) generation by the NFC hardware.
*
* No carrier modulation will occur unless a transmission is explicitly started.
*
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
FuriHalNfcError furi_hal_nfc_poller_field_on();
/**
* @brief Wait for an NFC HAL event in poller mode.
*
* @param[in] timeout_ms time to wait (timeout) in milliseconds.
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
FuriHalNfcEvent furi_hal_nfc_poller_wait_event(uint32_t timeout_ms);
/**
* @brief Wait for an NFC HAL event in listener mode.
* @param[in] timeout_ms time to wait (timeout) in milliseconds.
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
FuriHalNfcEvent furi_hal_nfc_listener_wait_event(uint32_t timeout_ms);
/**
* @brief Transmit data in poller mode.
*
* @param[in] tx_data pointer to a byte array containing the data to be transmitted.
* @param[in] tx_bits transmit data size, in bits.
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
FuriHalNfcError furi_hal_nfc_poller_tx(const uint8_t* tx_data, size_t tx_bits);
/**
* @brief Receive data in poller mode.
*
* The receive buffer must be big enough to accomodate all of the expected data.
*
* @param rx_data[out] pointer to a byte array to be filled with received data.
* @param rx_data_size[in] maximum received data size, in bytes.
* @param rx_bits[out] pointer to the variable to hold received data size, in bits.
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
FuriHalNfcError furi_hal_nfc_poller_rx(uint8_t* rx_data, size_t rx_data_size, size_t* rx_bits);
/**
* @brief Transmit data in listener mode.
*
* @param[in] tx_data pointer to a byte array containing the data to be transmitted.
* @param[in] tx_bits transmit data size, in bits.
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
FuriHalNfcError furi_hal_nfc_listener_tx(const uint8_t* tx_data, size_t tx_bits);
/**
* @brief Receive data in listener mode.
*
* The receive buffer must be big enough to accomodate all of the expected data.
*
* @param rx_data[out] pointer to a byte array to be filled with received data.
* @param rx_data_size[in] maximum received data size, in bytes.
* @param rx_bits[out] pointer to the variable to hold received data size, in bits.
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
FuriHalNfcError furi_hal_nfc_listener_rx(uint8_t* rx_data, size_t rx_data_size, size_t* rx_bits);
/**
* @brief Go to sleep in listener mode.
*
* Puts the passive target logic into Sleep (Halt) state.
*
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
FuriHalNfcError furi_hal_nfc_listener_sleep();
/**
* @brief Go to idle in listener mode.
*
* Puts the passive target logic into Sense (Idle) state.
*
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
FuriHalNfcError furi_hal_nfc_listener_idle();
/**
* @brief Enable reception in listener mode.
*
* Starts hardware receivers and receive decoders.
*
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
FuriHalNfcError furi_hal_nfc_listener_enable_rx();
/**
* @brief Reset communication.
*
* Resets the communication state and stops all activities: transmission, reception, etc.
*
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
FuriHalNfcError furi_hal_nfc_trx_reset();
/**
* @brief Enable generation of NFC HAL events.
*
* @warning This function must be called from the same thread from which
* the the furi_hal_nfc_*_wait_event() calls will be made.
*
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
FuriHalNfcError furi_hal_nfc_event_start();
/**
* @brief Disable generation of NFC HAL events.
*
* Unlike furi_hal_nfc_event_start(), this function may be called from any thread.
*
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
FuriHalNfcError furi_hal_nfc_event_stop();
/**
* @brief Manually emit the FuriHalNfcEventAbortRequest event.
*
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
FuriHalNfcError furi_hal_nfc_abort();
/**
* @brief Start frame wait timeout timer.
*
* @param[in] time_fc time to wait, in carrier cycles.
*/
void furi_hal_nfc_timer_fwt_start(uint32_t time_fc);
/**
* @brief Stop frame wait timeout timer.
*/
void furi_hal_nfc_timer_fwt_stop();
/**
* @brief Start block transmit (frame delay) timer.
*
* @param[in] time_fc time to wait, in carrier cycles.
*/
void furi_hal_nfc_timer_block_tx_start(uint32_t time_fc);
/**
* @brief Start block transmit (frame delay) timer.
*
* @param[in] time_us time to wait, in microseconds.
*/
void furi_hal_nfc_timer_block_tx_start_us(uint32_t time_us);
/**
* @brief Stop block transmit (frame delay) timer.
*/
void furi_hal_nfc_timer_block_tx_stop();
/**
* @brief Check whether block transmit (frame delay) timer is running.
*
* @returns true if timer is running, false otherwise.
*/
bool furi_hal_nfc_timer_block_tx_is_running();
/*
* Technology-specific functions.
*
* In a perfect world, this would not be necessary.
* However, the current implementation employs NFC hardware that partially implements
* certain protocols (e.g. ISO14443-3A), thus requiring methods to access such features.
*/
/******************* Iso14443a specific API *******************/
/**
* @brief Enumeration of ISO14443 (Type A) short frame types.
*/
typedef enum {
FuriHalNfcaShortFrameAllReq,
FuriHalNfcaShortFrameSensReq,
} FuriHalNfcaShortFrame;
/**
* @brief Transmit ISO14443 (Type A) short frame in poller mode.
*
* @param[in] frame short frame type to be transmitted.
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
FuriHalNfcError furi_hal_nfc_iso14443a_poller_trx_short_frame(FuriHalNfcaShortFrame frame);
/** Transmit ISO14443 (Type A) SDD frame in poller mode.
*
* @param[in] tx_data pointer to a byte array containing the data to be transmitted.
* @param[in] tx_bits transmit data size, in bits.
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
FuriHalNfcError furi_hal_nfc_iso14443a_tx_sdd_frame(const uint8_t* tx_data, size_t tx_bits);
/**
* Receive ISO14443 (Type A) SDD frame in poller mode.
*
* The receive buffer must be big enough to accomodate all of the expected data.
*
* @param rx_data[out] pointer to a byte array to be filled with received data.
* @param rx_data_size[in] maximum received data size, in bytes.
* @param rx_bits[out] pointer to the variable to hold received data size, in bits.
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
FuriHalNfcError
furi_hal_nfc_iso14443a_rx_sdd_frame(uint8_t* rx_data, size_t rx_data_size, size_t* rx_bits);
/**
* @brief Transmit ISO14443 (Type A) frame with custom parity bits in poller mode.
*
* Same as furi_hal_nfc_poller_tx(), but uses the parity bits provided
* by the user code instead of calculating them automatically.
*
* @param[in] tx_data pointer to a byte array containing the data to be transmitted.
* @param[in] tx_bits transmit data size, in bits.
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
FuriHalNfcError
furi_hal_nfc_iso14443a_poller_tx_custom_parity(const uint8_t* tx_data, size_t tx_bits);
/**
* @brief Set ISO14443 (Type A) collision resolution parameters in listener mode.
*
* Configures the NFC hardware for automatic collision resolution.
*
* @param[in] uid pointer to a byte array containing the UID.
* @param[in] uid_len UID length in bytes (must be supported by the protocol).
* @param[in] atqa ATQA byte value.
* @param[in] sak SAK byte value.
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
FuriHalNfcError furi_hal_nfc_iso14443a_listener_set_col_res_data(
uint8_t* uid,
uint8_t uid_len,
uint8_t* atqa,
uint8_t sak);
/**
* @brief Transmit ISO14443 (Type A) frame with custom parity bits in listener mode.
*
* @param[in] tx_data pointer to a byte array containing the data to be transmitted.
* @param[in] tx_parity pointer to a (bit-packed) byte array containing the parity to be transmitted.
* @param[in] tx_bits transmit data size, in bits.
* @returns FuriHalNfcErrorNone on success, any other error code on failure.
*/
FuriHalNfcError furi_hal_nfc_iso14443a_listener_tx_custom_parity(
const uint8_t* tx_data,
const uint8_t* tx_parity,
size_t tx_bits);
/** Send ISO15693 SOF in listener mode
*
* @return FuriHalNfcError
*/
FuriHalNfcError furi_hal_nfc_iso15693_listener_tx_sof();
#ifdef __cplusplus
}
#endif