From a4407ae9f1912ddc142ed139933efdda44ef9415 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 22 Dec 2019 11:19:06 +0100 Subject: [PATCH] add: saving as wave format for LF traces, thanks (@anon)\n chg: 'data save f w - reword the params to command --- client/cmddata.c | 69 ++++++++++++++++++++++++++++++++++------------ client/fileutils.c | 64 ++++++++++++++++++++++++++++++++++++++++++ client/fileutils.h | 24 ++++++++++++++++ 3 files changed, 140 insertions(+), 17 deletions(-) diff --git a/client/cmddata.c b/client/cmddata.c index cb78642b2..7af5c686e 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -1,6 +1,8 @@ //----------------------------------------------------------------------------- // Copyright (C) 2010 iZsh // +// iceman 2019 +// // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of // the license. @@ -32,6 +34,21 @@ int g_DemodClock = 0; static int CmdHelp(const char *Cmd); +static int usage_data_save(void) { + PrintAndLogEx(NORMAL, "Save trace from graph window , i.e. the GraphBuffer"); + PrintAndLogEx(NORMAL, "This is a text file with number -127 to 127. With the option `w` you can save it as wave file"); + PrintAndLogEx(NORMAL, "Filename should be without file extension"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: data save [h] [w] [f ]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " w save as wave format (.wav)"); + PrintAndLogEx(NORMAL, " f save file name"); + PrintAndLogEx(NORMAL, "Samples:"); + PrintAndLogEx(NORMAL, " data save f mytrace - save graphbuffer to file"); + PrintAndLogEx(NORMAL, " data save f mytrace w - save graphbuffer to wave file"); + return PM3_SUCCESS; +} static int usage_data_scale(void) { PrintAndLogEx(NORMAL, "Set cursor display scale."); PrintAndLogEx(NORMAL, "Setting the scale makes the differential `dt` reading between the yellow and purple markers meaningful. "); @@ -40,8 +57,8 @@ static int usage_data_scale(void) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Usage: data scale [h] "); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, " Sets scale of carrier frequency expressed in kHz"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " sets scale of carrier frequency expressed in kHz"); PrintAndLogEx(NORMAL, "Samples:"); PrintAndLogEx(NORMAL, " data scale 125 - if sampled in 125kHz"); return PM3_SUCCESS; @@ -49,7 +66,7 @@ static int usage_data_scale(void) { static int usage_data_printdemodbuf(void) { PrintAndLogEx(NORMAL, "Usage: data printdemodbuffer x o l "); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); + PrintAndLogEx(NORMAL, " h this help"); PrintAndLogEx(NORMAL, " i invert Demodbuffer before printing"); PrintAndLogEx(NORMAL, " x output in hex (omit for binary output)"); PrintAndLogEx(NORMAL, " o enter offset in # of bits"); @@ -1876,24 +1893,42 @@ int CmdSave(const char *Cmd) { int len = 0; char filename[FILE_PATH_SIZE] = {0x00}; + uint8_t cmdp = 0; + bool errors = false, as_wave = false, has_name = false; - len = strlen(Cmd); - if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; - memcpy(filename, Cmd, len); - - FILE *f = fopen(filename, "w"); - if (!f) { - PrintAndLogEx(WARNING, "couldn't open '%s'", filename); - return PM3_EFILE; + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + char ctmp = tolower(param_getchar(Cmd, cmdp)); + switch (ctmp) { + case 'h': + return usage_data_save(); + case 'f': + len = param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE); + if (len < 1) { + errors = true; + break; + } + has_name = true; + cmdp += 2; + break; + case 'w': + as_wave = true; + cmdp++; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } } - for (uint32_t i = 0; i < GraphTraceLen; i++) - fprintf(f, "%d\n", GraphBuffer[i]); + if (!has_name) errors = true; - fclose(f); + if (errors || cmdp == 0) return usage_data_save(); - PrintAndLogEx(SUCCESS, "saved to " _YELLOW_("'%s'"), Cmd); - return PM3_SUCCESS; + if ( as_wave ) + return saveFileWAVE(filename, GraphBuffer, GraphTraceLen); + else + return saveFilePM3(filename, GraphBuffer, GraphTraceLen); } static int CmdScale(const char *Cmd) { @@ -2269,7 +2304,7 @@ static command_t CommandTable[] = { {"printdemodbuffer", CmdPrintDemodBuff, AlwaysAvailable, "[x] [o] [l] -- print the data in the DemodBuffer - 'x' for hex output"}, {"rawdemod", CmdRawDemod, AlwaysAvailable, "[modulation] ... -see help (h option) -- Demodulate the data in the GraphBuffer and output binary"}, {"samples", CmdSamples, IfPm3Present, "[512 - 40000] -- Get raw samples for graph window (GraphBuffer)"}, - {"save", CmdSave, AlwaysAvailable, " -- Save trace (from graph window)"}, + {"save", CmdSave, AlwaysAvailable, "Save trace (from graph window)"}, {"setgraphmarkers", CmdSetGraphMarkers, AlwaysAvailable, "[orange_marker] [blue_marker] (in graph window)"}, {"scale", CmdScale, AlwaysAvailable, " -- Set cursor display scale in carrier frequency expressed in kHz"}, {"setdebugmode", CmdSetDebugMode, AlwaysAvailable, "<0|1|2> -- Set Debugging Level on client side"}, diff --git a/client/fileutils.c b/client/fileutils.c index 7c10fe50c..a56745148 100644 --- a/client/fileutils.c +++ b/client/fileutils.c @@ -41,6 +41,7 @@ #include #include +#include #include "pm3_cmd.h" #include "commonutil.h" @@ -399,6 +400,69 @@ out: return retval; } +int saveFileWAVE(const char *preferredName, int *data, size_t datalen) { + + if (data == NULL) return PM3_EINVARG; + char *fileName = newfilenamemcopy(preferredName, ".wav"); + if (fileName == NULL) return PM3_EMALLOC; + + int retval = PM3_SUCCESS; + + SF_INFO wave_info; + + // TODO update for other tag types + wave_info.samplerate = 125000; + wave_info.channels = 1; + wave_info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_U8; + SNDFILE* wave_file = sf_open(fileName, SFM_WRITE, &wave_info); + + if (!wave_file) { + PrintAndLogEx(WARNING, "file not found or locked. "_YELLOW_("'%s'"), fileName); + retval = PM3_EFILE; + goto out; + } + + // unfortunately need to upconvert to 16-bit samples because libsndfile doesn't do 8-bit(?) + for (int i = 0; i < datalen; i++) { + short sample = data[i] * 256; + sf_write_short(wave_file, &sample, 1); + } + + sf_close(wave_file); + PrintAndLogEx(SUCCESS, "saved " _YELLOW_("%d")" bytes to wave file " _YELLOW_("'%s'"), 2 * datalen, fileName); + +out: + free(fileName); + return retval; +} + +int saveFilePM3(const char *preferredName, int *data, size_t datalen) { + + if (data == NULL) return PM3_EINVARG; + char *fileName = newfilenamemcopy(preferredName, ".pm3"); + if (fileName == NULL) return PM3_EMALLOC; + + int retval = PM3_SUCCESS; + + FILE *f = fopen(fileName, "w"); + if (!f) { + PrintAndLogEx(WARNING, "file not found or locked. "_YELLOW_("'%s'"), fileName); + retval = PM3_EFILE; + goto out; + } + + for (uint32_t i = 0; i < datalen; i++) + fprintf(f, "%d\n", data[i]); + + fflush(f); + fclose(f); + PrintAndLogEx(SUCCESS, "saved " _YELLOW_("%d")" bytes to PM3 file " _YELLOW_("'%s'"), datalen, fileName); + +out: + free(fileName); + return retval; +} + int createMfcKeyDump(uint8_t sectorsCnt, sector_t *e_sector, char *fptr) { uint8_t tmpKey[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; int i; diff --git a/client/fileutils.h b/client/fileutils.h index 523e957a7..baff10bca 100644 --- a/client/fileutils.h +++ b/client/fileutils.h @@ -112,6 +112,30 @@ int saveFileEML(const char *preferredName, uint8_t *data, size_t datalen, size_t */ int saveFileJSON(const char *preferredName, JSONFileType ftype, uint8_t *data, size_t datalen); +/** STUB + * @brief Utility function to save WAVE data to a file. This method takes a preferred name, but if that + * file already exists, it tries with another name until it finds something suitable. + * E.g. dumpdata-15.wav + * + * @param preferredName + * @param data The binary data to write to the file + * @param datalen the length of the data + * @return 0 for ok + */ +int saveFileWAVE(const char *preferredName, int *data, size_t datalen); + +/** STUB + * @brief Utility function to save PM3 data to a file. This method takes a preferred name, but if that + * file already exists, it tries with another name until it finds something suitable. + * E.g. dump_trace.pm3 + * + * @param preferredName + * @param data The binary data to write to the file + * @param datalen the length of the data + * @return 0 for ok + */ +int saveFilePM3(const char *preferredName, int *data, size_t datalen); + /** * @brief Utility function to save a keydump. *