From 08c4e51e86b732faef6b24f24c2ae9d5870b1089 Mon Sep 17 00:00:00 2001 From: Matthew Kennedy Date: Thu, 26 Oct 2023 00:58:47 -0700 Subject: [PATCH] macos guards working --- Host/Source/LibOpenBLT/CMakeLists.txt | 2 +- Host/Source/LibOpenBLT/candriver.c | 3 + Host/Source/LibOpenBLT/openblt.c | 4 + Host/Source/LibOpenBLT/port/macos/critutil.c | 126 +++++++ Host/Source/LibOpenBLT/port/macos/netaccess.c | 332 ++++++++++++++++++ Host/Source/LibOpenBLT/xcptpcan.c | 3 + Host/Source/LibOpenBLT/xcptpusb.c | 3 + 7 files changed, 472 insertions(+), 1 deletion(-) create mode 100644 Host/Source/LibOpenBLT/port/macos/critutil.c create mode 100644 Host/Source/LibOpenBLT/port/macos/netaccess.c diff --git a/Host/Source/LibOpenBLT/CMakeLists.txt b/Host/Source/LibOpenBLT/CMakeLists.txt index fc852030..e8445bb0 100644 --- a/Host/Source/LibOpenBLT/CMakeLists.txt +++ b/Host/Source/LibOpenBLT/CMakeLists.txt @@ -103,7 +103,7 @@ if(WIN32) endif() endif() elseif(APPLE) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DPLATFORM_MACOS -DPLATFORM_64BIT -pthread -std=gnu99") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DPLATFORM_MACOS -DPLATFORM_64BIT -DNO_CAN_OR_USB -pthread -std=gnu99") set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64") elseif(UNIX) if(CMAKE_SIZEOF_VOID_P EQUAL 4) diff --git a/Host/Source/LibOpenBLT/candriver.c b/Host/Source/LibOpenBLT/candriver.c index bc316d1e..e9f38802 100644 --- a/Host/Source/LibOpenBLT/candriver.c +++ b/Host/Source/LibOpenBLT/candriver.c @@ -26,6 +26,8 @@ * \endinternal ****************************************************************************************/ +#ifndef NO_CAN_OR_USB + /**************************************************************************************** * Include files ****************************************************************************************/ @@ -281,4 +283,5 @@ void CanRegisterEvents(tCanEvents const * events) } /*** end of CanRegisterEvents ***/ +#endif // NO_CAN_OR_USB /*********************************** end of candriver.c ********************************/ diff --git a/Host/Source/LibOpenBLT/openblt.c b/Host/Source/LibOpenBLT/openblt.c index ae0f5fa1..5b94a3dc 100644 --- a/Host/Source/LibOpenBLT/openblt.c +++ b/Host/Source/LibOpenBLT/openblt.c @@ -39,8 +39,10 @@ #include "session.h" /* Communication session module */ #include "xcploader.h" /* XCP loader module */ #include "xcptpuart.h" /* XCP UART transport layer */ +#ifndef NO_CAN_OR_USB #include "xcptpcan.h" /* XCP CAN transport layer */ #include "xcptpusb.h" /* XCP USB transport layer */ +#endif // NO_CAN_OR_USB #include "xcptpnet.h" /* XCP TCP/IP transport layer */ @@ -173,6 +175,7 @@ LIBOPENBLT_EXPORT void BltSessionInit(uint32_t sessionType, xcpLoaderSettings.transport = XcpTpUartGetTransport(); } } +#ifndef NO_CAN_OR_USB else if (transportType == BLT_TRANSPORT_XCP_V10_CAN) { /* Verify transportSettings parameters because the XCP CAN transport layer @@ -210,6 +213,7 @@ LIBOPENBLT_EXPORT void BltSessionInit(uint32_t sessionType, /* Link the transport layer to the XCP loader settings. */ xcpLoaderSettings.transport = XcpTpUsbGetTransport(); } +#endif // NO_CAN_OR_USB else if (transportType == BLT_TRANSPORT_XCP_V10_NET) { /* Verify transportSettings parameters because the XCP NET transport layer diff --git a/Host/Source/LibOpenBLT/port/macos/critutil.c b/Host/Source/LibOpenBLT/port/macos/critutil.c new file mode 100644 index 00000000..cd88a224 --- /dev/null +++ b/Host/Source/LibOpenBLT/port/macos/critutil.c @@ -0,0 +1,126 @@ +/************************************************************************************//** +* \file port/linux/critutil.c +* \brief Critical section utility source file. +* \ingroup Utility +* \internal +*---------------------------------------------------------------------------------------- +* C O P Y R I G H T +*---------------------------------------------------------------------------------------- +* Copyright (c) 2017 by Feaser http://www.feaser.com All rights reserved +* +*---------------------------------------------------------------------------------------- +* L I C E N S E +*---------------------------------------------------------------------------------------- +* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +* modify it under the terms of the GNU General Public License as published by the Free +* Software Foundation, either version 3 of the License, or (at your option) any later +* version. +* +* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +* PURPOSE. See the GNU General Public License for more details. +* +* You have received a copy of the GNU General Public License along with OpenBLT. It +* should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy. +* +* \endinternal +****************************************************************************************/ + +/**************************************************************************************** +* Include files +****************************************************************************************/ +#include /* for assertions */ +#include /* for standard integer types */ +#include /* for boolean type */ +#include /* for posix threads */ +#include "util.h" /* Utility module */ + + +/**************************************************************************************** +* Local data declarations +****************************************************************************************/ +/** \brief Flag to determine if the critical section object was already initialized. */ +static volatile bool criticalSectionInitialized = false; + +/** \brief Critical section object. */ +static volatile pthread_mutex_t mtxCritSect; + + +/************************************************************************************//** +** \brief Initializes the critical section module. Should be called before the +** Enter/Exit functions are used. It is okay to call this initialization +** multiple times from different modules. +** +****************************************************************************************/ +void UtilCriticalSectionInit(void) +{ + /* Only initialize if not yet done so previously. */ + if (!criticalSectionInitialized) + { + /* Initialize the critical section object. */ + (void)pthread_mutex_init((pthread_mutex_t *)&mtxCritSect, NULL); + /* Set initialized flag. */ + criticalSectionInitialized = true; + } +} /*** end of UtilCriticalSectionInit ***/ + + +/************************************************************************************//** +** \brief Terminates the critical section module. Should be called once critical +** sections are no longer needed. Typically called from another module's +** termination function that also initialized it. It is okay to call this +** termination multiple times from different modules. +** +****************************************************************************************/ +void UtilCriticalSectionTerminate(void) +{ + /* Only terminate if it was initialized. */ + if (criticalSectionInitialized) + { + /* Reset the initialized flag. */ + criticalSectionInitialized = false; + /* Delete the critical section object. */ + (void)pthread_mutex_destroy((pthread_mutex_t *)&mtxCritSect); + } +} /*** end of UtilCriticalSectionTerminate ***/ + + + +/************************************************************************************//** +** \brief Enters a critical section. The functions UtilCriticalSectionEnter and +** UtilCriticalSectionExit should always be used in a pair. +** +****************************************************************************************/ +void UtilCriticalSectionEnter(void) +{ + /* Check initialization. */ + assert(criticalSectionInitialized); + + /* Only continue if actually initialized. */ + if (criticalSectionInitialized) + { + (void)pthread_mutex_lock((pthread_mutex_t *)&mtxCritSect); + } +} /*** end of UtilCriticalSectionEnter ***/ /*lint !e456 !e454 */ + + +/************************************************************************************//** +** \brief Leaves a critical section. The functions UtilCriticalSectionEnter and +** UtilCriticalSectionExit should always be used in a pair. +** +****************************************************************************************/ +void UtilCriticalSectionExit(void) +{ + /* Check initialization. */ + assert(criticalSectionInitialized); + + /* Only continue if actually initialized. */ + if (criticalSectionInitialized) + { + (void)pthread_mutex_unlock((pthread_mutex_t *)&mtxCritSect); /*lint !e455 */ + } +} /*** end of UtilCriticalSectionExit ***/ + + +/*********************************** end of critutil.c *********************************/ + diff --git a/Host/Source/LibOpenBLT/port/macos/netaccess.c b/Host/Source/LibOpenBLT/port/macos/netaccess.c new file mode 100644 index 00000000..6e08cccf --- /dev/null +++ b/Host/Source/LibOpenBLT/port/macos/netaccess.c @@ -0,0 +1,332 @@ +/************************************************************************************//** +* \file port/linux/netaccess.c +* \brief TCP/IP network access source file. +* \ingroup NetAccess +* \internal +*---------------------------------------------------------------------------------------- +* C O P Y R I G H T +*---------------------------------------------------------------------------------------- +* Copyright (c) 2017 by Feaser http://www.feaser.com All rights reserved +* +*---------------------------------------------------------------------------------------- +* L I C E N S E +*---------------------------------------------------------------------------------------- +* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +* modify it under the terms of the GNU General Public License as published by the Free +* Software Foundation, either version 3 of the License, or (at your option) any later +* version. +* +* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +* PURPOSE. See the GNU General Public License for more details. +* +* You have received a copy of the GNU General Public License along with OpenBLT. It +* should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy. +* +* \endinternal +****************************************************************************************/ + +/**************************************************************************************** +* Include files +****************************************************************************************/ +#include /* for assertions */ +#include /* for standard integer types */ +#include /* for NULL declaration */ +#include /* for boolean type */ +#include /* for string utilities */ +#include /* for close */ +#include /* for socket */ +#include /* for inet_addr */ +#include /* for hostent */ +#include "netaccess.h" /* TCP/IP network access module */ + + +/**************************************************************************************** +* Macro definitions +****************************************************************************************/ +/** \brief Constant value that indicates that the network socket is invalid. */ +#define NETACCESS_INVALID_SOCKET (-1) + + +/**************************************************************************************** +* Local data declarations +****************************************************************************************/ +/** \brief The socket that is used as an endpoint for the TCP/IP network + * communication. + */ +static int netAccessSocket; + + +/************************************************************************************//** +** \brief Initializes the network access module. +** +****************************************************************************************/ +void NetAccessInit(void) +{ + /* Invalidate the socket. */ + netAccessSocket = NETACCESS_INVALID_SOCKET; +} /*** end of NetAccessInit ***/ + + +/************************************************************************************//** +** \brief Terminates the network access module. +** +****************************************************************************************/ +void NetAccessTerminate(void) +{ + /* Make sure to disconnect form the server. */ + NetAccessDisconnect(); +} /*** end of NetAccessTerminate ***/ + + +/************************************************************************************//** +** \brief Connects to the TCP/IP server at the specified address and the given port. +** \param address The address of the server. This can be a hostname (such as +** mydomain.com) or an IP address (such as 127.0.0.1). +** \param port The port number on the server to connect to. +** \return True if successful, false otherwise. +** +****************************************************************************************/ +bool NetAccessConnect(char const * address, uint16_t port) +{ + bool result = false; + struct addrinfo hints = { 0 }; + struct addrinfo * serverinfo = NULL; + struct sockaddr_in serverIPv4 = { 0 }; + struct sockaddr_in6 serverIPv6 = { 0 }; + bool serverIPv4found = false; + bool serverIPv6found = false; + + /* Check parameters. */ + assert(address != NULL); + assert(port > 0); + + /* Start by invalidating the socket. */ + netAccessSocket = NETACCESS_INVALID_SOCKET; + + /* Only continue with valid parameters. */ + if ( (address != NULL) && (port > 0) ) /*lint !e774 */ + { + /* Set result to true and only reset it to false upon detection of a problem. */ + result = true; + + /* Initialize hints structure to aid in hostname resolving. Note that AF_UNSPEC is + * used to support both IPv4 and IPv6. + */ + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = (int)SOCK_STREAM; + hints.ai_flags |= AI_CANONNAME; + + /* Attempt to resolve the hostname. This converts the hostname to an IP address, if + * it wasn't already an IP address. + */ + if (getaddrinfo(address, NULL, &hints, &serverinfo) != 0) + { + /* Could not resolve the hostname. */ + result = false; + } + /* Sanity check on the pointer that should now be initialized and contain data. */ + else + { + if (serverinfo == NULL) + { + result = false; + } + } + /* The serverinfo pointer now points to an array with results of the hostname + * resolving. We only need one, so grab the first valid one. Prefer IPv4 over IPv6. + */ + if (result) + { + /* Point to the first entry. */ + struct addrinfo * entry = serverinfo; + /* Loop over the entries until a valid one was found. */ + while (entry != NULL) + { + /* Does this entry contain an IPv4 address? */ + if (entry->ai_family == AF_INET) + { + /* Copy this one for later usage. */ + memcpy (&serverIPv4, entry->ai_addr, entry->ai_addrlen); + serverIPv4.sin_family = AF_INET; + serverIPv4.sin_port = htons(port); + /* Set flag so we know which socket address variable to use later on. */ + serverIPv4found = true; + /* No need to go over the other entries, since we found a valid one. */ + break; + } + /* Does this entry contain an IPv6 address? */ + if (entry->ai_family == AF_INET6) + { + /* Copy this one for later usage. */ + memcpy (&serverIPv6, entry->ai_addr, entry->ai_addrlen); + serverIPv6.sin6_family = AF_INET6; + serverIPv6.sin6_port = htons(port); + /* Set flag so we know which socket address variable to use later on. */ + serverIPv6found = true; + /* No need to go over the other entries, since we found a valid one. */ + break; + } + /* Move on to the next one. */ + entry = entry->ai_next; + } + } + /* Check that a valid entry was found. */ + if (result) + { + if ( (!serverIPv4found) && (!serverIPv6found) ) + { + result = false; + } + } + /* Create the socket. */ + if (result) + { + /* Create the socket based on the family type. */ + if (serverIPv4found) + { + netAccessSocket = socket(serverIPv4.sin_family, (int)SOCK_STREAM, IPPROTO_TCP); + } + else + { + netAccessSocket = socket(serverIPv6.sin6_family, (int)SOCK_STREAM, IPPROTO_TCP); + } + /* Check the socket. */ + if (netAccessSocket < 0) + { + /* Could not create the socket. */ + netAccessSocket = NETACCESS_INVALID_SOCKET; + result = false; + } + } + /* Connect the socket. */ + if (result) + { + /* Get the socket address pointer based on the family type. */ + struct sockaddr * server_address; + if (serverIPv4found) + { + server_address = (struct sockaddr *)&serverIPv4; /*lint !e740 */ + } + else + { + server_address = (struct sockaddr *)&serverIPv6; /*lint !e740 */ + } + /* Attempt to connect. */ + if (connect(netAccessSocket, server_address, sizeof(struct sockaddr)) < 0) + { + /* Could not connect. Close the socket and negate result value. */ + close(netAccessSocket); + netAccessSocket = NETACCESS_INVALID_SOCKET; + result = false; + } + } + } + /* Give the result back to the caller. */ + return result; +} /*** end of NetAccessConnect ***/ + + +/************************************************************************************//** +** \brief Disconnects from the TCP/IP server. +** +****************************************************************************************/ +void NetAccessDisconnect(void) +{ + /* Close the socket if it is open. */ + if (netAccessSocket >= 0) + { + close(netAccessSocket); + netAccessSocket = NETACCESS_INVALID_SOCKET; + } +} /*** end of NetAccessDisconnect ***/ + + +/************************************************************************************//** +** \brief Sends data to the TCP/IP server. +** \param data Pointer to byte array with data to send. +** \param length Number of bytes to send. +** \return True if successful, false otherwise. +** +****************************************************************************************/ +bool NetAccessSend(uint8_t const * data, uint32_t length) +{ + bool result = false; + + /* Check parameters. */ + assert(data != NULL); + assert(length > 0); + + /* Only continue with valid parameters. */ + if ( (data != NULL) && (length > 0) ) /*lint !e774 */ + { + /* Only continue with a valid socket. */ + if (netAccessSocket >= 0) + { + /* Attempt to send the data. */ + if (send(netAccessSocket, data, length, 0) >= 0) + { + /* Successfully send the data. */ + result = true; + } + } + } + /* Give the result back to the caller. */ + return result; +} /*** end of NetAccessSend ***/ + + +/************************************************************************************//** +** \brief Receives data from the TCP/IP server in a blocking manner. +** \param data Pointer to byte array to store the received data. +** \param length Holds the max number of bytes that can be stored into the byte +** array. This function also overwrites this value with the number of bytes +** that were actually received. +** \param timeout Timeout in milliseconds for the data reception. +** \return True if successful, false otherwise. +** +****************************************************************************************/ +bool NetAccessReceive(uint8_t * data, uint32_t * length, uint32_t timeout) +{ + bool result = false; + struct timeval tv; + ssize_t receivedLen; + + /* Check parameters. */ + assert(data != NULL); + assert(length != NULL); + assert(timeout > 0); + + /* Only continue with valid parameters. */ + if ( (data != NULL) && (length != NULL) && (timeout > 0) ) /*lint !e774 */ + { + /* Only continue with a valid socket. */ + if (netAccessSocket >= 0) + { + /* Configure the timeout for the receive operation. */ + tv.tv_sec = (time_t)(timeout / 1000u); + tv.tv_usec = (timeout % 1000u) * 1000u; + if (setsockopt(netAccessSocket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(struct timeval)) >= 0) + { + /* Attempt to receive data. */ + receivedLen = recv(netAccessSocket, data, *length, 0); + /* Process the result. Everything < 0 indicate that an error occured. A value of + * zero is also treated as an error, since data was expected. + */ + if (receivedLen > 0) + { + /* Store the number of received bytes. */ + *length = (uint32_t)receivedLen; + /* Successfully received data. */ + result = true; + } + } + } + } + /* Give the result back to the caller. */ + return result; +} /*** end of NetAccessReceive ***/ + + +/*********************************** end of netaccess.c ********************************/ + diff --git a/Host/Source/LibOpenBLT/xcptpcan.c b/Host/Source/LibOpenBLT/xcptpcan.c index a51f2d4b..d5d37017 100644 --- a/Host/Source/LibOpenBLT/xcptpcan.c +++ b/Host/Source/LibOpenBLT/xcptpcan.c @@ -26,6 +26,8 @@ * \endinternal ****************************************************************************************/ +#ifndef NO_CAN_OR_USB + /**************************************************************************************** * Include files ****************************************************************************************/ @@ -412,4 +414,5 @@ static void XcpTpCanEventMessageReceived(tCanMsg const * msg) } /*** end of XcpTpCanEventMessageReceived ***/ +#endif // NO_CAN_OR_USB /*********************************** end of xcptpcan.c *********************************/ diff --git a/Host/Source/LibOpenBLT/xcptpusb.c b/Host/Source/LibOpenBLT/xcptpusb.c index 69b7931a..dd7ee05d 100644 --- a/Host/Source/LibOpenBLT/xcptpusb.c +++ b/Host/Source/LibOpenBLT/xcptpusb.c @@ -26,6 +26,8 @@ * \endinternal ****************************************************************************************/ +#ifndef NO_CAN_OR_USB + /**************************************************************************************** * Include files ****************************************************************************************/ @@ -226,4 +228,5 @@ static bool XcpTpUsbSendPacket(tXcpTransportPacket const * txPacket, } /*** end of XcpTpUsbSendPacket ***/ +#endif // NO_CAN_OR_USB /*********************************** end of xcptpusb.c *********************************/