common_type_error_t pfm_sync() {
	unsigned int i;
	common_type_error_t err;

	// Sync MAC layer
	for (i = 0; i < pfm_macVectorLength; i++) {
		err = pfm_macVector[i].sync();
		if (err != COMMON_TYPE_SUCCESS) {
			logging_adapter_info("The MAC module nr. %d can't be synchronized "
					"correctly.", i + 1);
			return err;
		}
	}

	// Sync App layer
	for (i = 0; i < pfm_appVectorLength; i++) {
		err = pfm_appVector[i].sync();
		if (err != COMMON_TYPE_SUCCESS) {
			logging_adapter_info("The Application module nr. %d can't be "
					"synchronized correctly.", i + 1);
			return err;
		}
	}

	return COMMON_TYPE_SUCCESS;
}
示例#2
0
common_type_error_t dlogg_mac_read(uint8_t *buffer, size_t length,
		dlogg_mac_chksum_t * chksum) {
	size_t remaining = length;
	ssize_t rd;

	assert(buffer != NULL);

	while (remaining > 0) {
		rd = read(dlogg_mac_ttyFD, &buffer[length - remaining], remaining);
		if (rd == 0) {
			logging_adapter_info("Timeout while reading from d-logg. %u more bytes "
					"expected, got %u so far.", (unsigned) remaining,
					(unsigned) length - remaining);
			return COMMON_TYPE_ERR_TIMEOUT;
		} else if (rd < 0) {
			logging_adapter_info("Can't read %u more bytes of data from d-logg: %s",
					(unsigned) remaining, strerror(errno));
			return COMMON_TYPE_ERR_IO;
		}
		remaining -= rd;
	}

	dlogg_mac_updateChksum(buffer, length, chksum);

	return COMMON_TYPE_SUCCESS;
}
示例#3
0
/**
 * @brief Parses the given prefix configuration value
 * @details If the prefix isn't known, the prefix variable remains unchanged
 * @param prefix The location to store the prefix
 * @param confVal The configured prefix
 * @return The status of the operation
 */
static inline common_type_error_t dlogg_stdval_getPrefixID(
		dlogg_stdval_prefix_t* prefix, const char* confVal) {

	assert(prefix != NULL);
	assert(confVal != NULL);

	if (strcmp(DLOGG_STDVAL_CONFIG_PRE_A, confVal) == 0) {
		*prefix = DLOGG_STDVAL_PRE_A;
	} else if (strcmp(DLOGG_STDVAL_CONFIG_PRE_AD, confVal) == 0) {
		*prefix = DLOGG_STDVAL_PRE_AD;
	} else if (strcmp(DLOGG_STDVAL_CONFIG_PRE_AA, confVal) == 0) {
		*prefix = DLOGG_STDVAL_PRE_AA;
	} else if (strcmp(DLOGG_STDVAL_CONFIG_PRE_E, confVal) == 0) {
		*prefix = DLOGG_STDVAL_PRE_E;
	} else if (strcmp(DLOGG_STDVAL_CONFIG_PRE_S, confVal) == 0) {
		*prefix = DLOGG_STDVAL_PRE_S;
	} else if (strcmp(DLOGG_STDVAL_CONFIG_PRE_WMZE, confVal) == 0) {
		*prefix = DLOGG_STDVAL_PRE_WMZE;
	} else if (strcmp(DLOGG_STDVAL_CONFIG_PRE_WMZP, confVal) == 0) {
		*prefix = DLOGG_STDVAL_PRE_WMZP;
	} else {
		logging_adapter_info("Unknown Channel prefix %s", confVal);
		return COMMON_TYPE_ERR_CONFIG;
	}

	return COMMON_TYPE_SUCCESS;
}
示例#4
0
/**
 * @brief Fetches the heat meter power value from the given sample
 * @details It assumes that all values are valid and that the ranges are checked
 * @param sample The reference to the addressed sample
 * @param channelID The valid channel identifier
 * @return The result of the operation
 */
static inline common_type_t dlogg_stdval_fetchWMZPChannel(
		dlogg_cd_sample_t* sample, uint8_t channelID) {
	common_type_t ret;

	assert(sample != NULL);

	ret.type = COMMON_TYPE_ERROR;
	ret.data.errVal = COMMON_TYPE_ERR;

	switch (sample->sampleType) {
	case DLOGG_CD_SAMPLE_UVR_61_3_V14:
		assert(channelID < 3);

		if (sample->data.uvr61_3_v14.heatMeterRegister & (1 << channelID)) {
			ret = dlogg_stdval_heatMeterSmall2commonPower(
					&sample->data.uvr61_3_v14.heatMeter[channelID]);
		} else {
			logging_adapter_info("The heat meter %u is not active",
					(unsigned) channelID + 1);
			ret.type = COMMON_TYPE_ERROR;
			ret.data.errVal = COMMON_TYPE_ERR_INVALID_ADDRESS;
		}

		break;
	default:
		assert(0);
	}
	return ret;
}
/**
 * @brief Frees resources allocated by the MAC layer
 * @details The function calls the module's free functions and tries to
 * deallocate them. The function doesn't stop immediately if an error occurs.
 * Instead it tries to deallocate as many resources as possible avoiding memory
 * leaks. It assumes that the macVector is allocated but the vector may not be
 * fully initialized
 * @return The status of the operation. Only the last error will be reported.
 */
static inline common_type_error_t pfm_freeMac() {
	unsigned int i;
	int err;
	common_type_error_t lastErr = COMMON_TYPE_SUCCESS, tmpErr;

	assert(pfm_macVector != NULL || pfm_macVectorLength == 0);

	err = 0;
	for (i = 0; i < pfm_macVectorLength; i++) {

		if (pfm_macVector[i].free != NULL ) {
			tmpErr = pfm_macVector[i].free();
			err |= (tmpErr == COMMON_TYPE_SUCCESS ? 0 : 1);
			lastErr = (tmpErr == COMMON_TYPE_SUCCESS ? lastErr : tmpErr);
		}

		if (pfm_macVector[i].handler != NULL ) {
			err |= dlclose(pfm_macVector[i].handler);
		}
	}

	free(pfm_macVector);
	pfm_macVector = NULL;
	pfm_macVectorLength = 0;

	if (err != 0) {
		logging_adapter_info("Can't successfully unload one or more modules.");
		return (
				lastErr == COMMON_TYPE_SUCCESS ? COMMON_TYPE_ERR_LOAD_MODULE : lastErr);
	}
	return COMMON_TYPE_SUCCESS;
}
示例#6
0
/**
 * @brief Translates the input type into a properly scaled common type
 * @details <p> Temperatures will be scaled in degree Celsius, volume flow to
 * l/h, radiation to W/m^2 and boolean values to [0,1]. If the input is not set
 * the function will return an error.</p>
 * <p>It seems that negative values are either encoded using ones or twos
 * complement. Since a value of 0xFFFF directly follows 0x0000 on temperature
 * readings twos complement encoding is assumed.</p>
 * @param input The input to translate
 * @return The proper common type
 */
static common_type_t dlogg_stdval_input2common(dlogg_cd_input_t input) {
	common_type_t ret;
	int16_t signedValue; // The signed interpretation of the received value

	// convert the data to the commonly used signed interpretation
	signedValue = ((input.val.sign?0xF000:0x0000) |
			(input.val.highValue << 8) | input.val.lowValue);

	logging_adapter_debug("Got input value: type=%u, high=0x%02x, low=0x%02x, "
			"sign=%u, sigValue=%d", (unsigned) input.val.type,
			(unsigned) input.val.highValue, (unsigned) input.val.lowValue,
			(unsigned) input.val.sign, (int) signedValue);

	switch (input.val.type) {
	case 0: // unused
		logging_adapter_info("An input value requested is currently unused");
		ret.type = COMMON_TYPE_ERROR;
		ret.data.errVal = COMMON_TYPE_ERR_INVALID_ADDRESS;
		break;
	case 1: // digital input
		ret.type = COMMON_TYPE_LONG;
		ret.data.longVal = input.val.sign;
		break;
	case 2: // temperature
		ret.type = COMMON_TYPE_DOUBLE;
		ret.data.doubleVal = signedValue * 0.1;
		break;
	case 3: // volume flow
		ret.type = COMMON_TYPE_DOUBLE;
		ret.data.doubleVal = signedValue * 4.0;
		break;
	case 6: // solar radiation
		ret.type = COMMON_TYPE_DOUBLE;
		ret.data.doubleVal = signedValue;
		break;
	case 7: // room temperature
		ret.type = COMMON_TYPE_DOUBLE;
		ret.data.doubleVal = signedValue * 0.1;
		break;
	default:
		logging_adapter_info("Invalid input type identifier read: 0x%20x",
				input.val.type);
		ret.type = COMMON_TYPE_ERROR;
		ret.data.errVal = COMMON_TYPE_ERR_INVALID_RESPONSE;
	}
	return ret;
}
/**
 * @brief Loads and initializes the application module and adds it to the global
 * list.
 * @details It assumes that the name used to lookup the shared library module
 * isn't null.
 * @param name The name or path of the application layer module
 * @return The index of the newly created list entry or -1.
 */
static int pfm_loadAppModule(const char* name) {
	pfm_app_t *oldVector = pfm_appVector;
	pfm_app_t *app;
	fieldbus_application_init_t init;
	common_type_error_t err;

	assert(name != NULL);

	pfm_appVector = realloc(pfm_appVector,
			(pfm_appVectorLength + 1) * sizeof(pfm_appVector[0]));
	if (pfm_appVector == NULL ) {
		pfm_appVector = oldVector;
		logging_adapter_info("Can't obtain more memory");
		return -1 ;
	}
	pfm_appVectorLength++;
	app = &pfm_appVector[pfm_appVectorLength - 1];
	memset(app, 0, sizeof(app[0]));

	app->name = name;
	app->handler = dlopen(name, RTLD_NOW);
	if (app->handler == NULL ) {
		pfm_appVectorRollback();
		logging_adapter_info("Can't load application module \"%s\": %s", name,
				dlerror());
		return -1 ;
	}

	init = pfm_lookupAppInterfaceFunctions(app);
	if (init == NULL ) {
		pfm_appVectorRollback();
		return -1 ;
	}

	err = init();
	if (err != COMMON_TYPE_SUCCESS) {
		pfm_appVectorRollback();
		logging_adapter_info("Can't initialize the \"%s\" module (err-no: %d)",
				name, (int) err);
		return -1 ;
	}

	return pfm_appVectorLength - 1;
}
示例#8
0
common_type_error_t fieldbus_mac_init(config_setting_t* configuration) {
	const char* interface;

	assert(configuration != NULL);

	if (!config_setting_is_group(configuration)) {
		logging_adapter_info("The MAC configuration isn't a group");
		return COMMON_TYPE_ERR_CONFIG;
	}

	if (!config_setting_lookup_string(configuration, DLOGG_MAC_CONFIG_INTERFACE,
			&interface)) {
		logging_adapter_info("Can't find the \"%s\" string configuration directive "
				"inside MAC group", DLOGG_MAC_CONFIG_INTERFACE);
		return COMMON_TYPE_ERR_CONFIG;
	}

	return dlogg_mac_initTTY(interface);
}
示例#9
0
/**
 * @brief initializes the tty interface
 * @details It assumes that the global file descriptor is currently closed (-1)
 * and that the given interface string is valid. After successfully opening the
 * device the termois settings will be saved globally.
 * @param interface The interface path to open
 * @return The status of the operation
 */
static inline common_type_error_t dlogg_mac_initTTY(const char* interface) {
	struct termios ttySettings, controlSettings;
	assert(dlogg_mac_ttyFD < 0);
	assert(interface != NULL);
	assert(!dlogg_mac_cData.restoreTioSettings);

	errno = 0;
	dlogg_mac_ttyFD = open(interface, O_RDWR | O_NOCTTY);
	if (dlogg_mac_ttyFD < 0) {
		logging_adapter_info("Can't open the device \"%s\": %s", interface,
				strerror(errno));
		return COMMON_TYPE_ERR_DEVICE_NOT_FOUND;
	}

	logging_adapter_debug("Successfully opened d-logg device \"%s\"", interface);

	// save old state
	if (tcgetattr(dlogg_mac_ttyFD, &dlogg_mac_oldTio)) {
		logging_adapter_info("Can't obtain the \"%s\" devices settings: %s",
				interface, strerror(errno));
		return COMMON_TYPE_ERR_IO;
	}
	dlogg_mac_cData.restoreTioSettings = 1;

	// Assemble new settings
	memset(&ttySettings, 0, sizeof(ttySettings));
	memset(&controlSettings, 0, sizeof(controlSettings));

	if (cfsetspeed(&ttySettings, B115200)) {
		logging_adapter_info("Can't set the \"%s\" device's speed: %s", interface,
				strerror(errno));
		return COMMON_TYPE_ERR_IO;
	}

	// Use non canonical mode, 8 bits, no parity, 1 stop bit, DTR: on, RTS: off
	ttySettings.c_cc[VMIN] = 0;
	ttySettings.c_cc[VTIME] = DLOGG_MAC_TIMEOUT;
	ttySettings.c_cflag |= CS8 | CREAD | CLOCAL;

	if (tcsetattr(dlogg_mac_ttyFD, TCSAFLUSH, &ttySettings)) {
		logging_adapter_info("Can't change the \"%s\" device's settings: %s",
				interface, strerror(errno));
		return COMMON_TYPE_ERR_IO;
	}
	if (tcgetattr(dlogg_mac_ttyFD, &controlSettings)) {
		logging_adapter_info("Can't obtain the \"%s\" devices settings: %s",
				interface, strerror(errno));
		return COMMON_TYPE_ERR_IO;
	}

	if (memcmp(&ttySettings, &controlSettings, sizeof(ttySettings)) != 0) {
		logging_adapter_info("Can't set all of the \"%s\" device's settings: %s",
				interface, strerror(errno));
		return COMMON_TYPE_ERR_IO;
	}

	logging_adapter_debug("Configured d-logg interface device \"%s\"", interface);

	return COMMON_TYPE_SUCCESS;
}
示例#10
0
/**
 * @brief Obtains the appropriate met-data structure and checks the range of the
 * internal values
 * @details The sensor number range depends on the internal sampleType
 * describing available data. Each range is present in a lookup-table containing
 * the maximum number of inputs
 * @param addr The address structure to check
 * @return The status of the operation
 */
static inline common_type_error_t dlogg_stdval_checkAddress(
		dlogg_stdval_addr_t * addr) {
	dlogg_cd_metadata_t * metadata = dlogg_cd_getMetadata(addr->lineID);
	dlogg_cd_sample_t * addressedSample;

	assert(addr != NULL);

	if (metadata == NULL ) {
		logging_adapter_info("The line number %u is not known.",
				(unsigned) addr->lineID);
		return COMMON_TYPE_ERR_CONFIG;
	}

	if (addr->controllerID >= metadata->sampleCount) {
		logging_adapter_info("Only %u controller(s) are present at line %u. "
				"Controller %u does not exist.", (unsigned) metadata->sampleCount,
				(unsigned) addr->lineID, ((unsigned) addr->controllerID) + 1);
		return COMMON_TYPE_ERR_CONFIG;
	}

	addressedSample = dlogg_cd_getCurrentData(addr->controllerID, addr->lineID);
	assert(addressedSample != NULL);

	assert(addressedSample->sampleType < sizeof(dlogg_stdval_capabilities) //
	/ sizeof(dlogg_stdval_capabilities[0]));
	assert(addr->prefixID < sizeof(dlogg_stdval_capabilities[0]) //
	/ sizeof(dlogg_stdval_capabilities[0][0]));

	if (addr->channelID
			>= dlogg_stdval_capabilities[addressedSample->sampleType][addr->prefixID]) {
		logging_adapter_info("The controller (sampleType=0x%x) doesn't have a "
				" (prefix=%u) channel nr. %u. The maximum number allowed is %u",
				(unsigned) addressedSample->sampleType, (unsigned) addr->prefixID,
				(unsigned) addr->channelID + 1,
				(unsigned) dlogg_stdval_capabilities[addressedSample->sampleType][addr->prefixID]);
		return COMMON_TYPE_ERR_CONFIG;
	}

	return COMMON_TYPE_SUCCESS;
}
示例#11
0
common_type_error_t fieldbus_mac_free() {
	common_type_error_t err = COMMON_TYPE_SUCCESS;

	// Deallocate TTY
	if (dlogg_mac_ttyFD >= 0) {
		if (dlogg_mac_cData.restoreTioSettings) {
			if (tcsetattr(dlogg_mac_ttyFD, TCSADRAIN, &dlogg_mac_oldTio)) {
				logging_adapter_info("Can't successfully restore the tty settings: %s",
						strerror(errno));
				err = COMMON_TYPE_ERR_IO;
			}
		}
		dlogg_mac_cData.restoreTioSettings = 0;

		if (close(dlogg_mac_ttyFD)) {
			logging_adapter_info("Can't close the tty device: %s", strerror(errno));
			err = COMMON_TYPE_ERR_IO;
		}
		dlogg_mac_ttyFD = -1;
	}
	return err;
}
/**
 * @details Assumes that the channelConf reference isn't null.
 */
int pfm_addChannel(config_setting_t* channelConf) {
	const char* driver = "";
	config_setting_t *address;
	int appIndex = -1;

	assert(channelConf != NULL);

	if (!config_setting_is_group(channelConf)) {
		logging_adapter_info("The given channel configuration isn't a valid group "
				"of directives");
		return -1;
	}

	if (!config_setting_lookup_string(channelConf, PFM_CONFIG_TYPE, &driver)) {
		logging_adapter_info("Can't load the \"%s\" string configuration "
				"directive.", PFM_CONFIG_TYPE);
		return -1;
	}

	address = config_setting_get_member(channelConf, PFM_CONFIG_ADDRESS);
	if (address == NULL ) {
		logging_adapter_info("Can't obtain the \"%s\" channel configuration's "
				"\"%s\" member", driver, PFM_CONFIG_ADDRESS);
		return -1;
	}

	// obtain the device driver
	appIndex = pfm_getAppIndex(driver);
	if (appIndex < 0 ) {
		logging_adapter_debug("Try to load application module \"%s\"", driver);
		appIndex = pfm_loadAppModule(driver);
	}
	if (appIndex < 0 ) {
		return -1;
	}

	return pfm_newChannel(appIndex, address);
}
/**
 * @brief Extracts the MAC module's names and loads the modules.
 * @param configuration The root configuration containing the mac member. The
 * root configuration has to be a group setting always.
 * @return The status of the operation
 */
common_type_error_t pfm_init(config_setting_t* configuration) {
	config_setting_t *mac;
	common_type_error_t err;
	int i;

	assert(config_setting_is_group(configuration));

	// Fetch and check the MAC module configuration sections
	mac = config_setting_get_member(configuration, PFM_CONFIG_MAC);
	if (mac == NULL ) {
		logging_adapter_info("Can't locate the \"%s\" list directive.",
				PFM_CONFIG_MAC);
		return COMMON_TYPE_ERR_CONFIG;
	}
	if (!config_setting_is_list(mac)) {
		logging_adapter_info("The \"%s\" directive isn't a list.", PFM_CONFIG_MAC);
		return COMMON_TYPE_ERR_CONFIG;
	}

	// Allocate the mac module vector.
	pfm_macVectorLength = config_setting_length(mac);
	assert(pfm_macVectorLength >= 0);
	pfm_macVector = malloc(pfm_macVectorLength * sizeof(pfm_macVector[0]));
	if (pfm_macVector == NULL ) {
		return COMMON_TYPE_ERR;
	}
	memset(pfm_macVector, 0, pfm_macVectorLength * sizeof(pfm_macVector[0]));

	// Load the mac modules
	for (i = 0; i < pfm_macVectorLength; i++) {
		err = pfm_installMacModule(config_setting_get_elem(mac, i), i);
		if (err != COMMON_TYPE_SUCCESS) {
			return err;
		}
	}

	return COMMON_TYPE_SUCCESS;
}
示例#14
0
common_type_error_t dlogg_mac_send(uint8_t *buffer, size_t length,
		dlogg_mac_chksum_t * chksum) {

	assert(buffer != NULL);

	if (write(dlogg_mac_ttyFD, buffer, length) != length) {
		logging_adapter_info("Can't write to the d-logg interface: %s",
				strerror(errno));
		return COMMON_TYPE_ERR_IO;
	}

	dlogg_mac_updateChksum(buffer, length, chksum);

	return COMMON_TYPE_SUCCESS;
}
示例#15
0
common_type_error_t dlogg_mac_read_chksum(dlogg_mac_chksum_t * chksum) {
	common_type_error_t err;
	dlogg_mac_chksum_t chksumRead;
	assert(chksum != NULL);
	err = dlogg_mac_read((uint8_t *) &chksumRead, sizeof(chksumRead), NULL );
	if (err != COMMON_TYPE_SUCCESS) {
		return err;
	}

	if (*chksum != chksumRead) {
		logging_adapter_info("Received invalid checksum %u, %u expected.",
				(unsigned int) chksumRead, (unsigned int) *chksum);
		return COMMON_TYPE_ERR_INVALID_RESPONSE;
	}
	return COMMON_TYPE_SUCCESS;
}
示例#16
0
/**
 * @brief Converts the analog output value to an appropriate common type value
 * @details If the output is not set an error will be returned. The output value
 * will be scaled to 1V.
 * @param analogOutput The source value
 * @return The converted target value
 */
static common_type_t dlogg_stdval_analogOutput2common(
		dlogg_cd_analogOutput_t analogOutput) {
	common_type_t ret;

	if (!analogOutput.val.activeN && analogOutput.val.voltage <= 100) {
		ret.type = COMMON_TYPE_DOUBLE;
		ret.data.doubleVal = analogOutput.val.voltage * 0.01;
	} else {
		logging_adapter_info("An analog output requested isn't set by the "
				"controller");
		ret.type = COMMON_TYPE_ERROR;
		ret.data.errVal = COMMON_TYPE_ERR_INVALID_ADDRESS;
	}

	return ret;
}
示例#17
0
/**
 * @brief Converts the drive output value to a value between [0,1]
 * @details If the value is not set an error will be returned
 * @param outputDrive The drive value
 * @return The common type value calculated
 */
static common_type_t dlogg_stdval_outputDrive2common(
		dlogg_cd_outputDrive_t outputDrive) {
	common_type_t ret;

	if (!outputDrive.activeN && outputDrive.speed <= 30) {
		ret.type = COMMON_TYPE_DOUBLE;
		ret.data.doubleVal = ((double) outputDrive.speed) / 30.0;
	} else {
		logging_adapter_info("A drive controlled output requested isn't set by "
				"the controller");
		ret.type = COMMON_TYPE_ERROR;
		ret.data.errVal = COMMON_TYPE_ERR_INVALID_ADDRESS;
	}

	return ret;
}
/**
 * @brief Adds a new channel to the list of known channels and returns it's id
 * @details If the function is unable to obtain memory, -1 is returned.
 * @param appIndex The index of the previously loaded app module within it's
 * vector
 * @param address The channel's address configuration
 * @return The index of the newly created channel
 */
static inline int pfm_newChannel(int appIndex, config_setting_t *address) {
	unsigned int index = pfm_channelVectorLength;
	pfm_channel_t * oldVector = pfm_channelVector;

	assert(appIndex >= 0);
	assert(appIndex < pfm_appVectorLength);
	assert(address != NULL);

	pfm_channelVector = realloc(pfm_channelVector,
			(pfm_channelVectorLength + 1) * sizeof(pfm_channelVector[0]));
	if (pfm_channelVector == NULL ) {
		pfm_channelVector = oldVector;
		logging_adapter_info("Can't obtain more memory");
		return -1;
	}

	pfm_channelVectorLength++;

	pfm_channelVector[index].address = address;
	pfm_channelVector[index].appIndex = appIndex;

	return index;
}
/**
 * @brief Tries to lookup the interface functions
 * @details Sets the functions within the given structure and returns the init
 * function. If the function is unable to obtain one or more interface functions
 * it will return NULL and log an appropriate error message. It assumes that the
 * given app reference is valid and that the handler as well as the name
 * contained is properly set. The function won't perform a roll-back operation
 * taking the invalid application layer from the appVector.
 * @param app The reference to the application structure to manipulate
 * @return The init function or null.
 */
static inline fieldbus_application_init_t pfm_lookupAppInterfaceFunctions(
		pfm_app_t *app) {
	fieldbus_application_init_t ret = NULL;
	char* errStr;
	union {
		void* vPtr;
		fieldbus_application_init_t initPtr;
		fieldbus_application_sync_t syncPtr;
		fieldbus_application_fetchValue_t fetchPtr;
		fieldbus_application_free_t freePtr;
	} ptrWorkaround;

	assert(app != NULL);
	assert(app->handler != NULL);
	assert(app->name != NULL);

	(void) dlerror();
	ptrWorkaround.vPtr = dlsym(app->handler, FIELDBUS_APPLICATION_INIT_NAME);
	ret = ptrWorkaround.initPtr;
	errStr = dlerror();
	if (errStr != NULL ) {
		logging_adapter_info("Can't load the \"%s\" function of one fieldbus "
				"application module \"%s\": %s", FIELDBUS_APPLICATION_INIT_NAME,
				app->name, errStr);
		return NULL ;
	}

	(void) dlerror();
	ptrWorkaround.vPtr = dlsym(app->handler,
			FIELDBUS_APPLICATION_FETCH_VALUE_NAME);
	app->fetchValue = ptrWorkaround.fetchPtr;
	errStr = dlerror();
	if (errStr != NULL ) {
		logging_adapter_info("Can't load the \"%s\" function of one fieldbus "
				"application module \"%s\": %s", FIELDBUS_APPLICATION_FETCH_VALUE_NAME,
				app->name, errStr);
		return NULL ;
	}

	(void) dlerror();
	ptrWorkaround.vPtr = dlsym(app->handler, FIELDBUS_APPLICATION_FREE_NAME);
	app->free = ptrWorkaround.freePtr;
	errStr = dlerror();
	if (errStr != NULL ) {
		logging_adapter_info("Can't load the \"%s\" function of one fieldbus "
				"application module \"%s\": %s", FIELDBUS_APPLICATION_FREE_NAME,
				app->name, errStr);
		return NULL ;
	}

	(void) dlerror();
	ptrWorkaround.vPtr = dlsym(app->handler, FIELDBUS_APPLICATION_SYNC_NAME);
	app->sync = ptrWorkaround.syncPtr;
	errStr = dlerror();
	if (errStr != NULL ) {
		logging_adapter_info("Can't load the \"%s\" function of one fieldbus "
				"application module \"%s\": %s", FIELDBUS_APPLICATION_SYNC_NAME,
				app->name, errStr);
		return NULL ;
	}

	return ret;
}
/**
 * @brief Loads the given module, adds its handler to the list of known modules
 * and initializes it.
 * @details If the configuration is invalid, an appropriate error message will
 * be reported.
 * @param modConfig The module's group configuration.
 * @param index The index within the MAC vector structure to populate.
 * @return The status of the operation
 */
static inline common_type_error_t pfm_installMacModule(
		config_setting_t *modConfig, const unsigned int index) {
	const char* name = "";
	char* errStr;
	/* Used to fix the POSIX - C99 conflict */
	union {
		void* vPtr;
		fieldbus_mac_init_t initPtr;
		fieldbus_mac_sync_t syncPtr;
		fieldbus_mac_free_t freePtr;
	} ptrWorkaround;

	common_type_error_t err;
	fieldbus_mac_init_t init;

	assert(modConfig != NULL);
	assert(index < pfm_macVectorLength);

	if (!config_setting_is_group(modConfig)) {
		logging_adapter_info("The \"%s\" directive contains an invalid list entry",
				PFM_CONFIG_MAC);
		return COMMON_TYPE_ERR_CONFIG;
	}
	if (!config_setting_lookup_string(modConfig, PFM_CONFIG_NAME, &name)) {
		logging_adapter_info(
				"Can't find the \"%s\" string directive inside the MAC "
						"module directive", PFM_CONFIG_NAME);
		return COMMON_TYPE_ERR_CONFIG;
	}
	assert(name != NULL);

	logging_adapter_debug("Try to load MAC module \"%s\"", name);

	pfm_macVector[index].handler = dlopen(name, RTLD_NOW | RTLD_GLOBAL);
	if (pfm_macVector[index].handler == NULL ) {
		logging_adapter_info("Can't load \"%s\": %s", name, dlerror());
		return COMMON_TYPE_ERR_LOAD_MODULE;
	}

	// Load end execute init function
	(void) dlerror();
	ptrWorkaround.vPtr = dlsym(pfm_macVector[index].handler, "fieldbus_mac_init");
	init = ptrWorkaround.initPtr;
	errStr = dlerror();
	if (errStr != NULL ) {
		logging_adapter_info("Can't successfully load the \"%s\" "
				"function: %s", FIELDBUS_MAC_INIT_NAME, errStr);
		return COMMON_TYPE_ERR_LOAD_MODULE;
	}

	err = init(modConfig);
	if (err != COMMON_TYPE_SUCCESS) {
		return err;
	}

	// Load free and sync
	(void) dlerror();
	ptrWorkaround.vPtr = dlsym(pfm_macVector[index].handler,
			FIELDBUS_MAC_SYNC_NAME);
	pfm_macVector[index].sync = ptrWorkaround.syncPtr;
	errStr = dlerror();
	if (errStr != NULL ) {
		logging_adapter_info("Can't successfully load the \"%s\" "
				"function: %s", FIELDBUS_MAC_SYNC_NAME, errStr);
		return COMMON_TYPE_ERR_LOAD_MODULE;
	}

	(void) dlerror();
	ptrWorkaround.vPtr = dlsym(pfm_macVector[index].handler,
			FIELDBUS_MAC_FREE_NAME);
	pfm_macVector[index].free = ptrWorkaround.freePtr;
	errStr = dlerror();
	if (errStr != NULL ) {
		logging_adapter_info("Can't successfully load the \"%s\" "
				"function: %s", FIELDBUS_MAC_FREE_NAME, errStr);
		return COMMON_TYPE_ERR_LOAD_MODULE;
	}

	assert(pfm_macVector[index].free != NULL);
	assert(pfm_macVector[index].sync != NULL);

	return COMMON_TYPE_SUCCESS;
}
示例#21
0
/**
 * @brief Parses the given configuration structure
 * @details The parameters set will be stored into the address structure but
 * availability of addresses will remain unchecked.
 * @param addr The address structure to store the results
 * @param addressConfig The configuration to read
 * @return The status of the operation
 */
static inline common_type_error_t dlogg_stdval_parseAddress(
		dlogg_stdval_addr_t * addr, config_setting_t *addressConfig) {
	common_type_error_t err;
	int lineID = 0, channel, controller = 1;
	const char * prefix;

	assert(addressConfig != NULL);
	assert(addr != NULL);

	if (!config_setting_is_group(addressConfig)) {
		logging_adapter_info("The address setting is not a group directive");
		return COMMON_TYPE_ERR_CONFIG;
	}

	// Use default value, if not set
	config_setting_lookup_int(addressConfig, DLOGG_STDVAL_CONFIG_LINE, &lineID);

	if (lineID < 0 || lineID > 255) {
		logging_adapter_info("Value of %s, %i out of range [0,255]",
				DLOGG_STDVAL_CONFIG_LINE, (int) lineID);
		return COMMON_TYPE_ERR_CONFIG;
	}

	if (!config_setting_lookup_int(addressConfig, DLOGG_STDVAL_CONFIG_CHN_NR,
			&channel)) {
		logging_adapter_info("Cant find the \"%s\" int directive within the "
				"address group", DLOGG_STDVAL_CONFIG_CHN_NR);
		return COMMON_TYPE_ERR_CONFIG;
	}

	if (channel < 1 || channel > 256) {
		logging_adapter_info("Value of %s, %i out of range [1,256]",
				DLOGG_STDVAL_CONFIG_CHN_NR, (int) channel);
		return COMMON_TYPE_ERR_CONFIG;
	}

	// Use default value, if not set
	config_setting_lookup_int(addressConfig, DLOGG_STDVAL_CONFIG_CONTROLLER,
			&controller);

	if (controller < 1 || controller > 2) {
		logging_adapter_info("Value of %s, %i out of range [1,2]",
				DLOGG_STDVAL_CONFIG_CONTROLLER, (int) controller);
		return COMMON_TYPE_ERR_CONFIG;
	}

	if (!config_setting_lookup_string(addressConfig,
			DLOGG_STDVAL_CONFIG_CHN_PREFIX, &prefix)) {
		logging_adapter_info("Can't find the \"%s\" string directive within the "
				"address group", DLOGG_STDVAL_CONFIG_CHN_PREFIX);
		return COMMON_TYPE_ERR_CONFIG;
	}

	err = dlogg_stdval_getPrefixID(&addr->prefixID, prefix);
	if (err != COMMON_TYPE_SUCCESS)
		return err;

	addr->lineID = lineID;
	addr->channelID = channel - 1;
	addr->controllerID = controller - 1;

//  May be needed for detailed debugging ...
//	logging_adapter_debug("Parsed address: lineID=%u, channelID=%u, "
//			"controllerID=%u, prefix=0x%02x", (unsigned) addr->lineID,
//			(unsigned) addr->channelID, (unsigned) addr->controllerID,
//			(unsigned) addr->prefixID);

	return COMMON_TYPE_SUCCESS;
}