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; }
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; }
/** * @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; }
/** * @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; }
/** * @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; }
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); }
/** * @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; }
/** * @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; }
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; }
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; }
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; }
/** * @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; }
/** * @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; }
/** * @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; }