From bd454a29fc9a81a776afd51bef0608cb9e7f2db0 Mon Sep 17 00:00:00 2001 From: penglei <1624952103@qq.com> Date: Sat, 8 Jun 2024 11:16:35 +0800 Subject: [PATCH] =?utf8?q?=E6=B7=BB=E5=8A=A0=E8=93=9D=E7=89=99=E4=BA=A7?= =?utf8?q?=E6=B5=8B=E9=BA=A6=E5=85=8B=E9=A3=8E=E6=B5=8B=E8=AF=95=E9=A1=B9?= =?utf8?q?=EF=BC=8C=E6=B7=BB=E5=8A=A0tar=E4=BF=9D=E5=AD=98exc=E6=96=87?= =?utf8?q?=E4=BB=B6=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .../brandy/brandy_standard/thread_pri_init.c | 3 + .../producttest/include/testmicrophoneC.h | 27 ++ .../producttest/include/testspeakerC.h | 16 - .../producttest/src/testmicrophone.cpp | 50 +++ .../nativeui/producttest/src/testspeak.cpp | 20 - .../factorytest_protocol.c | 19 +- .../drivers/peripheral/cywee/CMakeLists.txt | 4 +- .../cywee/src/custom_factory_core.c | 6 +- .../drivers/peripheral/cywee/src/main_dml.c | 5 +- .../drivers/peripheral/utils/CMakeLists.txt | 1 + .../drivers/peripheral/utils/custom_utils.c | 98 ++++- .../drivers/peripheral/utils/custom_utils.h | 5 + code/sdk/drivers/peripheral/utils/microtar.c | 389 ++++++++++++++++++ code/sdk/drivers/peripheral/utils/microtar.h | 90 ++++ 14 files changed, 678 insertions(+), 55 deletions(-) create mode 100644 code/sdk/application/wearable/fd230app/nativeui/producttest/include/testmicrophoneC.h delete mode 100644 code/sdk/application/wearable/fd230app/nativeui/producttest/include/testspeakerC.h create mode 100644 code/sdk/drivers/peripheral/utils/microtar.c create mode 100644 code/sdk/drivers/peripheral/utils/microtar.h diff --git a/code/sdk/application/brandy/brandy_standard/thread_pri_init.c b/code/sdk/application/brandy/brandy_standard/thread_pri_init.c index 8be0240d8..1a2375845 100755 --- a/code/sdk/application/brandy/brandy_standard/thread_pri_init.c +++ b/code/sdk/application/brandy/brandy_standard/thread_pri_init.c @@ -344,6 +344,9 @@ static void thread_main(const void *unused) { PRINT("thread_main start "NEWLINE); unused(unused); + + //reburn_second_dev(); + rc_calibration_func_notify(); bt_acore_btc_ipc_receive_init(); uapi_pm_control(PM_BT_POWER_UP_AND_RUN); diff --git a/code/sdk/application/wearable/fd230app/nativeui/producttest/include/testmicrophoneC.h b/code/sdk/application/wearable/fd230app/nativeui/producttest/include/testmicrophoneC.h new file mode 100644 index 000000000..797630689 --- /dev/null +++ b/code/sdk/application/wearable/fd230app/nativeui/producttest/include/testmicrophoneC.h @@ -0,0 +1,27 @@ +/* + * @Author: penglei 1624952103@qq.com + * @Date: 2024-06-07 11:18:25 + * @LastEditors: penglei 1624952103@qq.com + * @LastEditTime: 2024-06-07 19:57:20 + * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/producttest/include/testmicrophoneC.h + * @Description: + * + * Copyright (c) 2024 by ${git_name_email}, All Rights Reserved. + */ +#ifndef TEST_MICROPHONEC_H +#define TEST_MICROPHONEC_H + +#ifdef __cplusplus +#if __cplusplus +extern "C" +{ +#endif +#endif + void microhone_switch(bool isopen); + void check_spk(void); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif diff --git a/code/sdk/application/wearable/fd230app/nativeui/producttest/include/testspeakerC.h b/code/sdk/application/wearable/fd230app/nativeui/producttest/include/testspeakerC.h deleted file mode 100644 index c2f411c4b..000000000 --- a/code/sdk/application/wearable/fd230app/nativeui/producttest/include/testspeakerC.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef TEST_SPEAKERC_H -#define TEST_SPEAKERC_H - -#ifdef __cplusplus -#if __cplusplus -extern "C" -{ -#endif -#endif - int check_speaker(bool isopen); -#ifdef __cplusplus -#if __cplusplus -} -#endif -#endif -#endif diff --git a/code/sdk/application/wearable/fd230app/nativeui/producttest/src/testmicrophone.cpp b/code/sdk/application/wearable/fd230app/nativeui/producttest/src/testmicrophone.cpp index 27616e0de..a4659b6c4 100644 --- a/code/sdk/application/wearable/fd230app/nativeui/producttest/src/testmicrophone.cpp +++ b/code/sdk/application/wearable/fd230app/nativeui/producttest/src/testmicrophone.cpp @@ -204,4 +204,54 @@ namespace OHOS } return testmakephoneScrollView; } + + +#ifdef __cplusplus +#if __cplusplus +extern "C" +{ +#endif /* __cplusplus */ +#endif /* __cplusplus */ + + void microhone_switch(bool isopen) + { + char *args[6] = {0}; + const char *defaultArgs[6] = {"01", "mp3", "16000", "1", "16","/user/music/microphone.mp3"}; // 默认参数数组 + + int32_t argc = 1; + uint8_t *argv = (uint8_t*)"stop"; + + if(isopen) + { + for (int i = 0; i < 6; ++i) + { + args[i] = (char *)malloc(64); + sprintf(args[i], "%s", defaultArgs[i]); + } + AudioCaptureSample(6, (const char **)args); + } + else + { + AudioCaptureSample(argc, (const char **)&argv); + FILE *file =fopen("/user/music/microphone.mp3","rb"); + if(file==NULL) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ffffffffffffffffsssssss"); + } + fclose(file); + } + } + + void check_spk(void) + { + AlarmClockModel::GetInstance()->testPlayerStart("/user/music/microphone.mp3"); + } + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + + } \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230app/nativeui/producttest/src/testspeak.cpp b/code/sdk/application/wearable/fd230app/nativeui/producttest/src/testspeak.cpp index 75fa9966d..2347aa6a2 100644 --- a/code/sdk/application/wearable/fd230app/nativeui/producttest/src/testspeak.cpp +++ b/code/sdk/application/wearable/fd230app/nativeui/producttest/src/testspeak.cpp @@ -228,24 +228,4 @@ namespace OHOS } return testSPEAKScrollView; } - - #ifdef __cplusplus -#if __cplusplus -extern "C" -{ -#endif /* __cplusplus */ -#endif /* __cplusplus */ - - int check_speaker(bool isopen) - { - if(isopen) - return AlarmClockModel::GetInstance()->AlarmPlayerStart(); - else - return AlarmClockModel::GetInstance()->AlarmPlayerStop(); - } -#ifdef __cplusplus -#if __cplusplus -} -#endif /* __cplusplus */ -#endif /* __cplusplus */ } diff --git a/code/sdk/application/wearable/service/factorytest_service/factorytest_protocol.c b/code/sdk/application/wearable/service/factorytest_service/factorytest_protocol.c index d4ced75e7..3413eb5b9 100644 --- a/code/sdk/application/wearable/service/factorytest_service/factorytest_protocol.c +++ b/code/sdk/application/wearable/service/factorytest_service/factorytest_protocol.c @@ -1466,11 +1466,10 @@ void factorytest_protocol_soft_test_decode(uint8_t submode,uint8_t testitem,uint case BLE_TEST_CMD_SOFT_TEST_SUB_MODE_SPEAKER: if(testitem == 0x01) { - uint8_t send_data= 0; - uapi_check_speaker(1); - + uapi_microhone_switch(1); + factorytest_protocol_replymsg(BLE_TEST_CMD_MODE_SOFT_TEST, BLE_TEST_CMD_SOFT_TEST_SUB_MODE_SPEAKER, 0x01, @@ -1481,13 +1480,25 @@ void factorytest_protocol_soft_test_decode(uint8_t submode,uint8_t testitem,uint uint8_t send_data = 0; - uapi_check_speaker(0);; + uapi_microhone_switch(0); factorytest_protocol_replymsg(BLE_TEST_CMD_MODE_SOFT_TEST, BLE_TEST_CMD_SOFT_TEST_SUB_MODE_SPEAKER, 0x02, &send_data, 1); + } else if(testitem == 0x03) + { + + uint8_t send_data = 0; + + uapi_check_spk(); + + factorytest_protocol_replymsg(BLE_TEST_CMD_MODE_SOFT_TEST, + BLE_TEST_CMD_SOFT_TEST_SUB_MODE_SPEAKER, + 0x03, + &send_data, + 1); } break; diff --git a/code/sdk/drivers/peripheral/cywee/CMakeLists.txt b/code/sdk/drivers/peripheral/cywee/CMakeLists.txt index 30b939966..aa4808b4b 100644 --- a/code/sdk/drivers/peripheral/cywee/CMakeLists.txt +++ b/code/sdk/drivers/peripheral/cywee/CMakeLists.txt @@ -53,7 +53,7 @@ if("SUPPORT_AT_CYWEE" IN_LIST DEFINES) find_library(LIB_PATH_CWM_LIB_DML Lib/CWM_LIB_DML_clang_riscv.a ${CMAKE_CURRENT_SOURCE_DIR}) find_library(LIB_PATH_CWM_LIB Lib/CWM_LIB_clang_riscv.a ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(${TARGET_NAME} PRIVATE -Wl,--whole-archive ${LIB_PATH_CWM_LIB_DML} ${LIB_PATH_CWM_LIB} PRIVATE -Wl,--whole-archive) -endif() #target_link_libraries(${TARGET_NAME} PRIVATE -Wl,--whole-archive ${LIB_PATH_CWM_LIB} PRIVATE -Wl,--whole-archive) -#endif() +endif() + build_component() diff --git a/code/sdk/drivers/peripheral/cywee/src/custom_factory_core.c b/code/sdk/drivers/peripheral/cywee/src/custom_factory_core.c index 5107e1e16..915139a0d 100644 --- a/code/sdk/drivers/peripheral/cywee/src/custom_factory_core.c +++ b/code/sdk/drivers/peripheral/cywee/src/custom_factory_core.c @@ -78,11 +78,9 @@ int reburn_second_dev(void) { int len = 0, ret = 0; impl_prepare(&m_var); + printf("[reburn_second_dev] Built at %s %s\n", __DATE__, __TIME__); - reburn_log_printf("[reburn_second_dev] Built at %s %s\n", __DATE__, __TIME__); - printf("[reburn_second_dev] Built at \r\n"); if (!impl_checkMcuModel()) { - reburn_log_printf("cannot reburn: wrong model\n"); printf("cannot reburn: wrong model \r\n"); return STS_ERR_WRONG_MODEL; } @@ -91,11 +89,9 @@ int reburn_second_dev(void) { scl.iData[0] = 1; CWM_SettingControl(SCL_GET_LIB_INFO, &scl); if (scl.iData[5] < 3000) { - reburn_log_printf("%d Not a valid reburn library\n", scl.iData[5]); printf("%d Not a valid reburn library\n", scl.iData[5]); return STS_ERR_INVALID_LIB; } - reburn_log_printf("model:%s version:%d.%d.%d.%d product:%d\n", m_var.chip_name, scl.iData[1], scl.iData[2], scl.iData[3], scl.iData[4], scl.iData[5]); printf("model:%s version:%d.%d.%d.%d product:%d\n", m_var.chip_name, scl.iData[1], scl.iData[2], scl.iData[3], scl.iData[4], scl.iData[5]); impl_sec_env_init(); diff --git a/code/sdk/drivers/peripheral/cywee/src/main_dml.c b/code/sdk/drivers/peripheral/cywee/src/main_dml.c index 75961a90b..f6b61b235 100644 --- a/code/sdk/drivers/peripheral/cywee/src/main_dml.c +++ b/code/sdk/drivers/peripheral/cywee/src/main_dml.c @@ -704,9 +704,6 @@ void CWM_AP_dmlSensorDataOutput_listen(const dml_sensorData_t * pSdo) { } #endif -// int cm__hs1__init(void); -// int cm__hs1__deinit(void); - int cywee_main_dml(void) { if (cywee_installized == 1) @@ -716,7 +713,7 @@ int cywee_main_dml(void) } cywee_installized = 1; - //reburn_second_dev(); + int i; memset(&scl, 0, sizeof(scl)); scl.iData[0] = 1; diff --git a/code/sdk/drivers/peripheral/utils/CMakeLists.txt b/code/sdk/drivers/peripheral/utils/CMakeLists.txt index 460858452..1977a4e0f 100644 --- a/code/sdk/drivers/peripheral/utils/CMakeLists.txt +++ b/code/sdk/drivers/peripheral/utils/CMakeLists.txt @@ -10,6 +10,7 @@ set(SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/custom_cmd_service.c ${CMAKE_CURRENT_SOURCE_DIR}/custom_runtime.c ${CMAKE_CURRENT_SOURCE_DIR}/pdu.c + ${CMAKE_CURRENT_SOURCE_DIR}/microtar.c ) set(PUBLIC_HEADER diff --git a/code/sdk/drivers/peripheral/utils/custom_utils.c b/code/sdk/drivers/peripheral/utils/custom_utils.c index 268885743..a3a32f7c8 100644 --- a/code/sdk/drivers/peripheral/utils/custom_utils.c +++ b/code/sdk/drivers/peripheral/utils/custom_utils.c @@ -27,7 +27,7 @@ #ifdef FD230 #include "soundandvibration/include/SoundAndVibrationVolumeSettingC.h" #include "networkandcall/include/NetworkAndCallC.h" -#include "producttest/include/testspeakerC.h" +#include "producttest/include/testmicrophoneC.h" #endif #include #include @@ -47,6 +47,7 @@ #include "custom_utils.h" #include "cywee_service.h" +#include "microtar.h" errcode_t uapi_create_osThread_custom(app_task_definition_t *task_cfg) { @@ -293,10 +294,16 @@ bool stop_alipay_ble_service(void) } void startup_post_init_task(void) { - PRINT("startup_post_init_task !\r\n"); + //reburn_second_dev(); uapi_calendar_recover_date(); + int ret = uapi_save_exc(); + if(ret != 0) + PRINT("exc file save failed \r\n"); + else + PRINT("exc file save succed \r\n"); + if(!custom_ble_service_on_flag()) { stop_custom_ble_service(); @@ -1568,6 +1575,82 @@ void uapi_delete_files(void) } } +int uapi_save_exc(void) +{ + const char *folderPath = "/user/exc"; + const char *tarPath = "/user/tar/exc_%d.tar"; + + DIR *dir; + struct dirent *entry; + + mtar_t tar; + + char buffer[1024]; + + size_t bytesRead = 0; + FILE *fp; + int ret = 0; + + uint32_t timestamp = get_local_timestamp(); + char *str = (char *)malloc(200); + memset_s(str, 200, 0, 200); + sprintf(str, tarPath, timestamp); + + ret = mtar_open(&tar, str, "w"); + if (ret != MTAR_ESUCCESS) + { + PRINT("Unable to open/create %s\r\n",str); + return -1; + } + + dir = opendir(folderPath); + if (dir == NULL) + { + PRINT("Unable to open %s\r\n",folderPath); + return -1; + } + + while ((entry = readdir(dir)) != NULL) + { + if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) + { + char filePath[64]; + snprintf(filePath, sizeof(filePath), "%s/%s", filePath, entry->d_name); + + fp = fopen(filePath, "r"); + if(fp == NULL) + { + PRINT("Unable to open %s\n", filePath); + return -1; + } + + while ((bytesRead = fread(buffer, 1, sizeof(buffer), fp) > 0) ) + { + mtar_write_file_header(&tar, entry->d_name, bytesRead); + mtar_write_data(&tar, buffer, bytesRead); + + memset(buffer, 0, sizeof(buffer)); + + if (bytesRead < 1024 && !feof(fp)) + continue; + + if (feof(fp)) + { + fclose(fp); + break; + } + } + } + } + + /* Finalize -- this needs to be the last thing done before closing */ + mtar_finalize(&tar); + + /* Close archive */ + mtar_close(&tar); + closedir(dir); + return ret; +} #include "driver/calendar.h" @@ -2002,9 +2085,16 @@ int custom_exit_lpm(void) } #endif -int uapi_check_speaker(bool isopen) +void uapi_microhone_switch(bool isopen) +{ + #ifdef FD230 + microhone_switch(isopen); + #endif +} + +void uapi_check_spk(void) { #ifdef FD230 - return check_speaker(isopen); + check_spk(); #endif } \ No newline at end of file diff --git a/code/sdk/drivers/peripheral/utils/custom_utils.h b/code/sdk/drivers/peripheral/utils/custom_utils.h index 1e02923b2..2ded4d4b5 100644 --- a/code/sdk/drivers/peripheral/utils/custom_utils.h +++ b/code/sdk/drivers/peripheral/utils/custom_utils.h @@ -190,6 +190,11 @@ void uapi_cywee_set_user_info(int user_info[5]); void uapi_cywee_time_sync(void); void uapi_cywee_get_chipinfo(char *databuf,uint8_t len); void uapi_ppg_get_id(uint8_t *chip_id); + + +void uapi_microhone_switch(bool isopen); +void uapi_check_spk(void); + #include "custom_utilscpp.h" diff --git a/code/sdk/drivers/peripheral/utils/microtar.c b/code/sdk/drivers/peripheral/utils/microtar.c new file mode 100644 index 000000000..2e5bc40c9 --- /dev/null +++ b/code/sdk/drivers/peripheral/utils/microtar.c @@ -0,0 +1,389 @@ +/* + * Copyright (c) 2017 rxi + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include +#include +#include +#include + +#include "microtar.h" + +typedef struct { + char name[100]; + char mode[8]; + char owner[8]; + char group[8]; + char size[12]; + char mtime[12]; + char checksum[8]; + char type; + char linkname[100]; + char _padding[255]; +} mtar_raw_header_t; + + +static unsigned round_up(unsigned n, unsigned incr) { + return n + (incr - n % incr) % incr; +} + + +static unsigned checksum(const mtar_raw_header_t* rh) { + unsigned i; + unsigned char *p = (unsigned char*) rh; + unsigned res = 256; + for (i = 0; i < offsetof(mtar_raw_header_t, checksum); i++) + { + res += p[i]; + } + for (i = offsetof(mtar_raw_header_t, type); i < sizeof(*rh); i++) + { + res += p[i]; + } + return res; +} + + +static int tread(mtar_t *tar, void *data, unsigned size) +{ + int err = tar->read(tar, data, size); + tar->pos += size; + return err; +} + + +static int twrite(mtar_t *tar, const void *data, unsigned size) +{ + int err = tar->write(tar, data, size); + tar->pos += size; + return err; +} + + +static int write_null_bytes(mtar_t *tar, int n) +{ + int i, err; + char nul = '\0'; + for (i = 0; i < n; i++) + { + err = twrite(tar, &nul, 1); + if (err) + { + return err; + } + } + return MTAR_ESUCCESS; +} + + +static int raw_to_header(mtar_header_t *h, const mtar_raw_header_t *rh) +{ + unsigned chksum1, chksum2; + + /* If the checksum starts with a null byte we assume the record is NULL */ + if (*rh->checksum == '\0') + { + return MTAR_ENULLRECORD; + } + + /* Build and compare checksum */ + chksum1 = checksum(rh); + sscanf(rh->checksum, "%o", &chksum2); + if (chksum1 != chksum2) + { + return MTAR_EBADCHKSUM; + } + + /* Load raw header into header */ + sscanf(rh->mode, "%o", &h->mode); + sscanf(rh->owner, "%o", &h->owner); + sscanf(rh->size, "%o", &h->size); + sscanf(rh->mtime, "%o", &h->mtime); + h->type = rh->type; + strcpy(h->name, rh->name); + strcpy(h->linkname, rh->linkname); + + return MTAR_ESUCCESS; +} + + +static int header_to_raw(mtar_raw_header_t *rh, const mtar_header_t *h) +{ + unsigned chksum; + + /* Load header into raw header */ + memset(rh, 0, sizeof(*rh)); + sprintf(rh->mode, "%o", h->mode); + sprintf(rh->owner, "%o", h->owner); + sprintf(rh->size, "%o", h->size); + sprintf(rh->mtime, "%o", h->mtime); + rh->type = h->type ? h->type : MTAR_TREG; + strcpy(rh->name, h->name); + strcpy(rh->linkname, h->linkname); + + /* Calculate and write checksum */ + chksum = checksum(rh); + sprintf(rh->checksum, "%06o", chksum); + rh->checksum[7] = ' '; + + return MTAR_ESUCCESS; +} + + +const char* mtar_strerror(int err) +{ + switch (err) + { + case MTAR_ESUCCESS : return "success"; + case MTAR_EFAILURE : return "failure"; + case MTAR_EOPENFAIL : return "could not open"; + case MTAR_EREADFAIL : return "could not read"; + case MTAR_EWRITEFAIL : return "could not write"; + case MTAR_ESEEKFAIL : return "could not seek"; + case MTAR_EBADCHKSUM : return "bad checksum"; + case MTAR_ENULLRECORD : return "null record"; + case MTAR_ENOTFOUND : return "file not found"; + } + return "unknown error"; +} + + +static int file_write(mtar_t *tar, const void *data, unsigned size) { + unsigned res = fwrite(data, 1, size, tar->stream); + return (res == size) ? MTAR_ESUCCESS : MTAR_EWRITEFAIL; +} + +static int file_read(mtar_t *tar, void *data, unsigned size) { + unsigned res = fread(data, 1, size, tar->stream); + return (res == size) ? MTAR_ESUCCESS : MTAR_EREADFAIL; +} + +static int file_seek(mtar_t *tar, unsigned offset) { + int res = fseek(tar->stream, offset, SEEK_SET); + return (res == 0) ? MTAR_ESUCCESS : MTAR_ESEEKFAIL; +} + +static int file_close(mtar_t *tar) { + fclose(tar->stream); + return MTAR_ESUCCESS; +} + + +int mtar_open(mtar_t *tar, const char *filename, const char *mode) { + int err; + mtar_header_t h; + + /* Init tar struct and functions */ + memset(tar, 0, sizeof(*tar)); + tar->write = file_write; + tar->read = file_read; + tar->seek = file_seek; + tar->close = file_close; + + /* Assure mode is always binary */ + if ( strchr(mode, 'r') ) mode = "rb"; + if ( strchr(mode, 'w') ) mode = "wb"; + if ( strchr(mode, 'a') ) mode = "ab"; + /* Open file */ + tar->stream = fopen(filename, mode); + if (!tar->stream) { + return MTAR_EOPENFAIL; + } + /* Read first header to check it is valid if mode is `r` */ + if (*mode == 'r') { + err = mtar_read_header(tar, &h); + if (err != MTAR_ESUCCESS) { + mtar_close(tar); + return err; + } + } + + /* Return ok */ + return MTAR_ESUCCESS; +} + + +int mtar_close(mtar_t *tar) { + return tar->close(tar); +} + + +int mtar_seek(mtar_t *tar, unsigned pos) { + int err = tar->seek(tar, pos); + tar->pos = pos; + return err; +} + + +int mtar_rewind(mtar_t *tar) { + tar->remaining_data = 0; + tar->last_header = 0; + return mtar_seek(tar, 0); +} + + +int mtar_next(mtar_t *tar) { + int err, n; + mtar_header_t h; + /* Load header */ + err = mtar_read_header(tar, &h); + if (err) { + return err; + } + /* Seek to next record */ + n = round_up(h.size, 512) + sizeof(mtar_raw_header_t); + return mtar_seek(tar, tar->pos + n); +} + + +int mtar_find(mtar_t *tar, const char *name, mtar_header_t *h) { + int err; + mtar_header_t header; + /* Start at beginning */ + err = mtar_rewind(tar); + if (err) { + return err; + } + /* Iterate all files until we hit an error or find the file */ + while ( (err = mtar_read_header(tar, &header)) == MTAR_ESUCCESS ) { + if ( !strcmp(header.name, name) ) { + if (h) { + *h = header; + } + return MTAR_ESUCCESS; + } + mtar_next(tar); + } + /* Return error */ + if (err == MTAR_ENULLRECORD) { + err = MTAR_ENOTFOUND; + } + return err; +} + + +int mtar_read_header(mtar_t *tar, mtar_header_t *h) { + int err; + mtar_raw_header_t rh; + /* Save header position */ + tar->last_header = tar->pos; + /* Read raw header */ + err = tread(tar, &rh, sizeof(rh)); + if (err) { + return err; + } + /* Seek back to start of header */ + err = mtar_seek(tar, tar->last_header); + if (err) { + return err; + } + /* Load raw header into header struct and return */ + return raw_to_header(h, &rh); +} + + +int mtar_read_data(mtar_t *tar, void *ptr, unsigned size) { + int err; + /* If we have no remaining data then this is the first read, we get the size, + * set the remaining data and seek to the beginning of the data */ + if (tar->remaining_data == 0) { + mtar_header_t h; + /* Read header */ + err = mtar_read_header(tar, &h); + if (err) { + return err; + } + /* Seek past header and init remaining data */ + err = mtar_seek(tar, tar->pos + sizeof(mtar_raw_header_t)); + if (err) { + return err; + } + tar->remaining_data = h.size; + } + /* Read data */ + err = tread(tar, ptr, size); + if (err) { + return err; + } + tar->remaining_data -= size; + /* If there is no remaining data we've finished reading and seek back to the + * header */ + if (tar->remaining_data == 0) { + return mtar_seek(tar, tar->last_header); + } + return MTAR_ESUCCESS; +} + + +int mtar_write_header(mtar_t *tar, const mtar_header_t *h) { + mtar_raw_header_t rh; + /* Build raw header and write */ + header_to_raw(&rh, h); + tar->remaining_data = h->size; + return twrite(tar, &rh, sizeof(rh)); +} + + +int mtar_write_file_header(mtar_t *tar, const char *name, unsigned size) { + mtar_header_t h; + /* Build header */ + memset(&h, 0, sizeof(h)); + strcpy(h.name, name); + h.size = size; + h.type = MTAR_TREG; + h.mode = 0664; + /* Write header */ + return mtar_write_header(tar, &h); +} + + +int mtar_write_dir_header(mtar_t *tar, const char *name) { + mtar_header_t h; + /* Build header */ + memset(&h, 0, sizeof(h)); + strcpy(h.name, name); + h.type = MTAR_TDIR; + h.mode = 0775; + /* Write header */ + return mtar_write_header(tar, &h); +} + + +int mtar_write_data(mtar_t *tar, const void *data, unsigned size) { + int err; + /* Write data */ + err = twrite(tar, data, size); + if (err) { + return err; + } + tar->remaining_data -= size; + /* Write padding if we've written all the data for this file */ + if (tar->remaining_data == 0) { + return write_null_bytes(tar, round_up(tar->pos, 512) - tar->pos); + } + return MTAR_ESUCCESS; +} + + +int mtar_finalize(mtar_t *tar) { + /* Write two NULL records */ + return write_null_bytes(tar, sizeof(mtar_raw_header_t) * 2); +} \ No newline at end of file diff --git a/code/sdk/drivers/peripheral/utils/microtar.h b/code/sdk/drivers/peripheral/utils/microtar.h new file mode 100644 index 000000000..e6e73b462 --- /dev/null +++ b/code/sdk/drivers/peripheral/utils/microtar.h @@ -0,0 +1,90 @@ +/** + * Copyright (c) 2017 rxi + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the MIT license. See `microtar.c` for details. + */ + +#ifndef MICROTAR_H +#define MICROTAR_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include + +#define MTAR_VERSION "0.1.0" + +enum { + MTAR_ESUCCESS = 0, + MTAR_EFAILURE = -1, + MTAR_EOPENFAIL = -2, + MTAR_EREADFAIL = -3, + MTAR_EWRITEFAIL = -4, + MTAR_ESEEKFAIL = -5, + MTAR_EBADCHKSUM = -6, + MTAR_ENULLRECORD = -7, + MTAR_ENOTFOUND = -8 +}; + +enum { + MTAR_TREG = '0', + MTAR_TLNK = '1', + MTAR_TSYM = '2', + MTAR_TCHR = '3', + MTAR_TBLK = '4', + MTAR_TDIR = '5', + MTAR_TFIFO = '6' +}; + +typedef struct { + unsigned mode; + unsigned owner; + unsigned size; + unsigned mtime; + unsigned type; + char name[100]; + char linkname[100]; +} mtar_header_t; + + +typedef struct mtar_t mtar_t; + +struct mtar_t { + int (*read)(mtar_t *tar, void *data, unsigned size); + int (*write)(mtar_t *tar, const void *data, unsigned size); + int (*seek)(mtar_t *tar, unsigned pos); + int (*close)(mtar_t *tar); + void *stream; + unsigned pos; + unsigned remaining_data; + unsigned last_header; +}; + + +const char* mtar_strerror(int err); + +int mtar_open(mtar_t *tar, const char *filename, const char *mode); +int mtar_close(mtar_t *tar); + +int mtar_seek(mtar_t *tar, unsigned pos); +int mtar_rewind(mtar_t *tar); +int mtar_next(mtar_t *tar); +int mtar_find(mtar_t *tar, const char *name, mtar_header_t *h); +int mtar_read_header(mtar_t *tar, mtar_header_t *h); +int mtar_read_data(mtar_t *tar, void *ptr, unsigned size); + +int mtar_write_header(mtar_t *tar, const mtar_header_t *h); +int mtar_write_file_header(mtar_t *tar, const char *name, unsigned size); +int mtar_write_dir_header(mtar_t *tar, const char *name); +int mtar_write_data(mtar_t *tar, const void *data, unsigned size); +int mtar_finalize(mtar_t *tar); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file -- 2.17.1