Skip to content
Snippets Groups Projects
Select Git revision
  • 61d7d4049438adb626e218a1e5f726cb984eb432
  • master default protected
  • cmp_tool-improvement
  • v0.15
  • v0.14
  • v0.13
  • v0.12
  • v0.11
  • v0.09
  • v0.08
  • v0.07
  • v0.06
  • v0.05
13 results

rdcu_pkt_to_file.c

Blame
  • rdcu_pkt_to_file.c 10.70 KiB
    /**
     * @file   rdcu_pkt_to_file.c
     * @author Dominik Loidolt (dominik.loidolt@univie.ac.at),
     * @date   2020
     *
     * @copyright GPLv2
     * This program is free software; you can redistribute it and/or modify it
     * under the terms and conditions of the GNU General Public License,
     * version 2, as published by the Free Software Foundation.
     *
     * This program is distributed in the hope it will be useful, but WITHOUT
     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     * more details.
     *
     * @brief RDCU packets to file library
     *
     * This library provided a rmap_rx and rmap_tx function for the rdcu_rmap
     * library to write generated packets into text files.
     *
     */
    
    #include <stdint.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <limits.h>
    #include <errno.h>
    #include <sys/stat.h>
    
    #include "../include/rdcu_pkt_to_file.h"
    #include "../include/cmp_rdcu_extended.h"
    #include "../include/rdcu_rmap.h"
    #include "../include/rdcu_ctrl.h"
    #include "../include/rdcu_cmd.h"
    
    /* Name of directory were the RMAP packages are stored */
    static char tc_folder_dir[MAX_TC_FOLDER_DIR_LEN] = "TC_FILES";
    
    
    /**
     * @brief set the directory name were the RMAP packages are stored
     *
     * @param dir_name	Name of directory were the RMAP packages are stored
     */
    
    void set_tc_folder_dir(const char *dir_name)
    {
    	if (!dir_name)
    		return;
    
    	strncpy(tc_folder_dir, dir_name, sizeof(tc_folder_dir));
    	/*  Ensure null-termination. */
    	tc_folder_dir[sizeof(tc_folder_dir) - 1] = '\0';
    	return;
    }
    
    
    /**
     * @brief return a file to write with the name format dir_name/XXX.tc, where XXX
     *	is n_tc in decimal representation
     *
     * @param dir_name	name of directory were the RMAP packages are stored
     * @param n_tc		number of TC commands
     *
     * @return	pointer to the new file stream
     * @see https://developers.redhat.com/blog/2018/05/24/detecting-string-truncation-with-gcc-8/
     */
    
    static FILE *open_file(const char *dir_name, int n_tc)
    {
    	char *pathname;
    	FILE *fp;
    	int n;
    
    	errno = 0;
    	n = snprintf(NULL, 0, "%s/%04d.tc", dir_name, n_tc);
    	if (n < 0) {
    		perror("snprintf failed");
    		abort();
    	}
    
    	errno = 0;
    	pathname = (char *)malloc((size_t)n + 1);
    	if (!pathname) {
    		perror("malloc failed");
    		abort();
    	}
    
    	errno = 0;
    	n = snprintf(pathname, (size_t)n + 1, "%s/%04d.tc", dir_name, n_tc);
    	if (n < 0) {
    		perror("snprintf failed");
    		abort();
    	}
    
    	fp = fopen(pathname, "w");
    	free(pathname);
    	return fp;
    }
    
    
    /**
     * @brief Implementation of the rmap_rx function for the rdcu_rmap lib. All
     *	generated packages are write to a file.
     */
    
    static int32_t rmap_tx_to_file(const void *hdr, uint32_t hdr_size,
    			       const uint8_t non_crc_bytes, const void *data,
    			       uint32_t data_size)
    {
    	static int n_pkt = 1; /* number of packets */
    	static char tc_folder_dir_old[MAX_TC_FOLDER_DIR_LEN] = {0};
    	uint8_t *blob = NULL;
    	int n, i;
    	FILE *fp;
    
    	if (hdr == NULL)
    		return 0;
    
    	/* make sure that string is null-terminated */
    	tc_folder_dir[MAX_TC_FOLDER_DIR_LEN - 1] = '\0';
    
    	if (strcmp(tc_folder_dir, tc_folder_dir_old) != 0) {
    		struct stat st = { 0 };
    
    		n_pkt = 1;
    
    		/* creating a directory if that directory does not exist */
    		if (stat(tc_folder_dir, &st) == -1) {
    			int err;
    			#if defined(_WIN32) || defined(_WIN64)
    				err = mkdir(tc_folder_dir);
    			#else
    				err = mkdir(tc_folder_dir, 0700);
    			#endif
    			if (err)
    				return -1;
    		}
    
    		strncpy(tc_folder_dir_old, tc_folder_dir,
    			sizeof(tc_folder_dir_old));
    		tc_folder_dir_old[sizeof(tc_folder_dir_old) - 1] = '\0';
    	}
    
    	n = rdcu_package(NULL, hdr, hdr_size, non_crc_bytes, data, data_size);
    	if (n <= 0)
    		return -1;
    	blob = malloc(n);
    	if (!blob) {
    		printf("malloc for tx_pkt faild\n");
    		return -1;
    	}
    
    	n = rdcu_package(blob, hdr, hdr_size, non_crc_bytes, data, data_size);
    	if (n <= 0) {
    		free(blob);
    		return -1;
    	}
    
    	fp = open_file(tc_folder_dir, n_pkt);
    
    	if (fp == NULL) {
    		perror("fopen()");
    		free(blob);
    		return -1;
    	}
    
    	for (i = 0; i < n; i++) {
    		/* printf("%02X ", blob[i]); */
    		fprintf(fp, "%02X ", blob[i]);
    		/* if (i && !((i + 1) % 40)) */
    		/* printf("\n"); */
    	}
    
    	/* printf("\n"); */
    	fprintf(fp, "\n");
    	fclose(fp);
    
    	free(blob);
    
    	n_pkt++;
    	return 0;
    }
    
    
    /**
     * @brief Dummy implementation of the rmap_rx function for the rdcu_rmap lib. We
     * do not want to receive any packages.
     */
    
    static uint32_t rmap_rx_dummy(uint8_t *pkt)
    {
    	(void)(pkt);
    	return 0;
    }
    
    
    /**
     * @brief read out .rdcu_pkt_mode_cfg configure file
     *
     * @param icu_addr	RMAP source logical address
     * @param rdcu_addr	RMAP destination logical address
     * @param mtu		the maximum data transfer size per unit
     *
     * @returns 0 on success, otherwise error
     */
    
    static int read_rdcu_pkt_mode_cfg(uint8_t *icu_addr, uint8_t *rdcu_addr,
    				  int *mtu)
    {
    	/* TODO: Build string" %s/.rdcu_pkt_mode_cfg", RDCU_PKT_MODE_DIR */
    	char line[256];
    	char *end;
    	unsigned int read_all = 0;
    	FILE *fp = fopen(".rdcu_pkt_mode_cfg", "r");
    
    	*icu_addr = 0;
    	*rdcu_addr = 0;
    	*mtu = 0;
    
    	if (fp == NULL) {
    		perror("fopen()");
    		return -1;
    	}
    
    	while (fgets(line, sizeof(line), fp)) {
    		size_t l;
    		long i;
    		char *p;
    
    		p = strchr(line, '\n');
    		if (p) {
    			*p = '\0';
    		} else {
    			fprintf(stderr, "Error read in line to long.\n");
    			fclose(fp);
    			return -1;
    		}
    
    		if (line[0] == ' ' || line[0] == '\t' || line[0] == '#')
    			continue;
    		if (!strncmp(line, "ICU_ADDR", l = strlen("ICU_ADDR"))) {
    			end = NULL;
    			errno = 0;
    			i = strtol(line + l, &end, 0);
    			if (end == line + l || errno == ERANGE || i < 0 ||
    			    i > 0xFF) {
    				fprintf(stderr, "Error reading ICU_ADDR.\n");
    				errno = 0;
    				fclose(fp);
    				return -1;
    			}
    			*icu_addr = (uint8_t)i;
    			read_all |= 1UL << 0;
    			continue;
    		}
    		if (!strncmp(line, "RDCU_ADDR", l = strlen("RDCU_ADDR"))) {
    			end = NULL;
    			errno = 0;
    			i = strtol(line + l, &end, 0);
    			if (end == line + l || errno == ERANGE || i < 0
    			    || i > 0xFF) {
    				fprintf(stderr, "Error reading RDCU_ADDR.\n");
    				errno = 0;
    				fclose(fp);
    				return -1;
    			}
    			*rdcu_addr = (uint8_t)i;
    			read_all |= 1UL << 1;
    			continue;
    		}
    		if (!strncmp(line, "MTU", l = strlen("MTU"))) {
    			end = NULL;
    			errno = 0;
    			i = strtol(line + l, &end, 0);
    			if (end == line + l || errno == ERANGE || i < 0 ||
    			    i > INT_MAX) {
    				fprintf(stderr, "Error reading MTU.\n");
    				errno = 0;
    				fclose(fp);
    				return -1;
    			}
    			*mtu = (int)i;
    			read_all |= 1UL << 2;
    			continue;
    		}
    	}
    	fclose(fp);
    
    	/* all keywords read? */
    	if (read_all < 0x7)
    		return -1;
    
    	printf("Use ICU_ADDR = %#02X, RDCU_ADDR = %#02X and MTU = %d for the "
    	       "RAMP packets.\n", *icu_addr, *rdcu_addr, *mtu);
    
    	return 0;
    }
    
    
    /**
     * @brief initialise the RDCU packets to file library
     *
     * @note use the .rdcu_pkt_mode_cfg file to read the icu_addr, rdcu_addr and mtu
     *	parameters
     *
     * @returns 0 on success, otherwise error
     */
    
    int init_rmap_pkt_to_file(void)
    {
    	uint8_t icu_addr, rdcu_addr;
    	int mtu;
    
    	if (read_rdcu_pkt_mode_cfg(&icu_addr, &rdcu_addr, &mtu))
    		return -1;
    	rdcu_ctrl_init();
    	rdcu_set_source_logical_address(icu_addr);
    	rdcu_set_destination_logical_address(rdcu_addr);
    	rdcu_set_destination_key(RDCU_DEST_KEY);
    	rdcu_rmap_init(mtu, rmap_tx_to_file, rmap_rx_dummy);
    	return 0;
    }
    
    
    /**
     * @brief generate the rmap packets to set up a RDCU compression
     * @note note that the initialization function init_rmap_pkt_to_file() must be
     *	executed before
     * @note the configuration of the ICU_ADDR, RDCU_ADDR, MTU settings are in the
     *	.rdcu_pkt_mode_cfg file
     *
     * @param cfg	compressor configuration contains all parameters required for
     *		compression
     *
     * @returns 0 on success, error otherwise
     */
    
    int gen_write_rdcu_pkts(const struct cmp_cfg *cfg)
    {
    	struct stat st = { 0 };
    
    	if (!cfg)
    		return -1;
    
    	/* creating TC_DIR directory if that directory does not exist */
    	if (stat(TC_DIR, &st) == -1) {
    		int err;
    		#if defined(_WIN32) || defined(_WIN64)
    			err = mkdir(TC_DIR);
    		#else
    			err = mkdir(TC_DIR, 0700);
    		#endif
    		if (err)
    			return -1;
    	}
    
    	set_tc_folder_dir(TC_DIR "/compress_data");
    	if (rdcu_compress_data(cfg))
    		return -1;
    
    	return 0;
    }
    
    
    /**
     * @brief generate the rmap packets to read the result of a RDCU compression
     * @note note that the initialization function init_rmap_pkt_to_file() must be
     *	executed before
     * @note the configuration of the ICU_ADDR, RDCU_ADDR, MTU settings are in the
     *	.rdcu_pkt_mode_cfg file
     *
     * @param info	 compressor information contains information of an executed
     *		 compression
     *
     * @returns 0 on success, error otherwise
     */
    
    int gen_read_rdcu_pkts(const struct cmp_info *info)
    {
    	int s;
    	void *tmp_buf;
    	struct stat st = { 0 };
    
    	if (!info)
    		return -1;
    
    	/* creating TC_DIR directory if that directory does not exist */
    	if (stat(TC_DIR, &st) == -1) {
    		int err;
    		#if defined(_WIN32) || defined(_WIN64)
    			err = mkdir(TC_DIR);
    		#else
    			err = mkdir(TC_DIR, 0700);
    		#endif
    		if (err)
    			return -1;
    	}
    
    	set_tc_folder_dir(TC_DIR "/read_status");
    	if (rdcu_read_cmp_status(NULL))
    		return -1;
    
    	set_tc_folder_dir(TC_DIR "/read_info");
    	if (rdcu_read_cmp_info(NULL))
    		return -1;
    
    	set_tc_folder_dir(TC_DIR "/read_cmp_data");
    	s = rdcu_read_cmp_bitstream(info, NULL);
    	if (s < 0)
    		return -1;
    	tmp_buf = malloc((size_t)s);
    	if (!tmp_buf)
    		return -1;
    	s = rdcu_read_cmp_bitstream(info, tmp_buf);
    	free(tmp_buf);
    	if (s < 0)
    		return -1;
    
    	if (model_mode_is_used(info->cmp_mode_used)) {
    		set_tc_folder_dir(TC_DIR "/read_upmodel");
    		s = rdcu_read_model(info, NULL);
    		if (s < 0)
    			return -1;
    		tmp_buf = malloc((size_t)s);
    		if (!tmp_buf)
    			return -1;
    		s = rdcu_read_model(info, tmp_buf);
    		free(tmp_buf);
    		if (s < 0)
    			return -1;
    	}
    	return 0;
    }
    
    
    /**
     * @brief generate the rmap packets to set up a RDCU compression, read the
     *	bitstream and the updated model in parallel to write the data to compressed
     *	and the model and start the compression
     * @note the compressed data are read from cfg->rdcu_buffer_adr with the length
     *	of last_cmp_size
     * @note note that the initialization function init_rmap_pkt_to_file() must be
     *	executed before
     * @note the configuration of the ICU_ADDR, RDCU_ADDR, MTU settings are in the
     *	.rdcu_pkt_mode_cfg file
     *
     * @param cfg		compressor configuration contains all parameters required for
     *			compression
     * @param last_info	compression information from the last executed
     *			compression
     *
     * @returns 0 on success, error otherwise
     */
    
    int gen_rdcu_parallel_pkts(const struct cmp_cfg *cfg,
    			   const struct cmp_info *last_info)
    {
    	struct stat st = { 0 };
    
    	if (!cfg)
    		return -1;
    
    	/* creating TC_DIR directory if that directory does not exist */
    	if (stat(TC_DIR, &st) == -1) {
    		int err;
    		#if defined(_WIN32) || defined(_WIN64)
    			err = mkdir(TC_DIR);
    		#else
    			err = mkdir(TC_DIR, 0700);
    		#endif
    		if (err)
    			return -1;
    	}
    
    	set_tc_folder_dir(TC_DIR "/compress_data_parallel");
    	if (rdcu_compress_data_parallel(cfg, last_info))
    		return -1;
    
    	return 0;
    }