diff --git a/.gitignore b/.gitignore index d7a1ba1..a998bf7 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,7 @@ cargo.lock *.a2h *.bin /tmp.a2l +/a2lfile.a2l +/a2lfile.txt +/test.a2l +/xcp_lite.a2l diff --git a/tests/multi_thread.rs b/tests/multi_thread.rs index 1809669..adc438f 100644 --- a/tests/multi_thread.rs +++ b/tests/multi_thread.rs @@ -212,7 +212,7 @@ async fn test_multi_thread() { } thread::sleep(Duration::from_millis(250)); // Wait to give all threads a chance to initialize and enter their loop - test_executor(xcp, test_executor::TestMode::MultiThreadDAQ, "test_multi_thread.a2l", false).await; // Start the test executor XCP client + test_executor(xcp, test_executor::TestMode::MultiThreadDAQ, "test_multi_thread.a2l", true).await; // Start the test executor XCP client info!("Test done. Waiting for tasks to terminate"); for t in v { diff --git a/tests/tokio_multi_thread.rs b/tests/tokio_multi_thread.rs index 0a9b017..820befe 100644 --- a/tests/tokio_multi_thread.rs +++ b/tests/tokio_multi_thread.rs @@ -185,7 +185,7 @@ async fn test_tokio_multi_thread() { v.push(t); } - test_executor(xcp, test_executor::TestMode::MultiThreadDAQ, "test_tokio_multi_thread.a2l", false).await; // Start the test executor XCP client + test_executor(xcp, test_executor::TestMode::MultiThreadDAQ, "test_tokio_multi_thread.a2l", true).await; // Start the test executor XCP client for t in v { t.join().ok(); diff --git a/xcplib/xcpAppl.c b/xcplib/xcpAppl.c index 3ac2c04..40b5734 100644 --- a/xcplib/xcpAppl.c +++ b/xcplib/xcpAppl.c @@ -386,15 +386,12 @@ uint8_t ApplXcpGetCalPageMode(uint8_t segment) { #endif /**************************************************************************/ -// Provide infos for GET_ID -// The XCP command GET_ID provides different type of identification -// information to the XCP client -// Returns 0, when the information is not available +// Functions for upload of A2L file /**************************************************************************/ -static const char *gXcpA2lName = NULL; // A2L filename +static const char *gXcpA2lName = NULL; // A2L filename (without extension .a2l) -// This is used by the Rust ffi bindings only +// This is used by the Rust ffi to set the A2L name generated by the registry void ApplXcpSetA2lName(const char *name) { DBG_PRINTF3("Set A2L name to '%s'\n", name); gXcpA2lName = (char*)name; // must be static lifetime @@ -402,83 +399,50 @@ void ApplXcpSetA2lName(const char *name) { #ifdef XCP_ENABLE_IDT_A2L_UPLOAD // Enable GET_ID A2L content upload to host -static uint8_t* gXcpFile = NULL; // A2l file content +static FILE* gXcpFile = NULL; // A2l file content static uint32_t gXcpFileLength = 0; // A2L file length -BOOL ApplXcpReadA2L(uint8_t size, uint32_t addr, uint8_t* data) { - if (addr + size > gXcpFileLength) return FALSE; - memcpy(data, gXcpFile + addr, size); - return TRUE; -} - -// @@@@ ToDo: Implement a way to release the file memory after upload -/* -static void releaseFile(uint8_t* file) { - if (file != NULL) { - free(file); - } +void closeA2lFile() { + assert(gXcpFile != NULL); + fclose(gXcpFile); + gXcpFile = NULL; + DBG_PRINT3("Close A2L file\n"); } -*/ - -static uint8_t* loadFile(const char* filename, uint32_t* length) { - - uint8_t* fileBuf = NULL; // file content - uint32_t fileLen = 0; // file length - - DBG_PRINTF3("Load A2L file %s to memory buffer\n", filename); - -#if defined(_LINUX) // Linux - - FILE* fd; - fd = fopen(filename, "r"); - if (fd == NULL) { - DBG_PRINTF_ERROR("ERROR: file %s not found!\n", filename); - return NULL; - } - struct stat fdstat; - stat(filename, &fdstat); - fileBuf = (uint8_t*)malloc((size_t)(fdstat.st_size + 1)); - if (fileBuf == NULL) return NULL; - fileLen = (uint32_t)fread(fileBuf, 1, (uint32_t)fdstat.st_size, fd); - fclose(fd); - -#elif defined(_WIN) // Windows - - wchar_t wcfilename[256] = { 0 }; - MultiByteToWideChar(0, 0, filename, (int)strlen(filename), wcfilename, (int)strlen(filename)); - HANDLE hFile = CreateFileW((wchar_t*)wcfilename, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (hFile == INVALID_HANDLE_VALUE) { - DBG_PRINTF_ERROR("ERROR: file %s not found!\n", filename); - return NULL; - } - fileLen = (uint32_t)GetFileSize(hFile, NULL); - fileBuf = (uint8_t*)malloc(fileLen + 1); - if (fileBuf == NULL) { - DBG_PRINTF_ERROR("ERROR: out of memory!\n"); - CloseHandle(hFile); - return NULL; - } - if (!ReadFile(hFile, fileBuf, fileLen, NULL, NULL)) { - DBG_PRINTF_ERROR("ERROR: could not read from %s!\n", filename); - free(fileBuf); - CloseHandle(hFile); - return NULL; - } - fileBuf[fileLen] = 0; - CloseHandle(hFile); - -#endif - DBG_PRINTF3(" file %s ready for upload, size=%u\n\n", filename, fileLen); - assert(fileLen > 0); +uint32_t openA2lFile() { + char filename[256]; + SNPRINTF((char*)filename, 255, "%s.a2l", gXcpA2lName); + assert(gXcpFile == NULL); + gXcpFile = fopen(filename, "r"); + if (gXcpFile == NULL) { + DBG_PRINTF_ERROR("ERROR: file %s not found!\n", filename); + return 0; + } + struct stat fdstat; + stat(filename, &fdstat); + gXcpFileLength = (uint32_t)fdstat.st_size; + assert(gXcpFileLength > 0); + DBG_PRINTF3("A2L file %s ready for upload, size=%u\n\n", filename, gXcpFileLength); + return gXcpFileLength; +} - *length = fileLen; - return fileBuf; +BOOL ApplXcpReadA2L(uint8_t size, uint32_t addr, uint8_t* data) { + if (gXcpFile == NULL) return FALSE; + if (addr + size > gXcpFileLength) return FALSE; + if (size!=fread(data, 1, (uint32_t)size, gXcpFile)) return FALSE; + if (addr + size == gXcpFileLength) closeA2lFile(); // Close file after complete sequential read + return TRUE; } -#endif +#endif // XCP_ENABLE_IDT_A2L_UPLOAD +/**************************************************************************/ +// Provide infos for GET_ID +// The XCP command GET_ID provides different type of identification +// information to the XCP client +// Returns 0, when the information is not available +/**************************************************************************/ uint32_t ApplXcpGetId(uint8_t id, uint8_t* buf, uint32_t bufLen) { @@ -511,10 +475,14 @@ uint32_t ApplXcpGetId(uint8_t id, uint8_t* buf, uint32_t bufLen) { #ifdef XCP_ENABLE_IDT_A2L_UPLOAD case IDT_ASAM_UPLOAD: { + #ifdef XCP_LOAD_A2L_FILE char filename[256]; SNPRINTF((char*)filename, 255, "%s.a2l", gXcpA2lName); if (NULL==(gXcpFile=loadFile(filename,&gXcpFileLength))) return 0; len = gXcpFileLength; + #else + len = openA2lFile(); + #endif } break; #endif