From 0604c329f5d191ea0794b5e1037cc250cfe3b12f Mon Sep 17 00:00:00 2001 From: Matthew Kennedy Date: Thu, 26 Oct 2023 00:48:10 -0700 Subject: [PATCH] macos serial port implementation --- .../Source/LibOpenBLT/port/macos/serialport.c | 279 ++++++++++++++++++ Host/Source/LibOpenBLT/port/macos/timeutil.c | 71 +++++ .../Source/LibOpenBLT/port/macos/xcpprotect.c | 194 ++++++++++++ 3 files changed, 544 insertions(+) create mode 100644 Host/Source/LibOpenBLT/port/macos/serialport.c create mode 100644 Host/Source/LibOpenBLT/port/macos/timeutil.c create mode 100644 Host/Source/LibOpenBLT/port/macos/xcpprotect.c diff --git a/Host/Source/LibOpenBLT/port/macos/serialport.c b/Host/Source/LibOpenBLT/port/macos/serialport.c new file mode 100644 index 00000000..005b277f --- /dev/null +++ b/Host/Source/LibOpenBLT/port/macos/serialport.c @@ -0,0 +1,279 @@ +/************************************************************************************//** +* \file port/linux/serialport.c +* \brief Serial port source file. +* \ingroup SerialPort +* \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 /* UNIX standard functions */ +#include /* POSIX terminal control */ +#include /* file control definitions */ +#include /* system I/O control */ +#include "serialport.h" /* serial port module */ + + +/**************************************************************************************** +* Macro definitions +****************************************************************************************/ +/** \brief Invalid serial port device handle. */ +#define SERIALPORT_INVALID_HANDLE (-1) + + +/**************************************************************************************** +* Local data declarations +****************************************************************************************/ +/** \brief Serial port handle. */ +static int32_t portHandle; + + +/**************************************************************************************** +* Local constant declarations +****************************************************************************************/ +/** \brief Lookup table for converting this module's generic baudrate value to a value + * supported by the low level interface. + */ +static const speed_t baudrateLookup[] = +{ + B9600, /**< Index 0 = SERIALPORT_BR9600 */ + B19200, /**< Index 1 = SERIALPORT_BR19200 */ + B38400, /**< Index 2 = SERIALPORT_BR38400 */ + B57600, /**< Index 3 = SERIALPORT_BR57600 */ + B115200 /**< Index 4 = SERIALPORT_BR115200 */ +}; + + +/************************************************************************************//** +** \brief Initializes the serial port module. +** +****************************************************************************************/ +void SerialPortInit(void) +{ + /* Invalidate the port handle. */ + portHandle = SERIALPORT_INVALID_HANDLE; +} /*** end of SerialPortInit ***/ + + +/************************************************************************************//** +** \brief Terminates the serial port module. +** +****************************************************************************************/ +void SerialPortTerminate(void) +{ + /* Make sure the serial port is closed. */ + SerialPortClose(); +} /*** end of SerialPortTerminate ***/ + + +/************************************************************************************//** +** \brief Opens the connection with the serial port configured as 8,N,1 and no flow +** control. +** \param portname The name of the serial port to open, i.e. /dev/ttyUSB0. +** \param baudrate The desired communication speed. +** \return True if successful, false otherwise. +** +****************************************************************************************/ +bool SerialPortOpen(char const * portname, tSerialPortBaudrate baudrate) +{ + bool result = false; + struct termios options = { 0 }; + int32_t iFlags; + + /* Check parameters. */ + assert(portname != NULL); + + /* Only continue with valid parameters. */ + if (portname != NULL) /*lint !e774 */ + { + /* Assume the result to be okay from here on and only set it to error when a problem + * was detected. + */ + result = true; + /* Open the port. */ + portHandle = open(portname, O_RDWR | O_NOCTTY | O_NDELAY); + /* Check the result */ + if (portHandle == SERIALPORT_INVALID_HANDLE) + { + result = false; + } + + /* Configure the device to block during read operations. */ + if (result) + { + if (fcntl(portHandle, F_SETFL, 0) == -1) + { + SerialPortClose(); + result = false; + } + } + /* Get the current options for the port. */ + if (result) + { + if (tcgetattr(portHandle, &options) == -1) + { + SerialPortClose(); + result = false; + } + } + /* Configure the baudrate. */ + if (result) + { + if (cfsetispeed(&options, baudrateLookup[baudrate]) == -1) + { + SerialPortClose(); + result = false; + } + } + if (result) + { + if (cfsetospeed(&options, baudrateLookup[baudrate]) == -1) + { + SerialPortClose(); + result = false; + } + } + + if (result) + { + /* Input modes - clear indicated ones giving: no break, no CR to NL, + * no parity check, no strip char, no start/stop output (sic) control. + */ + options.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); + /* Output modes - clear giving: no post processing such as NL to CR+NL. */ + options.c_oflag &= ~(OPOST); + /* Control modes - set 8 bit chars */ + options.c_cflag |= (CS8); + /* Local modes - clear giving: echoing off, canonical off (no erase with + * backspace, ^U,...), no extended functions, no signal chars (^Z,^C). + */ + options.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); + /* Configure timeouts. */ + options.c_cc[VMIN] = 0; + options.c_cc[VTIME] = 1; /* in units of 1/10th of a second */ + /* Set the new options for the port. */ + if (tcsetattr(portHandle, TCSAFLUSH, &options) == -1) + { + SerialPortClose(); + result = false; + } + } + /* Turn on DTR. */ + if (result) + { + iFlags = TIOCM_DTR; + if (ioctl(portHandle, TIOCMBIS, &iFlags) == -1) + { + SerialPortClose(); + result = false; + } + } + } + + /* Give the result back to the caller. */ + return result; +} /*** end of SerialPortOpen ***/ + + +/************************************************************************************//** +** \brief Closes the connection with the serial port. +** +****************************************************************************************/ +void SerialPortClose(void) +{ + /* Close the port handle if valid. */ + if (portHandle != SERIALPORT_INVALID_HANDLE) + { + close(portHandle); + } + /* Invalidate handle. */ + portHandle = SERIALPORT_INVALID_HANDLE; +} /*** end of SerialPortClose ***/ + + +/************************************************************************************//** +** \brief Writes data to the serial port. +** \param data Pointer to byte array with data to write. +** \param length Number of bytes to write. +** \return True if successful, false otherwise. +** +****************************************************************************************/ +bool SerialPortWrite(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 */ + { + /* Submit the data for sending. */ + if ((uint32_t)write(portHandle, data, length) == length) + { + result = true; + } + } + /* Give the result back to the caller. */ + return result; +} /*** end of SerialPortWrite ***/ + + +/************************************************************************************//** +** \brief Reads data from the serial port in a blocking manner. +** \param data Pointer to byte array to store read data. +** \param length Number of bytes to read. +** \return True if successful, false otherwise. +** +****************************************************************************************/ +bool SerialPortRead(uint8_t * 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 */ + { + /* Attempt to read the requested data. */ + if ((uint32_t)read(portHandle, data, length) == length) + { + result = true; + } + } + /* Give the result back to the caller. */ + return result; +} /*** end of SerialPortRead ***/ + + +/*********************************** end of serialport.c *******************************/ + diff --git a/Host/Source/LibOpenBLT/port/macos/timeutil.c b/Host/Source/LibOpenBLT/port/macos/timeutil.c new file mode 100644 index 00000000..8cc0a7a0 --- /dev/null +++ b/Host/Source/LibOpenBLT/port/macos/timeutil.c @@ -0,0 +1,71 @@ +/************************************************************************************//** +* \file port/linux/timeutil.c +* \brief Time 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 standard integer types */ +#include /* for NULL declaration */ +#include /* for boolean type */ +#include /* UNIX standard functions */ +#include /* time definitions */ +#include "util.h" /* Utility module */ + + +/************************************************************************************//** +** \brief Get the system time in milliseconds. +** \return Time in milliseconds. +** +****************************************************************************************/ +uint32_t UtilTimeGetSystemTimeMs(void) +{ + uint32_t result = 0; + struct timeval tv; + + if (gettimeofday(&tv, NULL) == 0) + { + result = (((uint32_t)tv.tv_sec * 1000ul) + ((uint32_t)tv.tv_usec / 1000ul)); + } + /* Give the result back to the caller. */ + return result; +} /*** end of UtilTimeGetSystemTimeMs ***/ + + +/************************************************************************************//** +** \brief Performs a delay of the specified amount of milliseconds. +** \param delay Delay time in milliseconds. +** +****************************************************************************************/ +void UtilTimeDelayMs(uint16_t delay) +{ + (void)usleep(1000u * delay); +} /*** end of UtilTimeDelayMs **/ + + +/*********************************** end of timeutil.c *********************************/ + diff --git a/Host/Source/LibOpenBLT/port/macos/xcpprotect.c b/Host/Source/LibOpenBLT/port/macos/xcpprotect.c new file mode 100644 index 00000000..78aea757 --- /dev/null +++ b/Host/Source/LibOpenBLT/port/macos/xcpprotect.c @@ -0,0 +1,194 @@ +/************************************************************************************//** +* \file port/linux/xcpprotect.c +* \brief XCP Protection module source file. +* \ingroup XcpLoader +* \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 dynamic loading */ +#include "xcpprotect.h" /* XCP protection module */ + + +/**************************************************************************************** +* Type definitions +****************************************************************************************/ +/* Seed and key shared library function types. */ +typedef uint32_t ( * tXcpProtectLibComputeKey)(uint8_t resource, uint8_t seedLen, + uint8_t const * seedPtr, + uint8_t * keyLenPtr, uint8_t * keyPtr); +typedef uint32_t ( * tXcpProtectLibGetPrivileges)(uint8_t * resourcePtr); + + +/**************************************************************************************** +* Local data declarations +****************************************************************************************/ +/** \brief Handle to the dynamically loaded seed and key shared library. It can also be + * used as a flag to determine if the shared library was specified and success- + * fully loaded. + */ +static void * seedNKeyLibraryHandle; + +/** \brief Function pointer to the XCP_ComputeKeyFromSeed shared library function. */ +static tXcpProtectLibComputeKey xcpProtectLibComputeKey; + +/** \brief Function pointer to the XCP_GetAvailablePrivileges shared library function. */ +static tXcpProtectLibGetPrivileges xcpProtectLibGetPrivileges; + + +/************************************************************************************//** +** \brief Initializes the XCP protection module. +** \param seedKeyFile Filename of the seed and key shared library that contains the +** following functions: +** - XCP_ComputeKeyFromSeed() +** - XCP_GetAvailablePrivileges() +** +****************************************************************************************/ +void XcpProtectInit(char const * seedKeyFile) +{ + /* Init locals. */ + seedNKeyLibraryHandle = NULL; + /* Reset library function pointers. */ + xcpProtectLibComputeKey = NULL; + xcpProtectLibGetPrivileges = NULL; + + /* Only load the shared library is a valid file was specified. */ + if (seedKeyFile != NULL) + { + /* Attempt to load the shared library. */ + seedNKeyLibraryHandle = dlopen(seedKeyFile, RTLD_LAZY); + /* Load the function pointers from the shared library. */ + if (seedNKeyLibraryHandle != NULL) + { + xcpProtectLibComputeKey = dlsym(seedNKeyLibraryHandle, + "XCP_ComputeKeyFromSeed"); + xcpProtectLibGetPrivileges = dlsym(seedNKeyLibraryHandle, + "XCP_GetAvailablePrivileges"); + } + } +} /*** end of XcpProtectInit ***/ + + +/************************************************************************************//** +** \brief Terminates the XCP protection module. +** +****************************************************************************************/ +void XcpProtectTerminate(void) +{ + /* Reset library function pointers. */ + xcpProtectLibComputeKey = NULL; + xcpProtectLibGetPrivileges = NULL; + /* Only unload the shared library if one was loaded. */ + if (seedNKeyLibraryHandle != NULL) + { + /* Unload the shared library. */ + (void)dlclose(seedNKeyLibraryHandle); + /* Reset the handle. */ + seedNKeyLibraryHandle = NULL; + } +} /*** end of XcpProtectTerminate ***/ + + +/************************************************************************************//** +** \brief Computes the key for the requested resource. +** \param resource resource for which the unlock key is requested +** \param seedLen length of the seed +** \param seedPtr pointer to the seed data +** \param keyLenPtr pointer where to store the key length +** \param keyPtr pointer where to store the key data +** \return True if successful, false otherwise. +** +****************************************************************************************/ +bool XCPProtectComputeKeyFromSeed(uint8_t resource, uint8_t seedLen, + uint8_t const * seedPtr, uint8_t * keyLenPtr, + uint8_t * keyPtr) +{ + bool result = false; + + /* Check parameters. */ + assert(seedLen > 0); + assert(seedPtr != NULL); + assert(keyLenPtr != NULL); + assert(keyPtr != NULL); + + /* Only continue if the parameters are valid. */ + if ( (seedLen > 0) && (seedPtr != NULL) && (keyLenPtr != NULL) && + (keyPtr != NULL) ) /*lint !e774 */ + { + /* Only continue with a valid function pointer into the shared library. */ + if (xcpProtectLibComputeKey != NULL) + { + /* Call the library function. */ + if (xcpProtectLibComputeKey(resource, seedLen, seedPtr, keyLenPtr, keyPtr) == 0) + { + /* All good so update the result value accordingly. */ + result = true; + } + } + } + /* Give the result back to the caller. */ + return result; +} /*** end of XCPProtectComputeKeyFromSeed ***/ + + +/************************************************************************************//** +** \brief Obtains a bitmask of the resources for which an key algorithm is available. +** \param resourcePtr pointer where to store the supported resources for the key +** computation. +** \return XCP_RESULT_OK on success, otherwise XCP_RESULT_ERROR. +** +****************************************************************************************/ +bool XcpProtectGetPrivileges(uint8_t * resourcePtr) +{ + bool result = false; + + /* Check parameters. */ + assert(resourcePtr != NULL); + + /* Only continue if the parameter is valid. */ + if (resourcePtr != NULL) /*lint !e774 */ + { + /* Only continue with a valid function pointer into the shared library. */ + if (xcpProtectLibGetPrivileges != NULL) + { + /* Call the library function. */ + if (xcpProtectLibGetPrivileges(resourcePtr) == 0) + { + /* All good so update the result value accordingly. */ + result = true; + } + } + } + /* Give the result back to the caller. */ + return result; +} /*** end of XcpProtectGetPrivileges ***/ + + +/*********************************** end of xcpprotect.c *******************************/