| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321 |
- #include "flipper_i32hex_file.h"
- #include <string.h>
- #include <storage/storage.h>
- #include <toolbox/stream/stream.h>
- #include <toolbox/stream/file_stream.h>
- #include <toolbox/hex.h>
- //https://en.wikipedia.org/wiki/Intel_HEX
- #define TAG "FlipperI32HexFile"
- #define COUNT_BYTE_PAYLOAD 32 //how much payload will be used
- #define I32HEX_TYPE_DATA 0x00
- #define I32HEX_TYPE_END_OF_FILE 0x01
- #define I32HEX_TYPE_EXT_LINEAR_ADDR 0x04
- #define I32HEX_TYPE_START_LINEAR_ADDR 0x05
- struct FlipperI32HexFile {
- uint32_t addr;
- uint32_t addr_last;
- Storage* storage;
- Stream* stream;
- FuriString* str_data;
- FlipperI32HexFileStatus file_open;
- };
- FlipperI32HexFile* flipper_i32hex_file_open_write(const char* name, uint32_t start_addr) {
- furi_assert(name);
- FlipperI32HexFile* instance = malloc(sizeof(FlipperI32HexFile));
- instance->addr = start_addr;
- instance->addr_last = 0;
- instance->storage = furi_record_open(RECORD_STORAGE);
- instance->stream = file_stream_alloc(instance->storage);
- if(file_stream_open(instance->stream, name, FSAM_WRITE, FSOM_CREATE_ALWAYS)) {
- instance->file_open = FlipperI32HexFileStatusOpenFileWrite;
- FURI_LOG_D(TAG, "Open write file %s", name);
- } else {
- FURI_LOG_E(TAG, "Failed to open file %s", name);
- instance->file_open = FlipperI32HexFileStatusErrorNoOpenFile;
- }
- instance->str_data = furi_string_alloc();
- return instance;
- }
- FlipperI32HexFile* flipper_i32hex_file_open_read(const char* name) {
- furi_assert(name);
- FlipperI32HexFile* instance = malloc(sizeof(FlipperI32HexFile));
- instance->addr = 0;
- instance->addr_last = 0;
- instance->storage = furi_record_open(RECORD_STORAGE);
- instance->stream = file_stream_alloc(instance->storage);
- if(file_stream_open(instance->stream, name, FSAM_READ, FSOM_OPEN_EXISTING)) {
- instance->file_open = FlipperI32HexFileStatusOpenFileRead;
- FURI_LOG_D(TAG, "Open read file %s", name);
- } else {
- FURI_LOG_E(TAG, "Failed to open file %s", name);
- instance->file_open = FlipperI32HexFileStatusErrorNoOpenFile;
- }
- instance->str_data = furi_string_alloc();
- return instance;
- }
- void flipper_i32hex_file_close(FlipperI32HexFile* instance) {
- furi_assert(instance);
- furi_string_free(instance->str_data);
- file_stream_close(instance->stream);
- stream_free(instance->stream);
- furi_record_close(RECORD_STORAGE);
- }
- FlipperI32HexFileRet flipper_i32hex_file_bin_to_i32hex_set_data(
- FlipperI32HexFile* instance,
- uint8_t* data,
- uint32_t data_size) {
- furi_assert(instance);
- furi_assert(data);
- FlipperI32HexFileRet ret = {.status = FlipperI32HexFileStatusOK, .data_size = 0};
- if(instance->file_open != FlipperI32HexFileStatusOpenFileWrite) {
- ret.status = FlipperI32HexFileStatusErrorFileWrite;
- }
- uint8_t count_byte = 0;
- uint32_t ind = 0;
- uint8_t crc = 0;
- furi_string_reset(instance->str_data);
- if((instance->addr_last & 0xFF0000) < (instance->addr & 0xFF0000)) {
- crc = 0x02 + 0x04 + ((instance->addr >> 24) & 0xFF) + ((instance->addr >> 16) & 0xFF);
- crc = 0x01 + ~crc;
- //I32HEX_TYPE_EXT_LINEAR_ADDR
- furi_string_cat_printf(
- instance->str_data, ":02000004%04lX%02X\r\n", (instance->addr >> 16), crc);
- instance->addr_last = instance->addr;
- }
- while(ind < data_size) {
- if((ind + COUNT_BYTE_PAYLOAD) > data_size) {
- count_byte = data_size - ind;
- } else {
- count_byte = COUNT_BYTE_PAYLOAD;
- }
- //I32HEX_TYPE_DATA
- furi_string_cat_printf(
- instance->str_data, ":%02X%04lX00", count_byte, (instance->addr & 0xFFFF));
- crc = count_byte + ((instance->addr >> 8) & 0xFF) + (instance->addr & 0xFF);
- for(uint32_t i = 0; i < count_byte; i++) {
- furi_string_cat_printf(instance->str_data, "%02X", *data);
- crc += *data++;
- }
- crc = 0x01 + ~crc;
- furi_string_cat_printf(instance->str_data, "%02X\r\n", crc);
- ind += count_byte;
- instance->addr += count_byte;
- }
- if(instance->file_open) stream_write_string(instance->stream, instance->str_data);
- return ret;
- }
- FlipperI32HexFileRet flipper_i32hex_file_bin_to_i32hex_set_end_line(FlipperI32HexFile* instance) {
- furi_assert(instance);
- FlipperI32HexFileRet ret = {.status = FlipperI32HexFileStatusOK, .data_size = 0};
- if(instance->file_open != FlipperI32HexFileStatusOpenFileWrite) {
- ret.status = FlipperI32HexFileStatusErrorFileWrite;
- }
- furi_string_reset(instance->str_data);
- //I32HEX_TYPE_END_OF_FILE
- furi_string_cat_printf(instance->str_data, ":00000001FF\r\n");
- if(instance->file_open) stream_write_string(instance->stream, instance->str_data);
- return ret;
- }
- void flipper_i32hex_file_bin_to_i32hex_set_addr(FlipperI32HexFile* instance, uint32_t addr) {
- furi_assert(instance);
- instance->addr = addr;
- }
- const char* flipper_i32hex_file_get_string(FlipperI32HexFile* instance) {
- furi_assert(instance);
- return furi_string_get_cstr(instance->str_data);
- }
- static FlipperI32HexFileRet flipper_i32hex_file_parse_line(
- FlipperI32HexFile* instance,
- const char* str,
- uint8_t* data,
- uint32_t data_size) {
- furi_assert(instance);
- furi_assert(data);
- char* str1;
- uint32_t data_wrire_ind = 0;
- uint32_t data_len = 0;
- FlipperI32HexFileRet ret = {.status = FlipperI32HexFileStatusErrorData, .data_size = 0};
- //Search for start of data I32HEX
- str1 = strstr(str, ":");
- do {
- if(str1 == NULL) {
- ret.status = FlipperI32HexFileStatusErrorData;
- break;
- }
- str1++;
- if(!hex_char_to_uint8(*str1, str1[1], data + data_wrire_ind)) {
- ret.status = FlipperI32HexFileStatusErrorData;
- break;
- }
- str1++;
- if(++data_wrire_ind > data_size) {
- ret.status = FlipperI32HexFileStatusErrorOverflow;
- break;
- }
- data_len = 5 + data[0]; // +5 bytes per header and crc
- while(data_len > data_wrire_ind) {
- str1++;
- if(!hex_char_to_uint8(*str1, str1[1], data + data_wrire_ind)) {
- ret.status = FlipperI32HexFileStatusErrorData;
- break;
- }
- str1++;
- if(++data_wrire_ind > data_size) {
- ret.status = FlipperI32HexFileStatusErrorOverflow;
- break;
- }
- }
- ret.status = FlipperI32HexFileStatusOK;
- ret.data_size = data_wrire_ind;
- } while(0);
- return ret;
- }
- static bool flipper_i32hex_file_check_data(uint8_t* data, uint32_t data_size) {
- furi_assert(data);
- uint8_t crc = 0;
- uint32_t data_read_ind = 0;
- if(data[0] > data_size) return false;
- while(data_read_ind < data_size - 1) {
- crc += data[data_read_ind++];
- }
- return data[data_size - 1] == ((1 + ~crc) & 0xFF);
- }
- static FlipperI32HexFileRet flipper_i32hex_file_parse(
- FlipperI32HexFile* instance,
- const char* str,
- uint8_t* data,
- uint32_t data_size) {
- furi_assert(instance);
- furi_assert(data);
- FlipperI32HexFileRet ret = flipper_i32hex_file_parse_line(instance, str, data, data_size);
- if((ret.status == FlipperI32HexFileStatusOK) && (ret.data_size > 4)) {
- switch(data[3]) {
- case I32HEX_TYPE_DATA:
- if(flipper_i32hex_file_check_data(data, ret.data_size)) {
- ret.data_size -= 5;
- memcpy(data, data + 4, ret.data_size);
- ret.status = FlipperI32HexFileStatusData;
- } else {
- ret.status = FlipperI32HexFileStatusErrorCrc;
- ret.data_size = 0;
- }
- break;
- case I32HEX_TYPE_END_OF_FILE:
- if(flipper_i32hex_file_check_data(data, ret.data_size)) {
- ret.status = FlipperI32HexFileStatusEofFile;
- ret.data_size = 0;
- } else {
- ret.status = FlipperI32HexFileStatusErrorCrc;
- ret.data_size = 0;
- }
- break;
- case I32HEX_TYPE_EXT_LINEAR_ADDR:
- if(flipper_i32hex_file_check_data(data, ret.data_size)) {
- data[0] = data[4];
- data[1] = data[5];
- data[3] = 0;
- data[4] = 0;
- ret.status = FlipperI32HexFileStatusUdateAddr;
- ret.data_size = 4;
- } else {
- ret.status = FlipperI32HexFileStatusErrorCrc;
- ret.data_size = 0;
- }
- break;
- case I32HEX_TYPE_START_LINEAR_ADDR:
- ret.status = FlipperI32HexFileStatusErrorUnsupportedCommand;
- ret.data_size = 0;
- break;
- default:
- ret.status = FlipperI32HexFileStatusErrorUnsupportedCommand;
- ret.data_size = 0;
- break;
- }
- } else {
- ret.status = FlipperI32HexFileStatusErrorData;
- ret.data_size = 0;
- }
- return ret;
- }
- bool flipper_i32hex_file_check(FlipperI32HexFile* instance) {
- furi_assert(instance);
- uint32_t data_size = 280;
- uint8_t data[280] = {0};
- bool ret = true;
- if(instance->file_open != FlipperI32HexFileStatusOpenFileRead) {
- FURI_LOG_E(TAG, "File is not open");
- ret = false;
- } else {
- stream_rewind(instance->stream);
- while(stream_read_line(instance->stream, instance->str_data)) {
- FlipperI32HexFileRet parse_ret = flipper_i32hex_file_parse(
- instance, furi_string_get_cstr(instance->str_data), data, data_size);
- if(parse_ret.status < 0) {
- ret = false;
- }
- }
- stream_rewind(instance->stream);
- }
- return ret;
- }
- FlipperI32HexFileRet flipper_i32hex_file_i32hex_to_bin_get_data(
- FlipperI32HexFile* instance,
- uint8_t* data,
- uint32_t data_size) {
- furi_assert(instance);
- furi_assert(data);
- FlipperI32HexFileRet ret = {.status = FlipperI32HexFileStatusOK, .data_size = 0};
- if(instance->file_open != FlipperI32HexFileStatusOpenFileRead) {
- ret.status = FlipperI32HexFileStatusErrorFileRead;
- } else {
- stream_read_line(instance->stream, instance->str_data);
- ret = flipper_i32hex_file_parse(
- instance, furi_string_get_cstr(instance->str_data), data, data_size);
- }
- return ret;
- }
|