* @author Janez Paternoster
* @copyright 2021 Janez Paternoster
*
- * This file is part of CANopenNode, an opensource CANopen Stack.
- * Project home page is <https://github.com/CANopenNode/CANopenNode>.
- * For more information on CANopen see <http://www.can-cia.org/>.
+ * This file is part of <https://github.com/CANopenNode/CANopenNode>, a CANopen Stack.
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
+ * file except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and limitations under the License.
*/
#ifndef CO_APPLICATION_H
*
* @param [in,out] bitRate Stored CAN bit rate, can be overridden.
* @param [in,out] nodeId Stored CANopen NodeId, can be overridden.
- * @param [out] errInfo Variable may indicate error information - index of
- * erroneous OD entry.
+ * @param [out] errInfo Variable may indicate error information - index of erroneous OD entry.
*
* @return @ref CO_ReturnError_t CO_ERROR_NO in case of success.
*/
* @copyright 2004 - 2015 Janez Paternoster, 2017 - 2020 Neuberger Gebaeudeautomation GmbH
*
*
- * This file is part of CANopenNode, an opensource CANopen Stack.
- * Project home page is <https://github.com/CANopenNode/CANopenNode>.
- * For more information on CANopen see <http://www.can-cia.org/>.
+ * This file is part of <https://github.com/CANopenNode/CANopenNode>, a CANopen Stack.
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
+ * file except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and limitations under the License.
*/
#include <string.h>
static const uint32_t CO_INVALID_COB_ID = 0xffffffff;
-/******************************************************************************/
void CO_CANsetIdentToIndex(
uint32_t *lookup,
uint32_t index,
}
-/******************************************************************************/
static uint32_t CO_CANgetIndexFromIdent(
uint32_t *lookup,
uint32_t ident)
#endif /* CO_DRIVER_MULTI_INTERFACE */
-/** Disable socketCAN rx ******************************************************/
+/* Disable socketCAN rx */
static CO_ReturnError_t disableRx(CO_CANmodule_t *CANmodule)
{
uint32_t i;
}
-/** Set up or update socketCAN rx filters *************************************/
+/* Set up or update socketCAN rx filters */
static CO_ReturnError_t setRxFilters(CO_CANmodule_t *CANmodule)
{
size_t i;
}
-/******************************************************************************/
void CO_CANsetConfigurationMode(void *CANptr)
{
(void)CANptr;
}
-/******************************************************************************/
void CO_CANsetNormalMode(CO_CANmodule_t *CANmodule)
{
CO_ReturnError_t ret;
}
-/******************************************************************************/
CO_ReturnError_t CO_CANmodule_init(
CO_CANmodule_t *CANmodule,
void *CANptr,
}
-/** enable socketCAN *********************************************************/
+/* enable socketCAN */
#if CO_DRIVER_MULTI_INTERFACE == 0
static
#endif
}
/* enable software time stamp mode (hardware timestamps do not work properly
- * on all devices)*/
+ * on all devices) */
tmp = (SOF_TIMESTAMPING_SOFTWARE |
SOF_TIMESTAMPING_RX_SOFTWARE);
ret = setsockopt(interface->fd, SOL_SOCKET, SO_TIMESTAMPING, &tmp, sizeof(tmp));
}
-/******************************************************************************/
void CO_CANmodule_disable(CO_CANmodule_t *CANmodule)
{
uint32_t i;
}
-/******************************************************************************/
CO_ReturnError_t CO_CANrxBufferInit(
CO_CANmodule_t *CANmodule,
uint16_t index,
#if CO_DRIVER_MULTI_INTERFACE > 0
-/******************************************************************************/
bool_t CO_CANrxBuffer_getInterface(
CO_CANmodule_t *CANmodule,
uint16_t ident,
#endif /* CO_DRIVER_MULTI_INTERFACE */
-/******************************************************************************/
CO_CANtx_t *CO_CANtxBufferInit(
CO_CANmodule_t *CANmodule,
uint16_t index,
#if CO_DRIVER_MULTI_INTERFACE > 0
-/******************************************************************************/
CO_ReturnError_t CO_CANtxBuffer_setInterface(
CO_CANmodule_t *CANmodule,
uint16_t ident,
#endif /* CO_DRIVER_MULTI_INTERFACE */
#if CO_DRIVER_MULTI_INTERFACE > 0
-/* send CAN message ***********************************************************/
+/* send CAN message */
static CO_ReturnError_t CO_CANCheckSendInterface(
CO_CANmodule_t *CANmodule,
CO_CANtx_t *buffer,
CO_ReturnError_t CO_CANCheckSend(CO_CANmodule_t *CANmodule, CO_CANtx_t *buffer);
-/******************************************************************************/
CO_ReturnError_t CO_CANsend(CO_CANmodule_t *CANmodule, CO_CANtx_t *buffer)
{
CO_ReturnError_t err;
}
-/******************************************************************************/
CO_ReturnError_t CO_CANCheckSend(CO_CANmodule_t *CANmodule, CO_CANtx_t *buffer)
{
uint32_t i;
#endif /* CO_DRIVER_MULTI_INTERFACE == 0 */
-/******************************************************************************/
void CO_CANclearPendingSyncPDOs(CO_CANmodule_t *CANmodule)
{
(void)CANmodule;
}
-/******************************************************************************/
void CO_CANmodule_process(CO_CANmodule_t *CANmodule)
{
if (CANmodule == NULL || CANmodule->CANinterfaceCount == 0) return;
}
-/* Read CAN message from socket and verify some errors ************************/
+/* Read CAN message from socket and verify some errors */
static CO_ReturnError_t CO_CANread(
CO_CANmodule_t *CANmodule,
CO_CANinterface_t *interface,
}
-/* find msg inside rxArray and call corresponding CANrx_callback **************/
+/* find msg inside rxArray and call corresponding CANrx_callback */
static int32_t CO_CANrxMsg( /* return index of received message in rxArray or -1 */
CO_CANmodule_t *CANmodule,
struct can_frame *msg, /* CAN message input */
}
-/******************************************************************************/
bool_t CO_CANrxFromEpoll(CO_CANmodule_t *CANmodule,
struct epoll_event *ev,
CO_CANrxMsg_t *buffer,
* @copyright 2004 - 2020 Janez Paternoster
* @copyright 2018 - 2020 Neuberger Gebaeudeautomation GmbH
*
- * This file is part of CANopenNode, an opensource CANopen Stack.
- * Project home page is <https://github.com/CANopenNode/CANopenNode>.
- * For more information on CANopen see <http://www.can-cia.org/>.
+ * This file is part of <https://github.com/CANopenNode/CANopenNode>, a CANopen Stack.
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
+ * file except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and limitations under the License.
*/
CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE)
#endif
+#define CO_CONFIG_GFC (CO_CONFIG_GFC_ENABLE | \
+ CO_CONFIG_GFC_CONSUMER | \
+ CO_CONFIG_GFC_PRODUCER)
+
+#define CO_CONFIG_SRDO (CO_CONFIG_SRDO_ENABLE | \
+ CO_CONFIG_SRDO_CHECK_TX | \
+ CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE | \
+ CO_CONFIG_GLOBAL_FLAG_TIMERNEXT)
+
#ifndef CO_CONFIG_GTW
#define CO_CONFIG_GTW (CO_CONFIG_GTW_ASCII | \
CO_CONFIG_GTW_ASCII_SDO | \
* @copyright 2018 - 2020 Neuberger Gebaeudeautomation GmbH
*
*
- * This file is part of CANopenNode, an opensource CANopen Stack.
- * Project home page is <https://github.com/CANopenNode/CANopenNode>.
- * For more information on CANopen see <http://www.can-cia.org/>.
+ * This file is part of <https://github.com/CANopenNode/CANopenNode>, a CANopen Stack.
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
+ * file except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and limitations under the License.
*/
/* following macro is necessary for accept4() function call (sockets) */
* @copyright 2018 - 2020 Neuberger Gebaeudeautomation GmbH
*
*
- * This file is part of CANopenNode, an opensource CANopen Stack.
- * Project home page is <https://github.com/CANopenNode/CANopenNode>.
- * For more information on CANopen see <http://www.can-cia.org/>.
+ * This file is part of <https://github.com/CANopenNode/CANopenNode>, a CANopen Stack.
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
+ * file except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and limitations under the License.
*/
#ifndef CO_EPOLL_INTERFACE_H
* @param ep This object
* @param timerInterval_us Timer interval in microseconds
*
- * @return @ref CO_ReturnError_t CO_ERROR_NO, CO_ERROR_ILLEGAL_ARGUMENT or
- * CO_ERROR_SYSCALL.
+ * @return @ref CO_ReturnError_t CO_ERROR_NO, CO_ERROR_ILLEGAL_ARGUMENT or CO_ERROR_SYSCALL.
*/
CO_ReturnError_t CO_epoll_create(CO_epoll_t *ep, uint32_t timerInterval_us);
* @param socketTimeout_ms Timeout for established socket connection in [ms]
* @param localSocketPath File path, if commandInterface is local socket
*
- * @return @ref CO_ReturnError_t CO_ERROR_NO, CO_ERROR_ILLEGAL_ARGUMENT or
- * CO_ERROR_SYSCALL.
+ * @return @ref CO_ReturnError_t CO_ERROR_NO, CO_ERROR_ILLEGAL_ARGUMENT or CO_ERROR_SYSCALL.
*/
CO_ReturnError_t CO_epoll_createGtw(CO_epoll_gtw_t *epGtw,
int epoll_fd,
#ifdef __cplusplus
}
-#endif /*__cplusplus*/
+#endif /* __cplusplus */
#endif /* CO_EPOLL_INTERFACE_H */
* @copyright 2018 - 2020 Neuberger Gebaeudeautomation GmbH
*
*
- * This file is part of CANopenNode, an opensource CANopen Stack.
- * Project home page is <https://github.com/CANopenNode/CANopenNode>.
- * For more information on CANopen see <http://www.can-cia.org/>.
+ * This file is part of <https://github.com/CANopenNode/CANopenNode>, a CANopen Stack.
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
+ * file except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and limitations under the License.
*/
#include <string.h>
#include "301/CO_driver.h"
-/**
+/*
* Reset CAN interface and set to listen only mode
*/
static CO_CANinterfaceState_t CO_CANerrorSetListenOnly(
}
-/**
+/*
* Clear listen only
*/
static void CO_CANerrorClearListenOnly(
}
-/**
+/*
* Check and handle "bus off" state
*/
static CO_CANinterfaceState_t CO_CANerrorBusoff(
}
-/**
+/*
* Check and handle controller problems
*/
static CO_CANinterfaceState_t CO_CANerrorCrtl(
}
-/**
+/*
* Check and handle controller problems
*/
static CO_CANinterfaceState_t CO_CANerrorNoack(
}
-/******************************************************************************/
void CO_CANerror_init(
CO_CANinterfaceErrorhandler_t *CANerrorhandler,
int fd,
}
-/******************************************************************************/
void CO_CANerror_disable(
CO_CANinterfaceErrorhandler_t *CANerrorhandler)
{
}
-/******************************************************************************/
void CO_CANerror_rxMsg(
CO_CANinterfaceErrorhandler_t *CANerrorhandler)
{
}
-/******************************************************************************/
CO_CANinterfaceState_t CO_CANerror_txMsg(
CO_CANinterfaceErrorhandler_t *CANerrorhandler)
{
}
-/******************************************************************************/
CO_CANinterfaceState_t CO_CANerror_rxMsgError(
CO_CANinterfaceErrorhandler_t *CANerrorhandler,
const struct can_frame *msg)
* @copyright 2018 - 2020 Neuberger Gebaeudeautomation GmbH
*
*
- * This file is part of CANopenNode, an opensource CANopen Stack.
- * Project home page is <https://github.com/CANopenNode/CANopenNode>.
- * For more information on CANopen see <http://www.can-cia.org/>.
+ * This file is part of <https://github.com/CANopenNode/CANopenNode>, a CANopen Stack.
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
+ * file except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and limitations under the License.
*/
* openlog ("exampleprog", LOG_PID | LOG_PERROR, LOG_USER);
* @endcode
*
- * @param priority one of LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR, LOG_WARNING,
- * LOG_NOTICE, LOG_INFO, LOG_DEBUG
+ * @param priority one of LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR, LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG
* @param format format string as in printf
*/
void log_printf(int priority, const char *format, ...);
#ifdef __cplusplus
}
-#endif /*__cplusplus*/
+#endif /* __cplusplus */
#endif /* CO_ERROR_H */
* @copyright 2020 Neuberger Gebaeudeautomation GmbH
*
*
- * This file is part of CANopenNode, an opensource CANopen Stack.
- * Project home page is <https://github.com/CANopenNode/CANopenNode>.
- * For more information on CANopen see <http://www.can-cia.org/>.
+ * This file is part of <https://github.com/CANopenNode/CANopenNode>, a CANopen Stack.
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
+ * file except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and limitations under the License.
*/
* @author Janez Paternoster
* @copyright 2020 Janez Paternoster
*
- * This file is part of CANopenNode, an opensource CANopen Stack.
- * Project home page is <https://github.com/CANopenNode/CANopenNode>.
- * For more information on CANopen see <http://www.can-cia.org/>.
+ * This file is part of <https://github.com/CANopenNode/CANopenNode>, a CANopen Stack.
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
+ * file except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and limitations under the License.
*/
#include <stdio.h>
CANptr.can_ifindex = if_nametoindex(CANdevice);
}
- /* Valid NodeId is 1..127 or 0xFF(unconfigured) in case of LSSslaveEnabled*/
+ /* Valid NodeId is 1..127 or 0xFF(unconfigured) in case of LSSslaveEnabled */
if ((nodeIdFromArgs == 0 || nodeIdFromArgs > 127)
&& (!CO_isLSSslaveEnabled(CO)
|| nodeIdFromArgs != CO_LSS_NODE_ID_ASSIGNMENT)
-/*\r
- * CANopen data storage object for Linux\r
- *\r
- * @file CO_storageLinux.c\r
- * @author Janez Paternoster\r
- * @copyright 2021 Janez Paternoster\r
- *\r
- * This file is part of CANopenNode, an opensource CANopen Stack.\r
- * Project home page is <https://github.com/CANopenNode/CANopenNode>.\r
- * For more information on CANopen see <http://www.can-cia.org/>.\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-#include "CO_storageLinux.h"\r
-#include "301/crc16-ccitt.h"\r
-\r
-#include <stdio.h>\r
-#include <string.h>\r
-#include <stdlib.h>\r
-\r
-#if (CO_CONFIG_STORAGE) & CO_CONFIG_STORAGE_ENABLE\r
-\r
-\r
-/*\r
- * Function for writing data on "Store parameters" command - OD object 1010\r
- *\r
- * For more information see file CO_storage.h, CO_storage_entry_t.\r
- */\r
-static ODR_t storeLinux(CO_storage_entry_t *entry, CO_CANmodule_t *CANmodule) {\r
- ODR_t ret = ODR_OK;\r
- uint16_t crc_store;\r
-\r
- /* Create names for temporary and old file */\r
- size_t fn_len = strlen(entry->filename) + 5;\r
- char *filename_tmp = malloc(fn_len);\r
- char *filename_old = malloc(fn_len);\r
- if (filename_tmp == NULL || filename_old == NULL) {\r
- if (filename_tmp != NULL) free(filename_tmp);\r
- if (filename_old != NULL) free(filename_old);\r
- ret = ODR_OUT_OF_MEM;\r
- }\r
- else {\r
- strcpy(filename_tmp, entry->filename);\r
- strcpy(filename_old, entry->filename);\r
- strcat(filename_tmp, ".tmp");\r
- strcat(filename_old, ".old");\r
- }\r
-\r
- /* Open a temporary file and write data to it */\r
- if (ret == ODR_OK) {\r
- FILE *fp = fopen(filename_tmp, "w");\r
- if (fp == NULL) {\r
- ret = ODR_HW;\r
- }\r
- else {\r
- CO_LOCK_OD(CANmodule);\r
- size_t cnt = fwrite(entry->addr, 1, entry->len, fp);\r
- crc_store = crc16_ccitt(entry->addr, entry->len, 0);\r
- CO_UNLOCK_OD(CANmodule);\r
- cnt += fwrite(&crc_store, 1, sizeof(crc_store), fp);\r
- fclose(fp);\r
- if (cnt != (entry->len + sizeof(crc_store))) {\r
- ret = ODR_HW;\r
- }\r
- }\r
- }\r
-\r
- /* Verify data */\r
- if (ret == ODR_OK) {\r
- uint8_t *buf = NULL;\r
- FILE *fp = NULL;\r
- size_t cnt = 0;\r
- uint16_t crc_verify, crc_read;\r
-\r
- buf = malloc(entry->len + 4);\r
- if (buf != NULL) {\r
- fp = fopen(filename_tmp, "r");\r
- if (fp != NULL) {\r
- cnt = fread(buf, 1, entry->len + 4, fp);\r
- crc_verify = crc16_ccitt(buf, entry->len, 0);\r
- fclose(fp);\r
- memcpy(&crc_read, &buf[entry->len], sizeof(crc_read));\r
- }\r
- free(buf);\r
- }\r
- /* If size or CRC differs, report error */\r
- if (buf == NULL || fp == NULL || cnt != (entry->len+sizeof(crc_verify))\r
- || crc_store != crc_verify || crc_store != crc_read\r
- ) {\r
- ret = ODR_HW;\r
- }\r
- }\r
-\r
- /* rename existing file to *.old and *.tmp to existing */\r
- if (ret == ODR_OK) {\r
- rename(entry->filename, filename_old);\r
- if (rename(filename_tmp, entry->filename) != 0) {\r
- ret = ODR_HW;\r
- }\r
- }\r
-\r
- if (ret != ODR_OUT_OF_MEM) {\r
- free(filename_tmp);\r
- free(filename_old);\r
- }\r
-\r
- return ret;\r
-}\r
-\r
-\r
-/*\r
- * Function for restoring data on "Restore default parameters" command - OD 1011\r
- *\r
- * For more information see file CO_storage.h, CO_storage_entry_t.\r
- */\r
-static ODR_t restoreLinux(CO_storage_entry_t *entry, CO_CANmodule_t *CANmodule){\r
- (void) CANmodule;\r
- ODR_t ret = ODR_OK;\r
-\r
- /* close the file first, if auto storage */\r
- if ((entry->attr & CO_storage_auto) != 0 && entry->fp != NULL) {\r
- fclose(entry->fp);\r
- entry->fp = NULL;\r
- }\r
-\r
- /* Rename existing filename to *.old. */\r
- char *filename_old = malloc(strlen(entry->filename) + 5);\r
- if (filename_old == NULL) {\r
- ret = ODR_OUT_OF_MEM;\r
- }\r
- else {\r
- strcpy(filename_old, entry->filename);\r
- strcat(filename_old, ".old");\r
- rename(entry->filename, filename_old);\r
- free(filename_old);\r
- }\r
-\r
- /* create an empty file and write "-\n" to it. */\r
- if (ret == ODR_OK) {\r
- FILE *fp = fopen(entry->filename, "w");\r
- if (fp == NULL) {\r
- ret = ODR_HW;\r
- }\r
- else {\r
- fputs("-\n", fp);\r
- fclose(fp);\r
- }\r
- }\r
-\r
- return ret;\r
-}\r
-\r
-\r
-CO_ReturnError_t CO_storageLinux_init(CO_storage_t *storage,\r
- CO_CANmodule_t *CANmodule,\r
- OD_entry_t *OD_1010_StoreParameters,\r
- OD_entry_t *OD_1011_RestoreDefaultParam,\r
- CO_storage_entry_t *entries,\r
- uint8_t entriesCount,\r
- uint32_t *storageInitError)\r
-{\r
- CO_ReturnError_t ret;\r
-\r
- /* verify arguments */\r
- if (storage == NULL || entries == NULL || entriesCount == 0\r
- || storageInitError == NULL\r
- ) {\r
- return CO_ERROR_ILLEGAL_ARGUMENT;\r
- }\r
-\r
- storage->enabled = false;\r
-\r
- /* initialize storage and OD extensions */\r
- ret = CO_storage_init(storage,\r
- CANmodule,\r
- OD_1010_StoreParameters,\r
- OD_1011_RestoreDefaultParam,\r
- storeLinux,\r
- restoreLinux,\r
- entries,\r
- entriesCount);\r
- if (ret != CO_ERROR_NO) {\r
- return ret;\r
- }\r
-\r
- /* initialize entries */\r
- *storageInitError = 0;\r
- for (uint8_t i = 0; i < entriesCount; i++) {\r
- CO_storage_entry_t *entry = &entries[i];\r
- bool_t dataCorrupt = false;\r
- char *writeFileAccess = "w";\r
-\r
- /* verify arguments */\r
- if (entry->addr == NULL || entry->len == 0 || entry->subIndexOD < 2\r
- || strlen(entry->filename) == 0\r
- ) {\r
- *storageInitError = i;\r
- return CO_ERROR_ILLEGAL_ARGUMENT;\r
- }\r
-\r
- /* Open file, check existence and create temporary buffer */\r
- uint8_t *buf = NULL;\r
- FILE * fp = fopen(entry->filename, "r");\r
- if (fp == NULL) {\r
- dataCorrupt = true;\r
- ret = CO_ERROR_DATA_CORRUPT;\r
- }\r
- else {\r
- buf = malloc(entry->len + sizeof(uint16_t));\r
- if (buf == NULL) {\r
- fclose(fp);\r
- *storageInitError = i;\r
- return CO_ERROR_OUT_OF_MEMORY;\r
- }\r
- }\r
-\r
- /* Read data into temporary buffer first. Then verify and copy to addr*/\r
- if (!dataCorrupt) {\r
- size_t cnt = fread(buf, 1, entry->len + sizeof(uint16_t), fp);\r
-\r
- /* If file is empty, just skip loading, default values will be used,\r
- * no error. Otherwise verify length and crc and copy data. */\r
- if (!(cnt == 2 && buf[0] == '-')) {\r
- uint16_t crc1, crc2;\r
- crc1 = crc16_ccitt(buf, entry->len, 0);\r
- memcpy(&crc2, &buf[entry->len], sizeof(crc2));\r
-\r
- if (crc1 == crc2 && cnt == (entry->len + sizeof(crc2))) {\r
- memcpy(entry->addr, buf, entry->len);\r
- entry->crc = crc1;\r
- writeFileAccess = "r+";\r
- }\r
- else {\r
- dataCorrupt = true;\r
- ret = CO_ERROR_DATA_CORRUPT;\r
- }\r
- }\r
-\r
- free(buf);\r
- fclose(fp);\r
- }\r
-\r
- /* additional info in case of error */\r
- if (dataCorrupt) {\r
- uint32_t errorBit = entry->subIndexOD;\r
- if (errorBit > 31) errorBit = 31;\r
- *storageInitError |= ((uint32_t) 1) << errorBit;\r
- }\r
-\r
- /* open file for auto storage, if set so */\r
- if ((entry->attr & CO_storage_auto) != 0) {\r
- entry->fp = fopen(entry->filename, writeFileAccess);\r
- if (entry->fp == NULL) {\r
- *storageInitError = i;\r
- return CO_ERROR_ILLEGAL_ARGUMENT;\r
- }\r
- }\r
- } /* for (entries) */\r
-\r
- storage->enabled = true;\r
- return ret;\r
-}\r
-\r
-\r
-uint32_t CO_storageLinux_auto_process(CO_storage_t *storage,\r
- bool_t closeFiles)\r
-{\r
- uint32_t storageError = 0;\r
-\r
- /* verify arguments */\r
- if (storage == NULL) {\r
- return false;\r
- }\r
-\r
- /* loop through entries */\r
- for (uint8_t i = 0; i < storage->entriesCount; i++) {\r
- CO_storage_entry_t *entry = &storage->entries[i];\r
-\r
- if ((entry->attr & CO_storage_auto) == 0 || entry->fp == NULL)\r
- continue;\r
-\r
- /* If CRC of the current data differs, save the file */\r
- uint16_t crc = crc16_ccitt(entry->addr, entry->len, 0);\r
- if (crc != entry->crc) {\r
- size_t cnt;\r
- rewind(entry->fp);\r
- CO_LOCK_OD(storage->CANmodule);\r
- cnt = fwrite(entry->addr, 1, entry->len, entry->fp);\r
- CO_UNLOCK_OD(storage->CANmodule);\r
- cnt += fwrite(&crc, 1, sizeof(crc), entry->fp);\r
- fflush(entry->fp);\r
- if (cnt == (entry->len + sizeof(crc))) {\r
- entry->crc = crc;\r
- }\r
- else {\r
- /* error with save */\r
- uint32_t errorBit = entry->subIndexOD;\r
- if (errorBit > 31) errorBit = 31;\r
- storageError |= ((uint32_t) 1) << errorBit;\r
- }\r
- }\r
-\r
- if (closeFiles) {\r
- fclose(entry->fp);\r
- entry->fp = NULL;\r
- }\r
- }\r
-\r
- return storageError;\r
-}\r
-\r
-#endif /* (CO_CONFIG_STORAGE) & CO_CONFIG_STORAGE_ENABLE */\r
+/*
+ * CANopen data storage object for Linux
+ *
+ * @file CO_storageLinux.c
+ * @author Janez Paternoster
+ * @copyright 2021 Janez Paternoster
+ *
+ * This file is part of <https://github.com/CANopenNode/CANopenNode>, a CANopen Stack.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
+ * file except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and limitations under the License.
+ */
+
+#include "CO_storageLinux.h"
+#include "301/crc16-ccitt.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#if (CO_CONFIG_STORAGE) & CO_CONFIG_STORAGE_ENABLE
+
+
+/*
+ * Function for writing data on "Store parameters" command - OD object 1010
+ *
+ * For more information see file CO_storage.h, CO_storage_entry_t.
+ */
+static ODR_t storeLinux(CO_storage_entry_t *entry, CO_CANmodule_t *CANmodule) {
+ ODR_t ret = ODR_OK;
+ uint16_t crc_store;
+
+ /* Create names for temporary and old file */
+ size_t fn_len = strlen(entry->filename) + 5;
+ char *filename_tmp = malloc(fn_len);
+ char *filename_old = malloc(fn_len);
+ if (filename_tmp == NULL || filename_old == NULL) {
+ if (filename_tmp != NULL) free(filename_tmp);
+ if (filename_old != NULL) free(filename_old);
+ ret = ODR_OUT_OF_MEM;
+ }
+ else {
+ strcpy(filename_tmp, entry->filename);
+ strcpy(filename_old, entry->filename);
+ strcat(filename_tmp, ".tmp");
+ strcat(filename_old, ".old");
+ }
+
+ /* Open a temporary file and write data to it */
+ if (ret == ODR_OK) {
+ FILE *fp = fopen(filename_tmp, "w");
+ if (fp == NULL) {
+ ret = ODR_HW;
+ }
+ else {
+ CO_LOCK_OD(CANmodule);
+ size_t cnt = fwrite(entry->addr, 1, entry->len, fp);
+ crc_store = crc16_ccitt(entry->addr, entry->len, 0);
+ CO_UNLOCK_OD(CANmodule);
+ cnt += fwrite(&crc_store, 1, sizeof(crc_store), fp);
+ fclose(fp);
+ if (cnt != (entry->len + sizeof(crc_store))) {
+ ret = ODR_HW;
+ }
+ }
+ }
+
+ /* Verify data */
+ if (ret == ODR_OK) {
+ uint8_t *buf = NULL;
+ FILE *fp = NULL;
+ size_t cnt = 0;
+ uint16_t crc_verify, crc_read;
+
+ buf = malloc(entry->len + 4);
+ if (buf != NULL) {
+ fp = fopen(filename_tmp, "r");
+ if (fp != NULL) {
+ cnt = fread(buf, 1, entry->len + 4, fp);
+ crc_verify = crc16_ccitt(buf, entry->len, 0);
+ fclose(fp);
+ memcpy(&crc_read, &buf[entry->len], sizeof(crc_read));
+ }
+ free(buf);
+ }
+ /* If size or CRC differs, report error */
+ if (buf == NULL || fp == NULL || cnt != (entry->len+sizeof(crc_verify))
+ || crc_store != crc_verify || crc_store != crc_read
+ ) {
+ ret = ODR_HW;
+ }
+ }
+
+ /* rename existing file to *.old and *.tmp to existing */
+ if (ret == ODR_OK) {
+ rename(entry->filename, filename_old);
+ if (rename(filename_tmp, entry->filename) != 0) {
+ ret = ODR_HW;
+ }
+ }
+
+ if (ret != ODR_OUT_OF_MEM) {
+ free(filename_tmp);
+ free(filename_old);
+ }
+
+ return ret;
+}
+
+
+/*
+ * Function for restoring data on "Restore default parameters" command - OD 1011
+ *
+ * For more information see file CO_storage.h, CO_storage_entry_t.
+ */
+static ODR_t restoreLinux(CO_storage_entry_t *entry, CO_CANmodule_t *CANmodule){
+ (void) CANmodule;
+ ODR_t ret = ODR_OK;
+
+ /* close the file first, if auto storage */
+ if ((entry->attr & CO_storage_auto) != 0 && entry->fp != NULL) {
+ fclose(entry->fp);
+ entry->fp = NULL;
+ }
+
+ /* Rename existing filename to *.old. */
+ char *filename_old = malloc(strlen(entry->filename) + 5);
+ if (filename_old == NULL) {
+ ret = ODR_OUT_OF_MEM;
+ }
+ else {
+ strcpy(filename_old, entry->filename);
+ strcat(filename_old, ".old");
+ rename(entry->filename, filename_old);
+ free(filename_old);
+ }
+
+ /* create an empty file and write "-\n" to it. */
+ if (ret == ODR_OK) {
+ FILE *fp = fopen(entry->filename, "w");
+ if (fp == NULL) {
+ ret = ODR_HW;
+ }
+ else {
+ fputs("-\n", fp);
+ fclose(fp);
+ }
+ }
+
+ return ret;
+}
+
+
+CO_ReturnError_t CO_storageLinux_init(CO_storage_t *storage,
+ CO_CANmodule_t *CANmodule,
+ OD_entry_t *OD_1010_StoreParameters,
+ OD_entry_t *OD_1011_RestoreDefaultParam,
+ CO_storage_entry_t *entries,
+ uint8_t entriesCount,
+ uint32_t *storageInitError)
+{
+ CO_ReturnError_t ret;
+
+ /* verify arguments */
+ if (storage == NULL || entries == NULL || entriesCount == 0
+ || storageInitError == NULL
+ ) {
+ return CO_ERROR_ILLEGAL_ARGUMENT;
+ }
+
+ storage->enabled = false;
+
+ /* initialize storage and OD extensions */
+ ret = CO_storage_init(storage,
+ CANmodule,
+ OD_1010_StoreParameters,
+ OD_1011_RestoreDefaultParam,
+ storeLinux,
+ restoreLinux,
+ entries,
+ entriesCount);
+ if (ret != CO_ERROR_NO) {
+ return ret;
+ }
+
+ /* initialize entries */
+ *storageInitError = 0;
+ for (uint8_t i = 0; i < entriesCount; i++) {
+ CO_storage_entry_t *entry = &entries[i];
+ bool_t dataCorrupt = false;
+ char *writeFileAccess = "w";
+
+ /* verify arguments */
+ if (entry->addr == NULL || entry->len == 0 || entry->subIndexOD < 2
+ || strlen(entry->filename) == 0
+ ) {
+ *storageInitError = i;
+ return CO_ERROR_ILLEGAL_ARGUMENT;
+ }
+
+ /* Open file, check existence and create temporary buffer */
+ uint8_t *buf = NULL;
+ FILE * fp = fopen(entry->filename, "r");
+ if (fp == NULL) {
+ dataCorrupt = true;
+ ret = CO_ERROR_DATA_CORRUPT;
+ }
+ else {
+ buf = malloc(entry->len + sizeof(uint16_t));
+ if (buf == NULL) {
+ fclose(fp);
+ *storageInitError = i;
+ return CO_ERROR_OUT_OF_MEMORY;
+ }
+ }
+
+ /* Read data into temporary buffer first. Then verify and copy to addr */
+ if (!dataCorrupt) {
+ size_t cnt = fread(buf, 1, entry->len + sizeof(uint16_t), fp);
+
+ /* If file is empty, just skip loading, default values will be used,
+ * no error. Otherwise verify length and crc and copy data. */
+ if (!(cnt == 2 && buf[0] == '-')) {
+ uint16_t crc1, crc2;
+ crc1 = crc16_ccitt(buf, entry->len, 0);
+ memcpy(&crc2, &buf[entry->len], sizeof(crc2));
+
+ if (crc1 == crc2 && cnt == (entry->len + sizeof(crc2))) {
+ memcpy(entry->addr, buf, entry->len);
+ entry->crc = crc1;
+ writeFileAccess = "r+";
+ }
+ else {
+ dataCorrupt = true;
+ ret = CO_ERROR_DATA_CORRUPT;
+ }
+ }
+
+ free(buf);
+ fclose(fp);
+ }
+
+ /* additional info in case of error */
+ if (dataCorrupt) {
+ uint32_t errorBit = entry->subIndexOD;
+ if (errorBit > 31) errorBit = 31;
+ *storageInitError |= ((uint32_t) 1) << errorBit;
+ }
+
+ /* open file for auto storage, if set so */
+ if ((entry->attr & CO_storage_auto) != 0) {
+ entry->fp = fopen(entry->filename, writeFileAccess);
+ if (entry->fp == NULL) {
+ *storageInitError = i;
+ return CO_ERROR_ILLEGAL_ARGUMENT;
+ }
+ }
+ } /* for (entries) */
+
+ storage->enabled = true;
+ return ret;
+}
+
+
+uint32_t CO_storageLinux_auto_process(CO_storage_t *storage,
+ bool_t closeFiles)
+{
+ uint32_t storageError = 0;
+
+ /* verify arguments */
+ if (storage == NULL) {
+ return false;
+ }
+
+ /* loop through entries */
+ for (uint8_t i = 0; i < storage->entriesCount; i++) {
+ CO_storage_entry_t *entry = &storage->entries[i];
+
+ if ((entry->attr & CO_storage_auto) == 0 || entry->fp == NULL)
+ continue;
+
+ /* If CRC of the current data differs, save the file */
+ uint16_t crc = crc16_ccitt(entry->addr, entry->len, 0);
+ if (crc != entry->crc) {
+ size_t cnt;
+ rewind(entry->fp);
+ CO_LOCK_OD(storage->CANmodule);
+ cnt = fwrite(entry->addr, 1, entry->len, entry->fp);
+ CO_UNLOCK_OD(storage->CANmodule);
+ cnt += fwrite(&crc, 1, sizeof(crc), entry->fp);
+ fflush(entry->fp);
+ if (cnt == (entry->len + sizeof(crc))) {
+ entry->crc = crc;
+ }
+ else {
+ /* error with save */
+ uint32_t errorBit = entry->subIndexOD;
+ if (errorBit > 31) errorBit = 31;
+ storageError |= ((uint32_t) 1) << errorBit;
+ }
+ }
+
+ if (closeFiles) {
+ fclose(entry->fp);
+ entry->fp = NULL;
+ }
+ }
+
+ return storageError;
+}
+
+#endif /* (CO_CONFIG_STORAGE) & CO_CONFIG_STORAGE_ENABLE */
-/**\r
- * CANopen data storage object for Linux\r
- *\r
- * @file CO_storageLinux.h\r
- * @ingroup CO_storageLinux\r
- * @author Janez Paternoster\r
- * @copyright 2021 Janez Paternoster\r
- *\r
- * This file is part of CANopenNode, an opensource CANopen Stack.\r
- * Project home page is <https://github.com/CANopenNode/CANopenNode>.\r
- * For more information on CANopen see <http://www.can-cia.org/>.\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-#ifndef CO_STORAGE_LINUX_H\r
-#define CO_STORAGE_LINUX_H\r
-\r
-#include "storage/CO_storage.h"\r
-\r
-#if ((CO_CONFIG_STORAGE) & CO_CONFIG_STORAGE_ENABLE) || defined CO_DOXYGEN\r
-\r
-#ifdef __cplusplus\r
-extern "C" {\r
-#endif\r
-\r
-/**\r
- * @defgroup CO_storageLinux Data storage with Linux\r
- * Data initialize, store and restore functions with Linux.\r
- *\r
- * @ingroup CO_socketCAN\r
- * @{\r
- *\r
- * See also @ref CO_storage.\r
- */\r
-\r
-\r
-/**\r
- * Initialize data storage object (Linux specific)\r
- *\r
- * This function should be called by application after the program startup,\r
- * before @ref CO_CANopenInit(). This function initializes storage object,\r
- * OD extensions on objects 1010 and 1011, reads data from file, verifies them\r
- * and writes data to addresses specified inside entries. This function\r
- * internally calls @ref CO_storage_init().\r
- *\r
- * @param storage This object will be initialized. It must be defined by\r
- * application and must exist permanently.\r
- * @param CANmodule CAN device, used for @ref CO_LOCK_OD() macro.\r
- * @param OD_1010_StoreParameters OD entry for 0x1010 -"Store parameters".\r
- * Entry is optional, may be NULL.\r
- * @param OD_1011_RestoreDefaultParam OD entry for 0x1011 -"Restore default\r
- * parameters". Entry is optional, may be NULL.\r
- * @param entries Pointer to array of storage entries, see @ref CO_storage_init.\r
- * @param entriesCount Count of storage entries\r
- * @param [out] storageInitError If function returns CO_ERROR_DATA_CORRUPT,\r
- * then this variable contains a bit mask from subIndexOD values, where data\r
- * was not properly initialized. If other error, then this variable contains\r
- * index or erroneous entry.\r
- *\r
- * @return CO_ERROR_NO, CO_ERROR_DATA_CORRUPT if data can not be initialized,\r
- * CO_ERROR_ILLEGAL_ARGUMENT or CO_ERROR_OUT_OF_MEMORY.\r
- */\r
-CO_ReturnError_t CO_storageLinux_init(CO_storage_t *storage,\r
- CO_CANmodule_t *CANmodule,\r
- OD_entry_t *OD_1010_StoreParameters,\r
- OD_entry_t *OD_1011_RestoreDefaultParam,\r
- CO_storage_entry_t *entries,\r
- uint8_t entriesCount,\r
- uint32_t *storageInitError);\r
-\r
-\r
-/**\r
- * Automatically save data if differs from previous call.\r
- *\r
- * Should be called cyclically by program. Each interval it verifies, if crc\r
- * checksum of data differs from previous checksum. If it does, data are saved\r
- * into pre-opened file.\r
- *\r
- * @param storage This object\r
- * @param closeFiles If true, then all files will be closed. Use on end of the\r
- * program.\r
- *\r
- * @return 0 on success or bit mask from subIndexOD values, where data was not\r
- * able to be saved.\r
- */\r
-uint32_t CO_storageLinux_auto_process(CO_storage_t *storage,\r
- bool_t closeFiles);\r
-\r
-/** @} */ /* CO_storageLinux */\r
-\r
-#ifdef __cplusplus\r
-}\r
-#endif /* __cplusplus */\r
-\r
-#endif /* (CO_CONFIG_STORAGE) & CO_CONFIG_STORAGE_ENABLE */\r
-\r
-#endif /* CO_STORAGE_LINUX_H */\r
+/**
+ * CANopen data storage object for Linux
+ *
+ * @file CO_storageLinux.h
+ * @ingroup CO_storageLinux
+ * @author Janez Paternoster
+ * @copyright 2021 Janez Paternoster
+ *
+ * This file is part of <https://github.com/CANopenNode/CANopenNode>, a CANopen Stack.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
+ * file except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and limitations under the License.
+ */
+
+#ifndef CO_STORAGE_LINUX_H
+#define CO_STORAGE_LINUX_H
+
+#include "storage/CO_storage.h"
+
+#if ((CO_CONFIG_STORAGE) & CO_CONFIG_STORAGE_ENABLE) || defined CO_DOXYGEN
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup CO_storageLinux Data storage with Linux
+ * Data initialize, store and restore functions with Linux.
+ *
+ * @ingroup CO_socketCAN
+ * @{
+ *
+ * See also @ref CO_storage.
+ */
+
+
+/**
+ * Initialize data storage object (Linux specific)
+ *
+ * This function should be called by application after the program startup,
+ * before @ref CO_CANopenInit(). This function initializes storage object,
+ * OD extensions on objects 1010 and 1011, reads data from file, verifies them
+ * and writes data to addresses specified inside entries. This function
+ * internally calls @ref CO_storage_init().
+ *
+ * @param storage This object will be initialized. It must be defined by application and must exist permanently.
+ * @param CANmodule CAN device, used for @ref CO_LOCK_OD() macro.
+ * @param OD_1010_StoreParameters OD entry for 0x1010 -"Store parameters". Entry is optional, may be NULL.
+ * @param OD_1011_RestoreDefaultParam OD entry for 0x1011 -"Restore default
+ * parameters". Entry is optional, may be NULL.
+ * @param entries Pointer to array of storage entries, see @ref CO_storage_init.
+ * @param entriesCount Count of storage entries
+ * @param [out] storageInitError If function returns CO_ERROR_DATA_CORRUPT,
+ * then this variable contains a bit mask from subIndexOD values, where data
+ * was not properly initialized. If other error, then this variable contains
+ * index or erroneous entry.
+ *
+ * @return CO_ERROR_NO, CO_ERROR_DATA_CORRUPT if data can not be initialized,
+ * CO_ERROR_ILLEGAL_ARGUMENT or CO_ERROR_OUT_OF_MEMORY.
+ */
+CO_ReturnError_t CO_storageLinux_init(CO_storage_t *storage,
+ CO_CANmodule_t *CANmodule,
+ OD_entry_t *OD_1010_StoreParameters,
+ OD_entry_t *OD_1011_RestoreDefaultParam,
+ CO_storage_entry_t *entries,
+ uint8_t entriesCount,
+ uint32_t *storageInitError);
+
+
+/**
+ * Automatically save data if differs from previous call.
+ *
+ * Should be called cyclically by program. Each interval it verifies, if crc
+ * checksum of data differs from previous checksum. If it does, data are saved
+ * into pre-opened file.
+ *
+ * @param storage This object
+ * @param closeFiles If true, then all files will be closed. Use on end of the program.
+ *
+ * @return 0 on success or bit mask from subIndexOD values, where data was not able to be saved.
+ */
+uint32_t CO_storageLinux_auto_process(CO_storage_t *storage,
+ bool_t closeFiles);
+
+/** @} */ /* CO_storageLinux */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* (CO_CONFIG_STORAGE) & CO_CONFIG_STORAGE_ENABLE */
+
+#endif /* CO_STORAGE_LINUX_H */
* @author Janez Paternoster
* @copyright 2020 Janez Paternoster
*
- * This file is part of CANopenNode, an opensource CANopen Stack.
- * Project home page is <https://github.com/CANopenNode/CANopenNode>.
- * For more information on CANopen see <http://www.can-cia.org/>.
+ * This file is part of <https://github.com/CANopenNode/CANopenNode>, a CANopen Stack.
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
+ * file except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and limitations under the License.
*/
#include <stdio.h>
}
for (;;) {
- ssize_t nRead = read(fd_gtw, &replyBuf[count], BUF_SIZE); /* blocking*/
+ ssize_t nRead = read(fd_gtw, &replyBuf[count], BUF_SIZE); /* blocking */
if(nRead > 0) {
count += nRead;
replyBuf[count] = 0;
if (firstPass == 1) {
- /* check for response type. Only response value goes to stdout*/
+ /* check for response type. Only response value goes to stdout */
if (strstr(replyBuf, "] ERROR:") != NULL
&& strstr(replyBuf, "\r\n") != NULL
) {
}
-/******************************************************************************/
int main (int argc, char *argv[]) {
/* configurable options */
enum {out_all, out_data, out_flat} outputType = out_all;
exit(EXIT_FAILURE);
}
}
- else { // addrFamily == AF_UNIX
+ else { /* addrFamily == AF_UNIX */
fd_gtw = socket(AF_UNIX, SOCK_STREAM, 0);
if(fd_gtw == -1) {
perror("Socket creation failed");
size_t len = strlen(commBuf);
if (len < 1) continue;
- // send command
+ /* send command */
if (write(fd_gtw, commBuf, len) != len) { /* blocking function */
perror("Socket write failed");
free(commBuf);
exit(EXIT_FAILURE);
}
- // print reply, if command is complete
+ /* print reply, if command is complete */
if (commBuf[len - 1] == '\n') {
if (printReply(fd_gtw) == EXIT_FAILURE) {
ret = EXIT_FAILURE;
if (len < BUF_SIZE-2 && lastChar != '\n')
continue;
- // send command
+ /* send command */
if (write(fd_gtw, commBuf, len) != len) { /* blocking f. */
perror("Socket write failed");
free(commBuf);
size_t len = strlen(commBuf);
if (len < 1) continue;
- // send command
+ /* send command */
if (write(fd_gtw, commBuf, len) != len) { /* blocking function */
perror("Socket write failed");
free(commBuf);
exit(EXIT_FAILURE);
}
- // print reply, if command is complete
+ /* print reply, if command is complete */
if (commBuf[len - 1] == '\n') {
if (printReply(fd_gtw) == EXIT_FAILURE) {
ret = EXIT_FAILURE;